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,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-22
|
||||
@@ -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.
|
||||
@@ -0,0 +1,33 @@
|
||||
## Why
|
||||
|
||||
Styling is split across `ui.css`, `mall.css`, and ~4k lines of Vue scoped CSS, with two palettes (mall red vs admin blue) and no shared primitives. Adopting Tailwind v4 plus one token/kit package lets us rewrite every surface, refresh visuals, and give consoles accent presets without a second CSS stack.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **BREAKING**: Remove `@vmall/shared/ui.css` and `apps/mall/assets/mall.css`. Shared contract export becomes `theme.css`.
|
||||
- Add Tailwind v4 (`@tailwindcss/vite`) to mall, shop-admin, and platform admin.
|
||||
- Add `@vmall/ui`: Vue primitives (`VBtn`, `VBadge`, `VField`/`VInput`, `VCard`/`VPanel`, `VTable`, `VPage`) plus `useAccent()`.
|
||||
- One design system: commerce red (`#ca151e`) default; same radius/type/spacing on all three apps.
|
||||
- Mall keeps classic PC chrome (1200px grid, dark nav, mega-menu, 450px home hero) with refreshed tokens.
|
||||
- Shop-admin and platform admin: accent presets `red | blue | teal | violet`, persisted in `localStorage`. Mall stays red with no switcher.
|
||||
- Delete all Vue `<style scoped>` in the three apps after conversion.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `frontend-ui`: Shared Tailwind theme, UI kit, and console accent presets.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `frontend-mall`: Storefront MUST use the shared design system; visual IA (1200px / `#ca151e` / hero / mega-menu) stays; no public accent switcher.
|
||||
- `frontend-admin`: Platform console MUST use the shared kit and expose accent presets.
|
||||
- `frontend-shop-admin`: Merchant console MUST use the shared kit and expose accent presets.
|
||||
|
||||
## Impact
|
||||
|
||||
`packages/shared` (`ui.css` → `theme.css`), new `packages/ui`, three Nuxt apps (all SFCs), `AGENTS.md` / OpenSpec config (shared styles path). No API or money-handling changes. Three-app `pnpm` builds plus a mall visual pass.
|
||||
|
||||
## Non-goals
|
||||
|
||||
Dark mode, free hex picker, per-shop customer-facing branding, theming the public mall, Element Plus, mixing this with the catalog-module split.
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Shared design system in the platform console
|
||||
The platform admin console SHALL use `@vmall/ui` primitives and `@vmall/shared` theme tokens for chrome (buttons, fields, cards, tables, page headers, nav). It MUST NOT depend on Element Plus or the removed `ui.css` stylesheet.
|
||||
|
||||
#### Scenario: console chrome from the kit
|
||||
- **WHEN** an authenticated platform admin opens the dashboard
|
||||
- **THEN** primary actions and page chrome render through the shared kit with the current accent preset
|
||||
|
||||
### Requirement: Accent preset switcher
|
||||
Platform admin SHALL expose the shared accent preset control (`red`, `blue`, `teal`, `violet`) in the authenticated shell header.
|
||||
|
||||
#### Scenario: switcher visible
|
||||
- **WHEN** an authenticated platform admin opens the console
|
||||
- **THEN** they can select an accent preset without leaving the current page
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: B2B2C mall-style PC storefront shell
|
||||
The mall SHALL render a buyer-facing desktop shell modeled on a classic B2B2C PC mall: a 30px utility bar, logo/search/cart header, dark primary navigation with a hover category mega-menu, a 1200px content grid, and a value-proposition footer. The header SHALL remain fully visible while scrolling; no part of the shell SHALL auto-hide based on scroll position. The category mega-menu SHALL appear as a hover dropdown under the navigation "All Categories" entry on every page except the home page, where it is instead pinned in the hero row. The visual language SHALL use `#ca151e` for brand/price/active states, `#f5f5f5` section backgrounds, gray hairline borders, compact controls, and product-card hover lift/shadow. The implementation SHALL use the shared Tailwind theme and `@vmall/ui` primitives plus Nuxt-native semantic components, SHALL NOT depend on Element Plus, and SHALL NOT expose a theme-accent switcher.
|
||||
|
||||
#### Scenario: shopper opens any mall page
|
||||
- **WHEN** a shopper navigates to a buyer-facing route
|
||||
- **THEN** the shared desktop shell wraps the route content and its nav/search/cart controls are usable
|
||||
|
||||
#### Scenario: header persists while scrolling
|
||||
- **WHEN** a shopper scrolls any mall page
|
||||
- **THEN** the logo/search/cart header bar remains visible and is never collapsed or hidden by scroll position
|
||||
|
||||
#### Scenario: hover categories on a non-home page
|
||||
- **WHEN** a shopper hovers "All Categories" in the navigation on a page other than `/`
|
||||
- **THEN** the category mega-menu dropdown appears below the navigation and hides again on mouse leave
|
||||
|
||||
#### Scenario: mall has no accent switcher
|
||||
- **WHEN** a shopper inspects the mall shell
|
||||
- **THEN** there is no control to change brand accent and prices/active states remain `#ca151e`
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Shared design system on the storefront
|
||||
Mall pages SHALL style layout with Tailwind utilities and shared primitives. Mall-only chrome (mega-menu, carousel crop, 1200px shell, product-card hover lift) MAY live in `apps/mall` components but MUST consume shared tokens, not a private global stylesheet.
|
||||
|
||||
#### Scenario: storefront uses shared tokens
|
||||
- **WHEN** a shopper views the home page
|
||||
- **THEN** brand red, the 1200px grid, and the 450px hero height come from the shared theme keys rather than `mall.css`
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Shared design system in the merchant console
|
||||
The shop-admin console SHALL use `@vmall/ui` primitives and `@vmall/shared` theme tokens for chrome (buttons, fields, cards, tables, page headers, nav). It MUST NOT depend on Element Plus or the removed `ui.css` stylesheet.
|
||||
|
||||
#### Scenario: console chrome from the kit
|
||||
- **WHEN** an authenticated shop user opens shop-admin
|
||||
- **THEN** primary actions and page chrome render through the shared kit with the current accent preset
|
||||
|
||||
### Requirement: Accent preset switcher
|
||||
Shop-admin SHALL expose the shared accent preset control (`red`, `blue`, `teal`, `violet`) in the authenticated shell header.
|
||||
|
||||
#### Scenario: switcher visible
|
||||
- **WHEN** an authenticated shop user opens shop-admin
|
||||
- **THEN** they can select an accent preset without leaving the current page
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Shared Tailwind design system
|
||||
The three Nuxt apps SHALL load one token stylesheet from `@vmall/shared` (`theme.css`) and SHALL compose repeating chrome from `@vmall/ui` primitives (`VBtn`, `VBadge`, `VField`/`VInput`, `VCard`/`VPanel`, `VTable`, `VPage`). They MUST NOT depend on Element Plus, MUST NOT keep `packages/shared/src/ui.css` or `apps/mall/assets/mall.css`, and MUST NOT use Vue `<style scoped>` for app chrome after the migration. Default brand/primary color SHALL be `#ca151e`.
|
||||
|
||||
#### Scenario: apps share tokens
|
||||
- **WHEN** a developer opens mall, shop-admin, and platform admin with the default accent
|
||||
- **THEN** primary buttons, links, and active nav use `#ca151e` from the shared theme rather than per-app palettes
|
||||
|
||||
#### Scenario: no legacy stylesheets
|
||||
- **WHEN** the migration is complete
|
||||
- **THEN** `@vmall/shared` exports `theme.css` (not `ui.css`) and the three apps have no remaining `<style scoped>` blocks for layout or chrome
|
||||
|
||||
### Requirement: Console accent presets
|
||||
Shop-admin and platform admin SHALL let the signed-in operator pick an accent preset of `red`, `blue`, `teal`, or `violet`. The choice SHALL apply immediately to primary actions, links, and active navigation, SHALL persist in `localStorage` for that app origin, and SHALL restore on reload. An invalid stored value MUST fall back to `red`. The public mall MUST NOT expose this control and MUST remain on the red accent.
|
||||
|
||||
#### Scenario: operator switches accent
|
||||
- **WHEN** a platform admin or shop user selects the blue preset in the console header
|
||||
- **THEN** primary buttons and active nav in that app render with the blue preset without a full page reload
|
||||
|
||||
#### Scenario: accent survives reload
|
||||
- **WHEN** the operator reloads shop-admin or platform admin after choosing teal
|
||||
- **THEN** the console still uses the teal preset
|
||||
|
||||
#### Scenario: mall stays red
|
||||
- **WHEN** a shopper uses the mall after an operator has changed a console accent
|
||||
- **THEN** the mall still uses `#ca151e` and shows no accent switcher
|
||||
@@ -0,0 +1,38 @@
|
||||
## 1. Tooling and tokens
|
||||
|
||||
- [x] 1.1 Add Tailwind v4 and `@tailwindcss/vite` to mall, shop-admin, and platform admin; wire the Vite plugin in each `nuxt.config.ts`
|
||||
- [x] 1.2 Add `packages/shared/src/theme.css` with `@theme` keys (primary `#ca151e`, hover, soft, radius, type, `max-w-mall` 1200px, `h-hero` 450px) and `html[data-accent]` maps for `red|blue|teal|violet`
|
||||
- [x] 1.3 Export `./theme.css` from `@vmall/shared`; load it in all three apps while still loading `ui.css` / `mall.css`
|
||||
|
||||
## 2. `@vmall/ui` kit
|
||||
|
||||
- [x] 2.1 Scaffold `packages/ui` (`@vmall/ui`) in the pnpm workspace with Vue peer deps and exports
|
||||
- [x] 2.2 Implement `VBtn`, `VBadge`, `VField`/`VInput`, `VCard`/`VPanel`, `VTable`, `VPage` on shared tokens
|
||||
- [x] 2.3 Implement `useAccent()` (read/write `localStorage`, set `document.documentElement.dataset.accent`, invalid → `red`) and an accent swatch control
|
||||
- [x] 2.4 Add the kit as a dependency of the three Nuxt apps and transpile it if needed
|
||||
|
||||
## 3. Platform admin
|
||||
|
||||
- [x] 3.1 Convert `apps/admin` shell and pages to kit + Tailwind utilities; add the accent swatch to the authenticated header
|
||||
- [x] 3.2 Remove admin `<style scoped>` blocks
|
||||
- [x] 3.3 `pnpm --filter @vmall/admin build` green; browser-check accent switch + reload persistence
|
||||
|
||||
## 4. Shop-admin
|
||||
|
||||
- [x] 4.1 Convert `apps/shop-admin` shell and pages the same way; add the accent swatch
|
||||
- [x] 4.2 Remove shop-admin `<style scoped>` blocks
|
||||
- [x] 4.3 `pnpm --filter @vmall/shop-admin build` green; browser-check accent switch + reload persistence
|
||||
|
||||
## 5. Mall storefront
|
||||
|
||||
- [x] 5.1 Lock mall to `data-accent="red"` at boot; do not render the swatch
|
||||
- [x] 5.2 Convert mall shell (utility bar, header, dark nav, mega-menu, 1200px grid, footer) to tokens/utilities/kit
|
||||
- [x] 5.3 Convert mall pages (home hero/sidebar/carousel last-but-one; `goods/[id]`, integral, store last)
|
||||
- [x] 5.4 Remove all mall `<style scoped>` and stop loading `mall.css`
|
||||
|
||||
## 6. Cut over and docs
|
||||
|
||||
- [x] 6.1 Delete `packages/shared/src/ui.css` and the `./ui.css` export; point `AGENTS.md` / OpenSpec config at `theme.css` and `@vmall/ui`
|
||||
- [x] 6.2 Confirm no `<style scoped>` remains under `apps/mall`, `apps/shop-admin`, `apps/admin`
|
||||
- [x] 6.3 `pnpm --filter @vmall/mall build` plus admin and shop-admin builds all green
|
||||
- [x] 6.4 Browser pass: mall shell, home hero/sidebar, search grid, product detail, cart/checkout chrome; both consoles on default red and after a preset change
|
||||
@@ -6,7 +6,7 @@ context: |
|
||||
Tech stack:
|
||||
- Backend: Rust (axum 0.8, sqlx 0.8 + Postgres 18, redis 8, JWT, argon2) at apps/api, crate vmall-api. Modular monolith: handler → service → repository under src/modules/<context> (docs/adr/0001, docs/tech-specs/rust-api.md). HTTP REST is the public contract; GraphQL is not the primary API (docs/adr/0002). Money is stored as integer minor units + ISO currency code; never floats.
|
||||
- Frontends: three Nuxt 3 apps in pnpm workspace: apps/mall (customer storefront, port 3000), apps/shop-admin (merchant console, 3001), apps/admin (platform console, 3002).
|
||||
- Shared contract: packages/shared (@vmall/shared) — TS types, API client, en/zh locales, ui.css. Frontends must use it; no per-app API reimplementation.
|
||||
- Shared contract: packages/shared (@vmall/shared) — TS types, API client, en/zh locales, Tailwind v4 theme.css. Frontends must use it; no per-app API reimplementation. Shared Vue primitives live in packages/ui (@vmall/ui, Nuxt module); layout uses Tailwind utilities, no <style scoped>.
|
||||
- Dev infra: Postgres + Redis run in local docker (containers pg18, rdb8); databases vmall / vmall_test; API runs migrations on boot (sqlx migrate).
|
||||
|
||||
Conventions:
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
## Purpose
|
||||
The platform console for managing users, shops and currencies.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Platform user and shop management
|
||||
Platform admins SHALL assign user roles (with shop scope), create shops, and suspend/activate shops. Suspended shops' products MUST NOT be purchasable (enforced by API, reflected in UI).
|
||||
|
||||
@@ -29,3 +27,18 @@ Platform admins SHALL manage points products and inspect and fulfill redemption
|
||||
#### Scenario: points mall appears in admin navigation
|
||||
- **WHEN** an authenticated platform admin opens the admin console
|
||||
- **THEN** points-product and redemption-order management are reachable from the console nav
|
||||
|
||||
### Requirement: Shared design system in the platform console
|
||||
The platform admin console SHALL use `@vmall/ui` primitives and `@vmall/shared` theme tokens for chrome (buttons, fields, cards, tables, page headers, nav). It MUST NOT depend on Element Plus or the removed `ui.css` stylesheet.
|
||||
|
||||
#### Scenario: console chrome from the kit
|
||||
- **WHEN** an authenticated platform admin opens the dashboard
|
||||
- **THEN** primary actions and page chrome render through the shared kit with the current accent preset
|
||||
|
||||
### Requirement: Accent preset switcher
|
||||
Platform admin SHALL expose the shared accent preset control (`red`, `blue`, `teal`, `violet`) in the authenticated shell header.
|
||||
|
||||
#### Scenario: switcher visible
|
||||
- **WHEN** an authenticated platform admin opens the console
|
||||
- **THEN** they can select an accent preset without leaving the current page
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
## Purpose
|
||||
The buyer-facing storefront: shell, home page, discovery, shopping and transaction flows, and the buyer center.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Localized storefront
|
||||
The mall SHALL render every UI string and all catalog/store/marketing mock content in en or zh from one switcher, defaulting to en. Switching locale SHALL update the desktop shell and current page without a full reload.
|
||||
|
||||
@@ -31,7 +29,7 @@ A shopper SHALL be able to browse, view detail, add to cart, checkout with a shi
|
||||
- **THEN** they are sent to sign in and, once signed in, returned to that product page
|
||||
|
||||
### Requirement: B2B2C mall-style PC storefront shell
|
||||
The mall SHALL render a buyer-facing desktop shell modeled on a classic B2B2C PC mall: a 30px utility bar, logo/search/cart header, dark primary navigation with a hover category mega-menu, a 1200px content grid, and a value-proposition footer. The header SHALL remain fully visible while scrolling; no part of the shell SHALL auto-hide based on scroll position. The category mega-menu SHALL appear as a hover dropdown under the navigation "All Categories" entry on every page except the home page, where it is instead pinned in the hero row. The visual language SHALL use #ca151e for brand/price/active states, #f5f5f5 section backgrounds, gray hairline borders, compact controls, and product-card hover lift/shadow. The implementation SHALL use Nuxt-native semantic components and SHALL NOT depend on Element Plus.
|
||||
The mall SHALL render a buyer-facing desktop shell modeled on a classic B2B2C PC mall: a 30px utility bar, logo/search/cart header, dark primary navigation with a hover category mega-menu, a 1200px content grid, and a value-proposition footer. The header SHALL remain fully visible while scrolling; no part of the shell SHALL auto-hide based on scroll position. The category mega-menu SHALL appear as a hover dropdown under the navigation "All Categories" entry on every page except the home page, where it is instead pinned in the hero row. The visual language SHALL use `#ca151e` for brand/price/active states, `#f5f5f5` section backgrounds, gray hairline borders, compact controls, and product-card hover lift/shadow. The implementation SHALL use the shared Tailwind theme and `@vmall/ui` primitives plus Nuxt-native semantic components, SHALL NOT depend on Element Plus, and SHALL NOT expose a theme-accent switcher.
|
||||
|
||||
#### Scenario: shopper opens any mall page
|
||||
- **WHEN** a shopper navigates to a buyer-facing route
|
||||
@@ -45,6 +43,10 @@ The mall SHALL render a buyer-facing desktop shell modeled on a classic B2B2C PC
|
||||
- **WHEN** a shopper hovers "All Categories" in the navigation on a page other than `/`
|
||||
- **THEN** the category mega-menu dropdown appears below the navigation and hides again on mouse leave
|
||||
|
||||
#### Scenario: mall has no accent switcher
|
||||
- **WHEN** a shopper inspects the mall shell
|
||||
- **THEN** there is no control to change brand accent and prices/active states remain `#ca151e`
|
||||
|
||||
### Requirement: Mock API adapter
|
||||
The mall SHALL select its API adapter per domain, so one domain can be served by the live backend while the others stay on fixed data. The mall SHALL still ship a fixed-data adapter implementing the whole `@vmall/shared` API client surface, and the live/fixed choice SHALL be configurable per domain without changing page call sites. The fixed-data adapter SHALL remain able to serve every domain when the live backend is unavailable.
|
||||
|
||||
@@ -230,3 +232,11 @@ The mall SHALL use the shared selected API adapter for product and shop favorite
|
||||
#### Scenario: fixed adapter remains functional
|
||||
- **WHEN** the favorites domain is configured to fixed data
|
||||
- **THEN** detail controls and buyer-center favorite flows behave deterministically through the same shared client methods
|
||||
|
||||
### Requirement: Shared design system on the storefront
|
||||
Mall pages SHALL style layout with Tailwind utilities and shared primitives. Mall-only chrome (mega-menu, carousel crop, 1200px shell, product-card hover lift) MAY live in `apps/mall` components but MUST consume shared tokens, not a private global stylesheet.
|
||||
|
||||
#### Scenario: storefront uses shared tokens
|
||||
- **WHEN** a shopper views the home page
|
||||
- **THEN** brand red, the 1200px grid, and the 450px hero height come from the shared theme keys rather than `mall.css`
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
## Purpose
|
||||
The merchant console for managing a shop's products and fulfilling its orders.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Merchant product management
|
||||
Shop users SHALL manage only their own shop's products: create/edit bilingual content, manage SKUs, publish/unpublish with immediate effect on the storefront.
|
||||
|
||||
@@ -51,3 +49,18 @@ Shop users SHALL manage only their shop's group-buying activities in shop-admin,
|
||||
#### Scenario: group buying appears in shop navigation
|
||||
- **WHEN** an authenticated shop user opens shop-admin
|
||||
- **THEN** a group-buying management entry is reachable without leaving the shop-scoped console
|
||||
|
||||
### Requirement: Shared design system in the merchant console
|
||||
The shop-admin console SHALL use `@vmall/ui` primitives and `@vmall/shared` theme tokens for chrome (buttons, fields, cards, tables, page headers, nav). It MUST NOT depend on Element Plus or the removed `ui.css` stylesheet.
|
||||
|
||||
#### Scenario: console chrome from the kit
|
||||
- **WHEN** an authenticated shop user opens shop-admin
|
||||
- **THEN** primary actions and page chrome render through the shared kit with the current accent preset
|
||||
|
||||
### Requirement: Accent preset switcher
|
||||
Shop-admin SHALL expose the shared accent preset control (`red`, `blue`, `teal`, `violet`) in the authenticated shell header.
|
||||
|
||||
#### Scenario: switcher visible
|
||||
- **WHEN** an authenticated shop user opens shop-admin
|
||||
- **THEN** they can select an accent preset without leaving the current page
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# frontend-ui Specification
|
||||
|
||||
## Purpose
|
||||
Shared Tailwind v4 design system for the three Nuxt apps: one token stylesheet (`@vmall/shared/theme.css`, default brand `#ca151e`), the `@vmall/ui` Vue primitive kit, and persisted accent presets (`red | blue | teal | violet`) for the shop-admin and platform-admin consoles. The public mall stays locked to the red accent.
|
||||
## Requirements
|
||||
### Requirement: Shared Tailwind design system
|
||||
The three Nuxt apps SHALL load one token stylesheet from `@vmall/shared` (`theme.css`) and SHALL compose repeating chrome from `@vmall/ui` primitives (`VBtn`, `VBadge`, `VField`/`VInput`, `VCard`/`VPanel`, `VTable`, `VPage`). They MUST NOT depend on Element Plus, MUST NOT keep `packages/shared/src/ui.css` or `apps/mall/assets/mall.css`, and MUST NOT use Vue `<style scoped>` for app chrome after the migration. Default brand/primary color SHALL be `#ca151e`.
|
||||
|
||||
#### Scenario: apps share tokens
|
||||
- **WHEN** a developer opens mall, shop-admin, and platform admin with the default accent
|
||||
- **THEN** primary buttons, links, and active nav use `#ca151e` from the shared theme rather than per-app palettes
|
||||
|
||||
#### Scenario: no legacy stylesheets
|
||||
- **WHEN** the migration is complete
|
||||
- **THEN** `@vmall/shared` exports `theme.css` (not `ui.css`) and the three apps have no remaining `<style scoped>` blocks for layout or chrome
|
||||
|
||||
### Requirement: Console accent presets
|
||||
Shop-admin and platform admin SHALL let the signed-in operator pick an accent preset of `red`, `blue`, `teal`, or `violet`. The choice SHALL apply immediately to primary actions, links, and active navigation, SHALL persist in `localStorage` for that app origin, and SHALL restore on reload. An invalid stored value MUST fall back to `red`. The public mall MUST NOT expose this control and MUST remain on the red accent.
|
||||
|
||||
#### Scenario: operator switches accent
|
||||
- **WHEN** a platform admin or shop user selects the blue preset in the console header
|
||||
- **THEN** primary buttons and active nav in that app render with the blue preset without a full page reload
|
||||
|
||||
#### Scenario: accent survives reload
|
||||
- **WHEN** the operator reloads shop-admin or platform admin after choosing teal
|
||||
- **THEN** the console still uses the teal preset
|
||||
|
||||
#### Scenario: mall stays red
|
||||
- **WHEN** a shopper uses the mall after an operator has changed a console accent
|
||||
- **THEN** the mall still uses `#ca151e` and shows no accent switcher
|
||||
|
||||
Reference in New Issue
Block a user