feat(ui): adopt Tailwind v4 design system and archive change
- Add tailwindcss v4 + @tailwindcss/vite to mall, shop-admin, admin - Add @vmall/shared/theme.css tokens with html[data-accent] presets - Add @vmall/ui kit (VBtn/VBadge/VField/VInput/VCard/VPanel/VTable/VPage, VAccentSwatch, useAccent) as a Nuxt module - Convert all three apps to kit + utilities; delete ui.css/mall.css and every <style scoped>; consoles get accent presets, mall locked to red - Fix VCard boolean prop default (padding) and PDP/store stale useAsyncData keys on param navigation - Archive adopt-tailwind-design-system; new frontend-ui capability spec
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
## Context
|
||||
|
||||
Three Nuxt 3 apps share `@vmall/shared` (API types, locales, `ui.css`) and otherwise style themselves with global CSS plus Vue `<style scoped>` (~4k lines, mostly mall). There is no Tailwind/PostCSS today. Mall is a classic B2B2C PC chrome (`#ca151e`, 1200px, 450px hero); admin consoles are a blue SaaS shell. Operators asked for a full rewrite onto Tailwind, one design system, a visual refresh that **keeps mall IA**, red as the default accent, and **preset accent switching in shop-admin and platform admin only**.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Replace `ui.css`, `mall.css`, and all scoped CSS with Tailwind v4 utilities plus a small Vue kit.
|
||||
- One token set (red default) across mall, shop-admin, and platform admin.
|
||||
- Console accent presets (`red | blue | teal | violet`) persisted locally; mall locked to red.
|
||||
- Preserve mall shell behavior required by `frontend-mall`.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Dark mode, free hex picker, per-shop customer-facing branding, theming the public mall.
|
||||
- Element Plus or other component libraries.
|
||||
- Backend/API work; catalog module split.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Tailwind v4 via `@tailwindcss/vite`**, not `@nuxtjs/tailwindcss`. Apps already run Nuxt 3 + Vite 7; v4 is CSS-first (`@theme`) and avoids a PostCSS/v3-oriented module.
|
||||
|
||||
2. **Tokens in `@vmall/shared/theme.css`**, replacing `ui.css`. Shared stays the contract package (types, API, locales, theme). Vue is not added to shared.
|
||||
|
||||
3. **New `@vmall/ui`** for `VBtn`, `VBadge`, `VField`/`VInput`, `VCard`/`VPanel`, `VTable`, `VPage`, and `useAccent()`. Mall-only chrome (mega-menu, carousel, `w1200` shell, product-card lift) stays in `apps/mall`. Admin sidebar layouts stay in each admin app.
|
||||
|
||||
*Alternative considered:* put Vue primitives in shared — rejected so the API contract package stays Vue-free. *Alternative:* utilities only, no kit — rejected; repeating `.btn` / `.mbtn` as 10-class strings will rot.
|
||||
|
||||
4. **No `@apply` leftover stylesheets.** Layout = utilities; repeating chrome = kit. Spec-locked sizes become theme keys (`max-w-mall`, `h-hero`) rather than scattered `w-[1200px]`.
|
||||
|
||||
5. **Accent via `html[data-accent]`** mapping CSS variables that `@theme` aliases to `primary`. `useAccent()` writes `localStorage` (`vmall-accent` per app origin) and sets the dataset. Mall sets `data-accent="red"` at boot and does not render a switcher. Invalid stored values fall back to red.
|
||||
|
||||
*Alternative considered:* user-profile API — out of scope. *Alternative:* `class="dark"` — not in this change.
|
||||
|
||||
6. **Phased conversion, then delete.** Dual-load old CSS until each app is converted so screens are never unstyled; then remove globals and scoped blocks.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Mall visual regression] → Convert shell first; browser-pass spec flows (home hero, mega-menu, search grid, PDP); keep 1200px / 450px / `#ca151e` as tokens.
|
||||
- [Tailwind v4 + Nuxt 3 plugin friction] → Spike on admin app first; fall back to documented Vite plugin wiring, not a new CSS engine.
|
||||
- [Accent contrast on badges/tables] → Presets only; each preset defines primary + hover + soft background, not a raw hex.
|
||||
- [Shared package build gate] → `theme.css` change still requires all three app builds.
|
||||
- [Scope creep vs catalog split] → Separate OpenSpec change; do not mix PRs.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Scaffold `theme.css` + `@vmall/ui` + Vite plugin; keep loading `ui.css` / `mall.css`.
|
||||
2. Convert platform admin, then shop-admin (introduce accent swatches).
|
||||
3. Convert mall shell, then mall pages (largest last).
|
||||
4. Delete `ui.css`, `mall.css`, remaining `<style scoped>`; switch shared export to `theme.css`; update `AGENTS.md`.
|
||||
5. Rollback: git revert the change; no DB/API migration.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None that block implementation. If `@tailwindcss/vite` cannot register cleanly in a given Nuxt 3 minor, document the working plugin hook in this change rather than switching to UnoCSS.
|
||||
Reference in New Issue
Block a user