diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 731f6a0..db2760e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,7 @@ { "recommendations": [ "biomejs.biome", + "bradlc.vscode-tailwindcss", "charliermarsh.ruff", "ms-python.python", "ms-python.vscode-pylance", diff --git a/.vscode/settings.json b/.vscode/settings.json index 04668ab..a420741 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,10 @@ { + "css.customData": [".vscode/tailwind-css-v4-custom-data.json"], + "css.lint.unknownAtRules": "ignore", + "files.associations": { + "**/apps/web/**/*.css": "tailwindcss" + }, + "tailwindCSS.experimental.configFile": "apps/web/src/index.css", "javascript.preferences.quoteStyle": "single", "typescript.preferences.quoteStyle": "single", "[javascript]": { diff --git a/.vscode/tailwind-css-v4-custom-data.json b/.vscode/tailwind-css-v4-custom-data.json new file mode 100644 index 0000000..9653681 --- /dev/null +++ b/.vscode/tailwind-css-v4-custom-data.json @@ -0,0 +1,29 @@ +{ + "version": 1.1, + "atDirectives": [ + { + "name": "@theme", + "description": "Tailwind CSS v4: map design tokens to the framework theme (utilities, variants)." + }, + { + "name": "@plugin", + "description": "Tailwind CSS v4: load a first-party or third-party Tailwind plugin." + }, + { + "name": "@source", + "description": "Tailwind CSS v4: register source paths for class detection." + }, + { + "name": "@utility", + "description": "Tailwind CSS v4: define a custom utility." + }, + { + "name": "@variant", + "description": "Tailwind CSS v4: define a custom variant." + }, + { + "name": "@custom-variant", + "description": "Tailwind CSS v4: define a custom variant." + } + ] +} diff --git a/PLAN.md b/PLAN.md index 9740e6b..47b08a9 100644 --- a/PLAN.md +++ b/PLAN.md @@ -31,7 +31,7 @@ Tasks and subtasks for building the bread-recipes app (SolidJS + Python REST + O - [x] **4.4** Home page: fetch and list bread recipes with overview + thumbnail; navigate to detail on click. - [x] **4.5** Component library: evaluate options for SolidJS (e.g. **shadcn-solid** with Tailwind vs smaller stacks); record the decision; add the chosen tooling and migrate or adopt components on at least one real screen so the pattern is established. - [x] **4.6** Recipe page: full recipe content and larger image; deep-linkable route (e.g. by id). -- [ ] **4.7** **shadcn-solid adoption (full):** migrate remaining UI (app shell, home, recipe cards and detail sections, and any shared layout) to registry components and Tailwind utilities where it replaces bespoke CSS; align tokens with **`COMPONENT_LIBRARY.md`**; no orphaned hand-rolled controls that duplicate registry patterns. Update **`COMPONENT_LIBRARY.md`** when scope is complete. +- [x] **4.7** **shadcn-solid adoption (full):** migrate remaining UI (app shell, home, recipe cards and detail sections, and any shared layout) to registry components and Tailwind utilities where it replaces bespoke CSS; align tokens with **`COMPONENT_LIBRARY.md`**; no orphaned hand-rolled controls that duplicate registry patterns. Update **`COMPONENT_LIBRARY.md`** when scope is complete. - [ ] **4.8** MSW for tests; knip configured; Vitest coverage at 100% with a CI gate. ## 5. Contract testing (Pact) diff --git a/apps/web/COMPONENT_LIBRARY.md b/apps/web/COMPONENT_LIBRARY.md index 636cbb5..a298915 100644 --- a/apps/web/COMPONENT_LIBRARY.md +++ b/apps/web/COMPONENT_LIBRARY.md @@ -1,4 +1,4 @@ -# Component library (PLAN §4.5) +# Component library (PLAN §4.5 / §4.7) ## Decision: [shadcn-solid](https://shadcn-solid.com/) @@ -27,7 +27,27 @@ Implementation details (Kobalte, CVA, etc.) are whatever the **published registr 2. Add components: **`pnpm dlx shadcn-solid@latest add `** (e.g. **`button`**, **`card`**). Use **`--overwrite`** when refreshing an existing file. 3. Prefer **`@/`** imports; use **`./`** for same-folder modules where Biome allows (see project rules). -## Adoption so far +If the registry is unreachable, add components by porting the [shadcn/ui](https://ui.shadcn.com/) (React) registry output to Solid primitives, matching existing files in **`src/components/ui/`** (same **`cn()`**, CVA, and bread theme tokens **`var(--*)`** from **`src/index.css`**). -- **`src/components/ui/button.tsx`** — **shadcn-solid-style** `Button` + **`buttonVariants`** (see [Button](https://shadcn-solid.com/docs/components/button)). For router links, the docs recommend **`buttonVariants` on ``** — used on **recipe detail** for “← All recipes” (`RecipePage`). -- Existing bread **CSS variables** in **`src/index.css`** remain the source of theme tokens; utility classes reference them where the default shadcn HSL tokens are not wired yet. +## Adoption (§4.7 complete) + +| Component | Role | +| --------- | ---- | +| **`button.tsx`** | **`Button`**, **`buttonVariants`** — links use **`buttonVariants` on ``** (e.g. recipe detail “← All recipes”). | +| **`card.tsx`** | **`Card`**, **`CardHeader`**, **`CardTitle`**, **`CardDescription`**, **`CardContent`**, **`CardFooter`** — home recipe **cards**, recipe **hero** image, **ingredients** / **steps** panels. | +| **`alert.tsx`** | **`Alert`**, **`AlertDescription`** — API **error** states on home and recipe pages. | +| **`skeleton.tsx`** | **`Skeleton`** — **loading** placeholders (lists and detail). | +| **`separator.tsx`** | **`Separator`** — between **ingredients** and **steps** on the recipe detail view. | +| **`typography.tsx`** | **`SiteTitle`**, **`Heading2`**, **`Heading3Panel`**, **`RecipeCardTitle`**, **`TextLede`**, **`TextMuted`**, **`RecipeTimes`**, etc. — shared **type scales** and **meta** text so screens do not repeat long class strings. | +| **`cover-image.tsx`** | **`CoverImage`** — framed **thumbnail / hero** images (aspect ratio and **`object-cover`** on the frame). | +| **`loading-region.tsx`** | **`LoadingRegion`** — **`role="status"`**, **`aria-busy`**, and **skeleton** spacing for list/detail loading. | +| **`layout/shell.tsx`** | **`Shell`**, **`ShellHeader`**, **`ShellMain`**, **`ShellFooter`**, **`SiteBrand`**, **`ShellFooterNote`** — **app chrome** structure. | +| **`layout/PageBackLink.tsx`** | **`PageBackLink`** — back navigation row using **`buttonVariants`**. | +| **`recipe-detail/RecipeDetailPanel.tsx`** | **`RecipeDetailPanel`** — shared **card + panel heading** for **ingredients** and **steps**. | +| **`RecipeList.tsx`** | **`RecipeList`** — home **recipe grid** (`