@swiftsolve/rove-tokens 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/DESIGN.md ADDED
@@ -0,0 +1,138 @@
1
+ # Rove design
2
+
3
+ How to build Rove's interface with these tokens, for anyone writing Rove UI, people and coding agents alike. The [token reference](#token-reference) at the end lists every value; [`docs/rationale.md`](docs/rationale.md) explains why they are what they are.
4
+
5
+ ## Setup
6
+
7
+ ```css
8
+ @import '@swiftsolve/rove-tokens/tokens.css';
9
+ ```
10
+
11
+ Dark is the default, on `:root`. Add the `theme-light` class to the root element for Light. Every token has both values, so a screen that only uses tokens themes itself.
12
+
13
+ ## Rules
14
+
15
+ - **Use a token, never a raw value.** No hex colours, no pixel gaps, no font sizes typed by hand. If nothing fits, the design needs a new token in Figma, not a one-off in code.
16
+ - **Name by job, not by look.** Pick `--bg-surface` because it's content on the backdrop, not because it's the right grey. The Palette shades (`neutral/850`) aren't CSS variables, on purpose.
17
+
18
+ ### Surfaces
19
+
20
+ - Three backgrounds: `--bg-base` for the backdrop, `--bg-surface` for content that sits on it (cards, dialogs), `--bg-inset` for areas sunk into a surface (bands, inputs, soft and icon buttons). `--bg-chrome` is the title bar and rail, a half step off the backdrop. `--bg-popover` is a step lighter in Dark, for tooltips and menus. `--bg-hover` is a hovered surface, `--bg-scrim` goes behind dialogs.
21
+ - Cards get depth from `--shadow-panel`, not hard outlines. Tooltips and menus use `--shadow-popover` on `--bg-popover`; dialogs and hovered cards use `--shadow-raised`.
22
+ - Every line is `--border-default`: hairlines, and the edges of menus, tooltips and dialogs.
23
+ - For hovers, chips and tracks on a surface, use the `--fill-*` overlays, by strength: `--fill-faint` (3%), `--fill-subtle` (5%), `--fill-default` (7%), `--fill-strong` (16%). They flip with the theme, so they stay visible on both. A hovered row or expandable header uses `--fill-hover`: 3% white in Dark, 2% ink in Light, so in Light it stays lighter than an open `--bg-inset` panel below it.
24
+
25
+ ### Text and icons
26
+
27
+ - `--text-primary` for content, `--text-secondary` for supporting lines, `--text-tertiary` for the quietest text and for icons by default.
28
+ - On a solid fill (accent or negative), labels and icons use `--text-on-fill`.
29
+ - Words in the accent (a link, a highlighted value) use `--text-accent`, on a surface or on `--accent-muted` (a selected item, a tinted button).
30
+
31
+ ### Accent and buttons
32
+
33
+ - `--accent-default` is for accent icons and lines. It's too light for words in Light mode, and under a white label.
34
+ - Solid buttons use `--accent-fill`, hovering to `--accent-fill-hover`. Hovers deepen, never lighten, so the white label keeps its contrast.
35
+ - A solid red control (a solid negative button, the window close hover) uses `--status-negative-fill` and `--status-negative-fill-hover`.
36
+
37
+ ### Status
38
+
39
+ - `--status-*` (positive, good, warning, poor, negative) colour icons, bars and dots.
40
+ - Words in a status colour use `--text-*` of the same name, which also clear a tint of their hue (a badge). The `--status-*` shades are too light for text in Light mode.
41
+ - Download and upload in charts are `--series-down` and `--series-up`.
42
+
43
+ ### Tints and opacity
44
+
45
+ Tints are a colour mixed with transparent at one of the shared strengths, so a tinted tile reads the same everywhere:
46
+
47
+ ```css
48
+ background: color-mix(in srgb, var(--status-positive) var(--opacity-tint-md), transparent);
49
+ ```
50
+
51
+ Disabled controls use `--opacity-disabled`.
52
+
53
+ ### Spacing and shape
54
+
55
+ - Every gap, padding and margin is a `--spacing-*` step.
56
+ - Cards use `--card-padding` on every side. The rail and the content column share the side inset `--spacing-12`.
57
+ - Corners are `--radius-*`. `--radius-md` is for nav items and the page-header chip, a step rounder than `--radius-sm`; `--radius-full` makes pills.
58
+
59
+ ### Type
60
+
61
+ - Set text with a text style's class from `text-styles.css` (`.type-heading-large`), or all four of its `--type-<style>-*` variables, never a font size alone. Each style's use is in [Text styles](#text-styles).
62
+ - Numbers that are data (speeds, totals, chart labels) use the Number styles (`number-*`), set in Questrial; everything else is Inter.
63
+
64
+ ### Focus and motion
65
+
66
+ - Keyboard focus is `outline: var(--focus-outline)` with `outline-offset: var(--focus-offset)`. Rows flush with a card's edge draw it inside instead, with `--focus-inset`.
67
+ - Animate with `--ease-out` (or `--ease-in-out`) over `--duration-fast` or `--duration-normal`. A looping pulse uses `--ease-pulse`, which is symmetric, so it fades out and back in alike.
68
+
69
+ ### Icons
70
+
71
+ - Icons share a 24px grid, a 1.75px stroke and round caps.
72
+ - Icons are `--text-tertiary` by default. The active nav item's is `--accent-default`, an icon button's `--text-secondary`, a download icon `--series-down`, a secured or passing one `--status-positive`.
73
+ - The brand mark is always `--accent-default`, 22px in the title bar.
74
+
75
+ ## Changing the design
76
+
77
+ Figma is the source of truth. Change a token in the Rove Design System Figma file, export it with the plugin in `figma-plugin/` into `src/figma/`, then run `npm run build` (see the [README](README.md#update-the-tokens)). Don't edit `tokens.css`, `tokens/` or the values in `src/figma/` by hand. What Figma can't hold (shadows, easing curves, the focus outline) lives in `src/code-tokens.json`.
78
+
79
+ Everything below the next line is rewritten by `npm run build`; edit only above it.
80
+
81
+ <!-- Generated by npm run build from the Figma export and tokens.css. Edit above this line. -->
82
+
83
+ ## Token reference
84
+
85
+ Names and uses, from Figma. The values are in `tokens.css`; Dark and Light differ only in colour and shadow.
86
+
87
+ ### Colour
88
+
89
+ - **Backgrounds:** `--bg-base` (backdrop), `--bg-surface` (content on the backdrop), `--bg-hover` (hovered rows and buttons), `--bg-scrim` (behind dialogs), `--bg-inset` (sunken areas inside a surface), `--bg-popover` (tooltips and menus), `--bg-chrome` (title bar and rail)
90
+ - **Lines:** `--border-default` (hairlines)
91
+ - **Fills and overlays:** `--fill-default` (overlay), `--fill-subtle` (light overlay), `--fill-faint` (faintest overlay), `--fill-strong` (strong overlay), `--fill-selection` (text selection), `--fill-hover` (hovered rows and headers)
92
+ - **Text:** `--text-primary`, `--text-secondary`, `--text-tertiary` (default icon colour), `--text-accent` (accent words, also on accent/muted), `--text-positive`, `--text-good`, `--text-warning`, `--text-poor`, `--text-negative`, `--text-on-fill` (labels and icons on solid fills)
93
+ - **Accent:** `--accent-default`, `--accent-hover`, `--accent-press`, `--accent-muted` (tinted accent background), `--accent-fill` (fill under white labels), `--accent-fill-hover`
94
+ - **Status:** `--status-positive`, `--status-good` (between positive and warning), `--status-warning`, `--status-poor` (between warning and negative), `--status-negative`, `--status-negative-fill` (solid negative under white labels), `--status-negative-fill-hover` (negative fill hover)
95
+ - **Chart series:** `--series-down` (download), `--series-up` (upload)
96
+ - **Focus:** `--focus-ring` (keyboard focus ring)
97
+
98
+ ### Scales
99
+
100
+ - **Spacing:** `--spacing-<n>`, n in px: 2, 4, 6, 8, 10, 12, 14, 16, 20
101
+ - **Radius:** `--radius-xs` 5px, `--radius-sm` 8px, `--radius-md` 10px, `--radius-lg` 13px, `--radius-full` 999px
102
+ - **Font sizes:** `--font-size-2xs` 10px, `--font-size-xs` 11px, `--font-size-sm` 12px, `--font-size-md` 13px, `--font-size-lg` 14px, `--font-size-xl` 15px (dialog titles), `--font-size-2xl` 17px, `--font-size-3xl` 28px
103
+ - **Font families:** `--font-family-sans` Inter, `--font-family-numeric` Questrial
104
+ - **Focus:** `--focus-ring-width` 1px (focus ring stroke), `--focus-offset` 2px (focus ring offset)
105
+ - **Opacity:** `--opacity-tint-xs` 8% (faintest tint), `--opacity-tint-sm` 10% (light tint), `--opacity-tint-md` 14% (tint), `--opacity-tint-lg` 22% (strong tint), `--opacity-tint-xl` 28% (strongest tint), `--opacity-high` 80% (nearly opaque), `--opacity-disabled` 40% (disabled controls)
106
+ - **Layout:** `--rail-item-size` 38px (rail items), `--titlebar-height` 56px (title bar)
107
+ - **Cards:** `--card-padding` `var(--spacing-14)` (card inset), `--card-header-padding-y` `var(--card-padding)`, `--card-header-padding-x` `var(--card-padding)`, `--card-header-min-height` 42px (compact card header), `--card-header-height` 44px (card header), `--card-body-padding` `var(--card-padding)`, `--row-padding-y` 8px (data row, above and below)
108
+ - **Font weights:** `--weight-regular` 400, `--weight-medium` 500, `--weight-semibold` 600
109
+ - **Motion:** `--duration-fast` 140ms (hovers, small changes), `--duration-normal` 220ms (panels, page changes)
110
+
111
+ ### Text styles
112
+
113
+ Apply a style with its class from `text-styles.css`. Each class reads four variables, `--type-<style>-size`, `-weight`, `-line-height` and `-letter-spacing`; set all four if you use them directly.
114
+
115
+ | Style | Class | Size, weight | Use |
116
+ | --- | --- | --- | --- |
117
+ | Heading/Large | `.type-heading-large` | 17px 600 | Page titles, the wordmark. Code: .type-heading-large |
118
+ | Heading/Medium | `.type-heading-medium` | 15px 600 | Dialog titles. Code: .type-heading-medium |
119
+ | Heading/Small | `.type-heading-small` | 14px 600 | Card headings. Code: .type-heading-small |
120
+ | Body/Default | `.type-body-default` | 13px 400 | Body text. Code: .type-body-default |
121
+ | Overline | `.type-overline` | 11px 500 | Uppercase labels above values. Code: .type-overline |
122
+ | Caption | `.type-caption` | 11px 400 | Badges, captions, footer hints. Code: .type-caption |
123
+ | Label/Large | `.type-label-large` | 12px 600 | Solid button labels. Code: Button variant=solid |
124
+ | Number/Display | `.type-number-display` | 28px 400, Questrial | Live speeds. Add a 0.43px outside stroke. Code: .type-number-display .metric-value, at weight 600: Questrial has one weight, so the browser emboldens it. |
125
+ | Number/Large | `.type-number-large` | 17px 400, Questrial | Stat totals. Add a 0.26px outside stroke. Code: Readout size=compact |
126
+ | Number/Default | `.type-number-default` | 13px 400, Questrial | Data row values. Code: .type-number-default |
127
+ | Number/Small | `.type-number-small` | 10px 400, Questrial | Chart axes and scale. Code: .type-number-small |
128
+ | Label/Default | `.type-label-default` | 11px 600 | Bold small labels on tinted chips. Code: .type-label-default |
129
+ | Label/Small | `.type-label-small` | 11px 500 | Soft buttons, title bar status. Code: .type-label-small |
130
+ | Body/Small | `.type-body-small` | 12px 400 | Helper text, hints and units. Code: .type-body-small |
131
+
132
+ ### Code-only tokens
133
+
134
+ What Figma variables can't hold, from `src/code-tokens.json`.
135
+
136
+ - **Shadows:** `--shadow-panel`, `--shadow-raised`, `--shadow-popover`
137
+ - **Focus:** `--focus-outline`, `--focus-inset`
138
+ - **Motion:** `--ease-out`, `--ease-in-out`, `--ease-pulse`
package/README.md CHANGED
@@ -1,3 +1,128 @@
1
- # Temporary Holding Version
1
+ <div align="center">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ <img src="docs/assets/rove-mark.svg" width="72" height="72" alt="Rove Mark">
4
+
5
+ # Rove Tokens
6
+
7
+ Tokens for Rove, straight from the Rove Design System in Figma.
8
+
9
+ `@swiftsolve/rove-tokens`
10
+
11
+ [![Build](https://img.shields.io/github/actions/workflow/status/swiftsolve/rove-tokens/build.yml?label=build&labelColor=17181b)](https://github.com/swiftsolve/rove-tokens/actions/workflows/build.yml)
12
+ [![Slideshow](https://img.shields.io/github/actions/workflow/status/swiftsolve/rove-tokens/presentation.yml?label=slideshow&labelColor=17181b)](https://github.com/swiftsolve/rove-tokens/actions/workflows/presentation.yml)
13
+ [![Version](https://img.shields.io/github/package-json/v/swiftsolve/rove-tokens?label=version&labelColor=17181b&color=5b8cff)](https://github.com/swiftsolve/rove-tokens/tags)
14
+ [![Figma](https://img.shields.io/badge/Figma-source_of_truth-5b8cff?logo=figma&logoColor=white&labelColor=17181b)](https://www.figma.com/design/NoICIoyhWNOya9tOnNfEhH/Rove-Design-System)
15
+ [![DTCG](https://img.shields.io/badge/DTCG-2025.10-5b8cff?labelColor=17181b)](https://www.designtokens.org/tr/2025.10/format/)
16
+ [![Style Dictionary](https://img.shields.io/badge/Style_Dictionary-5-5b8cff?labelColor=17181b)](https://styledictionary.com/)
17
+ [![WCAG](https://img.shields.io/badge/WCAG_2.2-AA-5b8cff?labelColor=17181b)](#-contrast)
18
+ [![Themes](https://img.shields.io/badge/themes-Dark_·_Light-5b8cff?labelColor=17181b)](#-use)
19
+ [![Node](https://img.shields.io/badge/node-%E2%89%A522-5b8cff?logo=nodedotjs&logoColor=white&labelColor=17181b)](.nvmrc)
20
+
21
+ [🎨 Figma file](https://www.figma.com/design/NoICIoyhWNOya9tOnNfEhH/Rove-Design-System) &nbsp;·&nbsp;
22
+ [🖼️ Slideshow](https://swiftsolve.github.io/rove-tokens/) &nbsp;·&nbsp;
23
+ [📐 DESIGN.md](DESIGN.md) &nbsp;·&nbsp;
24
+ [💡 Rationale](docs/rationale.md)
25
+
26
+ </div>
27
+
28
+ ---
29
+
30
+ Figma is the source of truth; this package turns its variables and text styles into DTCG token files, and those into CSS with [Style Dictionary](https://styledictionary.com/).
31
+
32
+ > [!TIP]
33
+ > **Building Rove UI?** [`DESIGN.md`](DESIGN.md) says which token to use for what, with every value. It ships in the package, so coding agents in Rove can read it from `node_modules/@swiftsolve/rove-tokens/DESIGN.md`.
34
+
35
+ ## 📦 Use
36
+
37
+ ```bash
38
+ npm install @swiftsolve/rove-tokens
39
+ ```
40
+
41
+ The package ships `tokens.css`, `text-styles.css` and `tokens/` built. You can also install straight from a version tag (`github:swiftsolve/rove-tokens#v1.0.0`); then npm builds them on install, which needs Node 22 (see `.nvmrc`).
42
+
43
+ ```css
44
+ @import '@swiftsolve/rove-tokens/tokens.css';
45
+ @import '@swiftsolve/rove-tokens/text-styles.css'; /* optional: a class per text style */
46
+ ```
47
+
48
+ Dark values sit on `:root`, Light values on `:root.theme-light`. CSS names follow the Figma names: `bg/base` is `--bg-base`, `spacing/12` is `--spacing-12`.
49
+
50
+ Each Figma text style becomes four tokens: `--type-<style>-size`, `-weight`, `-line-height` (a unitless ratio) and `-letter-spacing` (in `em`). `Number/Display` gives `--type-number-display-size` and so on. A size bound to a variable comes through as that variable (`var(--font-size-3xl)`).
51
+
52
+ `text-styles.css` applies a style whole: `.type-heading-large` sets the font family and all four, plus the text case (Overline is uppercase). The classes set no colour and sit in `@layer components`, so Tailwind utilities on the same element still win.
53
+
54
+ ### 🧩 DTCG
55
+
56
+ `tokens/` holds the same tokens in the [Design Tokens Format](https://www.designtokens.org/tr/2025.10/format/) (2025.10), for Style Dictionary, Tokens Studio and similar tools:
57
+
58
+ | File | What |
59
+ | --- | --- |
60
+ | `palette.tokens.json` | Every colour, once |
61
+ | `color.dark.tokens.json`, `color.light.tokens.json` | The Color tokens in each theme, pointing at the palette (`{neutral.850}`) |
62
+ | `spacing.tokens.json`, `typography.tokens.json`, `opacity.tokens.json`, `layout.tokens.json`, `motion.tokens.json` | The other Figma collections |
63
+ | `text-styles.tokens.json` | Each text style as a `typography` token |
64
+ | `code.tokens.json` | The code-only tokens (shadows, easing curves, the focus outline) |
65
+
66
+ A theme is every file plus one of the two color files. Paths follow the Figma names (`bg/base` is `bg.base`). Tokens that other tokens point at but that aren't CSS variables (the palette, the shadow colours) are marked `"$extensions": { "net.swiftsolve.rove-tokens": { "css": false } }`. CSS-only expressions (`--focus-inset`, a `calc()`) aren't in them.
67
+
68
+ ## ♿ Contrast
69
+
70
+ The colours meet [WCAG 2.2](https://www.w3.org/TR/WCAG22/) level AA in both themes, on the surfaces they sit on: text clears 4.5:1 ([1.4.3 Contrast (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html)), and icons, bars and dots 3:1 ([1.4.11 Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html)). AAA (7:1) isn't a target. [Rationale](docs/rationale.md) has the close calls.
71
+
72
+ ## 📖 Storybook
73
+
74
+ **Rove Tokens** is a Storybook of every token in both themes: colour, palette, type, spacing, radius, effects, motion and layout.
75
+
76
+ ```bash
77
+ npm run storybook
78
+ ```
79
+
80
+ It opens on <http://localhost:6007>; the Theme menu in the toolbar switches Dark and Light. The pages read the DTCG files in `tokens/` and are styled with `tokens.css`, so a new build shows up without editing them. `npm run build:storybook` writes a static copy to `storybook-static/`.
81
+
82
+ ## 🔄 Update the tokens
83
+
84
+ 1. Change the variables or text styles in Figma.
85
+ 2. Export them to `src/figma/variables.json` and `src/figma/text-styles.json`, either with the plugin in `figma-plugin/` (Figma desktop: Plugins → Development → Import plugin from manifest; then **Export**) or by asking Claude to export them through the Figma connection.
86
+ 3. Run `npm run build` (Node 22) and check `tokens.css`. It writes the DTCG files, then generates `tokens.css` from them with Style Dictionary and `text-styles.css` from the text styles, then rewrites the token reference at the end of `DESIGN.md`. The build stops if a variable's code syntax doesn't match its name, or a DTCG reference doesn't resolve.
87
+ 4. Commit the change.
88
+
89
+ ## 🚀 Release
90
+
91
+ 1. On the Figma cover (`COVER` page), set **Version** to the one you're about to release and **Updated** to today's date (`27 Oct 2026`). They're the one place a release can't be stamped from here: Figma's API can't edit canvas text on this plan, so do it by hand or ask Claude to through the Figma connection.
92
+ 2. Bump, commit and tag in one step, then push both:
93
+
94
+ ```bash
95
+ npm version minor
96
+ ```
97
+
98
+ ```bash
99
+ git push --follow-tags
100
+ ```
101
+
102
+ Use `patch` for fixes and `major` for breaking changes.
103
+ 3. The tag runs three workflows: **Build** checks the tokens, **Publish** puts the version on [npm](https://www.npmjs.com/package/@swiftsolve/rove-tokens), and **Presentation** exports the Figma file and republishes <https://swiftsolve.github.io/rove-tokens/>. The page's header shows the version from `package.json`. To republish the slideshow between releases (after Figma edits), run Presentation by hand from the Actions tab.
104
+ 4. Update Rove to the new version (`npm install @swiftsolve/rove-tokens@latest`).
105
+
106
+ ## 🗂️ What's where
107
+
108
+ | Path | What |
109
+ | --- | --- |
110
+ | `src/figma/variables.json` | Raw Figma export. Every variable with a Web code syntax becomes that CSS variable. |
111
+ | `src/figma/text-styles.json` | Raw export of the local text styles: font, size, weight, line height, letter spacing, text case (when set) and the variables bound to them. Each style becomes a `--type-*` group. |
112
+ | `figma-plugin/` | The Figma plugin that writes the two exports. |
113
+ | `src/code-tokens.json` | What Figma variables can't hold: font stacks for the font-family variables, shadows, easing curves and the CSS expressions built on variables (`--focus-outline`). `{figma/name}` pulls a Figma value in per theme. |
114
+ | `DESIGN.md` | How to build Rove UI with the tokens. The rules at the top are written by hand; the token reference below the marker line is generated by the build. |
115
+ | `scripts/tokens/build.mjs` | `npm run build`: runs the steps below and writes `tokens.css` and `text-styles.css` at the package root, where the import paths point. |
116
+ | `scripts/tokens/dtcg.mjs` | Figma export → the DTCG files in `tokens/`, checking that every reference resolves in both themes. |
117
+ | `scripts/tokens/css.mjs` | DTCG files → `tokens.css`, with Style Dictionary and a `rove/css` format: Dark on `:root`, what differs in Light on `:root.theme-light`, each text style as four `--type-*` variables (letter spacing included). |
118
+ | `scripts/tokens/text-styles.mjs` | DTCG text styles → `text-styles.css`: a `.type-<style>` class per style that reads its `--type-*` variables. |
119
+ | `scripts/tokens/design.mjs` | Figma export and `tokens.css` → the token reference in `DESIGN.md`: every token by name and Figma description, with values for the scales (spacing, radius, type, opacity) but not the colours, so nobody copies a hex. |
120
+ | `scripts/presentation/export.mjs` | `npm run present`: exports the Figma file's pages to `presentation/index.html`, a slideshow styled with the tokens. Needs `FIGMA_TOKEN` (a Figma personal access token, `file_content:read`) in `.env.local`. |
121
+ | `scripts/presentation/open.mjs` | `npm run present:open`: opens the exported presentation in your browser. |
122
+ | `.storybook/` | The Rove Tokens Storybook's config, and the Inter and Questrial files it serves. |
123
+ | `stories/` | Its pages, one file per sidebar group. `tokens.js` reads the DTCG files. |
124
+ | `scripts/presentation/publish.mjs` | `npm run present:publish`: pushes the exported presentation to the `gh-pages` branch, which GitHub Pages serves at <https://swiftsolve.github.io/rove-tokens/>. Each publish replaces the last. |
125
+ | `.github/workflows/presentation.yml` | Runs the export and publish on every `v*` tag, or by hand. Needs the `FIGMA_TOKEN` repository secret. |
126
+ | `docs/rationale.md` | Why the values are what they are (contrast targets, theme choices). |
127
+
128
+ Every colour lives once in the Palette collection (`neutral/850`, `blue/450`; higher numbers are darker; a see-through shade adds `-a` and its opacity, `neutral/850-a10`), and the Color tokens point at it. The Palette isn't in `tokens.css`: a token that points at a shade gets the shade's value there. Figma-only collections (Icon tone, Capability level) and variables without a code syntax aren't in `tokens.css` either.
package/package.json CHANGED
@@ -1,6 +1,50 @@
1
1
  {
2
2
  "name": "@swiftsolve/rove-tokens",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.1.0",
4
+ "description": "Rove's design tokens, exported from the Rove Design System in Figma, as CSS and DTCG.",
5
+ "type": "module",
6
+ "license": "UNLICENSED",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/swiftsolve/rove-tokens.git"
10
+ },
11
+ "exports": {
12
+ "./tokens.css": "./tokens.css",
13
+ "./text-styles.css": "./text-styles.css",
14
+ "./tokens/*": "./tokens/*",
15
+ "./package.json": "./package.json"
16
+ },
17
+ "files": [
18
+ "tokens.css",
19
+ "text-styles.css",
20
+ "tokens",
21
+ "src",
22
+ "DESIGN.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "node scripts/tokens/build.mjs",
26
+ "present": "npm run build && node scripts/presentation/export.mjs",
27
+ "present:open": "node scripts/presentation/open.mjs",
28
+ "present:publish": "node scripts/presentation/publish.mjs",
29
+ "prepare": "npm run build",
30
+ "storybook": "storybook dev -p 6007",
31
+ "build:storybook": "storybook build"
32
+ },
33
+ "publishConfig": {
34
+ "registry": "https://registry.npmjs.org",
35
+ "access": "public"
36
+ },
37
+ "engines": {
38
+ "node": ">=22"
39
+ },
40
+ "devDependencies": {
41
+ "@storybook/addon-docs": "^10.6.5",
42
+ "@storybook/react-vite": "^10.6.5",
43
+ "@vitejs/plugin-react": "^5.2.0",
44
+ "react": "^18.3.1",
45
+ "react-dom": "^18.3.1",
46
+ "storybook": "^10.6.5",
47
+ "style-dictionary": "^5.7.1",
48
+ "vite": "^7.3.7"
49
+ }
50
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "description": "What Figma variables can't hold. `figma` sets how a Figma variable is written in CSS; `tokens` adds code-only tokens. `{figma/name}` pulls a Figma variable's raw value in for each theme.",
3
+ "figma": {
4
+ "font-family/sans": "'{font-family/sans}', system-ui, -apple-system, 'Segoe UI', sans-serif",
5
+ "font-family/numeric": "'{font-family/numeric}', ui-sans-serif, system-ui, sans-serif"
6
+ },
7
+ "tokens": {
8
+ "--shadow-panel": "0 1px 2px {shadow-color/panel-1}, 0 4px 12px {shadow-color/panel-2}",
9
+ "--shadow-raised": "0 12px 32px {shadow-color/raised}",
10
+ "--shadow-popover": "0 2px 6px {shadow-color/popover-1}, 0 6px 16px {shadow-color/popover-2}",
11
+
12
+ "--focus-outline": "var(--focus-ring-width) solid var(--focus-ring)",
13
+ "--focus-inset": "calc(-1 * var(--focus-ring-width))",
14
+
15
+ "--ease-out": "cubic-bezier(0.16, 1, 0.3, 1)",
16
+ "--ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
17
+ "--ease-pulse": "cubic-bezier(0.42, 0, 0.58, 1)"
18
+ }
19
+ }
@@ -0,0 +1,289 @@
1
+ {
2
+ "file": {
3
+ "name": "Rove Design System",
4
+ "key": "NoICIoyhWNOya9tOnNfEhH"
5
+ },
6
+ "styles": [
7
+ {
8
+ "name": "Heading/Large",
9
+ "description": "Page titles, the wordmark. Code: .type-heading-large",
10
+ "fontFamily": "Inter",
11
+ "fontStyle": "Semi Bold",
12
+ "fontWeight": 600,
13
+ "fontSize": 17,
14
+ "lineHeight": {
15
+ "unit": "PERCENT",
16
+ "value": 125
17
+ },
18
+ "letterSpacing": {
19
+ "unit": "PERCENT",
20
+ "value": 0
21
+ },
22
+ "boundVariables": {
23
+ "fontFamily": "font-family/sans",
24
+ "fontSize": "font-size/2xl"
25
+ }
26
+ },
27
+ {
28
+ "name": "Heading/Medium",
29
+ "description": "Dialog titles. Code: .type-heading-medium",
30
+ "fontFamily": "Inter",
31
+ "fontStyle": "Semi Bold",
32
+ "fontWeight": 600,
33
+ "fontSize": 15,
34
+ "lineHeight": {
35
+ "unit": "PERCENT",
36
+ "value": 145
37
+ },
38
+ "letterSpacing": {
39
+ "unit": "PERCENT",
40
+ "value": 0
41
+ },
42
+ "boundVariables": {
43
+ "fontFamily": "font-family/sans",
44
+ "fontSize": "font-size/xl"
45
+ }
46
+ },
47
+ {
48
+ "name": "Heading/Small",
49
+ "description": "Card headings. Code: .type-heading-small",
50
+ "fontFamily": "Inter",
51
+ "fontStyle": "Semi Bold",
52
+ "fontWeight": 600,
53
+ "fontSize": 14,
54
+ "lineHeight": {
55
+ "unit": "PERCENT",
56
+ "value": 120
57
+ },
58
+ "letterSpacing": {
59
+ "unit": "PERCENT",
60
+ "value": 0
61
+ },
62
+ "boundVariables": {
63
+ "fontFamily": "font-family/sans",
64
+ "fontSize": "font-size/lg"
65
+ }
66
+ },
67
+ {
68
+ "name": "Body/Default",
69
+ "description": "Body text. Code: .type-body-default",
70
+ "fontFamily": "Inter",
71
+ "fontStyle": "Regular",
72
+ "fontWeight": 400,
73
+ "fontSize": 13,
74
+ "lineHeight": {
75
+ "unit": "PERCENT",
76
+ "value": 145
77
+ },
78
+ "letterSpacing": {
79
+ "unit": "PERCENT",
80
+ "value": 0
81
+ },
82
+ "boundVariables": {
83
+ "fontFamily": "font-family/sans",
84
+ "fontSize": "font-size/md"
85
+ }
86
+ },
87
+ {
88
+ "name": "Overline",
89
+ "description": "Uppercase labels above values. Code: .type-overline",
90
+ "fontFamily": "Inter",
91
+ "fontStyle": "Medium",
92
+ "fontWeight": 500,
93
+ "fontSize": 11,
94
+ "lineHeight": {
95
+ "unit": "PERCENT",
96
+ "value": 120
97
+ },
98
+ "letterSpacing": {
99
+ "unit": "PERCENT",
100
+ "value": 6
101
+ },
102
+ "textCase": "UPPER",
103
+ "boundVariables": {
104
+ "fontFamily": "font-family/sans",
105
+ "fontSize": "font-size/xs"
106
+ }
107
+ },
108
+ {
109
+ "name": "Caption",
110
+ "description": "Badges, captions, footer hints. Code: .type-caption",
111
+ "fontFamily": "Inter",
112
+ "fontStyle": "Regular",
113
+ "fontWeight": 400,
114
+ "fontSize": 11,
115
+ "lineHeight": {
116
+ "unit": "PERCENT",
117
+ "value": 145
118
+ },
119
+ "letterSpacing": {
120
+ "unit": "PERCENT",
121
+ "value": 0
122
+ },
123
+ "boundVariables": {
124
+ "fontFamily": "font-family/sans",
125
+ "fontSize": "font-size/xs"
126
+ }
127
+ },
128
+ {
129
+ "name": "Label/Large",
130
+ "description": "Solid button labels. Code: Button variant=solid",
131
+ "fontFamily": "Inter",
132
+ "fontStyle": "Semi Bold",
133
+ "fontWeight": 600,
134
+ "fontSize": 12,
135
+ "lineHeight": {
136
+ "unit": "PERCENT",
137
+ "value": 145
138
+ },
139
+ "letterSpacing": {
140
+ "unit": "PERCENT",
141
+ "value": 0
142
+ },
143
+ "boundVariables": {
144
+ "fontFamily": "font-family/sans",
145
+ "fontSize": "font-size/sm"
146
+ }
147
+ },
148
+ {
149
+ "name": "Number/Display",
150
+ "description": "Live speeds. Add a 0.43px outside stroke. Code: .type-number-display .metric-value, at weight 600: Questrial has one weight, so the browser emboldens it.",
151
+ "fontFamily": "Questrial",
152
+ "fontStyle": "Regular",
153
+ "fontWeight": 400,
154
+ "fontSize": 28,
155
+ "lineHeight": {
156
+ "unit": "PERCENT",
157
+ "value": 100
158
+ },
159
+ "letterSpacing": {
160
+ "unit": "PERCENT",
161
+ "value": 0
162
+ },
163
+ "boundVariables": {
164
+ "fontFamily": "font-family/numeric",
165
+ "fontSize": "font-size/3xl"
166
+ }
167
+ },
168
+ {
169
+ "name": "Number/Large",
170
+ "description": "Stat totals. Add a 0.26px outside stroke. Code: Readout size=compact",
171
+ "fontFamily": "Questrial",
172
+ "fontStyle": "Regular",
173
+ "fontWeight": 400,
174
+ "fontSize": 17,
175
+ "lineHeight": {
176
+ "unit": "PERCENT",
177
+ "value": 100
178
+ },
179
+ "letterSpacing": {
180
+ "unit": "PERCENT",
181
+ "value": 0
182
+ },
183
+ "boundVariables": {
184
+ "fontFamily": "font-family/numeric",
185
+ "fontSize": "font-size/2xl"
186
+ }
187
+ },
188
+ {
189
+ "name": "Number/Default",
190
+ "description": "Data row values. Code: .type-number-default",
191
+ "fontFamily": "Questrial",
192
+ "fontStyle": "Regular",
193
+ "fontWeight": 400,
194
+ "fontSize": 13,
195
+ "lineHeight": {
196
+ "unit": "PERCENT",
197
+ "value": 135
198
+ },
199
+ "letterSpacing": {
200
+ "unit": "PERCENT",
201
+ "value": 0
202
+ },
203
+ "boundVariables": {
204
+ "fontFamily": "font-family/numeric",
205
+ "fontSize": "font-size/md"
206
+ }
207
+ },
208
+ {
209
+ "name": "Number/Small",
210
+ "description": "Chart axes and scale. Code: .type-number-small",
211
+ "fontFamily": "Questrial",
212
+ "fontStyle": "Regular",
213
+ "fontWeight": 400,
214
+ "fontSize": 10,
215
+ "lineHeight": {
216
+ "unit": "PERCENT",
217
+ "value": 100
218
+ },
219
+ "letterSpacing": {
220
+ "unit": "PERCENT",
221
+ "value": 0
222
+ },
223
+ "boundVariables": {
224
+ "fontFamily": "font-family/numeric",
225
+ "fontSize": "font-size/2xs"
226
+ }
227
+ },
228
+ {
229
+ "name": "Label/Default",
230
+ "description": "Bold small labels on tinted chips. Code: .type-label-default",
231
+ "fontFamily": "Inter",
232
+ "fontStyle": "Semi Bold",
233
+ "fontWeight": 600,
234
+ "fontSize": 11,
235
+ "lineHeight": {
236
+ "unit": "PERCENT",
237
+ "value": 145
238
+ },
239
+ "letterSpacing": {
240
+ "unit": "PERCENT",
241
+ "value": 0
242
+ },
243
+ "boundVariables": {
244
+ "fontFamily": "font-family/sans",
245
+ "fontSize": "font-size/xs"
246
+ }
247
+ },
248
+ {
249
+ "name": "Label/Small",
250
+ "description": "Soft buttons, title bar status. Code: .type-label-small",
251
+ "fontFamily": "Inter",
252
+ "fontStyle": "Medium",
253
+ "fontWeight": 500,
254
+ "fontSize": 11,
255
+ "lineHeight": {
256
+ "unit": "PERCENT",
257
+ "value": 145
258
+ },
259
+ "letterSpacing": {
260
+ "unit": "PERCENT",
261
+ "value": 0
262
+ },
263
+ "boundVariables": {
264
+ "fontFamily": "font-family/sans",
265
+ "fontSize": "font-size/xs"
266
+ }
267
+ },
268
+ {
269
+ "name": "Body/Small",
270
+ "description": "Helper text, hints and units. Code: .type-body-small",
271
+ "fontFamily": "Inter",
272
+ "fontStyle": "Regular",
273
+ "fontWeight": 400,
274
+ "fontSize": 12,
275
+ "lineHeight": {
276
+ "unit": "PERCENT",
277
+ "value": 145
278
+ },
279
+ "letterSpacing": {
280
+ "unit": "PERCENT",
281
+ "value": 0
282
+ },
283
+ "boundVariables": {
284
+ "fontFamily": "font-family/sans",
285
+ "fontSize": "font-size/sm"
286
+ }
287
+ }
288
+ ]
289
+ }