Design system - youneshenniwrites/fastapi-next-ecommerce GitHub Wiki

VINDOR design system

VINDOR uses Tailwind CSS v4 and locally owned shadcn/ui components. The visual identity is warm paper, forest green actions, restrained borders and editorial serif headings. This handbook documents the existing foundation as inspected on 11 September 2026; proposed patterns are explicitly marked.

Source of truth

Use existing components before introducing another abstraction. shadcn components are editable code in this repository; upstream examples must be adapted and reviewed, not pasted wholesale. Follow shadcn theming guidance for semantic token pairs. Preserve the installed configuration rather than reinitialising the app with a newer default theme.

Foundations

Token Current value Role
background #faf9f6 Paper page surface
foreground #25372e Main text
primary / primary-foreground #304e3c / #ffffff Main action and its text
secondary #e8ede4 Sage supporting surface
muted / muted-foreground #e8e6df / #646b63 Subtle surface and secondary text
border #dedfd7 Separators and input borders
ring #9a572d Keyboard focus
destructive #a12d27 Error emphasis

Use semantic utilities such as bg-primary text-primary-foreground, not repeated hex values. These are the current values, not a claim that every possible pairing meets contrast requirements; verify the actual foreground/background and interaction state.

Body typography uses Arial/Helvetica/sans-serif, 15px with relaxed line height. Editorial headings use Georgia. Radius tokens are sm 0.125rem, md 0.25rem and lg 0.5rem. Tailwind Preflight is enabled. There is no supported dark palette or dark-mode switch.

For spacing and responsive layout, reuse the nearest existing page composition and Tailwind scale. A separate mandated spacing/type scale has not been implemented. Preserve readable mobile stacking, content order and keyboard access; avoid fixed desktop dimensions that overflow narrow screens.

Available components

Component Intended use States to preserve
Button Actions; buttonVariants on real navigation links Focus, disabled, pending
Input Search and account fields Label, focus, disabled, invalid
Checkbox In-stock filter Label, checked, focus
Select Catalog sorting Themed popup, keyboard selection, Escape and scrolling
Badge Stock labels Meaning conveyed in text
Skeleton Loading content inside a labelled status Reduced motion
Sheet Mobile navigation Accessible title, focus trap, Escape, close on navigation

SiteHeader, SiteFooter, SectionHeading, ProductCard and ProductDetails compose the storefront. A product card is an app component, not evidence that the shadcn Card primitive is installed. Generic Dialog and toast components are not currently part of the local inventory; add them when a feature needs them. Field, Label and Separator were delivered in PR #75; account forms use React Hook Form, Zod and shadcn FieldError for validation feedback.

<Button type="submit" disabled={pending}>
  {pending ? "Signing in…" : "Sign in"}
</Button>

This is a usage illustration, not a complete form. Use anchors for navigation and buttons for actions; never nest interactive controls. Keep static composition on the server and isolate interactive client components.

Forms — React Hook Form and Zod

PR #75 implements shadcn’s React Hook Form and Zod approach: form state/submission in React Hook Form, schemas in Zod, and shadcn field/error presentation. The implementation uses useForm, zodResolver and shadcn Field, FieldLabel and FieldError. Native attributes remain semantic safeguards; noValidate lets the libraries provide inline feedback. PR #75 is merged and production delivery run 34598109776 completed; hosted inline validation has been verified.

  • Show clear inline errors after submission; revalidate corrections and focus the first invalid field.
  • Associate errors with inputs and expose invalid state to assistive technology. Do not communicate failure through colour alone.
  • Empty or invalid submission must not navigate, reload or call the API.
  • Preserve separate login/registration constraints, pre-hydration guards, pending state and server error handling. Never trim or log passwords.
  • Passwords start masked; the accessible Show password/Hide password toggle preserves value and validation and is disabled while pending.
  • Backend validation remains authoritative. Client schemas improve feedback rather than replacing API validation.

The PR includes field components, pinned library dependencies, schema tests and desktop/mobile browser verification (55 unit tests and 37 browser tests passed locally; two expected desktop skips). Do not copy examples that log or toast credential values.

Product patterns

Catalog pages must preserve loading, empty results, failure/retry, not-found and out-of-stock states. Account screens distinguish pending, guest, authenticated and unavailable states; follow Customer accounts for session boundaries.

Cart interactions are delivered through #72 on top of the cart API: an in-memory CartProvider receiving a private server snapshot from Server Components, with writes through Server Actions, add-to-cart controls, navigation count, and a cart page with quantity forms, removal and backend-provided subtotal. Controls reuse these foundations with accessible quantity/removal feedback and authoritative backend GBP totals. Checkout and sandbox payment controls are implemented; document their separate hosted and production limits.

Icons, imagery and accessibility

Use named lucide-react imports. Hide decorative icons from assistive technology; give icon-only buttons accessible names. Never create custom SVG icons or product illustrations. Use local licensed photography and maintain photo credits.

Keep visible keyboard focus. Existing base rules use a 2px warm outline with 4px offset for links, buttons, inputs and selects. Respect reduced motion, verify contrast in normal/hover/pending/error states, and test keyboard interaction on desktop and mobile layouts. Automated accessibility checks complement manual checks; they are not an accessibility certification.

Extending and maintaining the system

From frontend, use the pinned CLI command documented in the repository: npx --no-install shadcn add COMPONENT. Review generated source and dependencies, use the local @/lib/utils cn helper, and commit the lockfile with exact direct dependency versions. Add only components needed by the feature.

Each component change should record intended use, variants, interaction states and relevant examples here or in versioned guidance. Run the applicable lint/type/unit/build/browser checks; capture desktop/mobile evidence and check keyboard, focus, errors and reduced motion. Use the normal issue, self-review, policy-selected external review and CI process for code changes. Update this page when the implemented inventory or conventions change.

This initial handbook has no live component playground. Executable examples can be added later if needed; the component source remains the implementation reference.

Consistency update — PR #78, deployed

PR #78 applies the following conventions. These conventions are deployed on the public storefront in main commit d76f2a8f779e509afe8ce3fa04ead837d175fa5f.

  • Buttons, inputs, checkboxes and select triggers share the 4px rounded-md token. Form fields/actions use 48px height; compact catalog search/sort use 40px. Images remain rectangular; panels may use 8px and decorative badges may be circular.
  • Use the shared warm keyboard outline; avoid stacking component rings on it. All interactive controls compose shadcn primitives.
  • Catalog sorting uses shadcn Select. Keep its built-in viewport and scroll controls; do not nest another scroll panel in the popup. Use shadcn ScrollArea when a separate bounded scroll panel is required. Page scrolling remains native, without a global smooth-scroll animation on validation focus.
  • The homepage hero and approach render independently of the catalog request. Catalog skeletons match the two-column mobile/three-column desktop grid, 6:5 images and title/price/description positions. Product pages have their own image/text skeleton.
  • Inline account errors reserve space with a matching line height to avoid moving the submit control during correction.

Verification includes existing account journeys, desktop/mobile sorting, control radius assertions, keyboard/accessibility checks, reduced-motion loading and failure/retry paths. Final main CI passed 55 unit tests and 37 browser tests, with two expected desktop skips. Codex completed a clean review of 4a9012b; its finding is resolved. Production delivery successfully deployed the merged revision and verified database-backed catalog reads, API docs and session/origin checks.

Hosted desktop/mobile checks confirmed shadcn keyboard sorting, no mobile horizontal overflow, and empty sign-in submission staying on /login, focusing email and displaying both validation messages. The input's computed radius is 4px and its focus outline is 2px. Comparable production screenshots were captured before and after release at 1440×1000 and 390×844 viewports. Open VINDOR.

⚠️ **GitHub.com Fallback** ⚠️