@karmo-co/drift-kit-reference 0.0.0-stage → 23.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/LICENSE +7 -0
- package/README.md +24 -2
- package/bin/drift-kit-ref.js +169 -0
- package/manifest/components/accordion.md +47 -0
- package/manifest/components/action-bar.md +51 -0
- package/manifest/components/alert.md +53 -0
- package/manifest/components/app-shell.md +43 -0
- package/manifest/components/avatar.md +42 -0
- package/manifest/components/body.md +48 -0
- package/manifest/components/box.md +58 -0
- package/manifest/components/breadcrumb.md +59 -0
- package/manifest/components/button.md +46 -0
- package/manifest/components/calendar.md +69 -0
- package/manifest/components/card.md +71 -0
- package/manifest/components/checkbox.md +43 -0
- package/manifest/components/choice-card.md +61 -0
- package/manifest/components/code-input.md +56 -0
- package/manifest/components/date-picker.md +66 -0
- package/manifest/components/day-of-month.md +54 -0
- package/manifest/components/detail-list.md +37 -0
- package/manifest/components/divider.md +33 -0
- package/manifest/components/dropdown.md +52 -0
- package/manifest/components/dropzone.md +56 -0
- package/manifest/components/eyebrow.md +45 -0
- package/manifest/components/feedback-badge.md +35 -0
- package/manifest/components/glider.md +34 -0
- package/manifest/components/heading.md +47 -0
- package/manifest/components/hero.md +46 -0
- package/manifest/components/icon-button.md +41 -0
- package/manifest/components/icon-tile.md +44 -0
- package/manifest/components/icon.md +30 -0
- package/manifest/components/input.md +63 -0
- package/manifest/components/link.md +42 -0
- package/manifest/components/loading-spinner.md +42 -0
- package/manifest/components/logo.md +38 -0
- package/manifest/components/modal.md +53 -0
- package/manifest/components/pagination.md +54 -0
- package/manifest/components/payment-form.md +29 -0
- package/manifest/components/price-summary.md +30 -0
- package/manifest/components/radio.md +42 -0
- package/manifest/components/section-heading.md +41 -0
- package/manifest/components/select.md +99 -0
- package/manifest/components/shield.md +34 -0
- package/manifest/components/sidebar.md +73 -0
- package/manifest/components/stepper.md +53 -0
- package/manifest/components/switch.md +45 -0
- package/manifest/components/table.md +77 -0
- package/manifest/components/tabs.md +43 -0
- package/manifest/components/tag.md +43 -0
- package/manifest/components/textarea.md +52 -0
- package/manifest/components/toast.md +52 -0
- package/manifest/components/tooltip.md +42 -0
- package/manifest/components/top-bar.md +60 -0
- package/manifest/components/vehicle.md +43 -0
- package/manifest/index.json +402 -0
- package/manifest/migrations/1.0.0.md +50 -0
- package/manifest/migrations/10.0.0.md +154 -0
- package/manifest/migrations/11.0.0.md +24 -0
- package/manifest/migrations/12.0.0.md +38 -0
- package/manifest/migrations/13.0.0.md +50 -0
- package/manifest/migrations/14.0.0.md +148 -0
- package/manifest/migrations/15.0.0.md +140 -0
- package/manifest/migrations/16.0.0.md +196 -0
- package/manifest/migrations/17.0.0.md +19 -0
- package/manifest/migrations/18.0.0.md +23 -0
- package/manifest/migrations/19.0.0.md +15 -0
- package/manifest/migrations/2.0.0.md +18 -0
- package/manifest/migrations/20.0.0.md +43 -0
- package/manifest/migrations/21.0.0.md +97 -0
- package/manifest/migrations/22.0.0.md +17 -0
- package/manifest/migrations/23.0.0.md +86 -0
- package/manifest/migrations/3.0.0.md +34 -0
- package/manifest/migrations/4.0.0.md +147 -0
- package/manifest/migrations/5.0.0.md +73 -0
- package/manifest/migrations/6.0.0.md +67 -0
- package/manifest/migrations/7.0.0.md +71 -0
- package/manifest/migrations/8.0.0.md +16 -0
- package/manifest/migrations/9.0.0.md +107 -0
- package/manifest/rules.md +37 -0
- package/manifest/setup.md +28 -0
- package/manifest/tokens/border-width.md +12 -0
- package/manifest/tokens/border.md +147 -0
- package/manifest/tokens/font.md +90 -0
- package/manifest/tokens/icon.md +84 -0
- package/manifest/tokens/interactive.md +37 -0
- package/manifest/tokens/motion.md +69 -0
- package/manifest/tokens/radius.md +20 -0
- package/manifest/tokens/shadow.md +28 -0
- package/manifest/tokens/spacing.md +35 -0
- package/manifest/tokens/surface.md +138 -0
- package/manifest/tokens/text.md +92 -0
- package/package.json +20 -4
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"version": "23.4.0",
|
|
4
|
+
"built": "2026-10-22",
|
|
5
|
+
"components": [
|
|
6
|
+
{
|
|
7
|
+
"id": "accordion",
|
|
8
|
+
"name": "Accordion",
|
|
9
|
+
"purpose": "A list of things you can open: FAQs, settings, details on demand. Built on <details>, so it works before the script does, with motion that turns round mid-way."
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "action-bar",
|
|
13
|
+
"name": "Action bar",
|
|
14
|
+
"purpose": "A flow's controls along the bottom: Back, Next, what the step costs and how far along it is."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "alert",
|
|
18
|
+
"name": "Alert",
|
|
19
|
+
"purpose": "An inline, persistent message in the page: a status colour, an optional icon, title, body, actions and a dismiss button."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "app-shell",
|
|
23
|
+
"name": "App shell",
|
|
24
|
+
"purpose": "The layout that places a Sidebar, a Top bar, the page and an Action bar, in the viewport or in a box."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "avatar",
|
|
28
|
+
"name": "Avatar",
|
|
29
|
+
"purpose": "A person, as their photo or their initials: the photo fades in once it has loaded, and the initials stay if it never does."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "body",
|
|
33
|
+
"name": "Body",
|
|
34
|
+
"purpose": "The body-copy primitive: one element, eleven colours, two emphasis rungs, four sizes, eight weights, and, unlike the component- library original, aware of the surface it sits on."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "box",
|
|
38
|
+
"name": "Box",
|
|
39
|
+
"purpose": "A grouped surface: a panel that separates what is in it from what is around it, optionally laid out as a responsive grid of facts."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "breadcrumb",
|
|
43
|
+
"name": "Breadcrumb",
|
|
44
|
+
"purpose": "Where this page sits, and the way back up: the pages above it as quiet pills, its own name last."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "button",
|
|
48
|
+
"name": "Button",
|
|
49
|
+
"purpose": "Two families: four semantic variants (default / accent / outline / subtle) across primary and error statuses, and a four-rung neutral emphasis ladder: ghost (no chrome until you touch it), subtle (a filled tint), plain (flat on its surface with an edge), raised (that edge lifted above it), plus inverse (maximum contrast, opposite-theme fill)."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "calendar",
|
|
53
|
+
"name": "Calendar",
|
|
54
|
+
"purpose": "A month grid for choosing a date or a range: the engine behind Date picker, also usable on its own."
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "card",
|
|
58
|
+
"name": "Card",
|
|
59
|
+
"purpose": "A surface that goes somewhere: media over or beside a title, a subtitle and a row of meta, the whole card the target."
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "checkbox",
|
|
63
|
+
"name": "Checkbox",
|
|
64
|
+
"purpose": "Any number of these, or none. A native input, a painted box, three sizes, and a mixed state for a parent row."
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "choice-card",
|
|
68
|
+
"name": "Choice card",
|
|
69
|
+
"purpose": "A radio or checkbox drawn as a card, for a choice that needs room to explain itself: a payment frequency and its price, a saved card."
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"id": "code-input",
|
|
73
|
+
"name": "Code input",
|
|
74
|
+
"purpose": "A verification code, a PIN, a voucher. N characters, one per box, with one real input underneath them."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "date-picker",
|
|
78
|
+
"name": "Date picker",
|
|
79
|
+
"purpose": "A date field you can type into or pick from a calendar: one date (a date of birth among them) or a start and an end."
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "day-of-month",
|
|
83
|
+
"name": "Day of month",
|
|
84
|
+
"purpose": "A day of the month, 1 to 31, chosen from a grid: the day a bill is paid."
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "detail-list",
|
|
88
|
+
"name": "Detail list",
|
|
89
|
+
"purpose": "Rows of a glyph, a title and a line, with a value at the end, on a hairline between rows."
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "divider",
|
|
93
|
+
"name": "Divider",
|
|
94
|
+
"purpose": "A rule between things. An <hr> that follows the border palette, mostly steps with the surface level, and turns vertical without a wrapper."
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"id": "dropdown",
|
|
98
|
+
"name": "Dropdown",
|
|
99
|
+
"purpose": "A menu of commands hanging off a trigger. Select's surface, a menu's semantics: real focus, no value."
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "dropzone",
|
|
103
|
+
"name": "Dropzone",
|
|
104
|
+
"purpose": "A place to drop or browse for files: one file or a list, with the type, size and count checked on the way in and a plain message when something is refused."
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"id": "eyebrow",
|
|
108
|
+
"name": "Eyebrow",
|
|
109
|
+
"purpose": "Uppercase labels, the component-library's Overline, renamed. Three fixed sizes (12 / 11 / 10 px) with tracking that widens as the size shrinks, bold by default, the Body colour grammar."
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "feedback-badge",
|
|
113
|
+
"name": "Feedback badge",
|
|
114
|
+
"purpose": "A status's circle inside its own soft ring, with a white glyph. The big mark at the top of a success screen or an empty state."
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "glider",
|
|
118
|
+
"name": "Glider",
|
|
119
|
+
"purpose": "One value from a few options side by side, or several: a raised frame with a primary pill that slides to the choice."
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"id": "heading",
|
|
123
|
+
"name": "Heading",
|
|
124
|
+
"purpose": "The outline tier: Inter, six responsive sizes, nine weights, the Body colour grammar."
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "hero",
|
|
128
|
+
"name": "Hero",
|
|
129
|
+
"purpose": "The display tier: Syne on the heading ramp, five responsive sizes, four weights, the Body colour grammar."
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "icon",
|
|
133
|
+
"name": "Icon",
|
|
134
|
+
"purpose": "The icon primitive, built to behave like text: the same colour grammar, sizes named and fixed like the body rungs, weight as stroke width, and 1em when unsized."
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "icon-button",
|
|
138
|
+
"name": "Icon button",
|
|
139
|
+
"purpose": "A button whose whole label is its icon. Same rungs as Button, so the two line up in a row, plus one rung below Button's smallest because compact chrome is where most icon buttons actually live."
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"id": "icon-tile",
|
|
143
|
+
"name": "Icon tile",
|
|
144
|
+
"purpose": "A glyph on a small coloured square, subtle or solid, with one corner at every size."
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"id": "input",
|
|
148
|
+
"name": "Text input",
|
|
149
|
+
"purpose": "Label, field and caption, with leading and trailing slots, three sizes, and error, disabled and read-only states."
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"id": "link",
|
|
153
|
+
"name": "Link",
|
|
154
|
+
"purpose": "A way to go somewhere. Inline, it is the sentence it sits in; standalone, it has its own size and room for an icon."
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "loading-spinner",
|
|
158
|
+
"name": "Loading spinner",
|
|
159
|
+
"purpose": "The brand symbol inside a sweeping arc. It spins for at least half a second, so a fast load does not flash, and tells you when it has gone."
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"id": "logo",
|
|
163
|
+
"name": "Logo",
|
|
164
|
+
"purpose": "The brand mark, as a symbol or with its wordmark, in three colourways."
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"id": "modal",
|
|
168
|
+
"name": "Modal",
|
|
169
|
+
"purpose": "A dialog on a backdrop, and a bottom sheet on a phone. Focus trap, Escape, scroll lock and focus return included."
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"id": "pagination",
|
|
173
|
+
"name": "Pagination",
|
|
174
|
+
"purpose": "Where a long list is in pages, and the way to the others: a page list between two arrows, with an optional count of what is showing and a rows select."
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"id": "payment-form",
|
|
178
|
+
"name": "Payment form",
|
|
179
|
+
"purpose": "Stripe's Payment Element on the kit's tokens: its fields, labels, tabs and errors follow the theme, the surface and the tone around them, like any kit field."
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"id": "price-summary",
|
|
183
|
+
"name": "Price summary",
|
|
184
|
+
"purpose": "Labelled amounts on hairlines, then their total with a note under it. Credits in the brand tone."
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"id": "radio",
|
|
188
|
+
"name": "Radio",
|
|
189
|
+
"purpose": "One of these, and only one. Checkbox's twin, with a circular box, a drawn dot and a group that is not optional."
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "section-heading",
|
|
193
|
+
"name": "Section heading",
|
|
194
|
+
"purpose": "A glyph beside a title and a line under it, heading a list or a card from outside."
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"id": "select",
|
|
198
|
+
"name": "Select",
|
|
199
|
+
"purpose": "One value from a list. A field-shaped trigger, a floating listbox, and the keyboard that drives both."
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "shield",
|
|
203
|
+
"name": "Shield",
|
|
204
|
+
"purpose": "A shield that scales in, shakes when a code is wrong and pulses a tick in when it is right."
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"id": "sidebar",
|
|
208
|
+
"name": "Sidebar",
|
|
209
|
+
"purpose": "An app's main navigation. A rail on a desktop that collapses to its glyphs, and on a phone a bottom tab bar or a drawer, from one set of markup."
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "stepper",
|
|
213
|
+
"name": "Stepper",
|
|
214
|
+
"purpose": "Where someone is in a process with a known number of steps, and what is left."
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "switch",
|
|
218
|
+
"name": "Switch",
|
|
219
|
+
"purpose": "An on/off setting that takes effect immediately. Checkbox's label, description, sizes and states on a track and a thumb, with a settings-row treatment of its own."
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"id": "table",
|
|
223
|
+
"name": "Table",
|
|
224
|
+
"purpose": "Rows and columns, as a real <table>. Sorting, selection, sticky edges and the two rows that stand in for rows."
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"id": "tabs",
|
|
228
|
+
"name": "Tabs",
|
|
229
|
+
"purpose": "A strip of tabs that switch between panels of one page, on a hairline with a bar that slides to the selected tab."
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"id": "tag",
|
|
233
|
+
"name": "Tag",
|
|
234
|
+
"purpose": "A label, a category, a status. Six statuses, three variants, and a dot for the column where the word is already there."
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"id": "textarea",
|
|
238
|
+
"name": "Text area",
|
|
239
|
+
"purpose": "Several lines of text: notes, messages, comments. Input's field, sized in rows, with auto-grow, a character counter and a submit shortcut."
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"id": "toast",
|
|
243
|
+
"name": "Toast",
|
|
244
|
+
"purpose": "A message that arrives, says one thing and goes: a card with a badge, a title and a description, or a compact one-liner."
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"id": "tooltip",
|
|
248
|
+
"name": "Tooltip",
|
|
249
|
+
"purpose": "A floating label for an element that needs one word more than it can show."
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"id": "top-bar",
|
|
253
|
+
"name": "Top bar",
|
|
254
|
+
"purpose": "The page's banner: the brand, an optional row of links, and what the page puts at the end, from a help line to the account."
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"id": "vehicle",
|
|
258
|
+
"name": "Vehicle",
|
|
259
|
+
"purpose": "A photo of a vehicle, from the car-line photo catalogue trimmed to the car: on its own at any size, or stood on a panel the car overflows. 304 models ship with the kit."
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
"tokenGroups": [
|
|
263
|
+
{
|
|
264
|
+
"id": "surface",
|
|
265
|
+
"title": "Surfaces"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"id": "border",
|
|
269
|
+
"title": "Borders and edges"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"id": "text",
|
|
273
|
+
"title": "Text colours"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"id": "icon",
|
|
277
|
+
"title": "Icon colours"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"id": "interactive",
|
|
281
|
+
"title": "Interaction"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"id": "font",
|
|
285
|
+
"title": "Type"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"id": "motion",
|
|
289
|
+
"title": "Motion"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"id": "spacing",
|
|
293
|
+
"title": "Spacing"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"id": "radius",
|
|
297
|
+
"title": "Radius"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"id": "border-width",
|
|
301
|
+
"title": "Border width"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"id": "shadow",
|
|
305
|
+
"title": "Shadows"
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
"migrations": [
|
|
309
|
+
{
|
|
310
|
+
"major": "23.0.0",
|
|
311
|
+
"title": "23.0.0 - 2026-10-17"
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"major": "22.0.0",
|
|
315
|
+
"title": "22.0.0 - 2026-10-15"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"major": "21.0.0",
|
|
319
|
+
"title": "21.0.0 - 2026-10-14"
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"major": "20.0.0",
|
|
323
|
+
"title": "20.0.0 - 2026-10-12"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"major": "19.0.0",
|
|
327
|
+
"title": "19.0.0 - 2026-10-06"
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"major": "18.0.0",
|
|
331
|
+
"title": "18.0.0 - 2026-10-01"
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"major": "17.0.0",
|
|
335
|
+
"title": "17.0.0 - 2026-09-24"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"major": "16.0.0",
|
|
339
|
+
"title": "16.0.0 - 2026-09-22"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"major": "15.0.0",
|
|
343
|
+
"title": "15.0.0 - 2026-09-22"
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"major": "14.0.0",
|
|
347
|
+
"title": "14.0.0 - 2026-09-22"
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"major": "13.0.0",
|
|
351
|
+
"title": "13.0.0 - 2026-09-19"
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"major": "12.0.0",
|
|
355
|
+
"title": "12.0.0 - 2026-09-18"
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"major": "11.0.0",
|
|
359
|
+
"title": "11.0.0 - 2026-09-18"
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"major": "10.0.0",
|
|
363
|
+
"title": "10.0.0 - 2026-09-17"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"major": "9.0.0",
|
|
367
|
+
"title": "9.0.0 - 2026-09-14"
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"major": "8.0.0",
|
|
371
|
+
"title": "8.0.0 - 2026-09-12"
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"major": "7.0.0",
|
|
375
|
+
"title": "7.0.0 — 2026-09-12"
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"major": "6.0.0",
|
|
379
|
+
"title": "6.0.0 — 2026-09-11"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"major": "5.0.0",
|
|
383
|
+
"title": "5.0.0 — 2026-09-10"
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"major": "4.0.0",
|
|
387
|
+
"title": "4.0.0 — 2026-09-10"
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"major": "3.0.0",
|
|
391
|
+
"title": "3.0.0 — 2026-09-09"
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"major": "2.0.0",
|
|
395
|
+
"title": "2.0.0 — 2026-09-09"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"major": "1.0.0",
|
|
399
|
+
"title": "1.0.0 — 2026-08-18"
|
|
400
|
+
}
|
|
401
|
+
]
|
|
402
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
## 1.0.0 — 2026-08-18
|
|
2
|
+
|
|
3
|
+
The source is reorganised by token collection and by component, and the package
|
|
4
|
+
now has exactly one CSS entry point.
|
|
5
|
+
|
|
6
|
+
### Breaking
|
|
7
|
+
|
|
8
|
+
- Per-layer exports removed. `./core.css`, `./tokens.css`,
|
|
9
|
+
`./components-tokens.css` and `./components.css` are gone; everything is
|
|
10
|
+
`./drift-kit.css`. A layered interface let a consumer assemble an incoherent
|
|
11
|
+
subset — component CSS without its tokens — which is a silent-failure class,
|
|
12
|
+
not a feature.
|
|
13
|
+
- Core Drift is no longer a vendored CDN snapshot. The upstream token layers are
|
|
14
|
+
generated from component-library's own SCSS partials (`refresh:tokens`
|
|
15
|
+
replaces `refresh:core`), which drops 193 declarations that the CDN snapshot
|
|
16
|
+
carried and the SCSS source does not: 95 legacy `--ui-*` palette
|
|
17
|
+
declarations, 68 declared solely inside component-library's hashed React
|
|
18
|
+
CSS-module selectors, and 30 more in hashed `@keyframes`/`@property`/
|
|
19
|
+
`@supports` blocks and two `.pretty-scrollbar` rules (1,264 CSS-module rules
|
|
20
|
+
removed in total). All 193 are accounted for — 0 unexplained. Migrating the
|
|
21
|
+
`--ui-*` palette and the extracted CSS-module rules into the three Forge
|
|
22
|
+
prototypes that use them is a later project stage, not yet done. The bundle
|
|
23
|
+
falls from 519,815 to 334,060 bytes (507.6 KB → 326.2 KB, a 181 KB / 35.7%
|
|
24
|
+
reduction).
|
|
25
|
+
|
|
26
|
+
#### Structure
|
|
27
|
+
|
|
28
|
+
- `src/tokens/**` mirrors component-library's collection layout — brand,
|
|
29
|
+
responsive, dynamic, alias, mapped — so an upstream diff maps 1:1 onto our
|
|
30
|
+
files. Our extensions live below an `UPSTREAM … END UPSTREAM` fence in the
|
|
31
|
+
same group file; `refresh:tokens` rewrites only the fenced bytes.
|
|
32
|
+
- `src/components/<name>/` holds each component's `tokens.css`, `styles.css` and
|
|
33
|
+
`behaviour.js` together, replacing two files that held eleven components
|
|
34
|
+
between them.
|
|
35
|
+
- `src/manifest.js` is the only place cascade order is encoded: 87 CSS entries
|
|
36
|
+
and 7 JS entries, matching the 87 `.css` files on disk one-for-one.
|
|
37
|
+
- The bundle ships 6 self-hosted `@font-face` rules (Inter and Syne, 6
|
|
38
|
+
`.woff2` files) — unchanged from the retired snapshot.
|
|
39
|
+
|
|
40
|
+
##### Gates
|
|
41
|
+
|
|
42
|
+
- The build fails on: a CSS file absent from the manifest, a manifest entry that
|
|
43
|
+
does not exist, a surviving `@import`/`@use`, component styles ordered before
|
|
44
|
+
component tokens, a malformed fence, or a Karmo token shadowed by a later
|
|
45
|
+
upstream fence (`check:placement`).
|
|
46
|
+
- `npm test` (11 tests) proves the restructure lost nothing: canonical-form
|
|
47
|
+
equality against a frozen pre-restructure bundle, and (selector, property,
|
|
48
|
+
value) parity between the converted upstream tokens and the retired
|
|
49
|
+
snapshot.
|
|
50
|
+
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
## 10.0.0 - 2026-09-17
|
|
2
|
+
|
|
3
|
+
Breaking change to Input's markup. Anything that hand-wrote
|
|
4
|
+
`dk-component-input` markup needs the new shape below.
|
|
5
|
+
|
|
6
|
+
- **The wrapping `<label>` doubled as the accessible name and silently
|
|
7
|
+
absorbed the caption.** Measured with the new contract gate (see below)
|
|
8
|
+
before any fix: a field labelled "Full name" with a "Helper text goes
|
|
9
|
+
here." caption announced as one string, `"FULL NAME Helper text goes
|
|
10
|
+
here."`, and had no separate accessible description at all (empty string).
|
|
11
|
+
The all-caps portion is the label's own `text-transform: uppercase`
|
|
12
|
+
bleeding into the accessible-name computation, not a second defect.
|
|
13
|
+
- **Fixed by giving the label and the field their own elements.** The root
|
|
14
|
+
is now `<div class="dk-component-input">`, optionally carrying
|
|
15
|
+
`data-size="small"`, `"medium"` or `"large"`. The label is a real
|
|
16
|
+
`<label class="dk-component-input__label" for="ID">`. The field wrapper is
|
|
17
|
+
`<div class="dk-component-input__field">` (a `<span>` still renders
|
|
18
|
+
correctly, `<div>` is what the docs now teach). Measured after the fix:
|
|
19
|
+
the accessible name is the label alone, `"Full name"`, and the caption is
|
|
20
|
+
wired in as the accessible description through
|
|
21
|
+
`<p class="dk-component-input__caption" id="ID-caption">` plus
|
|
22
|
+
`aria-describedby="ID-caption"` on the control. `check:contract` now
|
|
23
|
+
passes for Input.
|
|
24
|
+
- **Migrated Forge's `model-approval` prototype to the new shape: 24
|
|
25
|
+
instances, 12 in `index.html` and 12 in `v2.html`.** Every one already had
|
|
26
|
+
a control `id`, so the migration reused it rather than inventing one.
|
|
27
|
+
`grep -c` for the old `<label class="dk-component-input">` shape returns 0
|
|
28
|
+
in both files. Input's own docs entry in `design-system/registry.js`
|
|
29
|
+
carried one further instance, migrated separately while that entry was
|
|
30
|
+
rebuilt, and Modal's own Preview and Trigger
|
|
31
|
+
examples in the same file carried two more, migrated in the final review
|
|
32
|
+
fix wave so the docs no longer teach the retired shape anywhere on the
|
|
33
|
+
Modal page. A handful of other embedded Input snippets outside Input's
|
|
34
|
+
own docs, `model-approval`, and Modal, Forge's root `index.html` and
|
|
35
|
+
`assets/forge-cards.js`, still use the old wrapping-label shape. They
|
|
36
|
+
render fine (the class names carry the CSS regardless of tag), but they
|
|
37
|
+
are out of scope for this change and were left alone.
|
|
38
|
+
- **Fix: `outline: none` on the control silently removed the focus ring
|
|
39
|
+
from a `<textarea>` or `<select>` field, and the disabled border with
|
|
40
|
+
it.** Both the resting focus ring and the disabled-border hook were
|
|
41
|
+
narrowed to `:has(input:focus-visible)` and `:has(input:disabled)` while
|
|
42
|
+
`outline: none` stayed on all three control types, `input`, `textarea`
|
|
43
|
+
and `select`. A textarea or select inside a field therefore lost its
|
|
44
|
+
native outline and matched no rule that restored one: no focus indicator
|
|
45
|
+
at all, and no border change when disabled. Both selectors now read
|
|
46
|
+
`:has(:is(input, textarea, select):focus-visible)` and
|
|
47
|
+
`:has(:is(input, textarea, select):disabled)`. Verified with a keyboard
|
|
48
|
+
probe on a textarea field: before the fix the field's border and
|
|
49
|
+
box-shadow stayed at their resting values on real focus; after, the
|
|
50
|
+
border switches to the primary ring colour and the box-shadow shows the
|
|
51
|
+
usual 4px focus ring, matching an `<input>` field exactly.
|
|
52
|
+
- **The error state is `aria-invalid="true"` on the control, not a modifier
|
|
53
|
+
class.** `.dk-component-input--error` and `.dk-component-input--disabled`
|
|
54
|
+
are both gone; the CSS now keys off `:has(input[aria-invalid="true"])` and
|
|
55
|
+
`:has(input:disabled)`. The visual state and what a screen reader
|
|
56
|
+
announces read off the same attribute, so they cannot drift apart the way
|
|
57
|
+
a class and an ARIA attribute set separately could.
|
|
58
|
+
- **Three field heights, 38 / 44 / 52px for small / medium / large, all
|
|
59
|
+
`border-box`, each moving the box and the type together at 14 / 16 /
|
|
60
|
+
18px.** None is written as a literal: each is `calc()`'d from the
|
|
61
|
+
primitive scale, padding doubled plus the line box. Small and medium land
|
|
62
|
+
on Button's first two rungs so a field and a button share a row cleanly,
|
|
63
|
+
and Forge's `check:contract` measures a rendered field against a rendered
|
|
64
|
+
button to keep them there. Large deliberately does not match Button's
|
|
65
|
+
56px: a 52px field is the proportion a form wants, and a large field
|
|
66
|
+
usually stands alone.
|
|
67
|
+
- **`medium` is a real value.** It was `small | large` with the middle rung
|
|
68
|
+
unnamed. Omitting the attribute still lands on the same rule, but Button
|
|
69
|
+
names its middle rung and one component spelling the middle size while
|
|
70
|
+
another leaves a hole is not something anyone should have to discover.
|
|
71
|
+
- **That same derivation fixes the 46px these three heights replace.** The
|
|
72
|
+
old field was `min-height: 44px` under `box-sizing: content-box` with a
|
|
73
|
+
1px border, which rendered at 46px, two pixels proud of Button's 44px
|
|
74
|
+
medium in the same row. The field is `border-box` now, so it lines up
|
|
75
|
+
exactly.
|
|
76
|
+
- **Two new slots, leading and trailing**, `.dk-component-input__leading`
|
|
77
|
+
and `__trailing`, sizing a child `svg` or `i` to 20px, stepping to 16px
|
|
78
|
+
at `data-size="small"` so they match the action buttons beside them. For
|
|
79
|
+
a currency prefix, a unit, or a search glyph.
|
|
80
|
+
- **The field is flush with its surface and defined by its border.**
|
|
81
|
+
Background is `--dk-surface-current`, so the field tracks
|
|
82
|
+
`data-surface` at every level instead of holding one colour. The border
|
|
83
|
+
and the placeholder read three new mapped tokens,
|
|
84
|
+
`--dk-border-field-default`, `--dk-border-field-hover` and
|
|
85
|
+
`--dk-text-field-placeholder`, declared per theme because the neutral
|
|
86
|
+
ramp is not mirrored between light and dark and every borrowed token
|
|
87
|
+
therefore reads wrong in one of them. Hover moves the border and the
|
|
88
|
+
fill together.
|
|
89
|
+
- **Two in-field actions**, `.dk-component-input__action` with
|
|
90
|
+
`data-input-reveal` or `data-input-clear`, wired by a new
|
|
91
|
+
`components/input/behaviour.js` (`dk.component.input.init()`, auto-run
|
|
92
|
+
on `DOMContentLoaded`). The reveal toggle flips `type` between
|
|
93
|
+
`password` and `text`, moves `aria-pressed`, and swaps its accessible
|
|
94
|
+
name; both glyphs live in the markup and CSS shows one, so the picture
|
|
95
|
+
cannot drift from the announced state. The clear button empties the
|
|
96
|
+
control, fires a bubbling native `input` event, and hides itself while
|
|
97
|
+
the field is empty. These are real buttons in the tab order with their
|
|
98
|
+
own names and focus rings, which is why the field's own ring keys off
|
|
99
|
+
`:has(input:focus-visible)` rather than `:focus-within`.
|
|
100
|
+
- **Autofill no longer looks autofilled.** Chrome and Safari paint their
|
|
101
|
+
own fill at a level `background-color` cannot beat; the control now
|
|
102
|
+
stays genuinely transparent so it keeps following the field behind it,
|
|
103
|
+
including on hover.
|
|
104
|
+
- **The required asterisk is warning, not error.** An unfilled required
|
|
105
|
+
field is a prompt, not a failure, and a form of ten of them should not
|
|
106
|
+
open entirely in red.
|
|
107
|
+
- **The error message has its own colour token**,
|
|
108
|
+
`--dk-component-input-error-color`. It read `--dk-text-error-default`,
|
|
109
|
+
which is the status fill and glyph rung and measures 3.48:1 on a white
|
|
110
|
+
page, below AA for body text.
|
|
111
|
+
- **A React component**: `Input`, `InputProps`, `InputSize`, exported from
|
|
112
|
+
`src/react/index.ts`. Falls back to `useId()` when the caller passes no
|
|
113
|
+
`id`, wires `aria-describedby` to caption then error (caption first) when
|
|
114
|
+
both are present, and sets `aria-invalid` only when an `error` prop is
|
|
115
|
+
given, never a class. `revealable` and `clearable` give the two in-field
|
|
116
|
+
actions; clearing goes through the prototype's value setter so it works
|
|
117
|
+
for a controlled and an uncontrolled field alike.
|
|
118
|
+
- **A new gate: `check:contract`, added to Forge.** A stylesheet cannot
|
|
119
|
+
assert what a screen reader announces or what height a control renders
|
|
120
|
+
at, so this gate loads each documented component's live page, takes an
|
|
121
|
+
accessibility snapshot, and measures `getBoundingClientRect()`, against a
|
|
122
|
+
`contract` block declared in that component's registry entry. Input is
|
|
123
|
+
the first component to carry one. It also checks cross-component height
|
|
124
|
+
cohorts, which is what replaced Input reading Button's padding tokens
|
|
125
|
+
directly: an agreement between two components is a thing to assert, not
|
|
126
|
+
to implement by coupling.
|
|
127
|
+
|
|
128
|
+
**Kit-wide, not Input.** Two files that affect every component:
|
|
129
|
+
|
|
130
|
+
- **`kit/reset.css`** zeroes the browser's own margin on anything carrying
|
|
131
|
+
a `dk-component-` class, and gives form controls `font: inherit`. Every
|
|
132
|
+
text-bearing component was doing this by hand and Input forgot, which
|
|
133
|
+
put its caption 14px out of place. Scoped to kit classes and written at
|
|
134
|
+
zero specificity with `:where()`, so a consumer's markup is untouched
|
|
135
|
+
and any component rule wanting a margin still wins. A new Forge gate,
|
|
136
|
+
`check:ua-defaults`, proves nothing else is falling through.
|
|
137
|
+
- **`kit/selection.css`** paints selected text in the brand primary with
|
|
138
|
+
white on top, the same in both themes. Scoped to `[data-brand]`, the
|
|
139
|
+
attribute a page sets to opt into the kit, because selection is
|
|
140
|
+
document-wide and this stylesheet loads into applications whose markup
|
|
141
|
+
the kit does not own.
|
|
142
|
+
|
|
143
|
+
**Migration.** Replace `<label class="dk-component-input">...</label>` with
|
|
144
|
+
`<div class="dk-component-input">...</div>`. Turn
|
|
145
|
+
`<span class="dk-component-input__label">Text</span>` into
|
|
146
|
+
`<label class="dk-component-input__label" for="ID">Text</label>`, where `ID`
|
|
147
|
+
is the control's own `id`. Turn
|
|
148
|
+
`<span class="dk-component-input__field">` into
|
|
149
|
+
`<div class="dk-component-input__field">` (optional, a span still works).
|
|
150
|
+
If there is a caption, give it `id="ID-caption"` and add
|
|
151
|
+
`aria-describedby="ID-caption"` to the control. Replace any reliance on
|
|
152
|
+
`.dk-component-input--error` or `.dk-component-input--disabled` with
|
|
153
|
+
`aria-invalid="true"` or the native `disabled` attribute.
|
|
154
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## 11.0.0 - 2026-09-18
|
|
2
|
+
|
|
3
|
+
- **Search input is now called Search bar**, and its source directory moves
|
|
4
|
+
with it. Input takes `type="search"` and gets a suggested magnifier and a
|
|
5
|
+
clear button with it, so there are genuinely two things, and one name for both
|
|
6
|
+
gave nobody a way to say which they meant. This is the prominent one: the
|
|
7
|
+
large rung, an elevation no other field has, one per page, no visible label.
|
|
8
|
+
A form field sits in the page; a search bar sits on top of it.
|
|
9
|
+
- **BREAKING: the class and token names follow.** `.dk-component-search`
|
|
10
|
+
becomes `.dk-component-search-bar`, and the parts go from a hyphen to the
|
|
11
|
+
`__` every other component in the kit uses:
|
|
12
|
+
`.dk-component-search-icon` and `.dk-component-search-input` become
|
|
13
|
+
`.dk-component-search-bar__icon` and `.dk-component-search-bar__input`. Search
|
|
14
|
+
bar was the only component naming its parts with a hyphen, so fixing the name
|
|
15
|
+
and leaving the convention broken would have been half a job. The token prefix
|
|
16
|
+
moves with them, `--dk-component-search-*` to `--dk-component-search-bar-*`,
|
|
17
|
+
a clean 1:1 rename of six names.
|
|
18
|
+
|
|
19
|
+
**Migration.** Search and replace, longest first so the root does not eat the
|
|
20
|
+
parts: `dk-component-search-input` to `dk-component-search-bar__input`, then
|
|
21
|
+
`dk-component-search-icon` to `dk-component-search-bar__icon`, then the bare
|
|
22
|
+
`dk-component-search` to `dk-component-search-bar`, then
|
|
23
|
+
`--dk-component-search-` to `--dk-component-search-bar-`.
|
|
24
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
## 12.0.0 - 2026-09-18
|
|
2
|
+
|
|
3
|
+
**Icon button, rebuilt.** It was a 34-line port with no token collection, the
|
|
4
|
+
only component in the kit without one.
|
|
5
|
+
|
|
6
|
+
- **BREAKING: `.dk-component-icon-btn` becomes `.dk-component-icon-button`**,
|
|
7
|
+
matching its own directory and the kit's no-abbreviation convention. Every
|
|
8
|
+
consumer is migrated in this release: 23 tags in Forge and five inside the kit
|
|
9
|
+
(Toast's close button, Dropzone's clear, three comments).
|
|
10
|
+
- **BREAKING: it now lines up with Button.** Measured before: 28 / 32 / 40 / 48
|
|
11
|
+
against Button's 40 / 46 / 58 / 66 at the same size names, so an icon button
|
|
12
|
+
beside a text one was 12 to 18px short at every rung but the smallest. Height
|
|
13
|
+
is now derived the way Button's is, from the same padding and line-height
|
|
14
|
+
primitives, NOT from Button's own tokens, which would be a
|
|
15
|
+
component-to-component dependency. Three `check:contract` cohorts assert the
|
|
16
|
+
pairs so it cannot drift back.
|
|
17
|
+
- **BREAKING: four rungs, `extra-small` to `large`.** small, medium and large
|
|
18
|
+
are Button's exactly; `extra-small` sits below Button's ladder because a text
|
|
19
|
+
button that small stops being pressable and an icon one does not. Measured
|
|
20
|
+
across Forge, every icon button in the product sat at 28, 32 or 40px, all at
|
|
21
|
+
or below Button's smallest, and nothing used the old top two rungs. Forge's
|
|
22
|
+
usages are remapped to the nearest new rung, so rendered sizes move by at most
|
|
23
|
+
2px.
|
|
24
|
+
- **BREAKING: `.dk-component-icon-btn--subtle` retires into `data-variant`.**
|
|
25
|
+
It was documented as "the transparent-at-rest variant" and set
|
|
26
|
+
`background-color: var(--dk-surface-default-body)`: an opaque white square on
|
|
27
|
+
any surface that was not white. `data-variant="plain"` is the real thing.
|
|
28
|
+
Three variants now, `subtle` (the default, and the look this already had),
|
|
29
|
+
`plain`, and `raised`, which pairs with Button's raised.
|
|
30
|
+
- **The accessible name is asserted, not assumed.** With no text, `aria-label`
|
|
31
|
+
is the only thing between this control and "button" being all a screen reader
|
|
32
|
+
can say about it, so `check:contract` now checks it.
|
|
33
|
+
- Gone with the rewrite: five hardcoded icon sizes, a hardcoded 4px focus ring, a
|
|
34
|
+
`scale(0.9)` press that pressed harder than every other control in the kit, and
|
|
35
|
+
an alias colour read straight into a component rule.
|
|
36
|
+
- Full docs: api table, three examples including one proving the row alignment,
|
|
37
|
+
and a playground.
|
|
38
|
+
|