import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Tokens / Tokens Guide" />

<div className="sb-doc">

# Tokens

<p className="excerpt">Tokens are Shade's visual atoms — colours, type sizes, spacing, radii, shadows, motion. Every primitive, component, and pattern resolves down to these. Browse the live galleries in the sidebar; the rules for using them are short.</p>

## The galleries

- [**Colors**](?path=/docs/tokens-colors--docs) — surface, text, border, state, chart, and the raw palette.
- [**Typography**](?path=/docs/tokens-typography--docs) — font families, size ramp, line-heights.
- [**Spacing**](?path=/docs/tokens-spacing--docs) — the 0.4rem base unit and the semantic gap scale primitives use.
- [**Radius**](?path=/docs/tokens-radius--docs) — numeric and semantic radii (`radius-control`, `radius-surface`, `radius-pill`).
- [**Shadows**](?path=/docs/tokens-shadows--docs) — elevation tokens for cards, popovers, and modals.
- [**Motion**](?path=/docs/tokens-motion--docs) — durations, easings, and named animations.
- [**Breakpoints**](?path=/docs/tokens-breakpoints--docs) — responsive cut-offs backing Tailwind's `md:` / `lg:` variants.

Toggle light/dark from the Storybook toolbar to see semantic tokens flip.

## Two flavours

**Semantic tokens** are named by purpose — `--background`, `--text-primary`, `--border-default`, `--surface-elevated`. They flip between light and dark mode automatically. Reach for these by default.

**Raw tokens** are concrete values — `--color-gray-500`, `--text-base`, `--spacing`. They never change between modes. Use only when no semantic token fits (chart series, brand assets, illustrations).

## Source files

- `apps/shade/theme-variables.css` — semantic tokens + dark-mode overrides.
- `apps/shade/tailwind.theme.css` — Tailwind `@theme` block: raw catalogue and bindings.
- Semantic color variables should resolve directly to raw `--color-*` tokens, not to another semantic token. For example, prefer `--text-primary: var(--color-black)` over `--text-primary: var(--foreground)`.

## Rules of consumption

- Prefer Tailwind utilities — `bg-background`, `text-foreground`, `rounded-md` — over inline styles.
- Never hard-code hex or `hsl()` values for UI chrome. They don't theme and don't dark-mode. Chart tokens are the current exception until the chart palette has its own raw scale.
- Inside stylesheets, use `var(--token)` directly. Don't wrap variables in color functions.
- Don't write `dark:` variants for colour. The tokens do that. (Exceptions: assets like logos and illustrations.)

## Surface elevation

Surfaces are ordered by how high they sit. Pick by what's behind the element, not by component type.

1. **`--background`** — the page canvas. Default for body, app shell, editor.
2. **`--surface-elevated`** — one step above page. Use for sidebars, cards, top bars, sticky headers, the elevated edges of stats panels.
3. **`--surface-elevated-2`** — one step above elevated. Reserved for floating menus that open ON TOP of an elevated surface — `DropdownMenu`, `Select`, `Popover`, and the sidebar user menu. The job is to make the popover read as floating above its trigger.

In light mode all three flatten to near-white, so borders and shadows carry the visual elevation. In dark mode they're three distinct colours so layered surfaces stay legible without relying on borders alone.

## Interactive surfaces

Hover, active, and selected states are their own tokens — don't reach for raw greys or apply `/30` opacity modifiers ad-hoc.

| Token | Use for |
| --- | --- |
| `--interactive-hover` | Generic hover: dropdown items, menu items, list rows, filter options. The catch-all. |
| `--button-hover` | Outline / dropdown `Button` hover. Currently aliased to `--interactive-hover`; kept separate so the button surface can diverge later. |
| `--tab-hover` / `--tab-active` | `Tabs` (button, button-sm, pill, kpis), `PageMenu`, sidebar menu items, active `Toggle` (dark). |
| `--table-row-hover` | Shade `Table` row hover. Also used by visually-table-like lists (analytics top posts, comments list, members sticky cell). |

In dark mode `--interactive-hover`, `--button-hover`, and `--tab-hover` are translucent (`gray-900/30`) so they composite over whatever surface sits behind them. `--table-row-hover` is opaque (it matches `--surface-elevated`) — use it where you need an opaque fill, like sticky table cells where content scrolls underneath.

## Form control borders

Inputs, textareas, outline `Button`s, dropdown triggers, and the `inputSurface` recipe use `--control-border`, not `--border-default`. In dark mode it lifts a step above the page border so form controls keep enough contrast against the page surface. Borders inside cards or popovers can keep using `--border-default`.

## Dropdown surface contract

`DropdownMenu`, `Select`, and `Popover` (the three Radix-backed floating menus that Filters uses) share one visual recipe: `bg-surface-elevated-2` + `border border-border/60 dark:border-border/30` + `shadow-md`. Treat them as one component for any surface decision — change all three together.

</div>
