shelving
Version:
Toolkit for using data in JavaScript.
222 lines (195 loc) • 9.54 kB
CSS
/*
* Base styles for the shelving UI library. See `modules/ui/README.md` for the styling system overview.
*
* Every `*.module.css` `@import`s this file at the very top. It does three things:
*
* 1. Declares the cascade-layer order (lowest → highest priority):
* • `defaults` — `:root` design tokens + body baseline + low-priority opt-in defaults.
* • `components` — component-defining CSS. The bulk of the codebase.
* • `variants` — cross-cutting opt-in modifiers (Color, Status, Align, Spacing, Padding, Gap,
* Thickness, Width, Typography, Flex). Always beat components.
* • `overrides` — top-priority structural overrides like `:first-child` / `:last-child` margin
* collapses, which must beat variant-set margins.
*
* 2. Defines the design-token constants at `:root` — colours, sizes, spacing, etc.
*
* 3. Sets baseline typography on `body` so a page with no `<Layout>` still reads correctly.
*
* Re-declaring the same layer order across every importer is a no-op. Unlayered rules beat all layered
* rules — themes should override tokens at `:root` (via inheritance), not via class selectors.
*/
@layer defaults, components, variants, overrides;
@layer defaults {
:root {
color-scheme: light;
/* Semantic widths */
--width-narrow: min(100%, 22.5rem);
--width-wide: min(100%, 33.75rem);
/* Font weights */
--weight-normal: 400;
--weight-strong: 700;
/* Semantic font weights */
--weight-label: var(--weight-strong);
/* Font faces */
--font-sans: system-ui;
--font-mono: ui-monospace, "SF Mono", "Consolas", "Menlo", monospace;
--font-serif: "Palatino", "Garamond", serif;
/* Semantic font faces */
--font-body: var(--font-sans);
--font-code: var(--font-mono);
/* Sizings */
--size: 1rem;
--size-scale: 1.25;
--size-xxsmall: calc(var(--size) * pow(var(--size-scale), -3));
--size-xsmall: calc(var(--size) * pow(var(--size-scale), -2));
--size-small: calc(var(--size) * pow(var(--size-scale), -1));
--size-normal: calc(var(--size) * pow(var(--size-scale), 0));
--size-large: calc(var(--size) * pow(var(--size-scale), 1));
--size-xlarge: calc(var(--size) * pow(var(--size-scale), 2));
--size-xxlarge: calc(var(--size) * pow(var(--size-scale), 3));
--size-xxxlarge: calc(var(--size) * pow(var(--size-scale), 4));
/* Semantic sizes */
--size-icon: var(--size-large);
/* Relative sizes */
--size-smaller: 0.875em;
--size-larger: 1.5em;
--size-xlarger: 2.5em;
--size-xxlarger: 5em;
/* Line heights */
--leading: clamp(1.05em, calc(1em + 0.5rem), 1.5em);
--leading-normal: 1.5;
/* Spacings */
--space: 1rem;
--space-xxsmall: calc(var(--space) * 0.25); /* 4px */
--space-xsmall: calc(var(--space) * 0.5); /* 8px */
--space-small: calc(var(--space) * 0.75); /* 12px */
--space-normal: calc(var(--space) * 1); /* 16px */
--space-large: calc(var(--space) * 1.5); /* 24px */
--space-xlarge: calc(var(--space) * 2); /* 32px */
--space-xxlarge: calc(var(--space) * 3); /* 48px */
/* Semantic spacings */
--spacing-section: 2rem; /* Default top margin for titles/headings/section blocks. */
--spacing-paragraph: var(
--space-normal
); /* Default block-spacing for most prose-level elements (Paragraph, Heading body margin, List, Definitions, Table, etc.). */
/* Radii */
--radius: 1rem;
--radius-xxsmall: calc(var(--radius) * 0.25); /* 4px */
--radius-xsmall: calc(var(--radius) * 0.5); /* 8px */
--radius-small: calc(var(--radius) * 0.75); /* 12px */
--radius-normal: calc(var(--radius) * 1); /* 16px */
--radius-large: calc(var(--radius) * 1.5); /* 24px */
--radius-xlarge: calc(var(--radius) * 2); /* 32px */
--radius-xxlarge: calc(var(--radius) * 3); /* 48px */
/* Strokes — border thicknesses, also exposed via the Thickness variant utility. */
--stroke: 2px;
--stroke-xxthin: calc(var(--stroke) * 0.25);
--stroke-xthin: calc(var(--stroke) * 0.5);
--stroke-thin: calc(var(--stroke) * 0.75);
--stroke-normal: calc(var(--stroke) * 1);
--stroke-thick: calc(var(--stroke) * 1.5);
--stroke-xthick: calc(var(--stroke) * 2);
--stroke-xxthick: calc(var(--stroke) * 3);
/* Semantic strokes */
--stroke-hairline: 1px;
--stroke-focus: var(--stroke-thick);
/* Durations */
--duration-fast: 150ms;
--duration-normal: 300ms;
--duration-slow: 600ms;
/* Grows */
--grow-greedy: 1000000; /* Take up as much space as possible. */
--grow-normal: 1000; /* Take up a normal amount of space. */
--grow-timid: 1; /* Take up minimal space. */
--grow-none: 0;
/* Vivid palette — the saturated middle of the 5-step scale, one per hue. */
--vivid-gray: oklch(60% 0.01 240); /* Subtle blue tint so neutrals don't feel "dead". */
--vivid-red: oklch(62% 0.2 30); /* Slightly desaturated from default — takes the edge off without losing red identity. */
--vivid-orange: oklch(74% 0.157 60);
--vivid-yellow: oklch(86% 0.16 92);
--vivid-green: oklch(72% 0.185 130);
--vivid-aqua: oklch(72% 0.121 185);
--vivid-blue: oklch(57% 0.216 260); /* OKLCH form of #156ef4 — warmer hue (260) than the previous 240. */
--vivid-purple: oklch(58% 0.25 300);
--vivid-pink: oklch(68% 0.239 350);
/* Brand aliases — themes can repoint these without renaming the named-palette tokens. */
--vivid-primary: var(--vivid-blue);
--vivid-secondary: var(--vivid-purple);
--vivid-tertiary: var(--vivid-aqua);
--light-primary: var(--light-blue);
--light-secondary: var(--light-purple);
--light-tertiary: var(--light-aqua);
--dark-primary: var(--dark-blue);
--dark-secondary: var(--dark-purple);
--dark-tertiary: var(--dark-aqua);
/* Light palette — 20% vivid blended into white. Pastel surfaces; chroma reduces naturally so
* the result isn't a high-saturation salmon/lime. */
--light-gray: color-mix(in oklch, var(--vivid-gray) 15%, white);
--light-red: color-mix(in oklch, var(--vivid-red) 25%, white);
--light-orange: color-mix(in oklch, var(--vivid-orange) 25%, white);
--light-yellow: color-mix(in oklch, var(--vivid-yellow) 25%, white);
--light-green: color-mix(in oklch, var(--vivid-green) 25%, white);
--light-aqua: color-mix(in oklch, var(--vivid-aqua) 25%, white);
--light-blue: color-mix(in oklch, var(--vivid-blue) 25%, white);
--light-purple: color-mix(in oklch, var(--vivid-purple) 25%, white);
--light-pink: color-mix(in oklch, var(--vivid-pink) 25%, white);
/* Dark palette — same hue, lowered lightness for foregrounds. */
--dark-gray: oklch(from var(--vivid-gray) calc(l - 0.3) c h);
--dark-red: oklch(from var(--vivid-red) calc(l - 0.22) c h);
--dark-orange: oklch(from var(--vivid-orange) calc(l - 0.22) c h);
--dark-yellow: oklch(from var(--vivid-yellow) calc(l - 0.22) c h);
--dark-green: oklch(from var(--vivid-green) calc(l - 0.22) c h);
--dark-aqua: oklch(from var(--vivid-aqua) calc(l - 0.22) c h);
--dark-blue: oklch(from var(--vivid-blue) calc(l - 0.22) c h);
--dark-purple: oklch(from var(--vivid-purple) calc(l - 0.22) c h);
--dark-pink: oklch(from var(--vivid-pink) calc(l - 0.22) c h);
/* The 5-step scale — variant classes (.red, .success, etc.) override the middle three at their scope.
* `--color-black` and `--color-white` aren't literal black/white in every theme — they're the darkest
* and lightest *ends* of the active scale (a dark theme inverts them). For literal black/white pixels
* (e.g. blending hover states neutrally) use the CSS keywords `black` / `white` directly. */
--color-black: black;
--color-dark: var(--dark-gray);
--color-vivid: var(--vivid-gray);
--color-light: var(--light-gray);
--color-white: white;
/* Other semantic colour tokens (separate concerns from the scale). */
--color-link: var(--vivid-blue);
--color-focus: var(--vivid-blue);
--color-shadow: color-mix(in oklch, var(--vivid-gray) 40%, transparent);
/* Shadows */
--shadow-xxsmall: 0 0.125rem 0.5rem -0.25rem var(--color-shadow);
--shadow-xsmall: 0 0.25rem 1rem -0.5rem var(--color-shadow);
--shadow-small: 0 0.375rem 1.5rem -0.75rem var(--color-shadow);
--shadow-normal: 0 0.5rem 2rem -1rem var(--color-shadow);
--shadow-large: 0 0.75rem 3rem -1.5rem var(--color-shadow);
--shadow-xlarge: 0 1rem 4rem -2rem var(--color-shadow);
--shadow-xxlarge: 0 1.5rem 6rem -3rem var(--color-shadow);
}
/* Typography reset — body uses `dark` text (1 step softer than pure black) on `white` bg so variant
* scopes (e.g. `<aside red>`) can tint body text via `--color-dark`. Components that want max contrast
* (Inputs, Titles) reach for `--color-black` explicitly. */
body {
font-family: var(--font-body);
font-weight: var(--weight-normal);
font-size: var(--size-normal);
line-height: var(--leading);
color: var(--color-dark);
background: var(--color-white);
}
/* Darken vivid for higher contrast — 2-step pairings (vivid+white, light+vivid) gain readability
* without any per-component changes. The light and dark ends already provide enough contrast for
* 3-step pairings (white+dark, light+black), so they don't need to move. */
@media (prefers-contrast: more) {
:root {
--vivid-gray: var(--dark-gray);
--vivid-red: var(--dark-red);
--vivid-orange: var(--dark-orange);
--vivid-yellow: var(--dark-yellow);
--vivid-green: var(--dark-green);
--vivid-aqua: var(--dark-aqua);
--vivid-blue: var(--dark-blue);
--vivid-purple: var(--dark-purple);
--vivid-pink: var(--dark-pink);
}
}
}