105 lines
4.6 KiB
Markdown
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
|