Files
famapp/docs/tasks/1a-badges-avatars.md
T
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

4.6 KiB

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>:

    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>:
    <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-400text-[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-400text-[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 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