fix: tighten sharing and shadcn composition
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# 76 — Shadcn component implementation (Tiers 1–3)
|
||||
|
||||
## Goal
|
||||
|
||||
Implement the three shadcn component adoption tiers that replace ad-hoc UI patterns across the app with shadcn/ui primitives. This is the **execution** phase — components are already installed (see `2026-06-13-shadcn-component-install.md`).
|
||||
|
||||
| Tier | Name | Tasks | Files touched |
|
||||
| ---- | ------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| 1 | Garden badges → Badge, topbar avatar → Avatar, + fallback, semantic token | 5 sub-tasks | topbar.tsx, sidebar.tsx, plant-detail.tsx, push-opt-in.tsx, care-schedule-editor.tsx, plant-widget.tsx |
|
||||
| 2 | Skeleton loading, Tabs nav, Sonner toasts, FieldGroup audit, Separator | 5 sub-tasks | d/[slug]/page.tsx, plant-detail.tsx, container-detail.tsx, layout.tsx, notify-channel-toggles.tsx |
|
||||
| 3 | Garden empty-state, Switch for notify channels | 2 sub-tasks | plant-list.tsx, container-list.tsx, notify-channel-toggles.tsx |
|
||||
|
||||
## Depends on
|
||||
|
||||
- `2026-06-13-shadcn-component-install.md` — components are already in `src/components/ui/`
|
||||
- The shadcn migration map at `2026-06-13-shadcn-migration.md`
|
||||
|
||||
## Scope by tier
|
||||
|
||||
### Tier 1 (detailed brief: `docs/tasks/1a-badges-avatars.md`)
|
||||
|
||||
**Task 1a — Garden health badges → `<Badge>`**
|
||||
|
||||
- File: `src/modules/garden/components/plant-detail.tsx` lines 44-48, 119-123
|
||||
- Replace hand-crafted `badge-success/danger/warning` classes with shadcn `<Badge variant="default|destructive|secondary">`
|
||||
- Delete the `healthBadgeClass()` helper function
|
||||
|
||||
**Task 1b — Topbar avatar → `<Avatar>`**
|
||||
|
||||
- File: `src/components/topbar.tsx` lines 60-75
|
||||
- Replace manual `<span className="avatar">` with `<Avatar><AvatarImage/><AvatarFallback/></Avatar>`
|
||||
|
||||
**Task 1c — HouseholdPill avatars → `<Avatar>`**
|
||||
|
||||
- File: `src/components/sidebar.tsx` lines 106-120
|
||||
- Replace inner span elements with Avatar components (keep avatarColor hash for fallback background)
|
||||
|
||||
**Task 1d — Generic AvatarFallbackWithName component**
|
||||
|
||||
- New file: `src/components/avatar-fallback.tsx`
|
||||
- Thin wrapper that handles the Image/Fallback pattern with name/initial logic
|
||||
- Imported by both topbar.tsx and sidebar.tsx to remove duplication
|
||||
|
||||
**Task 1e — share-green → semantic token**
|
||||
|
||||
- Files: push-opt-in.tsx (line ~104), care-schedule-editor.tsx (line ~185), plant-widget.tsx urgencyLabel, plus any other green-600/green-500 in garden components
|
||||
- Add `--c-success` CSS variable to the global theme
|
||||
- Replace all hardcoded green-600 references with `var(--c-success)`
|
||||
|
||||
### Tier 2 (detailed brief: `docs/tasks/1b-skeleton-tabs-toasts.md`)
|
||||
|
||||
**Task 2a — Skeleton loading states**
|
||||
|
||||
- d/[slug]/page.tsx inline animate-pulse → `<Skeleton>` components
|
||||
- plant-detail.tsx & container-detail.tsx uploadingImage → skeleton overlay
|
||||
- Any other animate-pulse patterns outside skeleton.tsx itself
|
||||
|
||||
**Task 2b — Settings/garden Tabs navigation → `<Tabs>`**
|
||||
|
||||
- File: `src/modules/garden/components/plant-detail.tsx` lines 162-180
|
||||
- File: `src/modules/garden/components/container-detail.tsx` lines 138-155
|
||||
- Replace manual button-based tabs with shadcn Tabs/TabsList/TabsTrigger/TabsContent
|
||||
|
||||
**Task 2c — Toast notifications via sonner**
|
||||
|
||||
- Add `<Toaster>` to app layout (`src/app/layout.tsx`)
|
||||
- Convert delete confirmations, calendar schedule success/error, and share-link actions to `toast.success()`/`toast.error()` calls
|
||||
|
||||
**Task 2d — Form FieldGroup audit**
|
||||
|
||||
- Audit: container-form.tsx, plant-form.tsx, household edit forms
|
||||
- Check consistency of Label + Input + error pattern
|
||||
- Fix any non-shadcn form fields found
|
||||
|
||||
**Task 2e — Manual separators → `<Separator>`**
|
||||
|
||||
- Remove border-bottom on garden detail tab bars, replace with shadcn Separator (usually alongside the Tabs component)
|
||||
|
||||
### Tier 3 (detailed brief: `docs/tasks/1c-emptystate-switch.md`)
|
||||
|
||||
**Task 3a — Garden empty-state component**
|
||||
|
||||
- File: `src/modules/garden/components/plant-list.tsx` line 22 → use EmptyState from ui/empty.tsx
|
||||
- File: `src/modules/garden/components/container-list.tsx` line 39 → use EmptyState
|
||||
- Use appropriate icons (Sprout for plants, Container for containers)
|
||||
|
||||
**Task 3b — Notify channel toggles → `<Switch>`**
|
||||
|
||||
- File: `src/components/notify-channel-toggles.tsx`
|
||||
- Replace native `<input type="checkbox">` with shadcn `<Switch>` component
|
||||
- Keep server action integration (setNotifChannel)
|
||||
- Disabled state for ntfy when unconfigured
|
||||
|
||||
## Acceptance criteria (all tiers)
|
||||
|
||||
1. Zero `badge-success`, `badge-danger`, `badge-warning` class names remain in garden code
|
||||
2. All avatars rendered via shadcn Avatar components (verified by DOM/JSX inspection)
|
||||
3. All loading states use `<Skeleton>` — no animate-pulse patterns outside skeleton.tsx
|
||||
4. Garden detail pages use shadcn Tabs component (not manual buttons)
|
||||
5. Toaster rendered in app layout, delete/cancel actions show toasts
|
||||
6. EmptyState used in all garden list pages (no ad-hoc empty text paragraphs)
|
||||
7. Notification channels use shadcn Switch components
|
||||
8. `pnpm lint` passes with zero errors/warnings
|
||||
9. `pnpm typecheck` passes with zero errors
|
||||
|
||||
## Execution order
|
||||
|
||||
Execute tiers sequentially: 1 → 2 → 3. Each tier builds on the previous one's patterns and fixes foundational issues before adding polish.
|
||||
|
||||
Detailed task briefs are in:
|
||||
|
||||
- Tier 1: `docs/tasks/1a-badges-avatars.md`
|
||||
- Tier 2: `docs/tasks/1b-skeleton-tabs-toasts.md`
|
||||
- Tier 3: `docs/tasks/1c-emptystate-switch.md`
|
||||
Reference in New Issue
Block a user