| 1 | import type { Config } from "tailwindcss"; |
| 2 | |
| 3 | export default { |
| 4 | // Dictionaries carry per-locale class names (e.g. the Arabic and Hindi |
| 5 | // docs guide's `leading-loose`); unscanned, those utilities never exist. |
| 6 | content: ["./app/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}", "./lib/i18n/dictionaries/**/*.ts"], |
| 7 | theme: { |
| 8 | extend: { |
| 9 | colors: { |
| 10 | // Every colour resolves through the role tokens |
| 11 | // (app/styles/tokens-roles.css), so the stage and both appearances |
| 12 | // re-ink it. Alpha modifiers mix the role toward transparent. |
| 13 | ...Object.fromEntries( |
| 14 | Object.entries({ |
| 15 | canvas: "--bg", |
| 16 | surface: "--surface", |
| 17 | panel: "--panel", |
| 18 | fg: "--text", |
| 19 | muted: "--muted", |
| 20 | line: "--line", |
| 21 | accent: "--accent", |
| 22 | "on-accent": "--on-accent", |
| 23 | hover: "--hover", |
| 24 | selected: "--selected", |
| 25 | attention: "--attention", |
| 26 | live: "--live", |
| 27 | success: "--success", |
| 28 | danger: "--danger", |
| 29 | // Legacy names still used by the docs pages (post-renovation sweep). |
| 30 | paper: "--paper", |
| 31 | "paper-deep": "--paper-deep", |
| 32 | "paper-edge": "--paper-edge", |
| 33 | "paper-card": "--paper-card", |
| 34 | "paper-line": "--paper-line", |
| 35 | "paper-line-soft": "--paper-line-soft", |
| 36 | ink: "--ink", |
| 37 | "ink-soft": "--ink-soft", |
| 38 | "ink-mute": "--ink-mute", |
| 39 | indigo: "--indigo", |
| 40 | "indigo-deep": "--indigo-deep", |
| 41 | "indigo-pale": "--indigo-pale", |
| 42 | ochre: "--ochre", |
| 43 | jade: "--jade", |
| 44 | cobalt: "--cobalt", |
| 45 | }).map(([name, role]) => [ |
| 46 | name, |
| 47 | `color-mix(in srgb, var(${role}) calc(<alpha-value> * 100%), transparent)`, |
| 48 | ]), |
| 49 | ), |
| 50 | }, |
| 51 | fontFamily: { |
| 52 | // One face, as GPUI set_theme: every family resolves through the |
| 53 | // role stacks in app/styles/tokens-roles.css (Shannon Sans subsets |
| 54 | // loaded in app/[locale]/layout.tsx; system mono for code). |
| 55 | display: ["var(--font-display)"], |
| 56 | body: ["var(--font-body)"], |
| 57 | cjk: ["var(--font-cjk)"], |
| 58 | mono: ["var(--font-mono)"], |
| 59 | }, |
| 60 | // `transition-colors` and friends use the same motion tokens as |
| 61 | // app/styles, so reduced motion stills them too. |
| 62 | transitionDuration: { DEFAULT: "var(--dur-state)" }, |
| 63 | transitionTimingFunction: { DEFAULT: "var(--ease-spring)" }, |
| 64 | }, |
| 65 | // Replaces Tailwind's scale with the GPUI radius grammar |
| 66 | // (app/styles/tokens-roles.css): 6px controls, 10px surfaces (cards, |
| 67 | // code, menus), 14px raised sheets, and pills. Nothing in between. |
| 68 | borderRadius: { |
| 69 | none: "0", |
| 70 | sm: "var(--radius-control)", |
| 71 | DEFAULT: "var(--radius-control)", |
| 72 | lg: "var(--radius-surface)", |
| 73 | xl: "var(--radius-sheet)", |
| 74 | full: "var(--radius-pill)", |
| 75 | }, |
| 76 | // Replaces Tailwind's scale so wide tracking cannot be generated: labels |
| 77 | // are sentence case at normal tracking. `wide` stays for Han body copy. |
| 78 | letterSpacing: { |
| 79 | tighter: "-0.05em", |
| 80 | tight: "-0.025em", |
| 81 | crisp: "-0.018em", |
| 82 | normal: "0em", |
| 83 | wide: "0.025em", |
| 84 | }, |
| 85 | }, |
| 86 | // No all-caps anywhere, as in the GPUI app: the `uppercase` utility and |
| 87 | // its siblings are not generated. |
| 88 | corePlugins: { textTransform: false }, |
| 89 | plugins: [], |
| 90 | } satisfies Config; |
| 91 |