FlowPOS Frontend PWA — Theming & Styling Guide
Reference for anyone restyling the
apps/frontend-pwa/app in light or dark mode.
Overview
The PWA is built with Vite 6 + React 19 + Shadcn/ui + Tailwind CSS. All colors flow through CSS custom properties (HSL variables) defined once in a single stylesheet and mapped into Tailwind's theme. Because every Shadcn component reads from these variables, a complete restyle is concentrated in just a few files — no component internals need to change.
Primary files — the "big three"
These three files cover ~95% of a full visual overhaul.
1. apps/frontend-pwa/src/index.css — The main file
Defines all design tokens as HSL triplets:
:root { ... }— light mode variables (starts around line 7).dark { ... }— dark mode overrides (starts around line 48)
Tokens defined here:
| Group | Variables |
|---|---|
| Surfaces | --background, --foreground, --card, --card-foreground, --popover, --popover-foreground |
| Brand | --primary, --primary-foreground, --secondary, --secondary-foreground |
| States | --muted, --muted-foreground, --accent, --accent-foreground, --destructive, --destructive-foreground |
| Chrome | --border, --input, --ring |
| Sidebar | --sidebar, --sidebar-foreground, --sidebar-primary, --sidebar-primary-foreground, --sidebar-accent, --sidebar-accent-foreground, --sidebar-border, --sidebar-ring |
| Shape | --radius |
| Charts | --chart-1 … --chart-5 |
Changing values here propagates to every Shadcn component automatically.
2. apps/frontend-pwa/tailwind.config.js
darkMode: ["class"]— dark mode is toggled by adding/removing the.darkclass on the root element (don't change unless switching strategy).theme.extend.colors— maps every token tohsl(var(--...)). Edit here to add new color tokens or change theborderRadiusscale.- Includes
tailwindcss-animateplugin and accordion keyframes. - Add a
fontFamilyextension here when introducing custom typography.
3. apps/frontend-pwa/src/App.css
Legacy Vite starter CSS with a couple of .dark rules (.read-the-docs, #root layout). Audit and trim during a restyle — it can override your new theme in subtle ways.
Secondary files
Touch only if the restyle requires it.
| File | What it controls |
|---|---|
apps/frontend-pwa/components.json | Shadcn generator config: baseColor (currently slate), style, CSS variable mode. Edit only when changing the Shadcn baseline. |
apps/frontend-pwa/index.html | Google Material Symbols Rounded font <link> (lines 8–11). Edit when swapping icon or text fonts. |
apps/frontend-pwa/src/tours/tours.css | Driver.js tour overlay styles. These are independent of Shadcn tokens — update manually if the restyle needs to cover tour popovers. |
apps/frontend-pwa/postcss.config.js | Standard Tailwind + Autoprefixer pipeline. No changes needed for a restyle. |
Theme toggle machinery — reference only
These files wire up dark mode correctly and should not need edits during a restyle.
apps/frontend-pwa/src/contexts/ThemeProvider.tsx— React context that adds/removes the.darkclass on the root element and exposesuseTheme().apps/frontend-pwa/src/components/common/ThemeToggle.tsx— Sun/Moon header button that callsuseTheme().
Recommended workflow
- Draft your new palette as HSL triplets (e.g.
222 47% 11%). - Replace the values inside
:rootand.darkinsrc/index.css. - If adding tokens not already in the set, register them in
tailwind.config.jsundertheme.extend.colors. - Update
--radiusinindex.cssfor a different corner-roundness feel. - Audit and clean up
App.cssleftovers. - If typography changes, add the font in
index.htmland extendfontFamilyintailwind.config.js.
Gotchas
- HSL triplet format — values in
:root/.darkare raw triplets (222 47% 11%), nothsl(...)wrappers and not hex. Tailwind wraps them. Pastinghsl(...)or hex there silently breaks colors. - Keep
:rootand.darkin sync — both blocks must define the same variable names. Adding a token to:rootwithout a.darkcounterpart causes dark mode to fall back to inherited/undefined values. components.jsonpath mismatch — it referencestailwind.config.tswhile the real file istailwind.config.js. No runtime impact, but theshadcnCLI may warn when runningnpx shadcn add. Fix opportunistically.- Tour overlay is independent —
src/tours/tours.cssuses its own Driver.js classes and won't automatically follow your new Shadcn tokens.
Verification
pnpm --filter frontend-pwa run dev # starts on port 5173
- Toggle between light and dark via the header Sun/Moon button.
- Confirm all core Shadcn surfaces pick up the new tokens: buttons, cards, dialogs, popovers, inputs, sidebar.
- Spot-check screens with custom color usage: sale form, discount modal, tour overlays.