@daydreamui/tokens 0.0.0-stage → 0.4.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/README.md CHANGED
@@ -1,3 +1,182 @@
1
- # Temporary Holding Version
1
+ # Tokens
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
+ A local Daydream plugin for exploring, extracting, and applying a visual theme.
4
+ Enable **Tokens** in Daydream's Plugins page (⌥⌘P). No account or external service is used.
5
+
6
+ From this repository, install the plugin with:
7
+
8
+ ```sh
9
+ pnpm install
10
+ pnpm ship plugins/daydream.tokens --enable
11
+ ```
12
+
13
+ The build produces `plugins/daydream.tokens/dist/index.js`. The install command
14
+ copies the plugin into the user’s Daydream plugins folder and records its trust.
15
+
16
+ 1. Choose one of ten brand-inspired presets. The carousel shows three at a time.
17
+ Or select viewports and choose **Extract from selection**; selecting an element
18
+ extracts its containing page. Or select a frame in Figma desktop and choose
19
+ **From Figma**, shown while Figma's Dev Mode MCP server answers.
20
+ 2. Use **Refine tokens** to edit values. **Reset edits** restores the starting point.
21
+ Both operations affect only the preview.
22
+ 3. **Apply to selected viewports** writes the theme and adopts existing styles on
23
+ all selected pages. One Undo restores the entire action. Repeated viewports and
24
+ shared stylesheets are written once.
25
+ 4. **Create specimen page** creates a responsive HTML page for exploring the theme.
26
+
27
+ The preview is a temporary working draft, retained while the panel is minimized
28
+ and reset on reload or project change. The applied theme is ordinary CSS in the
29
+ project's files. Undo changes the pages; it does not replace the working draft.
30
+
31
+ ## Applying a theme
32
+
33
+ Apply first reads each selected page's rendered styles and plans its source edits,
34
+ then writes through the public plugin API in one transaction. A refused write
35
+ cancels the transaction. It maps matching global color variables to semantic roles and converts supported
36
+ literal declarations to references to the new theme. Generated variables use a
37
+ `--tokens-` prefix, keeping the project’s existing token names and formats intact.
38
+ Component and conditional variable definitions remain authored. Inline styles are
39
+ edited through the same API.
40
+
41
+ Mapped styles include page, surface, action, text and border colors, font families,
42
+ heading weight/tracking (including the weight in a heading’s `font` shorthand),
43
+ corner radii, padding and gaps. Font conversion follows
44
+ the observed body and heading families, preserving other families such as code and
45
+ icon fonts. Spacing and radius values
46
+ in px/rem retain their proportions to the observed base value; zero values stay
47
+ zero. CSSOM parses individual values and supported shorthands. The plugin retains
48
+ selectors, media queries, `!important`, comments, content and layout dimensions.
49
+
50
+ A dedicated `:root:where(html)` rule holds the theme. Definitions are written into
51
+ every stylesheet whose declarations adopt references, so unselected consumers of
52
+ shared CSS receive the definitions too. Low-specificity heading, action and input
53
+ rules cover otherwise unstyled elements in an unconditional editable stylesheet.
54
+ Pages with authored cascade layers receive token values and source conversions,
55
+ but no generic element defaults: an unlayered fallback would override those
56
+ layers. Reapplying clears earlier generated defaults on these pages. Shared sheets
57
+ also omit defaults when another page on the canvas uses layers. This conservative
58
+ behavior stays within the existing plugin API; a page’s unstyled elements keep
59
+ their browser defaults when layers are present.
60
+ A page with only media-restricted sheets refuses Apply before any writes and asks
61
+ for an unconditional stylesheet. Applying again updates these rules; a sparse
62
+ extracted theme preserves omitted tokens and defaults still used by earlier edits. A page with no stylesheet gains its normal Daydream stylesheet/link;
63
+ Undo removes that creation. Shared stylesheets affect every page that links them,
64
+ including unselected pages.
65
+
66
+ Role inference is heuristic. Unmatched colors, gradients, background images,
67
+ shadows, SVG paints, complex calculations and unsupported units stay as authored.
68
+ Existing variable usages stay intact; editable definitions may be updated or mapped.
69
+ Interleaved comments inside a value are preserved by leaving that value unchanged.
70
+ A necessary edit to a read-only or unsupported rule refuses the action before any
71
+ writes. Conflicting mappings of a shared rule cancel the whole transaction. Adoption is
72
+ bounded to 2,000 elements per page and operates on page viewports, including independent variants.
73
+
74
+ ## Extracting a theme
75
+
76
+ Extraction uses computed styles from mounted pages. It proposes colors, typography,
77
+ borders, radii, padding/gaps and shadows. Hidden subtrees are excluded. Duplicate
78
+ viewports do not inflate observations; responsive differences remain alternatives.
79
+ Results are bounded to 2,000 elements per viewport and five values per category.
80
+
81
+ Values include browser defaults and are resolved at the selected widths. Extraction
82
+ does not recover aliases, original units, hover states, pseudo-elements, iframe
83
+ content or fonts/assets, and does not write to the project. Missing preview roles
84
+ use specimen fallbacks.
85
+
86
+ ## From Figma
87
+
88
+ **From Figma** reads the variables of what is selected in Figma desktop and loads
89
+ them into the preview, named after the selected frame as Figma's listing of the
90
+ selection names it (else "From Figma"). With several frames selected — up to 12;
91
+ past that the error line names the cap — the variables of each are read by id,
92
+ all at once under one bound of 40 s, and merged by name — the first frame's
93
+ value of a name wins — under the origin "3 frames from Figma"; a frame Figma
94
+ refuses, or that has not answered by the bound, is left out and counted among
95
+ the tokens left out, and only every one left out is an error. A layer inside a
96
+ component instance, which Figma lists with an id of its own shape and refuses
97
+ to read by it, is left out before anything is asked and counted too; with
98
+ nothing else selected the error line says to select its frame. Nothing
99
+ selected, Figma not there, and Figma too slow to answer are each one sentence.
100
+ It needs Figma desktop open with the Dev Mode MCP server enabled in its
101
+ preferences (the server runs on this machine at `http://127.0.0.1:3845`), and a
102
+ selected frame. The button is
103
+ there only while that server answers: the panel asks when it opens, when a
104
+ project opens and when this window gets focus back, so switching to Figma to
105
+ select and returning is enough. Nothing is sent anywhere, and nothing is written
106
+ to the project until Apply. The plugin's host part holds the connection
107
+ (`bridge.ts`, through `@daydream/figma-devmode`); without a Daydream host, or
108
+ with the host part off, the button is simply absent.
109
+
110
+ A variable's path becomes one custom property: lowercase, every run of
111
+ characters outside `a-z0-9` one dash (`color/brand/500` → `--color-brand-500`,
112
+ `Spacing/MD` → `--spacing-md`), a collision numbered `-2`, `-3`. Colors and
113
+ values with a unit stay as written. A bare number becomes `px`, unless the name
114
+ says it is unitless (`opacity`, `weight`, `line-height`, `ratio`, `z`); with
115
+ its `px` it is a length, so a weight never takes it. A family name or a stack
116
+ under a font-like name (`font`, `family`, `type`) is kept as written (`Arial`,
117
+ `Inter, sans-serif`); any other string is quoted. A value written as a reference
118
+ to another variable (`{color/brand/500}`; a `$` is a literal) becomes
119
+ `var(--color-brand-500)` when that variable is in the set — Figma's own server
120
+ answers an alias resolved to its value, so this serves a pasted or hand-written
121
+ text; a live import holds values alone, and a string whose text happens to be
122
+ another variable's name is that text, quoted. Booleans, nested objects,
123
+ references to variables outside the set, references that loop (two variables
124
+ aliasing each other, one aliasing itself) and values the browser cannot parse
125
+ are left out and counted in the status line.
126
+
127
+ The shared roles are suggested from the end of each path, each role once, as a
128
+ reference to the raw token (`--primary: var(--color-brand-500)`), so Apply
129
+ writes `--tokens-primary: var(--tokens-color-brand-500)`: `background` from
130
+ names ending in `background`, `bg`, `canvas`, `page` or `surface-0`; `foreground`
131
+ from `foreground`, `fg`, `text`, `text-primary`, `text-default`, `on-background`
132
+ or `ink`; `card` from `card`, `surface`, `elevated` or `panel`; `muted` from
133
+ `muted`, `subtle` or `secondary-surface`; `muted-foreground` from
134
+ `muted-foreground`, `text-secondary`, `secondary`, `hint` or `placeholder`;
135
+ `primary` from `primary`, `brand`, `accent`, `action` or `cta`;
136
+ `primary-foreground` from `primary-foreground`, `on-primary`, `on-brand` or
137
+ `on-accent`; `border` from `border`, `stroke`, `outline` or `divider`; `radius`
138
+ from `radius`, `corner` or `rounded`; `spacing` from `spacing`, `space`, `gap` or
139
+ `unit`; `font-sans` from `font-sans`, `font-family`, `sans`, `body-font` or
140
+ `font-body`; `font-heading` from `font-heading`, `heading-font` or `display`;
141
+ `heading-weight` from `heading-weight` or `weight-bold`; `heading-tracking` from
142
+ `heading-tracking`, `tracking` or `letter-spacing`. A trailing scale step
143
+ (`500`, `md`, `default`) is set aside, and `500`, `default`, `base`, `main` or
144
+ `md` is preferred when a scale has several steps; a variable named exactly as a
145
+ role is that role when its value is of the role's kind, and is renamed with a
146
+ number (`--primary-2`) when it is not, so a length never stands as a colour.
147
+ A role no name answers is left out, as a sparse extraction is. The role tokens come first in Refine, then the raw tokens they reference,
148
+ then the rest in Figma's order, up to the 100 tokens a theme may hold. An alias
149
+ is kept with what it points at, link by link, or left out whole, so nothing a
150
+ theme holds points at nothing; what the cap leaves out is counted too.
151
+
152
+ ## Presets
153
+
154
+ Presets are original interpretations, not official brand themes or extracted design
155
+ systems. They use system fonts and contain no brand assets. Their references are
156
+ [Apple](https://www.apple.com/), [BMW](https://www.bmw.com/),
157
+ [Spotify](https://open.spotify.com/), [Airbnb](https://www.airbnb.com/),
158
+ [Nike](https://www.nike.com/), [Stripe](https://stripe.com/),
159
+ [Linear](https://linear.app/), [Notion](https://www.notion.com/),
160
+ [IKEA](https://www.ikea.com/), and [Ferrari](https://www.ferrari.com/).
161
+ This is an independent implementation with no Graphical API or archive integration.
162
+
163
+ The shared vocabulary is `--background`, `--foreground`, `--card`, `--muted`,
164
+ `--muted-foreground`, `--primary`, `--primary-foreground`, `--border`, `--radius`,
165
+ `--font-sans`, `--spacing`, `--font-heading`, `--heading-weight`, and
166
+ `--heading-tracking`. These are preview names; Apply writes `--tokens-background`,
167
+ `--tokens-primary`, etc. References between supplied tokens follow those names.
168
+ Extracted alternatives are retained as additional tokens.
169
+
170
+ ## Validation
171
+
172
+ `pnpm test:kernel <daydream-checkout> plugins/daydream.tokens` covers real canvas
173
+ rendering, extraction, carousel navigation, source adoption, shared files, inline
174
+ styles, responsive rules, repeated application, refusal rollback, undo and specimen
175
+ creation, and the From Figma gesture with the host part's answers supplied in
176
+ memory. The conversion and the host part are unit tests over hand-written
177
+ variables and an injected client: no test contacts Figma. The plugin requires a
178
+ Daydream build reporting API 3.0; see the repository’s kernel pin and release gate
179
+ before shipping. Its runtime dependency is the workspace package
180
+ `@daydream/figma-devmode`: its host entry is what the host part loads, and its
181
+ browser entry (`@daydream/figma-devmode/browser`, the reachability probe) is
182
+ what the panel bundles.