Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .changeset/activate-shadcn-color-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
'@accounter/client': patch
---

Activate the shadcn colour tokens, which have been compiling to nothing since the Tailwind v4
migration.

`components.json` declared `cssVariables: false` and pointed `tailwind.config.cjs` — a file that does
not exist anywhere in the monorepo. It was deleted during the v3 → v4 migration and the theme layer
was never ported to v4's CSS-first `@theme`, so `--color-card`, `--color-muted-foreground`,
`--color-destructive` and the rest were never registered and Tailwind never generated the utilities
that reference them. Roughly 380 usages across ~100 files were inert: `text-muted-foreground`,
`bg-card`, `border-border` and `text-destructive` each emitted **zero** rules into the bundle, so
secondary text rendered as full-strength body colour, `bg-muted`/`bg-accent`/`bg-card` were
transparent, and error text rendered black instead of red.

`src/index.css` now defines the full token set in `@theme` on shadcn's `gray` base, with `.dark`
overrides in `@layer base`. Values are literal `oklch()` rather than `var(--color-gray-500)`
references, because Tailwind v4 only emits the default palette variables it sees used — referencing
one that happens to be unused elsewhere would resolve to nothing. Tokens that stood in for an
existing default were given that default's value, so classes which were previously no-ops stay
visually unchanged: `--color-background`/`--color-card` are white (already the page background),
`--color-foreground` is gray-950 (already the inherited text colour), and `--color-border` is gray-200
to match the `border-color` compatibility rule already in the base layer. The visible changes are the
genuinely broken cases — muted text now reads gray-500, `text-destructive` reads red-600, and
`bg-muted`/`bg-accent`/`bg-secondary` gain their light tint.

Also fixes `business/client/charts-section.tsx`, which set its axis ticks with
`hsl(var(--muted-foreground))`. That is v3 syntax: the v4 token is `--color-muted-foreground` and
holds a colour rather than an HSL triplet, so the `hsl()` wrapper produced an invalid value and the
ticks fell back to Recharts' default. Its `hsl(var(--chart-N))` siblings are correct and unchanged —
the `--chart-*` family really is stored as triplets.

Dark mode remains inert: `next-themes` is installed but no `ThemeProvider` is mounted, so nothing ever
puts `.dark` on an ancestor. The overrides are defined so the ~425 `dark:` utilities already in the
codebase are correct when that switch is eventually wired.
4 changes: 2 additions & 2 deletions packages/client/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.cjs",
"config": "",
"css": "src/index.css",
"baseColor": "gray",
"cssVariables": false,
"cssVariables": true,
"prefix": ""
},
"aliases": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ export function ChartsSection() {
<XAxis
dataKey="month"
className="text-xs"
tick={{ fill: 'hsl(var(--muted-foreground))' }}
tick={{ fill: 'var(--color-muted-foreground)' }}
/>
<YAxis className="text-xs" tick={{ fill: 'hsl(var(--muted-foreground))' }} />
<YAxis className="text-xs" tick={{ fill: 'var(--color-muted-foreground)' }} />
<ChartTooltip content={<ChartTooltipContent />} />
<Line
type="monotone"
Expand Down
90 changes: 90 additions & 0 deletions packages/client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,56 @@

@plugin 'tailwindcss-animate';

/*
shadcn/ui colour tokens.

These were never ported when this project moved from Tailwind v3 (which configured them in a
`tailwind.config.cjs` that no longer exists) to v4's CSS-first `@theme`. Until now the token
namespace was simply undefined, so every `text-muted-foreground` / `bg-card` / `border-border` /
`text-destructive` in the codebase — roughly 380 usages across ~100 files — compiled to no rule at
all and rendered as inherited black on transparent.

Values follow shadcn's `gray` base (see `components.json`) and are written as literal `oklch()`
rather than `var(--color-gray-500)` on purpose: Tailwind v4 only emits the default palette
variables it sees used, so referencing one that happens to be unused elsewhere would resolve to
nothing.

Plain `@theme`, NOT `@theme inline` — inline substitutes the literal value into each utility, which
would make the `.dark` overrides below dead code.
*/
@theme {
--color-background: #fff;
--color-foreground: oklch(13% 0.028 261.692); /* gray-950 */

--color-card: #fff;
--color-card-foreground: oklch(13% 0.028 261.692); /* gray-950 */

--color-popover: #fff;
--color-popover-foreground: oklch(13% 0.028 261.692); /* gray-950 */

--color-primary: oklch(21% 0.034 264.665); /* gray-900 */
--color-primary-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

--color-secondary: oklch(96.7% 0.003 264.542); /* gray-100 */
--color-secondary-foreground: oklch(21% 0.034 264.665); /* gray-900 */

--color-muted: oklch(96.7% 0.003 264.542); /* gray-100 */
--color-muted-foreground: oklch(55.1% 0.027 264.364); /* gray-500 */

--color-accent: oklch(96.7% 0.003 264.542); /* gray-100 */
--color-accent-foreground: oklch(21% 0.034 264.665); /* gray-900 */

--color-destructive: oklch(57.7% 0.245 27.325); /* red-600 */
--color-destructive-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

/*
Kept at gray-200 to match the `border-color` compatibility rule in the base layer below, so
`border-border` renders identically to a border with no colour utility at all.
*/
--color-border: oklch(92.8% 0.006 264.531); /* gray-200 */
--color-input: oklch(92.8% 0.006 264.531); /* gray-200 */
--color-ring: oklch(70.7% 0.022 261.325); /* gray-400 */

--animate-accordion-up: accordion-up 0.2s ease-out;
--animate-accordion-down: accordion-down 0.2s ease-out;

Expand Down Expand Up @@ -55,6 +104,47 @@
}
}

/*
Dark-mode overrides for the tokens defined in `@theme` above.

Note this is currently inert: nothing in the app ever puts `.dark` on an ancestor. `next-themes` is
installed but no `ThemeProvider` is mounted (`root-layout.tsx` mounts MUI's), so `useTheme()` sits
at its `system` default and never writes a class. These values are still correct to define — the
~425 `dark:` utilities already in the codebase are waiting on the same switch — but activating dark
mode is a separate change.
*/
@layer base {
.dark {
--color-background: oklch(13% 0.028 261.692); /* gray-950 */
--color-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

--color-card: oklch(21% 0.034 264.665); /* gray-900 */
--color-card-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

--color-popover: oklch(21% 0.034 264.665); /* gray-900 */
--color-popover-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

--color-primary: oklch(98.5% 0.002 247.839); /* gray-50 */
--color-primary-foreground: oklch(21% 0.034 264.665); /* gray-900 */

--color-secondary: oklch(27.8% 0.033 256.848); /* gray-800 */
--color-secondary-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

--color-muted: oklch(27.8% 0.033 256.848); /* gray-800 */
--color-muted-foreground: oklch(70.7% 0.022 261.325); /* gray-400 */

--color-accent: oklch(27.8% 0.033 256.848); /* gray-800 */
--color-accent-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

--color-destructive: oklch(70.4% 0.191 22.216); /* red-400 */
--color-destructive-foreground: oklch(98.5% 0.002 247.839); /* gray-50 */

--color-border: oklch(27.8% 0.033 256.848); /* gray-800 */
--color-input: oklch(27.8% 0.033 256.848); /* gray-800 */
--color-ring: oklch(44.6% 0.03 256.802); /* gray-600 */
}
}

/* shadcn charts styles */
@layer base {
:root {
Expand Down
Loading