Files
famapp/docs/tasks/1a-badges-avatars.md
ginnoir a312d4ce39
CI / checks (push) Successful in 12m55s
CI / build (push) Successful in 15m16s
fix: tighten sharing and shadcn composition
2026-06-13 05:20:01 -05:00

105 lines
4.6 KiB
Markdown

# Tier 1: Garden badges → Badge, topbar avatar → Avatar, + fallback, share-green → semantic token
## Goal
Replace ad-hoc badge and avatar styling across the app with shadcn/ui component primitives. Standardize color tokens for green success/warning indicators. Create a reusable avatar fallback pattern.
## Affected files (6)
### Task 1a: Garden health badges → Badge variant
**File:** `src/modules/garden/components/plant-detail.tsx`
- **Current state (line ~44-48):** `healthBadgeClass(status)` returns hand-crafted class names (`badge-success`, `badge-danger`, `badge-warning`) not from shadcn.
- **Line 119-123:** Badge rendered as a span with those classes.
- **Change:** Replace with `<Badge>` component:
- "healthy" → `variant="default"` (primary color)
- "sick" → `variant="destructive"`
- "sick/other" → `variant="secondary"`
- Delete `healthBadgeClass()` function. Remove the span and replace with Badge import + usage.
### Task 1b: Topbar avatar → `<Avatar>`
**File:** `src/components/topbar.tsx`
- **Current state (line ~60-75):** Manual `<span className="avatar">` with inline width/height/background styles, plus conditional img tag or initial text fallback.
- **Change:** Replace with shadcn `<Avatar>`:
```tsx
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
<Avatar style={{ width: 28, height: 28 }}>
{userRow?.image ? (
<AvatarImage src={userRow.image} alt="" />
) : (
<AvatarFallback>{initial}</AvatarFallback>
)}
</Avatar>;
```
- Remove the `getUserAvatar` function — already fetches name/email/image. Just pass the image directly.
### Task 1c: HouseholdPill avatars → Avatar with fallback
**File:** `src/components/sidebar.tsx`
- **Current state (line ~106-120):** Manual span-based avatar circles for household members. Uses `avatarColor()` hash function.
- **Change:** Replace inner spans with `<Avatar>`:
```tsx
<Avatar
style={{
width: 32,
height: 32,
marginLeft: i > 0 ? -6 : 0,
boxShadow: "0 0 0 1.5px var(--card)",
}}
>
{m.image ? (
<AvatarImage src={m.image} alt={m.name ?? m.email ?? ""} />
) : (
<AvatarFallback style={{ background: avatarColor(m.id) }}>{initial}</AvatarFallback>
)}
</Avatar>
```
- The `avatarColor()` function stays as-is — it produces the color variable for the fallback background.
### Task 1d: Create a generic Avatar fallback wrapper (reusable component)
**File:** `src/components/avatar-fallback.tsx` (new)
- **Purpose:** A thin wrapper that takes `(name|initial, image?)` and renders the right Avatar/AvatarImage/Fallback pattern with proper fallback initials.
- **Export:** `AvatarFallbackWithName` — accepts `{ name?: string; initial?: string; image?: string | null; size?: "sm" | "default" | "lg" }`
- Used by both topbar and sidebar avatars, removing code duplication.
### Task 1e: share-green → semantic token
**Files affected:**
1. `src/components/push-opt-in.tsx` line ~104: `text-green-600 dark:text-green-400` → `text-[var(--c-success)] dark:text-[var(--c-success)]`
2. `src/modules/garden/components/care-schedule-editor.tsx` line ~185: green borders for "Active" button → use a semantic border class like `border-[var(--c-success)] text-[var(--c-success)]`
3. `src/modules/garden/components/plant-widget.tsx` urgency colors: ensure overdue/due-today colors use semantic CSS vars rather than hardcoded greens/red/amber
**Changes:**
- In `src/lib/themes.ts` or the global CSS root, add: `--c-success: #16a34a; dark: --c-success: #4ade80;` (or pick from existing palette)
- Replace all `text-green-600`/`dark:text-green-400` → `text-[var(--c-success)] dark:text-[var(--c-success)]`
- Similarly for border-green-400 → `border-[var(--c-success)]`
## Acceptance criteria
1. No hardcoded badge-success/badge-danger/badge-warning class names remain in plant-detail.tsx
2. Topbar avatar renders via shadcn Avatar components (verified by DOM inspection)
3. HouseholdPill avatars use shadcn Avatar components
4. AvatarFallbackWithName component exists and is imported by both topbar.tsx and sidebar.tsx
5. All green-600/green-500 references replaced with --c-success semantic variable
6. Zero TypeScript errors, zero lint errors
## Steps
1. Edit plant-detail.tsx: replace healthBadgeClass usage with <Badge> component
2. Create src/components/avatar-fallback.tsx
3. Edit topbar.tsx: use Avatar from shadcn + AvatarFallbackWithName
4. Edit sidebar.tsx: update HouseholdPill to use Avatar components
5. Search for remaining green-600/green-500/border-green references and replace with --c-success
6. Run `pnpm lint` and `pnpm typecheck` to verify no errors