chore(storybook): derive the primary shade from the theme in the guard

The guard restated `primaryShade.light` as a literal 7, so re-pinning the
theme's primary shade would have made it fail even with the preview
annotations correctly applied — a guard that has to be edited alongside a
legitimate theme change just trains people to edit it.

Derive the shade from `theme.primaryShade`, handling both of Mantine's
forms (a bare number and `{ light, dark }`) and falling back to Mantine's
own default of 6 when a theme pins none.

Verified by temporarily re-pinning the theme to `{ light: 8, dark: 8 }`:
the guard still passes, where the hard-coded 7 would have failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0119LaPQ3v4NyBK3ZTdM9j84
This commit is contained in:
cliffhall 2026-08-10 23:54:44 -04:00
commit d1135dfe7c

View file

@ -30,14 +30,29 @@ import { theme } from "../theme/theme";
// function; it was verified out-of-band by temporarily giving a story a real
// violation and confirming the suite went red (see the PR for #1898).
// The primary shade the theme pins for the light scheme — the value Mantine
// derives `--mantine-primary-color-filled` from. Read from the theme rather
// than hard-coded so a palette change can't silently invalidate the guard.
const LIGHT_PRIMARY_SHADE = 7;
// Mantine's own default when a theme pins no `primaryShade` — the value it
// falls back to when deriving `--mantine-primary-color-filled`.
const MANTINE_DEFAULT_LIGHT_PRIMARY_SHADE = 6;
// The shade Mantine derives `--mantine-primary-color-filled` from. Everything
// here is read from the theme rather than restated, so re-pinning
// `primaryShade` or repainting the palette moves the expectation with it — a
// guard that had to be edited alongside a legitimate theme change would just
// train people to edit it, which is the opposite of what it's for.
//
// The light branch is the one that matters: `./preview` renders every story
// with `defaultColorScheme="light"` and an `initialGlobals.colorScheme` of
// `"light"`. `primaryShade` is `number | { light, dark }` in Mantine's types,
// so both forms are handled.
function lightPrimaryShade(): number {
const shade = theme.primaryShade;
if (typeof shade === "number") return shade;
return shade?.light ?? MANTINE_DEFAULT_LIGHT_PRIMARY_SHADE;
}
function expectedPrimaryColor(): string {
const palette = theme.colors?.[theme.primaryColor ?? ""];
const color = palette?.[LIGHT_PRIMARY_SHADE];
const color = palette?.[lightPrimaryShade()];
if (!color) throw new Error("theme is missing its primary color palette");
return color;
}