origam 2.13.0 → 2.14.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/CHANGELOG.md +1975 -0
- package/dist/src/components/Avatar/OrigamAvatar.vue +14 -0
- package/dist/src/components/Messages/OrigamMessages.vue +1 -0
- package/dist/src/components/TextField/OrigamTextField.vue +1 -1
- package/dist/src/consts/Commons/rounded.const.d.ts +1 -1
- package/dist/src/enums/Commons/rounded.enum.cjs +12 -2
- package/dist/src/enums/Commons/rounded.enum.d.ts +25 -0
- package/dist/src/enums/Commons/rounded.enum.js +10 -0
- package/dist/src/themes/origam.theme.cjs +2 -2
- package/dist/src/themes/origam.theme.js +2 -2
- package/dist/src/types/Commons/rounded.type.d.ts +14 -2
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,1975 @@
|
|
|
1
|
+
# origam — Changelog
|
|
2
|
+
|
|
3
|
+
This changelog tracks releases of the `origam` package itself. Token-value
|
|
4
|
+
churn (Tokens Studio sync from Figma, semantic primitive shifts) lives in
|
|
5
|
+
[`tokens/CHANGELOG.md`](./tokens/CHANGELOG.md) — keep them separate so
|
|
6
|
+
"the design moved" never blocks a release of "the code shipped a new
|
|
7
|
+
component".
|
|
8
|
+
|
|
9
|
+
Format inspired by [Keep a Changelog](https://keepachangelog.com).
|
|
10
|
+
This project follows [Semantic Versioning](https://semver.org).
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## [Unreleased]
|
|
15
|
+
|
|
16
|
+
## [2.14.0] - 2026-08-07
|
|
17
|
+
|
|
18
|
+
Reported from a real integration, not from a code review. Each item was
|
|
19
|
+
reproduced before being fixed, and the fix verified against the running
|
|
20
|
+
component.
|
|
21
|
+
|
|
22
|
+
### ⚠️ BREAKING — `<origam-avatar>` is now a circle by default
|
|
23
|
+
|
|
24
|
+
The base theme sized avatar corners with `rounded: 'lg'` — a 16px rounded
|
|
25
|
+
square. Every avatar that does not set `rounded` explicitly now renders as a
|
|
26
|
+
circle (`rounded: 'full'`).
|
|
27
|
+
|
|
28
|
+
**Why**: an avatar is round in the overwhelming majority of interfaces, and
|
|
29
|
+
until now obtaining one required knowing that a second, undocumented radius
|
|
30
|
+
scale existed (see the `rounded` fix below). The mismatch showed: a
|
|
31
|
+
rounded-square avatar dropped into a circular trigger left a visible ring
|
|
32
|
+
around it — reported from the field as *"a square inside a circle"*.
|
|
33
|
+
|
|
34
|
+
**Migration** — restore the previous shape app-wide in one line, through the
|
|
35
|
+
theme layer:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
createOrigam({ theme: { components: { 'origam-avatar': { rounded: 'lg' } } } })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
or per instance with `<origam-avatar rounded="lg">`.
|
|
42
|
+
|
|
43
|
+
### Fixed — dead `aria-describedby` on input fields (accessibility)
|
|
44
|
+
|
|
45
|
+
A screen reader announced **no validation message at all**. The defect was
|
|
46
|
+
invisible to the eye: the message rendered correctly.
|
|
47
|
+
|
|
48
|
+
`<origam-text-field>` filtered `id` out of the props it forwarded, so
|
|
49
|
+
`<origam-input>` never received it and invented its own. It then derived
|
|
50
|
+
`<id>-messages` and pointed `aria-describedby` at it — but `<origam-messages>`
|
|
51
|
+
declared an `id` prop and applied it to **no element**, giving each message a
|
|
52
|
+
different id instead. The reference resolved to nothing.
|
|
53
|
+
|
|
54
|
+
`<origam-messages>` now applies the received `id` to its root, and
|
|
55
|
+
`<origam-text-field>` no longer filters `id` out. Verified in a browser:
|
|
56
|
+
`aria-describedby` resolves to an element that exists.
|
|
57
|
+
|
|
58
|
+
**Second effect of the same fix**: an `id` passed to a text field now actually
|
|
59
|
+
reaches its `<input>`. `document.getElementById(...)` finds it, and an
|
|
60
|
+
external `<label for>` associates correctly — both previously failed silently.
|
|
61
|
+
|
|
62
|
+
### Fixed — `<origam-avatar size>` ignored outside a flex container
|
|
63
|
+
|
|
64
|
+
The root element declared no `display`, so with `tag="span"` it inherited the
|
|
65
|
+
browser's `inline` — and an inline box ignores `width`/`height`. The avatar
|
|
66
|
+
collapsed to its content and `size` did nothing, with no warning.
|
|
67
|
+
|
|
68
|
+
It appeared to work only when the parent happened to be a flex container,
|
|
69
|
+
which blockifies its children. Measured on one real page: the same component
|
|
70
|
+
rendered 32×32 under `inline-flex` but **30×30 under `position: relative`**
|
|
71
|
+
for a requested size of 72.
|
|
72
|
+
|
|
73
|
+
The root now declares `display: inline-flex` — `inline-flex` rather than
|
|
74
|
+
`block` because `tag="span"` exists so an avatar can sit in phrasing content,
|
|
75
|
+
inside a `<button>` whose content model rejects block-level elements. Consumers
|
|
76
|
+
who worked around this with `.origam-avatar { display: inline-flex }` can drop
|
|
77
|
+
the override; it remains harmless.
|
|
78
|
+
|
|
79
|
+
### Fixed — `rounded` rejected the token scale, hiding the circular variant
|
|
80
|
+
|
|
81
|
+
`TRounded` only described the component scale (`x-small` … `x-large`,
|
|
82
|
+
`shaped`), none of which produces a circle. The radius rungs — `none`, `xs`,
|
|
83
|
+
`sm`, `md`, `lg`, `xl` and **`full`**, the one that yields a circle — were
|
|
84
|
+
already honoured at runtime (the brand themes have shipped `rounded: 'md'` for
|
|
85
|
+
a while) but failed to type-check and never appeared in autocompletion.
|
|
86
|
+
|
|
87
|
+
A round avatar was therefore undiscoverable: it required knowing that a second,
|
|
88
|
+
undocumented scale existed. Reported from the field as *"a square inside a
|
|
89
|
+
circle"* — a rounded-square avatar in a circular trigger leaves a visible ring.
|
|
90
|
+
|
|
91
|
+
The rungs are now a first-class `ROUNDED_TOKEN` enum and part of `TRounded`.
|
|
92
|
+
`rounded="full"` type-checks. The two scales stay separate on purpose: one
|
|
93
|
+
names an intent (`shaped`), the other a radius rung — `x-small` and `xs` are
|
|
94
|
+
not interchangeable.
|
|
95
|
+
|
|
96
|
+
### Fixed — the published package shipped no changelog
|
|
97
|
+
|
|
98
|
+
`files` listed `CHANGELOG.md`, but the file lives at the monorepo root and had
|
|
99
|
+
no counterpart in `packages/ds/`, so npm silently packed nothing. Consumers had
|
|
100
|
+
no way to tell what a release contained. A `prepack` step now copies it in —
|
|
101
|
+
verified: 96 kB of changelog in the tarball.
|
|
102
|
+
|
|
103
|
+
## [2.13.0] - 2026-08-05
|
|
104
|
+
|
|
105
|
+
### ⚠️ BREAKING — `<origam-select>` dropdown rows now follow the control
|
|
106
|
+
|
|
107
|
+
A `<origam-select>` opened a menu whose rows measured 48px whatever the
|
|
108
|
+
control was set to. The most common case — a select with **no** `size` prop —
|
|
109
|
+
was the worst: a 48px row under a 36px control. Rows now match the control
|
|
110
|
+
exactly at every size (36/36 unsized, 28/28 small, 44/44 large, 60/60
|
|
111
|
+
x-large + comfortable).
|
|
112
|
+
|
|
113
|
+
**Why this is breaking**: the fix corrects how `density` is applied to
|
|
114
|
+
**every** list, not only dropdowns. Density becomes a coherent ±8px offset
|
|
115
|
+
aligned on the field model, where it previously amounted to −24px in
|
|
116
|
+
`compact` and did nothing at all in `comfortable`:
|
|
117
|
+
|
|
118
|
+
| standalone list row, no `size` | before | after |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `default` | 56px | 56px |
|
|
121
|
+
| `compact` | 32px | **48px** |
|
|
122
|
+
| `comfortable` | 56px | **64px** |
|
|
123
|
+
|
|
124
|
+
The old 32px came from counting density three times (−8 on `min-height`,
|
|
125
|
+
−8 on each block padding). `comfortable` had no rule at all and was a no-op.
|
|
126
|
+
Anything relying on `density="compact"` on an `<origam-list>` will render
|
|
127
|
+
8–16px taller.
|
|
128
|
+
|
|
129
|
+
`ISizeProps` is added to `IListProps` (a forwarding prop — the list paints
|
|
130
|
+
nothing from it) and to `IListItemProps` (which paints the row height).
|
|
131
|
+
|
|
132
|
+
### ⚠️ BREAKING — `useStyle()` no longer overwrites a consumer `id`
|
|
133
|
+
|
|
134
|
+
`useStyle()` generated its own id and the component put it on its root,
|
|
135
|
+
silently overwriting an `id` passed as a prop. On `<origam-btn>` this broke
|
|
136
|
+
every `<label for>`, `aria-labelledby`, `aria-controls` and
|
|
137
|
+
`aria-describedby` pointing at a button. The consumer's `id` now wins and the
|
|
138
|
+
generated rule follows it.
|
|
139
|
+
|
|
140
|
+
**Why this is breaking**: components previously always carried a generated
|
|
141
|
+
id. Anything keyed on that generated id (a CSS selector, a test locator)
|
|
142
|
+
will no longer match when the consumer supplies an `id`.
|
|
143
|
+
|
|
144
|
+
### Fixed
|
|
145
|
+
|
|
146
|
+
- **The generated stylesheet was being discarded entirely.** `StyleValue`
|
|
147
|
+
includes `false`, and Vue resolves an unpassed prop whose declared type
|
|
148
|
+
contains Boolean to `false`, never `undefined` — so every component
|
|
149
|
+
exposing the shared `style` prop emitted `#id {false}`, which is not a
|
|
150
|
+
declaration. Browsers dropped it through error recovery; jsdom dropped the
|
|
151
|
+
**whole** sheet. Nested style arrays were also flattened one level only,
|
|
152
|
+
landing an object in the sheet as `[object Object]`.
|
|
153
|
+
- **CSS injection through the `id` prop.** Now that the id comes from the
|
|
154
|
+
consumer and is interpolated verbatim into a `<style>` element, an id such
|
|
155
|
+
as `a { } body { display: none }` appended arbitrary rules to the document.
|
|
156
|
+
A new `escapeCssIdent()` utility delegates to native `CSS.escape`, with a
|
|
157
|
+
spec-conformant fallback for jsdom and SSR, which expose no `CSS` global.
|
|
158
|
+
- **Interpolation placeholders silently rendered empty.** `t()` is variadic
|
|
159
|
+
— `t(key, ...params)` — but five call sites passed it an **array**, so the
|
|
160
|
+
array landed in `params[0]` where the template expected the value itself.
|
|
161
|
+
This stayed invisible while `stringifyParam` accepted any value (`[3]`
|
|
162
|
+
stringified to `"3"`); once it was narrowed to primitives, an array began
|
|
163
|
+
rendering as an **empty string** and the placeholder vanished. Visible
|
|
164
|
+
effects: `<origam-file-field display="counter">` displayed `" files"`
|
|
165
|
+
instead of `"3 files"`, and the `max_length` validation message of
|
|
166
|
+
`<origam-text-field>` / `<origam-textarea-field>` showed an empty limit.
|
|
167
|
+
|
|
168
|
+
### Security
|
|
169
|
+
|
|
170
|
+
`brace-expansion` overrides were pinned to the **vulnerable** versions
|
|
171
|
+
(`^2.1.2` / `^5.0.8`) — set for an earlier advisory and never moved since.
|
|
172
|
+
They are raised to the patched floors (`^2.1.4` / `^5.0.9`), which clears
|
|
173
|
+
the three `high` DoS advisories (unbounded expansion) that `pnpm audit`
|
|
174
|
+
reported through `minimatch`.
|
|
175
|
+
|
|
176
|
+
Nuxt advisories published during this release cycle are cleared too:
|
|
177
|
+
`@nuxt/devtools` (**critical**), and five `high` on `nuxt` itself
|
|
178
|
+
(server-side RCE via Runtime, unauthenticated OOM crash, CPU exhaustion
|
|
179
|
+
while parsing). `nuxt` moves to `^4.5.1` and `typeorm` to `^0.3.31`,
|
|
180
|
+
staying on the `0.3.x` line — the fix landed there, and `1.x` is a
|
|
181
|
+
breaking change. `pnpm audit --prod` now reports **no known
|
|
182
|
+
vulnerabilities**.
|
|
183
|
+
|
|
184
|
+
Scope note for consumers: the published `origam` package depends only on
|
|
185
|
+
`@mdi/font` and `qrcode-generator`, with `shiki` / `vue` / `vue-i18n` /
|
|
186
|
+
`vue-router` as peers. None of the packages above ship with it — they all
|
|
187
|
+
come from `@origam/marketing`, which is `private` and never published. You
|
|
188
|
+
were never exposed; the deployed site was.
|
|
189
|
+
|
|
190
|
+
One change does reach the published package. Nuxt 4.5 made TypeScript
|
|
191
|
+
unable to name the type `defineNuxtModule` returns, so the default export
|
|
192
|
+
of the `origam/nuxt` sub-export is now explicitly annotated as
|
|
193
|
+
`NuxtModule`. Behaviour is unchanged — it is a declaration-emit fix.
|
|
194
|
+
|
|
195
|
+
### ⚠️ BREAKING — i18n locale keys migrated to `snake_case`
|
|
196
|
+
|
|
197
|
+
All locale keys shipped by the DS (`packages/ds/src/assets/locales/en.json`,
|
|
198
|
+
`fr.json`) now follow the project-wide i18n convention: every key **segment**
|
|
199
|
+
is `snake_case` (`a-z`, `0-9`, `_`). Nested structure is unchanged — only the
|
|
200
|
+
casing of each segment changes (e.g. `dataTable.ariaLabel.sortBy` →
|
|
201
|
+
`data_table.aria_label.sort_by`).
|
|
202
|
+
|
|
203
|
+
**Why this is breaking**: `createOrigam({ messages })` lets a consumer
|
|
204
|
+
override any locale message by key path. Any override keyed on an old
|
|
205
|
+
camelCase path (e.g. `'origam.dataTable.sortBy'`) will silently stop applying
|
|
206
|
+
— the DS falls back to its own bundled (English) string with **no error**,
|
|
207
|
+
which is easy to miss until a French (or other locale) screen renders in
|
|
208
|
+
English.
|
|
209
|
+
|
|
210
|
+
**All 65 `t()` call sites and their indirect prop-default equivalents were
|
|
211
|
+
updated in the same commit** — verified with a cross-reference script (every
|
|
212
|
+
literal `origam.*` key still referenced in `packages/ds/src` was checked
|
|
213
|
+
against both locale files; zero leftover old-casing key strings remain
|
|
214
|
+
anywhere in `packages/ds/src`). Fallback strings (the second argument to
|
|
215
|
+
`t(key, fallback)`) are unchanged — only the key paths moved.
|
|
216
|
+
|
|
217
|
+
If you override any DS locale key, update the key path using the table below.
|
|
218
|
+
|
|
219
|
+
| Old key | New key |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `origam.bottomNav.ariaLabel` | `origam.bottom_nav.aria_label` |
|
|
222
|
+
| `origam.calendar.ariaLabel` | `origam.calendar.aria_label` |
|
|
223
|
+
| `origam.calendar.monthGrid` | `origam.calendar.month_grid` |
|
|
224
|
+
| `origam.calendar.moreEvents` | `origam.calendar.more_events` |
|
|
225
|
+
| `origam.calendar.viewSwitcher` | `origam.calendar.view_switcher` |
|
|
226
|
+
| `origam.carousel.ariaLabel.delimiter` | `origam.carousel.aria_label.delimiter` |
|
|
227
|
+
| `origam.clipboard.copiedAriaLabel` | `origam.clipboard.copied_aria_label` |
|
|
228
|
+
| `origam.clipboard.copyAriaLabel` | `origam.clipboard.copy_aria_label` |
|
|
229
|
+
| `origam.code.copiedAriaLabel` | `origam.code.copied_aria_label` |
|
|
230
|
+
| `origam.code.copyAriaLabel` | `origam.code.copy_aria_label` |
|
|
231
|
+
| `origam.colorPicker.canvas.ariaLabel` | `origam.color_picker.canvas.aria_label` |
|
|
232
|
+
| `origam.colorPicker.canvas.value` | `origam.color_picker.canvas.value` |
|
|
233
|
+
| `origam.confirmEdit.cancel` | `origam.confirm_edit.cancel` |
|
|
234
|
+
| `origam.confirmEdit.ok` | `origam.confirm_edit.ok` |
|
|
235
|
+
| `origam.dataFooter.firstPage` | `origam.data_footer.first_page` |
|
|
236
|
+
| `origam.dataFooter.itemsPerPageAll` | `origam.data_footer.items_per_page_all` |
|
|
237
|
+
| `origam.dataFooter.itemsPerPageText` | `origam.data_footer.items_per_page_text` |
|
|
238
|
+
| `origam.dataFooter.lastPage` | `origam.data_footer.last_page` |
|
|
239
|
+
| `origam.dataFooter.nextPage` | `origam.data_footer.next_page` |
|
|
240
|
+
| `origam.dataFooter.pageText` | `origam.data_footer.page_text` |
|
|
241
|
+
| `origam.dataFooter.prevPage` | `origam.data_footer.prev_page` |
|
|
242
|
+
| `origam.dataIterator.loadingText` | `origam.data_iterator.loading_text` |
|
|
243
|
+
| `origam.dataIterator.noResultsText` | `origam.data_iterator.no_results_text` |
|
|
244
|
+
| `origam.dataTable.ariaLabel.activateAscending` | `origam.data_table.aria_label.activate_ascending` |
|
|
245
|
+
| `origam.dataTable.ariaLabel.activateDescending` | `origam.data_table.aria_label.activate_descending` |
|
|
246
|
+
| `origam.dataTable.ariaLabel.activateNone` | `origam.data_table.aria_label.activate_none` |
|
|
247
|
+
| `origam.dataTable.ariaLabel.sortAscending` | `origam.data_table.aria_label.sort_ascending` |
|
|
248
|
+
| `origam.dataTable.ariaLabel.sortDescending` | `origam.data_table.aria_label.sort_descending` |
|
|
249
|
+
| `origam.dataTable.ariaLabel.sortNone` | `origam.data_table.aria_label.sort_none` |
|
|
250
|
+
| `origam.dataTable.itemsPerPageText` | `origam.data_table.items_per_page_text` |
|
|
251
|
+
| `origam.dataTable.sortBy` | `origam.data_table.sort_by` |
|
|
252
|
+
| `origam.dataTableRow.collapseRow` | `origam.data_table_row.collapse_row` |
|
|
253
|
+
| `origam.dataTableRow.expandRow` | `origam.data_table_row.expand_row` |
|
|
254
|
+
| `origam.datePicker.header` | `origam.date_picker.header` |
|
|
255
|
+
| `origam.datePicker.input.placeholder` | `origam.date_picker.input.placeholder` |
|
|
256
|
+
| `origam.datePicker.itemsSelected` | `origam.date_picker.items_selected` |
|
|
257
|
+
| `origam.datePicker.range.header` | `origam.date_picker.range.header` |
|
|
258
|
+
| `origam.datePicker.range.title` | `origam.date_picker.range.title` |
|
|
259
|
+
| `origam.datePicker.title` | `origam.date_picker.title` |
|
|
260
|
+
| `origam.datePickerRangeField.text` | `origam.date_picker_range_field.text` |
|
|
261
|
+
| `origam.fileField.browse` | `origam.file_field.browse` |
|
|
262
|
+
| `origam.fileField.counter` | `origam.file_field.counter` |
|
|
263
|
+
| `origam.fileField.counterSize` | `origam.file_field.counter_size` |
|
|
264
|
+
| `origam.fileField.dropzoneSubtitle` | `origam.file_field.dropzone_subtitle` |
|
|
265
|
+
| `origam.fileField.dropzoneTitle` | `origam.file_field.dropzone_title` |
|
|
266
|
+
| `origam.fileInput.counter` | `origam.file_input.counter` |
|
|
267
|
+
| `origam.fileInput.counterSize` | `origam.file_input.counter_size` |
|
|
268
|
+
| `origam.fileUpload.browse` | `origam.file_upload.browse` |
|
|
269
|
+
| `origam.fileUpload.divider` | `origam.file_upload.divider` |
|
|
270
|
+
| `origam.fileUpload.title` | `origam.file_upload.title` |
|
|
271
|
+
| `origam.infiniteScroll.empty` | `origam.infinite_scroll.empty` |
|
|
272
|
+
| `origam.infiniteScroll.loadMore` | `origam.infinite_scroll.load_more` |
|
|
273
|
+
| `origam.input.appendAction` | `origam.input.append_action` |
|
|
274
|
+
| `origam.input.prependAction` | `origam.input.prepend_action` |
|
|
275
|
+
| `origam.media.castToDevice` | `origam.media.cast_to_device` |
|
|
276
|
+
| `origam.media.nextTrack` | `origam.media.next_track` |
|
|
277
|
+
| `origam.media.normalSpeed` | `origam.media.normal_speed` |
|
|
278
|
+
| `origam.media.playbackSpeed` | `origam.media.playback_speed` |
|
|
279
|
+
| `origam.media.previousTrack` | `origam.media.previous_track` |
|
|
280
|
+
| `origam.media.stopCasting` | `origam.media.stop_casting` |
|
|
281
|
+
| `origam.noDataText` | `origam.no_data_text` |
|
|
282
|
+
| `origam.pagination.ariaLabel.currentPage` | `origam.pagination.aria_label.current_page` |
|
|
283
|
+
| `origam.pagination.ariaLabel.first` | `origam.pagination.aria_label.first` |
|
|
284
|
+
| `origam.pagination.ariaLabel.last` | `origam.pagination.aria_label.last` |
|
|
285
|
+
| `origam.pagination.ariaLabel.next` | `origam.pagination.aria_label.next` |
|
|
286
|
+
| `origam.pagination.ariaLabel.page` | `origam.pagination.aria_label.page` |
|
|
287
|
+
| `origam.pagination.ariaLabel.previous` | `origam.pagination.aria_label.previous` |
|
|
288
|
+
| `origam.pagination.ariaLabel.root` | `origam.pagination.aria_label.root` |
|
|
289
|
+
| `origam.rating.ariaLabel.item` | `origam.rating.aria_label.item` |
|
|
290
|
+
| `origam.stepper.progressSteps` | `origam.stepper.progress_steps` |
|
|
291
|
+
| `origam.stepper.stepAriaLabel` | `origam.stepper.step_aria_label` |
|
|
292
|
+
| `origam.timePicker.am` | `origam.time_picker.am` |
|
|
293
|
+
| `origam.timePicker.pm` | `origam.time_picker.pm` |
|
|
294
|
+
| `origam.timePicker.title` | `origam.time_picker.title` |
|
|
295
|
+
| `origam.video.disableCaptions` | `origam.video.disable_captions` |
|
|
296
|
+
| `origam.video.enableCaptions` | `origam.video.enable_captions` |
|
|
297
|
+
| `origam.video.enterFullscreen` | `origam.video.enter_fullscreen` |
|
|
298
|
+
| `origam.video.enterPip` | `origam.video.enter_pip` |
|
|
299
|
+
| `origam.video.exitFullscreen` | `origam.video.exit_fullscreen` |
|
|
300
|
+
| `origam.video.exitPip` | `origam.video.exit_pip` |
|
|
301
|
+
|
|
302
|
+
### ⚠️ BREAKING — `<origam-title>` now defaults to `h2`, not `h1`
|
|
303
|
+
|
|
304
|
+
Every `<origam-title>` written **without** an explicit `tag` renders an
|
|
305
|
+
`<h2>` instead of an `<h1>`. This changes the rendered DOM, the heading
|
|
306
|
+
outline, any CSS keyed on `h1`, and the result of automated a11y audits.
|
|
307
|
+
|
|
308
|
+
**Why**: a document carries exactly one `h1`, so `h1` is the one level a
|
|
309
|
+
shared component must never emit by default — two untagged titles on a page
|
|
310
|
+
produced two `h1`s and broke both the heading order and the a11y audit. `h2`
|
|
311
|
+
is the deepest level that is always valid under a page-owned `h1`, and
|
|
312
|
+
repeating it is legal. The correct level depends on document position, which
|
|
313
|
+
the component cannot know: pass `tag` explicitly whenever it matters.
|
|
314
|
+
|
|
315
|
+
**Migration** — restore the old behaviour app-wide in one line, through the
|
|
316
|
+
defaults layer:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
createOrigam({ theme: { components: { 'origam-title': { tag: 'h1' } } } })
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
⚠️ **This migration only works from this release onwards.** On any earlier
|
|
323
|
+
version it silently does nothing: `OrigamTitle`'s template bound `:is="tag"`,
|
|
324
|
+
and in `<script setup>` a bare prop name in the template resolves against the
|
|
325
|
+
raw `$props`, never against the `useDefaults()` proxy — so the theme value
|
|
326
|
+
was read and then ignored. Fixed here by binding `:is="props.tag"`, the same
|
|
327
|
+
correction as the seven components in #250. Do not conclude the snippet is
|
|
328
|
+
wrong if you try it on 2.12.x.
|
|
329
|
+
|
|
330
|
+
### Fixed
|
|
331
|
+
|
|
332
|
+
- **`useStyle()` no longer overwrites a consumer-supplied `id`.** The
|
|
333
|
+
composable returns the id a component puts on its root element *and* the
|
|
334
|
+
selector of the `#<id> { … }` rule it injects — the two must be the same
|
|
335
|
+
value or the rule stops matching. It now accepts that id from the caller
|
|
336
|
+
(`useStyle(styles, () => props.id)`), reactively, so an `id` that only
|
|
337
|
+
appears on a later render is still picked up. Applied to `OrigamBtn`, where
|
|
338
|
+
the generated id silently replaced the consumer's and broke every
|
|
339
|
+
`<label for>` / `aria-labelledby` / `aria-controls` / `aria-describedby`
|
|
340
|
+
association targeting a button, and to `OrigamTitle`, where element and
|
|
341
|
+
rule had diverged. ⚠️ **138 of the 140 components calling `useStyle` are
|
|
342
|
+
still affected**, in three shapes: 14 swallow a consumer `id` outright
|
|
343
|
+
(same defect as Btn); 114 bind no id to their root at all, so where the
|
|
344
|
+
component also declares an `id` prop — 192 of 217 do — that prop is inert
|
|
345
|
+
and a consumer simply cannot set an id (measured on `OrigamCard` and
|
|
346
|
+
`OrigamKbd`, which render no `id` attribute even when one is passed); and
|
|
347
|
+
10 bind some other id while the rule keeps targeting the generated one,
|
|
348
|
+
the same divergence just fixed on Title. Tracked separately; a blanket
|
|
349
|
+
default was deliberately rejected because `OrigamSnackbarGroup` uses
|
|
350
|
+
`props.id` as a group *name*, not a DOM id.
|
|
351
|
+
- **The injected stylesheet is valid CSS again.** Every rule carried a bare
|
|
352
|
+
`false` in its body (`#id {false}`). Vue's `StyleValue` type includes
|
|
353
|
+
`false`, so the shared `style` prop compiles to a runtime type containing
|
|
354
|
+
`Boolean`, and Vue resolves an unpassed boolean-typed prop to the concrete
|
|
355
|
+
value `false` — which was serialised verbatim. 192 of 217 components
|
|
356
|
+
declare that prop. No visual impact: Chromium, Firefox and WebKit all
|
|
357
|
+
discard the invalid declaration by CSS error recovery and apply the rest
|
|
358
|
+
unchanged. The cost was invalid CSS shipped to consumers, and jsdom
|
|
359
|
+
rejecting every generated sheet under test ("Could not parse CSS
|
|
360
|
+
stylesheet"). Numbers are dropped for the same reason, and an object nested
|
|
361
|
+
inside an array is now expanded instead of reaching the sheet as
|
|
362
|
+
`[object Object]`.
|
|
363
|
+
- **`<origam-title>` reads its theme defaults.** It never called
|
|
364
|
+
`useDefaults()`, so `theme.components['origam-title']` was inert.
|
|
365
|
+
|
|
366
|
+
### Added
|
|
367
|
+
|
|
368
|
+
- **`escapeCssIdent()`** (`origam/utils`) — escapes an arbitrary string for
|
|
369
|
+
interpolation as a CSS ident. Required now that `useStyle()` builds a real
|
|
370
|
+
stylesheet rule out of a consumer-supplied id: without it an id such as
|
|
371
|
+
`a { } body { display: none }` appends attacker- or typo-controlled rules
|
|
372
|
+
to the document, and ids that are legal in HTML but illegal as a CSS ident
|
|
373
|
+
(leading digit, dots, colons) silently kill their own rule. Delegates to
|
|
374
|
+
the native `CSS.escape` when present, with a spec-equivalent fallback for
|
|
375
|
+
jsdom and SSR — the two were compared over 34 inputs in Chromium and are
|
|
376
|
+
byte-identical.
|
|
377
|
+
|
|
378
|
+
### Changed
|
|
379
|
+
|
|
380
|
+
- **`useStyle(styles, uniq)`** — `uniq` widened from `string | undefined` to
|
|
381
|
+
`MaybeRefOrGetter<string | undefined>`. Backward compatible: a plain string
|
|
382
|
+
still behaves exactly as before, and an empty value falls back to the
|
|
383
|
+
generated `<name>-<uid>` id rather than emitting the invalid selector `#`.
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## [2.12.1] — 2026-07-31
|
|
388
|
+
|
|
389
|
+
**Hotfix — `vue-router` 5 is now accepted.** A consuming project could not
|
|
390
|
+
upgrade to Nuxt 4.5.1: Nuxt pulls `vue-router` 5, while origam declared an
|
|
391
|
+
optional peer of `vue-router: "^4.5.0"`. The peer range is widened to
|
|
392
|
+
`"^4.5.0 || ^5.0.0"`.
|
|
393
|
+
|
|
394
|
+
Nothing else changed — no runtime code, no public API, no dependency added.
|
|
395
|
+
The widening is strictly additive: projects on `vue-router` 4 are unaffected,
|
|
396
|
+
projects on 5 stop being blocked.
|
|
397
|
+
|
|
398
|
+
Vue Router 5 is, in the maintainers' own words, "a *boring* release, it
|
|
399
|
+
merges unplugin-vue-router into the core package with no breaking changes",
|
|
400
|
+
and the official migration guide states: "If you're using Vue Router 4
|
|
401
|
+
without unplugin-vue-router, there are no breaking changes". origam does not
|
|
402
|
+
use unplugin-vue-router, nor the iife build (the single documented breaking
|
|
403
|
+
change is that the iife bundle no longer ships `@vue/devtools-api`).
|
|
404
|
+
|
|
405
|
+
Verified on both majors before shipping: every symbol origam imports
|
|
406
|
+
(`useLink`, `RouterLink.useLink`, `RouteLocationRaw`, `Router`,
|
|
407
|
+
`RouteLocationNormalizedLoaded`, `NavigationGuardNext`, `UseLinkOptions`)
|
|
408
|
+
still exists in 5.2.0; type-check of the design system is clean against
|
|
409
|
+
4.6.4 and 5.2.0 alike; and the built `dist` was exercised at runtime under
|
|
410
|
+
both — href resolution, named routes, click navigation, external hrefs,
|
|
411
|
+
`isActive`, and the tag fallback when no `to` is passed all behave
|
|
412
|
+
identically.
|
|
413
|
+
|
|
414
|
+
**Consumer note.** `vue-router` 5 requires `vue` `^3.5.34 || ^4.0.0`, while
|
|
415
|
+
origam's peer on `vue` remains `^3.5.0`. A project pinned between Vue 3.5.0
|
|
416
|
+
and 3.5.33 that adopts `vue-router` 5 will hit a conflict — between `vue`
|
|
417
|
+
and `vue-router` directly, not with origam.
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## [2.12.0] — 2026-07-29
|
|
422
|
+
|
|
423
|
+
**Hotfix — `vue-i18n` is optional again.** A consuming project reported that
|
|
424
|
+
origam could not be enabled at all: `createOrigam()` reached `createLocale()`,
|
|
425
|
+
which imported `vue-i18n` at module level, even though the package declares it
|
|
426
|
+
as an **optional** peer. Any project without `vue-i18n` failed at import time.
|
|
427
|
+
|
|
428
|
+
### Fixed
|
|
429
|
+
|
|
430
|
+
- **`createLocale()` no longer imports `vue-i18n`.** The default locale is now
|
|
431
|
+
backed by a built-in adapter shipped with the DS. Runtime *and* type
|
|
432
|
+
dependencies are gone — `grep vue-i18n` over the published `dist/` returns
|
|
433
|
+
only a string literal (the vue-i18n adapter's own `name` field) and a
|
|
434
|
+
comment. (Reported by a consumer.)
|
|
435
|
+
- The `vue-i18n` **type** imports in `locale.interface.ts` / `locale.util.ts`
|
|
436
|
+
are replaced by locally-declared structural types. An `import type` costs
|
|
437
|
+
nothing at runtime but still breaks `tsc` for a project that does not install
|
|
438
|
+
the package once `skipLibCheck` is `false` — the same class of bug, one step
|
|
439
|
+
further.
|
|
440
|
+
|
|
441
|
+
### Added
|
|
442
|
+
|
|
443
|
+
- **`createBuiltinAdapter()`**, exported from `origam/utils`. Resolves dotted
|
|
444
|
+
keys, falls back to the fallback locale then to the key itself, and
|
|
445
|
+
interpolates both positional (`{0}`) and named (`{value}`) params — the only
|
|
446
|
+
two forms used by the DS's own messages.
|
|
447
|
+
|
|
448
|
+
It deliberately does **not** reimplement `vue-i18n`: no plurals, no linked
|
|
449
|
+
messages, no date formatting. A consumer needing those keeps `vue-i18n` and
|
|
450
|
+
passes their own adapter.
|
|
451
|
+
|
|
452
|
+
### Changed — read this if you use `vue-i18n`
|
|
453
|
+
|
|
454
|
+
**The default adapter is no longer `vue-i18n`.** If you relied on
|
|
455
|
+
`createOrigam()` building a `vue-i18n` instance for you, pass it explicitly:
|
|
456
|
+
|
|
457
|
+
```ts
|
|
458
|
+
import { createOrigam } from 'origam'
|
|
459
|
+
import { createVueI18nAdapter } from 'origam/utils'
|
|
460
|
+
import { createI18n, useI18n } from 'vue-i18n'
|
|
461
|
+
|
|
462
|
+
const i18n = createI18n({ legacy: false, locale: 'en' })
|
|
463
|
+
|
|
464
|
+
createOrigam({
|
|
465
|
+
locale: { adapter: createVueI18nAdapter({ i18n, useI18n }) }
|
|
466
|
+
})
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
Nothing changes for the DS's own strings — they resolve identically through
|
|
470
|
+
either adapter. This is a **minor** rather than a patch precisely because that
|
|
471
|
+
default changed.
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## [2.11.0] — 2026-07-28
|
|
476
|
+
|
|
477
|
+
Theming-resolution release. Every fix here has the same root cause: a
|
|
478
|
+
component **declared** theme-able props but never **consumed** them, so an
|
|
479
|
+
`IOrigamTheme.components` block was a silent no-op. Minor rather than patch
|
|
480
|
+
because the public prop surface grew (see *Added*), even though every commit
|
|
481
|
+
is labelled `fix`.
|
|
482
|
+
|
|
483
|
+
### Added
|
|
484
|
+
|
|
485
|
+
- **`ISelectionControlProps` now extends `IBorderProps` / `IRoundedProps` /
|
|
486
|
+
`IElevationProps`**, inherited by `ICheckboxBtnProps` and `IRadioBtnProps`.
|
|
487
|
+
`OrigamSelectionControl` consumes them through the standard
|
|
488
|
+
`useBorder` / `useRounded` / `useElevation` composables, on the
|
|
489
|
+
state-layer box that owns the control's visible surface — same relay point
|
|
490
|
+
as `OrigamSwitchTrack`. Checkbox and Radio therefore accept `border`,
|
|
491
|
+
`rounded` and `elevation`, from a prop or from a theme. (#241)
|
|
492
|
+
|
|
493
|
+
::: warning Known limit — `rounded` alone paints nothing at rest
|
|
494
|
+
The state-layer box has no background and no border by default, so a
|
|
495
|
+
`rounded` passed on its own is measurable in the computed style but
|
|
496
|
+
produces no visible difference at rest. It shows on hover (the state layer
|
|
497
|
+
now follows the radius), or combined with `border` / `elevation` / a
|
|
498
|
+
custom background. The glyph itself (`mdi-checkbox-*`, `mdi-radiobox-*`)
|
|
499
|
+
is an icon-font character and keeps its own shape — reshaping the mark
|
|
500
|
+
would be a rendering change, not a prop. Documented in the Checkbox and
|
|
501
|
+
Radio pages.
|
|
502
|
+
:::
|
|
503
|
+
|
|
504
|
+
### Fixed
|
|
505
|
+
|
|
506
|
+
- **`OrigamBtnGroup`** forwarded `density`/`color`/`bgColor`/`size`/`hover`/
|
|
507
|
+
`active` to its children unconditionally, overwriting theme defaults with
|
|
508
|
+
`undefined`. Now filtered through `usePassedProps()` — the helper that
|
|
509
|
+
detects whether the *consumer* actually passed a prop, since Vue coerces an
|
|
510
|
+
unpassed boolean to `false`, never `undefined`. (#274)
|
|
511
|
+
- **`:is="tag"` bypassed theme resolution** on 7 components — `OrigamAvatar`,
|
|
512
|
+
`OrigamBtnGroup`, `OrigamExpansionPanel`, `OrigamLabel`, `OrigamMessages`,
|
|
513
|
+
`OrigamTab`, `OrigamTabs`. In `<script setup>` the template binds each prop
|
|
514
|
+
from the *raw* `$props`, independently of the local
|
|
515
|
+
`props = useDefaults(_props)`, so a bare `:is="tag"` never saw the theme's
|
|
516
|
+
value. The audit the ticket asked for widened the scope from 1 file to 7.
|
|
517
|
+
(#250)
|
|
518
|
+
- **`OrigamSelectionControl` declared `grid-area: control` unconditionally**,
|
|
519
|
+
assuming it always sits inside a Field/Input named grid. Any consumer
|
|
520
|
+
placing a bare control in its own grid saw every instance collapse onto one
|
|
521
|
+
cell. The declaration was in fact **dead code** on the Field/Input path —
|
|
522
|
+
`.origam-input__control` already owns `grid-area: control` *and* is
|
|
523
|
+
`display: flex`, and a `grid-area` on a flex child has no effect — so it is
|
|
524
|
+
removed rather than scoped. (#247)
|
|
525
|
+
- **The Checkbox/Radio hover halo hardcoded `border-radius: 100%`**, staying
|
|
526
|
+
circular even under `rounded="md"` — while being the only surface the prop
|
|
527
|
+
could paint. Now `inherit`. (#241)
|
|
528
|
+
|
|
529
|
+
### Internal
|
|
530
|
+
|
|
531
|
+
- Marketing i18n: locale files split one per top-level namespace, an
|
|
532
|
+
`i18n:check` script wired into CI, and 195 missing translation keys filled
|
|
533
|
+
(400 → 205). EN/FR parity reached **0 gap** — the admin backoffice went
|
|
534
|
+
from 0 % to fully translated. No change to the published package.
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## [2.10.0] — 2026-07-27
|
|
539
|
+
|
|
540
|
+
Field-rendering release. No new API — no component, prop, emit or slot was
|
|
541
|
+
added, and no source file was created. The minor bump is there to flag one
|
|
542
|
+
**visible rendering change** for consumers of `origam/styles` (see *Changed*);
|
|
543
|
+
everything else is a fix.
|
|
544
|
+
|
|
545
|
+
### Changed
|
|
546
|
+
|
|
547
|
+
- **`--origam-field__input---padding-start` / `-end` now resolve to `0`**
|
|
548
|
+
(was `var(--origam-space---4)`, i.e. 16px) for consumers of the bundled
|
|
549
|
+
`origam/styles` (`main.css`). The inline spacing of a field is owned by the
|
|
550
|
+
**root** token `--origam-field---padding-start`, which is unchanged at
|
|
551
|
+
`{space.4}`; the input wrapper sits inside it, so a second inline padding
|
|
552
|
+
doubled it — and it truncated the value text of narrow controls
|
|
553
|
+
(`elevated` → `ele…`). Consumers importing `origam/tokens/css/{light,dark}`
|
|
554
|
+
are **unaffected**: those sheets already emitted `0` since 2026-07-24.
|
|
555
|
+
Fields keep their inline spacing, supplied by the root token. (#295)
|
|
556
|
+
|
|
557
|
+
### Fixed
|
|
558
|
+
|
|
559
|
+
- **Tokens** — `field.input.padding-start/end` was `0` in the generated sheets
|
|
560
|
+
but `{space.4}` in the token source, so every `tokens:build` silently
|
|
561
|
+
reverted the fix, and `main.css` (produced by the separate `styles:build`
|
|
562
|
+
step) had drifted to a third value. The source now carries the intent and
|
|
563
|
+
the pipeline is idempotent — a second full build produces no diff. (#295)
|
|
564
|
+
- **`OrigamSliderField`** — the `rounded` prop was inert: radii were
|
|
565
|
+
hardcoded instead of going through `useRounded()`. (#283)
|
|
566
|
+
- **`OrigamApp`** — did not call `useDefaults()`, so
|
|
567
|
+
`theme.components['origam-app']` (`bgColor`, `fullHeight`) was ignored.
|
|
568
|
+
- **`OrigamField`** — inline padding is floored at the corner radius so
|
|
569
|
+
content clears the rounded outline, and the outline's start leg is widened
|
|
570
|
+
to match, the left corner no longer rendering flatter than the right.
|
|
571
|
+
Prepended fields are excluded to avoid a swatch/icon box artifact.
|
|
572
|
+
- **`OrigamField`** — the outlined floating label was pinned to the notch
|
|
573
|
+
corner by a hard `margin: 0 4px` while the input text and the resting label
|
|
574
|
+
both sit at `--origam-field__input---padding-start`, leaving the label
|
|
575
|
+
misaligned with its own value — visibly so on large-radius themes.
|
|
576
|
+
- **`OrigamColorPickerField`** — the swatch sat inside the field's inline
|
|
577
|
+
padding, so any consumer raising `--origam-field---padding-start` opened a
|
|
578
|
+
gap between the colour and the left border. Also fixed: the field wrapping
|
|
579
|
+
onto two lines when given content, and the swatch's square outer corner.
|
|
580
|
+
- **`OrigamColorPicker`** — a class typo on the hue/alpha slider fill
|
|
581
|
+
occluded both gradients.
|
|
582
|
+
- **`OrigamDatePickerField`** — wrapped onto two lines when given content in
|
|
583
|
+
`range` mode.
|
|
584
|
+
|
|
585
|
+
### Internal
|
|
586
|
+
|
|
587
|
+
- Quality Gate unblocked: the two SonarQube new-code violations that had kept
|
|
588
|
+
the `Build` workflow red on every `develop` push since 2026-07-22 are
|
|
589
|
+
resolved — a nested ternary in `OrigamSliderField` and a duplicate
|
|
590
|
+
`:deep()` selector in `OrigamColorPickerField`. Both were pure
|
|
591
|
+
maintainability findings, no behaviour change. (#296)
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
## [2.9.0] — 2026-07-22
|
|
596
|
+
|
|
597
|
+
Theming-enablement release. This ships the design-token **hooks** and the
|
|
598
|
+
`useDefaults` **wiring** that let a consumer configure a component's
|
|
599
|
+
appearance entirely from an `IOrigamTheme` object (props-first), plus the
|
|
600
|
+
CSS hooks brand themes need for translucency and separation. No breaking
|
|
601
|
+
changes — every addition is opt-in via a new component token with an inert
|
|
602
|
+
(`none`) fallback, so existing renders are byte-identical until a theme
|
|
603
|
+
sets a value.
|
|
604
|
+
|
|
605
|
+
### Added
|
|
606
|
+
|
|
607
|
+
- **`useDefaults()` now resolves per-component theme defaults on 11 more
|
|
608
|
+
components** that declared theme-configurable props but never read
|
|
609
|
+
`theme.components['origam-<name>']` — their theme config was silently
|
|
610
|
+
inert before this. This is the mechanism that makes props-first theming
|
|
611
|
+
actually apply. (#242)
|
|
612
|
+
- **Translucency & focus hooks on 7 components.** New component tokens,
|
|
613
|
+
each consumed with an inert fallback (`var(--…, none)`):
|
|
614
|
+
`--origam-chip---backdrop-filter`, `--origam-snackbar-item---backdrop-filter`,
|
|
615
|
+
`--origam-field---backdrop-filter` (+ `--origam-field---focus-ring-*`),
|
|
616
|
+
`--origam-switch__track---backdrop-filter`,
|
|
617
|
+
`--origam-selection-control__input---backdrop-filter`,
|
|
618
|
+
`--origam-tooltip---backdrop-filter`, `--origam-overlay-scrim---backdrop-filter`.
|
|
619
|
+
These give brand themes real `backdrop-filter` translucency (glass, frosted
|
|
620
|
+
surfaces) without per-instance `:style` overrides. (#253)
|
|
621
|
+
- **`OrigamAvatarGroup` separation ring.** Overlapping avatars now get a
|
|
622
|
+
legible seam via a dedicated `outline` — a CSS property distinct from
|
|
623
|
+
`box-shadow`, so it coexists with each theme's own avatar shadow with no
|
|
624
|
+
specificity or ordering tricks. Driven by new
|
|
625
|
+
`--origam-avatar-group__item---outline-{color,width,style}` tokens
|
|
626
|
+
(defaults `color.surface.default` / `2px` / `solid`). Only avatars rendered
|
|
627
|
+
inside an `<origam-avatar-group>` get it; a standalone `<origam-avatar>`
|
|
628
|
+
never does. (#263)
|
|
629
|
+
- **`usePassedProps()` composable helper.** Reports which props a consumer
|
|
630
|
+
actually passed by reading `vnode.props`, distinguishing a real value from
|
|
631
|
+
Vue 3 coercing an unpassed boolean prop to `false`. Used so a
|
|
632
|
+
theme-provided value is no longer overwritten by an `undefined → false`
|
|
633
|
+
default. (#263)
|
|
634
|
+
|
|
635
|
+
### Fixed
|
|
636
|
+
|
|
637
|
+
- **Live theme switching now updates component default *props*, not just CSS
|
|
638
|
+
variables.** The Nuxt module's theme singleton could be duplicated when the
|
|
639
|
+
host app resolved `origam/nuxt` (source) and `origam/composables` (compiled
|
|
640
|
+
`dist`) to two physical module files — two independent `_theme` singletons,
|
|
641
|
+
so the plugin's watcher (which reassigns the resolved per-component
|
|
642
|
+
defaults) listened to a different instance than the one `setTheme()`
|
|
643
|
+
mutated. Props stayed frozen on a live switch while cssVars followed (pure
|
|
644
|
+
CSS cascade). The singleton is now anchored on `globalThis` on the client
|
|
645
|
+
(server stays module-level to avoid leaking state across concurrent SSR
|
|
646
|
+
requests). (#275)
|
|
647
|
+
- **`OrigamRadio`, `OrigamTabs` and `OrigamSliderField` now call
|
|
648
|
+
`useDefaults()`.** They declared theme-configurable props (`activeBgColor`,
|
|
649
|
+
`variant`, `color`/`bgColor`) but never resolved
|
|
650
|
+
`theme.components['origam-<name>']`, so that theme config was silently inert.
|
|
651
|
+
(#279)
|
|
652
|
+
- **`OrigamDialog` `scrim` now renders.** `scrim` was missing from the
|
|
653
|
+
component's `withDefaults(...)`, so Vue 3 coerced the unpassed boolean to
|
|
654
|
+
`false` and forwarded it to `OrigamOverlay`, overriding the overlay's own
|
|
655
|
+
`scrim: true` default — the backdrop never showed. Anchored `scrim: true` in
|
|
656
|
+
`withDefaults` (same pattern as the existing `openOnClick` default). (#279)
|
|
657
|
+
- **`useDefaults` wiring no longer collapses `<origam-code>`'s header zone.**
|
|
658
|
+
The origam base theme carried a `compact: true` default (authored in a bulk
|
|
659
|
+
pass before `useDefaults` was wired, never visually validated); once the
|
|
660
|
+
wiring landed it forced every code block without an explicit `compact` prop
|
|
661
|
+
into the condensed single-line pill layout, dropping the
|
|
662
|
+
header/filename/line-numbers/lang-badge. Removed from the base theme. (#249)
|
|
663
|
+
- **`OrigamBtnGroup` renders as a single rounded surface.** The group applies
|
|
664
|
+
its `rounded`/`elevation` on the outer wrapper with `overflow: hidden`
|
|
665
|
+
clipping children to the inner curvature — no forced child heights, no
|
|
666
|
+
inner-radius tokens; group height derives from `OrigamBtn`'s own border-box
|
|
667
|
+
height calc. (#239)
|
|
668
|
+
- **`OrigamSwitchTrack.error` widened from `boolean` to `string | boolean`**
|
|
669
|
+
to match the canonical Commons `IValidationProps`, so the parent's
|
|
670
|
+
validation surface is type-assignable again (was `vue-tsc` TS2345, CI red).
|
|
671
|
+
Consumed by truthiness only — behaviour unchanged. (#239)
|
|
672
|
+
- **`OrigamLayout` / `OrigamApp` `full-height` no longer clamps content
|
|
673
|
+
taller than one screen.** The full-height wrapper was `height: 100vh`
|
|
674
|
+
(a hard clamp) instead of `min-height: 100vh` ("occupy at least the
|
|
675
|
+
viewport"). Content overflowing past one screen still rendered (nothing
|
|
676
|
+
was clipped — no `overflow: hidden` on that element), but the wrapper's
|
|
677
|
+
own box never grew to match, so any ancestor sizing itself off that box
|
|
678
|
+
(e.g. a themed page background) stopped short of the actual page height.
|
|
679
|
+
`full-height` pages now grow naturally past one screen and the
|
|
680
|
+
background/box always matches the true content height.
|
|
681
|
+
- Fixed a handful of pre-existing `$type: "dimension"` component tokens
|
|
682
|
+
with non-numeric values (`auto`, `calc(...)`) that crashed the
|
|
683
|
+
`size/rem` Style Dictionary transform and silently blocked
|
|
684
|
+
`tokens:build` / the full package build (`btn.width`, `dialog.max-width`,
|
|
685
|
+
`dialog.max-height`, `contextual-menu.max-height`, `menu.max-height`,
|
|
686
|
+
`expansion-panel.header.append.margin-inline-start`,
|
|
687
|
+
`expansion-panel.popout.max-width(-active)`,
|
|
688
|
+
`expansion-panel.inset.max-width-active`) — retyped to `"other"`,
|
|
689
|
+
matching the established pattern already used for equivalent tokens
|
|
690
|
+
elsewhere in the same files. No visual/behavioural change; this only
|
|
691
|
+
unblocks the build pipeline.
|
|
692
|
+
|
|
693
|
+
> The 8 marketing brand themes (glass · cartoon · geek · apple · editorial ·
|
|
694
|
+
> material · ecom) that these hooks enable live in the private
|
|
695
|
+
> `@origam/marketing` package and are **not** part of the npm `origam`
|
|
696
|
+
> release — this changelog tracks the published library only.
|
|
697
|
+
|
|
698
|
+
---
|
|
699
|
+
|
|
700
|
+
## [2.8.1] — 2026-07-15
|
|
701
|
+
|
|
702
|
+
### Fixed
|
|
703
|
+
|
|
704
|
+
- **The npm tarball now ships `README.md` and `LICENSE`.** The publish runs
|
|
705
|
+
from `packages/ds/` exclusively, but the package dir contained neither
|
|
706
|
+
file — both listed in the `files` array yet silently absent from every
|
|
707
|
+
published version (the npm page showed no readme at all). The new
|
|
708
|
+
npm-facing README covers install, quick start (plugin + token sheets +
|
|
709
|
+
Nuxt module), the theming model and the granular exports, and links to
|
|
710
|
+
the upcoming documentation site (https://origam.dev).
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
## [2.8.0] — 2026-07-15
|
|
715
|
+
|
|
716
|
+
### Added
|
|
717
|
+
|
|
718
|
+
- **Border per-side props are now wired** (`useBorder`). The discrete
|
|
719
|
+
`borderTop` / `borderRight` / `borderBottom` / `borderLeft` props on
|
|
720
|
+
`IBorderProps` — declared but never read until now — each accept a
|
|
721
|
+
number (px), a boolean (legacy thin opt-in) or a free-form
|
|
722
|
+
`"width style color"` string (same grammar as the global `border`
|
|
723
|
+
shorthand). New per-side color overrides ship alongside:
|
|
724
|
+
`borderTopColor` / `borderRightColor` / `borderBottomColor` /
|
|
725
|
+
`borderLeftColor` (`TColor` — semantic intent or raw CSS color).
|
|
726
|
+
Precedence is specific-over-global (global `border`, then standalone
|
|
727
|
+
`borderColor` / `borderStyle`, then per-side width/style, then per-side
|
|
728
|
+
color) and documented on `useBorder`. Emitted declarations are physical
|
|
729
|
+
(`border-top-width`, …). `useStateEffect` forwards the 8 new props, so
|
|
730
|
+
Card, Sheet and every other consumer gets them for free. Pilot
|
|
731
|
+
component: Card (story + doc + e2e).
|
|
732
|
+
- **`useElevation` accepts a free-form custom `box-shadow` value.**
|
|
733
|
+
`elevation` (new `TElevation` type) still takes a named origam rung or
|
|
734
|
+
a Material 0–24 number, and now also any shadow-like CSS string
|
|
735
|
+
(`var()` / `calc()` / `rgba()` / hex / length / `inset` signals),
|
|
736
|
+
emitted verbatim as `box-shadow`. Previously a custom string silently
|
|
737
|
+
produced NO shadow (`parseInt` read a leading `0` and resolved to the
|
|
738
|
+
`none` rung). Pilot component: Card (story + doc + e2e).
|
|
739
|
+
|
|
740
|
+
### Changed
|
|
741
|
+
|
|
742
|
+
- **`OrigamBlockquote`: `bgColor` renamed to `accentColor` (non-breaking).**
|
|
743
|
+
`bgColor` never painted a surface fill on Blockquote — it drove the
|
|
744
|
+
decorative accent (bar, background quote glyph, author label), which the
|
|
745
|
+
`bgColor` name misrepresented. `accentColor` is now the canonical prop;
|
|
746
|
+
`bgColor` keeps working as a deprecated alias (`accentColor` wins when
|
|
747
|
+
both are set) and logs a console warning once per session. Scope: this
|
|
748
|
+
pass only touches Blockquote — `bgColor` stays canonical and
|
|
749
|
+
non-deprecated on surface-fill components (Btn, Card, Chip, Badge,
|
|
750
|
+
Alert, Pagination, …). Removal of the `bgColor` alias on Blockquote is
|
|
751
|
+
targeted for v3.0.0. See `ROADMAP.md` — "Renommer `bgColor` →
|
|
752
|
+
`accentColor`".
|
|
753
|
+
|
|
754
|
+
### Fixed
|
|
755
|
+
|
|
756
|
+
- **`useMargin`: 2-value strings work again.** `margin="8px 16px"` silently
|
|
757
|
+
produced no styles (the 2-value case was missing from
|
|
758
|
+
`formatMarginStylesVar`; padding already had it). Both utils now document
|
|
759
|
+
the intentional 4-value order convention: values are grouped by logical
|
|
760
|
+
axis — `block-start`, `inline-start`, `block-end`, `inline-end`
|
|
761
|
+
(top / left / bottom / right) — NOT the native CSS clockwise shorthand.
|
|
762
|
+
RTL-safe by design, arbitrated in #216.
|
|
763
|
+
|
|
764
|
+
### Internal
|
|
765
|
+
|
|
766
|
+
- Marketing `/theming` — the Theme Builder ships six rich, validated
|
|
767
|
+
controls built from origam components (color/accentColor with intents +
|
|
768
|
+
custom picker, density, rounded with per-corner link/unlink, elevation
|
|
769
|
+
presets + full custom box-shadow, border with per-side width AND color
|
|
770
|
+
link/unlink, padding/margin devtools-style box-model with axis linking).
|
|
771
|
+
- Marketing playground isolation: the `origam` preview theme now carries a
|
|
772
|
+
complete GENERATED reset of every component var (~2700/mode, derived from
|
|
773
|
+
the DS baseline sheets) — ambient brand themes can no longer leak into
|
|
774
|
+
the playground preview.
|
|
775
|
+
- Marketing package restructured to the project architecture (`src/`
|
|
776
|
+
srcDir, locales under `src/assets/locales`, wireframes under
|
|
777
|
+
`wireframes/`).
|
|
778
|
+
|
|
779
|
+
---
|
|
780
|
+
|
|
781
|
+
## [2.7.3] — 2026-07-10
|
|
782
|
+
|
|
783
|
+
### Fixed
|
|
784
|
+
|
|
785
|
+
- **`OrigamField`: the `rounded` prop now drives the whole field chrome.**
|
|
786
|
+
The prop used to round the outer box only (inline `border-radius`), while
|
|
787
|
+
the inner chrome (outline legs, per-corner radii) reads
|
|
788
|
+
`--origam-field---border-radius` — which the prop never touched, so the
|
|
789
|
+
outline corners stayed at the default and mismatched the box (themes had
|
|
790
|
+
to force the var with `!important` hacks). The field now mirrors the
|
|
791
|
+
radius resolved from the `rounded` prop into its component var, keeping
|
|
792
|
+
box and outline in sync for every field type (text, select, textarea,
|
|
793
|
+
number, password, date, file, color). `shaped` / `shaped-invert` are
|
|
794
|
+
unaffected and stay SCSS-owned.
|
|
795
|
+
|
|
796
|
+
---
|
|
797
|
+
|
|
798
|
+
## [2.7.2] — 2026-07-09
|
|
799
|
+
|
|
800
|
+
### Fixed
|
|
801
|
+
|
|
802
|
+
- **Default text (and every `currentColor` icon) rendered browser-black in
|
|
803
|
+
dark mode.** The semantic text token flips correctly
|
|
804
|
+
(`neutral-900 → neutral-50`) and `app.json` has declared
|
|
805
|
+
`app.color` / `app.background-color` all along — but nothing consumed
|
|
806
|
+
them. `OrigamApp` now paints the base pair
|
|
807
|
+
(`color: var(--origam-app---color)`,
|
|
808
|
+
`background-color: var(--origam-app---background-color)`), and
|
|
809
|
+
`OrigamThemeProvider` (`display: contents`) sets the inherited `color`
|
|
810
|
+
so a local `data-mode="dark"` sub-tree gets readable defaults too.
|
|
811
|
+
Verified in both modes (computed styles) with no light-mode change.
|
|
812
|
+
|
|
813
|
+
---
|
|
814
|
+
|
|
815
|
+
## [2.7.1] — 2026-07-09
|
|
816
|
+
|
|
817
|
+
### Fixed
|
|
818
|
+
|
|
819
|
+
- **`origam/styles` CSS entry shipped empty.** `src/assets/css/main.css` was
|
|
820
|
+
0 bytes in every published version (2.6.x, 2.7.0), so
|
|
821
|
+
`import 'origam/styles'` (the `style`/`import`/`require` conditions)
|
|
822
|
+
delivered no tokens and no utility classes — only the SCSS path
|
|
823
|
+
(`@use 'origam/styles'`) worked. `main.css` is now compiled from
|
|
824
|
+
`main.scss` at build time (`styles:build`): the full aggregate
|
|
825
|
+
(primitives + light + dark + utilities + reset, ~366 KB) ships in the
|
|
826
|
+
package.
|
|
827
|
+
|
|
828
|
+
### Internal
|
|
829
|
+
|
|
830
|
+
- New brand identity: the "cube sonobe" logo (modular origami — identical
|
|
831
|
+
folded units assembling into a structure) replaces the legacy mark across
|
|
832
|
+
the repo (docs/stories/marketing assets; not part of the npm tarball).
|
|
833
|
+
- npm publishing is handled by CI again (release workflow auth fixed).
|
|
834
|
+
|
|
835
|
+
---
|
|
836
|
+
|
|
837
|
+
## [2.7.0] — 2026-07-08
|
|
838
|
+
|
|
839
|
+
### Added
|
|
840
|
+
|
|
841
|
+
- `OrigamThemeProvider` now applies the active theme's **component default
|
|
842
|
+
props** to its sub-tree (props-first theming cascades into sub-trees via
|
|
843
|
+
`provideDefaults`), not just the `data-theme` / `data-mode` attributes. A
|
|
844
|
+
`<origam-theme-provider theme="brand-x">` wrapper therefore gives every
|
|
845
|
+
descendant that brand's per-component defaults.
|
|
846
|
+
- Glass theme: `OrigamAlert` glassmorphism (transparency + blur).
|
|
847
|
+
|
|
848
|
+
### Changed
|
|
849
|
+
|
|
850
|
+
- **`shiki` is now an OPTIONAL peer dependency** (removed from `dependencies`).
|
|
851
|
+
`OrigamCode` degrades gracefully to plain, un-highlighted code when `shiki`
|
|
852
|
+
is not installed (a one-time console warning is emitted; line numbers,
|
|
853
|
+
highlight-lines and copy keep working). **Migration:** add `shiki` (`^4.3.1`)
|
|
854
|
+
to your app's dependencies to keep syntax highlighting. This drops a heavy
|
|
855
|
+
(~3 MB) hard dependency from apps that don't render code blocks.
|
|
856
|
+
|
|
857
|
+
### Fixed
|
|
858
|
+
|
|
859
|
+
- `OrigamPagination` colored mode (`color` / `bgColor`) now fills the page
|
|
860
|
+
buttons. The theme's default `text` btn variant
|
|
861
|
+
(`background-color: transparent !important`) was swallowing the intent fill,
|
|
862
|
+
leaving resting buttons transparent; the row now forces the `flat` variant
|
|
863
|
+
when a colour is set.
|
|
864
|
+
- Cartoon dark `/theming`: fields adopt the theme and the primary btn contrast
|
|
865
|
+
is corrected.
|
|
866
|
+
|
|
867
|
+
### Internal
|
|
868
|
+
|
|
869
|
+
- Restored the green `vue-tsc` type-check gate under TypeScript 6.
|
|
870
|
+
- E2E suite stabilised: sharded CI plus deterministic fixture-drift fixes
|
|
871
|
+
(variant-index / navigation realignment) — the "flaky" bucket was
|
|
872
|
+
deterministic drift, not timing.
|
|
873
|
+
|
|
874
|
+
---
|
|
875
|
+
|
|
876
|
+
## [2.6.3] — 2026-07-03
|
|
877
|
+
|
|
878
|
+
### Changed
|
|
879
|
+
|
|
880
|
+
- Internal code-quality cleanup to green the SonarQube quality gate
|
|
881
|
+
(`new_violations`): removed redundant type assertions, merged duplicate
|
|
882
|
+
imports, extracted nested template literals, `||` → `??`, dropped a redundant
|
|
883
|
+
`| undefined`, converted a call-signature interface to a function type, and
|
|
884
|
+
removed a leftover CSS comment. **No API or runtime behaviour change** — pure
|
|
885
|
+
refactor (PR #87).
|
|
886
|
+
- Marketing site (private, not part of the published `origam` package):
|
|
887
|
+
`@nuxtjs/i18n` 9 → 10 and `@nuxtjs/seo` 2 → 5 (locales moved to `i18n/locales/`;
|
|
888
|
+
v10 config breaking changes handled) — PR #88.
|
|
889
|
+
|
|
890
|
+
---
|
|
891
|
+
|
|
892
|
+
## [2.6.2] — 2026-07-03
|
|
893
|
+
|
|
894
|
+
### Changed
|
|
895
|
+
|
|
896
|
+
- Dependency maintenance (Dependabot): TypeScript 5.8 → 6.0, ESLint 9 → 10
|
|
897
|
+
(+ `typescript-eslint`, `eslint-plugin-vue`), Style Dictionary 4 → 5
|
|
898
|
+
(+ `@tokens-studio/sd-transforms` 1 → 2), Shiki 3 → 4 (VitePress docs), and a
|
|
899
|
+
dev-tooling batch (`jsdom` 25 → 29, `happy-dom`, `sass`, `@types/node`,
|
|
900
|
+
`unplugin-vue-components`, `lint-staged`, `globals`…). **Vite and Vue stay
|
|
901
|
+
pinned** (`vite ~7.3.6`, `vue 3.5.35`) — their bumps were declined (Vite ≥ 7.3.5
|
|
902
|
+
broke the build; the Vue override neutralises the bump). `react-dom` bump
|
|
903
|
+
closed (not a dependency of a Vue design system).
|
|
904
|
+
|
|
905
|
+
### Fixed
|
|
906
|
+
|
|
907
|
+
- CI publish (`release.yml`): the npm publish step failed with **E404** because
|
|
908
|
+
`pnpm publish` did not expand the `${NODE_AUTH_TOKEN}` placeholder from
|
|
909
|
+
setup-node's `.npmrc` → the PUT went out unauthenticated. The resolved token is
|
|
910
|
+
now written to the `.npmrc` pnpm reads before publish (PR #82). 2.5.0/2.5.1/2.6.0
|
|
911
|
+
had failed here; 2.6.1 was published manually as a stop-gap.
|
|
912
|
+
- Test robustness: `transition.composable.spec.ts` used an invalid CSS sentinel
|
|
913
|
+
(`transformOrigin: 'original'`) that jsdom 29 now rejects; switched to a valid
|
|
914
|
+
value `top left` (PR #84).
|
|
915
|
+
|
|
916
|
+
---
|
|
917
|
+
|
|
918
|
+
## [2.6.1] — 2026-07-02
|
|
919
|
+
|
|
920
|
+
### Added
|
|
921
|
+
|
|
922
|
+
- `OrigamCode` — `compact` and `prompt` display modes (commit `5ebc6702`).
|
|
923
|
+
Compact mode collapses the component to a single line (no gutter, no
|
|
924
|
+
filename bar); `prompt` mode renders a shell-style `$` prefix. Two-axis
|
|
925
|
+
theming support: the component now tracks both `data-theme` and
|
|
926
|
+
`data-mode` on the host `<html>` element so it correctly switches in
|
|
927
|
+
dark/light sub-trees (`fix(ds): OrigamCode two-axis theming` — commit
|
|
928
|
+
`e2e716f2`). Scroller fill repaired in the same pass.
|
|
929
|
+
- `backdrop-filter` glassmorphism tokens on `Card` / `Sheet` / `Toolbar` /
|
|
930
|
+
`Menu` — new token group `component.{card,sheet,toolbar,menu}.backdrop-filter`
|
|
931
|
+
emitted as `--origam-{cmp}---backdrop-filter` CSS vars. Allows consumers
|
|
932
|
+
to build frosted-glass surfaces without overrides (commit `71647594`).
|
|
933
|
+
|
|
934
|
+
### Changed
|
|
935
|
+
|
|
936
|
+
- Brand themes removed from the DS (ADR-004) — the `origam` package now
|
|
937
|
+
ships only the `light` and `dark` base token sets. Consumer themes
|
|
938
|
+
(`sobre`, `geek`, `glass`, `cartoon`, `apple`, `ecom`, `editorial`,
|
|
939
|
+
`material`) are now authored in semantic JSON and installed via
|
|
940
|
+
`createOrigam({ themes: [...] })` rather than bundled into the lib.
|
|
941
|
+
The DS stays unopinionated; themes travel with the consumer
|
|
942
|
+
(commits `fbea1e3f`, `5f1bf51c`, `e0a47050`, `edc30e80`, `f7c56f06`,
|
|
943
|
+
`3b9f8510`).
|
|
944
|
+
|
|
945
|
+
### Fixed
|
|
946
|
+
|
|
947
|
+
- `OrigamImg` — `markBooted` `requestAnimationFrame` callback was called
|
|
948
|
+
during SSR, crashing server-render (`fix(ds): guard OrigamImg markBooted
|
|
949
|
+
rAF behind IN_BROWSER` — commit `6b09c5df`).
|
|
950
|
+
- Six SSR/theming gaps surfaced by the marketing site refactor: theme cookie
|
|
951
|
+
injection race, `data-mode` missing on first SSR render, component-level
|
|
952
|
+
token var scope, active-theme guard in `useTheme`, Menu/Tooltip token
|
|
953
|
+
resolution under sub-tree providers, Nuxt hydration mismatch on theme
|
|
954
|
+
toggle (commit `b9fe3219`).
|
|
955
|
+
- `OrigamSelect` — the chevron icon opened then instantly re-closed the menu
|
|
956
|
+
on the very first click (field not yet focused): the opening `mousedown`
|
|
957
|
+
bubbled to the control handler and double-toggled. The toggle now only
|
|
958
|
+
runs when the field is already focused; otherwise the event bubbles to the
|
|
959
|
+
single control handler that opens + focuses in one pass (PR #70).
|
|
960
|
+
- Sass `mixed-decls` deprecation warnings eliminated in `OrigamBtn` and
|
|
961
|
+
`OrigamSwitchTrack` — declarations that followed a nested rule (`@media` /
|
|
962
|
+
`&:focus-visible`) are moved above it. Pure reorder, identical compiled CSS
|
|
963
|
+
(PR #73).
|
|
964
|
+
- Layout offset counted twice in SSR / production builds (invisible in dev):
|
|
965
|
+
Vue's hydration-mismatch recovery could abandon a layout item mid-`setup()`
|
|
966
|
+
after it registered, leaving an orphan in `registered` so a 240 px drawer
|
|
967
|
+
reserved 480 px. `useLayoutItem`'s `register()` now evicts stale entries
|
|
968
|
+
occupying the same `(order, position)` slot (PR #76).
|
|
969
|
+
|
|
970
|
+
---
|
|
971
|
+
|
|
972
|
+
## [2.6.0] — 2026-06-11
|
|
973
|
+
|
|
974
|
+
> **The bracket + a11y + theming release.** `OrigamBracket` ships as a
|
|
975
|
+
> production-ready e-sport tournament component (double-elimination, Grand
|
|
976
|
+
> Final, statuses, full cross-cutting prop surface). `v-contrast` becomes
|
|
977
|
+
> the DS-wide WCAG text-legibility guard applied to every colour-bearing
|
|
978
|
+
> component. A two-axis theming engine (`data-theme` × `data-mode`) replaces
|
|
979
|
+
> the previous single-axis approach and enables brand themes to be installed
|
|
980
|
+
> at runtime via `createOrigam()`. Multiple composables and layout components
|
|
981
|
+
> also land fixes. 170 commits total in this range (DS-relevant subset
|
|
982
|
+
> documented below).
|
|
983
|
+
|
|
984
|
+
### Added
|
|
985
|
+
|
|
986
|
+
- `v-contrast` directive — runtime WCAG 2.1 AA text-legibility guard
|
|
987
|
+
(`feat(ds): v-contrast directive` — commit `8a80787a`). Applied
|
|
988
|
+
automatically to every colour-bearing component in the same cycle
|
|
989
|
+
(`feat(ds/a11y): apply v-contrast to all colour-bearing components` —
|
|
990
|
+
commit `4a4d4473`). Two correctness fixes landed before release: correct
|
|
991
|
+
WCAG luminance maths for composite translucent backgrounds (commit
|
|
992
|
+
`96ff45c4`), and `color(srgb …)` token format support + guard against
|
|
993
|
+
clobbering an explicit `color` prop (commits `34786ed5`, `12a3e378`).
|
|
994
|
+
- `OrigamBracket` — **major enrichment** on top of the 2.3.0 initial
|
|
995
|
+
component. Full double-elimination layout with two independent trees +
|
|
996
|
+
a Grand Final match (`feat(ds/bracket): real two-tree double-elimination
|
|
997
|
+
layout` — commit `dee1c23d`; Grand Final — commit `560eaf5b`).
|
|
998
|
+
Full cross-cutting prop surface on both `OrigamBracketMatch`
|
|
999
|
+
(`rounded` / `elevation` / `border` / `color` / `bgColor` — commit
|
|
1000
|
+
`8998f0e3`) and `OrigamBracketCompetitor` (commit `3088ad31`).
|
|
1001
|
+
Distinct status indicators (live, forfeit) + live-link prop (commit
|
|
1002
|
+
`4d38c65c`). Connector trait inherits match `border-width` / `style` /
|
|
1003
|
+
`color` (commit `94242ab3`). State variant (hover / active) wired
|
|
1004
|
+
(commits `0f4d5924`, `5edeca52`, `92edcd1b`). Auto-contrast on match
|
|
1005
|
+
text and seed numbers via `v-contrast` (commit `4cd5bc44`).
|
|
1006
|
+
`OrigamDivider` used internally for the match divider (commit `c472bb71`).
|
|
1007
|
+
- `OrigamBlockquote` — **major enrichment** from the initial Wave 4 stub.
|
|
1008
|
+
Two-axis colour model: `color` (foreground / accent) and `bgColor`
|
|
1009
|
+
(surface / left-bar background) applied on all 5 variants
|
|
1010
|
+
(`feat(ds/blockquote): two-axis colour model` — commit `ccfe8c82`).
|
|
1011
|
+
`bgColor` accent on every variant including `elegant` and `minimal`
|
|
1012
|
+
(commit `b2f5c1f3`). `color` also drives the source label (commit
|
|
1013
|
+
`d80e88ca`). Accent pseudo-element decoupled from the `border` prop
|
|
1014
|
+
(commit `c5843ee1`, revert + re-land in same release).
|
|
1015
|
+
- `OrigamBottomNav` — three additions: dimension props (`width`, `height`,
|
|
1016
|
+
etc.) now apply (fix — commit `21d44f63`); `position` prop
|
|
1017
|
+
(`start | center | end`) controls item distribution (commit `395a797e`);
|
|
1018
|
+
`active` state exposed and diffused to the child buttons (commit
|
|
1019
|
+
`5bdb3e85`).
|
|
1020
|
+
- `OrigamAvatarGroup` — three additions: `rounded`, `elevation`, `border`
|
|
1021
|
+
propagated to all child avatars (commit `725303bd`); `hover` / `active`
|
|
1022
|
+
state fan-out made reactive (commit `e163cfba`); click-outside collapses
|
|
1023
|
+
an expanded group (commit `c364aae3`).
|
|
1024
|
+
- `OrigamAppbar` — `scroll-behavior="active"` engages the active surface
|
|
1025
|
+
state on scroll (commit `07feb981`). `hide` and `inverted` scroll
|
|
1026
|
+
behaviours repaired; `scrollBehavior` now accepts combined tokens
|
|
1027
|
+
(commits `01912f4c`, `b625ea1e`). Removed dead props: `absolute`
|
|
1028
|
+
(commit `50c5ea32`), `floating` (commit `3d707ef5`), `width` /
|
|
1029
|
+
`minWidth` / `maxWidth` (commit `c5e7a6b9` — layout owns the
|
|
1030
|
+
cross-axis).
|
|
1031
|
+
- Two-axis theming engine — `data-theme` (brand identity) × `data-mode`
|
|
1032
|
+
(light/dark) replace the previous single `data-theme` approach. Shadow
|
|
1033
|
+
tokens gain per-theme variants (commit `f7c56f06`). `createOrigam()`
|
|
1034
|
+
gains a `theme` option to install one or multiple presets at init time,
|
|
1035
|
+
SSR no-flash (commits `edc30e80`, `5f1bf51c`, `3b9f8510`). Token
|
|
1036
|
+
authoring via semantic JSON (colors, radius, typography, shadow, spacing,
|
|
1037
|
+
animation groups) — `feat(ds): semantic JSON theme authoring` (commit
|
|
1038
|
+
`e0a47050`).
|
|
1039
|
+
- Field validation surface extended to 5 additional field components
|
|
1040
|
+
(`InlineEdit`, `OtpInputField`, `Clipboard`, `NumberField`,
|
|
1041
|
+
`SliderField`) via unified `useValidation` wiring (commit `27977831`).
|
|
1042
|
+
- `OrigamStatus` — forces its intent onto `color` / `bgColor` (non-
|
|
1043
|
+
overridable) so status badges are always correctly painted regardless of
|
|
1044
|
+
surrounding theme (commit `8a72740a`).
|
|
1045
|
+
|
|
1046
|
+
### Changed
|
|
1047
|
+
|
|
1048
|
+
- `OrigamAudio` — dimension props (`width`, `height`) now apply (commit
|
|
1049
|
+
`adaf4395`); content fills the available height with controls pushed
|
|
1050
|
+
to the bottom (commit `97207e26`); progress row grows when the bar is
|
|
1051
|
+
taller (commit `8f8f1c1f`); `rounded="none"` and shaped variants added
|
|
1052
|
+
(commit `073d0513`). Compact disc rendering fixed — oversized with
|
|
1053
|
+
floating grooves (commit `bef36e20`). Reactive `autoplay` (commit
|
|
1054
|
+
`0dc90fea`). Play-button focus tint lingering + playlist active item
|
|
1055
|
+
blinking fixed (commit `6e6042bb`).
|
|
1056
|
+
- `OrigamToolbar` — `hover` / `active` now drive the surface colour
|
|
1057
|
+
(state-aware) (commit `c966e9c6`).
|
|
1058
|
+
- `OrigamAlert` — removed redundant `prominent` prop (commit `f32af0a8`).
|
|
1059
|
+
- `OrigamAvatar` — `color` prop now applies; `v-contrast` was previously
|
|
1060
|
+
overriding an explicit `color` (commit `369e0afa`). Dead `start` / `end`
|
|
1061
|
+
props removed (commit `84f324fe`).
|
|
1062
|
+
- `OrigamApp` — now exposes only `color` / `bgColor` and forwards them to
|
|
1063
|
+
the layout (commit `111f6596`).
|
|
1064
|
+
- DS-wide: `useStateEffect` repaired — runtime prop changes for
|
|
1065
|
+
`color` / `bgColor` and similar were silently ignored after initial
|
|
1066
|
+
mount (commit `a1a66120`). Reactive-update loops in `AvatarGroup` and
|
|
1067
|
+
`RadioGroup` killed (commit `4c5eb18d`).
|
|
1068
|
+
- Monorepo migration — `packages/ds`, `packages/marketing`,
|
|
1069
|
+
`packages/stories`, `packages/docs`, `packages/tests`,
|
|
1070
|
+
`packages/figma-plugin` are now first-class pnpm workspace packages
|
|
1071
|
+
(commits `4d53558b`, `70f1819f`, `fa0ed997`).
|
|
1072
|
+
|
|
1073
|
+
### Fixed
|
|
1074
|
+
|
|
1075
|
+
- `OrigamBtn` — `border-color` and `border-style` are now customisable
|
|
1076
|
+
props (commit `b44add69`).
|
|
1077
|
+
- `OrigamField` — themed `border-radius` now resolves via the real
|
|
1078
|
+
component token (commit `851b2a2f`).
|
|
1079
|
+
- `OrigamExpansionPanels` — `useElevation` import missing, causing
|
|
1080
|
+
`ReferenceError` at mount (commit `2eef9288`).
|
|
1081
|
+
- `OrigamDatePicker` — crash guard for empty `daysInMonth` when reading
|
|
1082
|
+
`date` prop (commit `896b9eec`).
|
|
1083
|
+
- `OrigamBorder` — numeric `border-width` values were invisible (missing
|
|
1084
|
+
`border-style` and `border-color` defaults) (commit `e9a151ec`).
|
|
1085
|
+
- `rounded="none"` — did not actually remove the border radius; affected
|
|
1086
|
+
`OrigamAudio` and other consumers (commit `073d0513`).
|
|
1087
|
+
- `fix(ds): /* @vite-ignore */ on shiki dynamic import` — defensive guard
|
|
1088
|
+
to silence the Vite bundler warning on the `OrigamCode` lazy highlighter
|
|
1089
|
+
import (commit `f6bbc494`).
|
|
1090
|
+
- DS/marketing integration — MDI class prefix resolution, search hotkey
|
|
1091
|
+
double-fire, Menu anchor positioning (commit `d113a245`); lib dist
|
|
1092
|
+
missing CSS in first production deploy (commit `62667fbc`).
|
|
1093
|
+
|
|
1094
|
+
---
|
|
1095
|
+
|
|
1096
|
+
## [2.5.1] — 2026-05-27
|
|
1097
|
+
|
|
1098
|
+
> **Patch.** Two housekeeping commits with no public API impact.
|
|
1099
|
+
|
|
1100
|
+
### Changed
|
|
1101
|
+
|
|
1102
|
+
- Repository structure cleaned up: unit specs moved to `tests/TU/`,
|
|
1103
|
+
the dev playground dropped (commit `52f7dc70`).
|
|
1104
|
+
- `.gitignore` updated to exclude `tests/a11y/.report` and
|
|
1105
|
+
`tests/a11y/.results` artefacts (commit `6c2ef153`).
|
|
1106
|
+
|
|
1107
|
+
---
|
|
1108
|
+
|
|
1109
|
+
## [2.5.0] — 2026-05-24
|
|
1110
|
+
|
|
1111
|
+
> **The accessibility release.** WCAG 2.1 AA pass across the entire
|
|
1112
|
+
> component catalogue, critical backlog items (Select combobox pattern,
|
|
1113
|
+
> DataTable caption, ColorPicker keyboard), and a VitePress sidebar
|
|
1114
|
+
> reorganised by UI taxonomy.
|
|
1115
|
+
|
|
1116
|
+
### Fixed
|
|
1117
|
+
|
|
1118
|
+
- WCAG 2.1 AA pass — 35 targeted fixes across 36 components covering:
|
|
1119
|
+
missing `aria-label` on icon-only buttons, incorrect `role` assignments,
|
|
1120
|
+
focus management gaps, colour-contrast warnings on default token values,
|
|
1121
|
+
and keyboard-navigation holes in Slider / Rating / Switch / Radio
|
|
1122
|
+
(commit `1ad0aeaf`).
|
|
1123
|
+
- Critical a11y backlog:
|
|
1124
|
+
- `OrigamSelect` — full combobox ARIA pattern (`role="combobox"` +
|
|
1125
|
+
`aria-expanded` + `aria-activedescendant` + `aria-autocomplete`).
|
|
1126
|
+
- `OrigamDataTable` — `<caption>` element added so screen readers
|
|
1127
|
+
announce the table purpose.
|
|
1128
|
+
- `OrigamColorPicker` — keyboard navigation restored; tab order and
|
|
1129
|
+
focus ring corrected.
|
|
1130
|
+
- A11y test infrastructure wired (commit `b3dd8552`).
|
|
1131
|
+
- VitePress docs — SSR crash in the build resolved; chart legend guard
|
|
1132
|
+
against undefined series data (commit `6cfb0029`).
|
|
1133
|
+
|
|
1134
|
+
### Changed
|
|
1135
|
+
|
|
1136
|
+
- VitePress component sidebar reorganised by UI taxonomy (layout /
|
|
1137
|
+
navigation / data-display / forms / feedback / utility) instead of
|
|
1138
|
+
flat alphabetical order (commit `0bd5e2f2`).
|
|
1139
|
+
|
|
1140
|
+
---
|
|
1141
|
+
|
|
1142
|
+
## [2.4.0] — 2026-05-23
|
|
1143
|
+
|
|
1144
|
+
> **The chart engine + media kit + Wave 4 release.** In-house chart
|
|
1145
|
+
> engine (27 primitives, 19 families, pure SVG, zero external dep),
|
|
1146
|
+
> atomic media kit (`OrigamAudio` with waveform / vinyl / stem-tracks /
|
|
1147
|
+
> playlist, `OrigamVideo` YouTube-style player, `OrigamMediaScrubber`
|
|
1148
|
+
> and `OrigamMediaController` primitives), native `SliderField`, six
|
|
1149
|
+
> utility / content components (`OrigamGrid`, `OrigamMasonry`,
|
|
1150
|
+
> `OrigamEmptyState`, `OrigamClipboard`, `OrigamInlineEdit`,
|
|
1151
|
+
> `OrigamNumberFormat`), `OrigamWatermark`, `OrigamQRCode`,
|
|
1152
|
+
> `OrigamCalendar`, `OrigamTextMask`, gradient support on color props,
|
|
1153
|
+
> and a DS-wide reuse-interfaces audit. 149 commits.
|
|
1154
|
+
|
|
1155
|
+
### Added
|
|
1156
|
+
|
|
1157
|
+
#### Chart engine
|
|
1158
|
+
|
|
1159
|
+
- `OrigamChart` + `useChart` — in-house chart component. 8 base types
|
|
1160
|
+
(`line` / `area` / `bar` / `column` / `pie` / `donut` / `scatter` /
|
|
1161
|
+
`radar`). Pure SVG rendering (no canvas, no `d3`, no `chart.js`, no
|
|
1162
|
+
`echarts`). Tooltip inline-positioned via mouse move; legend as
|
|
1163
|
+
`<ul role="list">` with click-to-toggle series visibility. Animated
|
|
1164
|
+
entrance with `prefers-reduced-motion` respect. Custom slots for
|
|
1165
|
+
`tooltip` / `legend-item` / `title` / `empty`. ARIA `role="img"` with
|
|
1166
|
+
`<title>` + `<desc>`; every data point is `tabindex="0"` +
|
|
1167
|
+
`role="button"` with a descriptive `aria-label`. Pure-function SVG
|
|
1168
|
+
path utilities — SSR-safe. `tokens/component/chart.json` (title,
|
|
1169
|
+
subtitle, axis, grid, tooltip, legend, point, bar, pie, radar,
|
|
1170
|
+
animation groups). (commit `b46541ce`)
|
|
1171
|
+
- Family split into 9 per-type components (`OrigamChartCartesian`,
|
|
1172
|
+
`OrigamChartPolar`, `OrigamChartRadar`, `OrigamChartGauge`, …) sharing
|
|
1173
|
+
the engine via `OrigamChartAxis` and `OrigamChartLegend` sub-components
|
|
1174
|
+
(commits `4da143c9`, `c950c364`, `ef4ab360`).
|
|
1175
|
+
- 15 additional chart families extending the base engine:
|
|
1176
|
+
- **Honeycomb / Treemap / Sankey / Word-cloud** (commit `94902edc`)
|
|
1177
|
+
- **Heatmap / Sunburst / Box-plot / Pictorial** (commit `c1e69d60`)
|
|
1178
|
+
- **Candlestick / Streamgraph** (commit `c5edc9b0`)
|
|
1179
|
+
- **Pyramid / Funnel** family with outside labels + leader lines on
|
|
1180
|
+
narrow bands (commits `445acb05`, `f4af7a27`, `293905bc`)
|
|
1181
|
+
- **Polar-bar / Variwide** (commit `26380205`)
|
|
1182
|
+
- **Pareto / Bullet** (commit `39f141a3`)
|
|
1183
|
+
- **Combination chart** (line + column / area + line) (commit
|
|
1184
|
+
`4406e92d` area, `10d012ad` bar-axis swap)
|
|
1185
|
+
- **Map / Choropleth / Flight-routes / Plot bands** (commit `c728bd94`,
|
|
1186
|
+
`6e72e7f4`)
|
|
1187
|
+
- **Stacked percent / Multi-axis Y** (commit `6e72e7f4`)
|
|
1188
|
+
- **Drilldown** (commit `8f827e7d`)
|
|
1189
|
+
- **Sparkline / Zoom-pan / RangeSelector** (commit `23d97e29`)
|
|
1190
|
+
- **Annotations** (arrows, label callouts, circle highlights, brackets)
|
|
1191
|
+
(commit `e1e41b89`)
|
|
1192
|
+
- Chart composables wired to full DS cross-cutting prop surface
|
|
1193
|
+
(`IDimensionProps` via `useDimension`, `margin`, `padding`, `rounded`,
|
|
1194
|
+
`elevation`, `bgColor`) (commits `7179cd6c`, `e16742e0`).
|
|
1195
|
+
- Scatter chart: `z` dimension drives bubble radius (commit `2eb6c868`).
|
|
1196
|
+
- Pie / donut: multi-series concentric rings; per-slice legend toggle
|
|
1197
|
+
(commit `ba51275b`).
|
|
1198
|
+
- DS intent colours and custom CSS colours resolve to the correct token
|
|
1199
|
+
namespace in charts (commit `8166cd1e`).
|
|
1200
|
+
- 7 canonical transverse emit interfaces (`IChartEmits`, etc.) added
|
|
1201
|
+
(commit `e1c7b890`).
|
|
1202
|
+
- DS-wide typed `defineEmits` migration — 7 batches covering 54+
|
|
1203
|
+
components (commits `01381e41`, `a03627a8`, `ce40e686`, `2ce1ccd2`,
|
|
1204
|
+
`3347bc58`, `279fb2f0`, `e91c9518`).
|
|
1205
|
+
|
|
1206
|
+
#### Media kit
|
|
1207
|
+
|
|
1208
|
+
- `OrigamAudio` + `useAudioPlayer` + `useWaveform` — in-house audio
|
|
1209
|
+
player. Custom UI (play/pause, scrubber, volume, waveform via
|
|
1210
|
+
`OfflineAudioContext`). Media Session API for lock-screen controls +
|
|
1211
|
+
metadata. Cover image. 3 controls modes. Vinyl disc animation. Stem-
|
|
1212
|
+
tracks (multi-channel mute/solo). Playlist with tri-state loop and
|
|
1213
|
+
random shuffle. Zero external dep. ARIA: dynamic `aria-label`,
|
|
1214
|
+
`role="slider"` on scrubber, `role="img"` on waveform. SSR-safe.
|
|
1215
|
+
`tokens/component/sound.json` (commits `293efc06`, `d3781288`,
|
|
1216
|
+
`9c12e283`, `f3d3c797`). Waveform + album ported from `OrigamSound`
|
|
1217
|
+
(commit `d5a0246b`). `useWaveform` moved to Audio namespace (commit
|
|
1218
|
+
`d4822f26`). `<OrigamSound>` namespace retired — superseded by
|
|
1219
|
+
`<OrigamAudio>` (commit `a77911bc`).
|
|
1220
|
+
- `OrigamVideo` + `useVideoPlayer` — in-house video player. YouTube-style
|
|
1221
|
+
restructure: custom UI (play/pause, scrubber, volume, fullscreen, PIP,
|
|
1222
|
+
captions), 3 controls modes, WebVTT captions with language switcher,
|
|
1223
|
+
`aspect-ratio` preset, download prop + quality switcher in cog menu,
|
|
1224
|
+
YouTube-style skip ripple (half-disk + chevrons stagger). Zero external
|
|
1225
|
+
dep. ARIA: `role="slider"` on scrubber, `role="status"` / `role="alert"`
|
|
1226
|
+
on state overlays. SSR-safe. `tokens/component/video.json` (commits
|
|
1227
|
+
`8a37102e`, `97420a99`, `31dcfdae`, `f50ccbdb`, `dcccb4dd`, `0208b2f3`,
|
|
1228
|
+
`9bbbea96`, `75b0779f`, `80e2a9c0`).
|
|
1229
|
+
- `OrigamMediaScrubber` — reusable horizontal + vertical media scrubber
|
|
1230
|
+
primitive (thin track, buffer indicator, hover thumb + tooltip). Used
|
|
1231
|
+
by both `OrigamAudio` and `OrigamVideo` for their respective scrubber
|
|
1232
|
+
and volume controls (commits `9f87c917`, `9e050390`, `15d53094`).
|
|
1233
|
+
- `OrigamMediaController` — shared media-control shell extracted from
|
|
1234
|
+
`useVideoPlayer` (commit `2cbb9618`). `useMediaPlayer` base composable
|
|
1235
|
+
split out (commit `c2a9f282`).
|
|
1236
|
+
|
|
1237
|
+
#### New utility / content components
|
|
1238
|
+
|
|
1239
|
+
- `OrigamGrid` + `OrigamGridItem` — declarative CSS Grid wrapper. Props
|
|
1240
|
+
for `columns` / `rows` / `areas` / `gap` (token or raw CSS) /
|
|
1241
|
+
`autoFlow` / `align*` / `justify*` and item-level `column` / `row` /
|
|
1242
|
+
`area` / `*Self` shorthands. Object syntax (`{ start, end }`) or raw
|
|
1243
|
+
CSS strings (`'1 / 5'`, `'span 2'`) for span control. Token group
|
|
1244
|
+
`--origam-grid---gap-{xs,sm,md,lg,xl}` (commit `0ebb1cd4`).
|
|
1245
|
+
- `OrigamMasonry` + `useMasonry` — Pinterest-style masonry layout.
|
|
1246
|
+
CSS-first via `grid-template-rows: masonry` (detected via `useCssSupport`
|
|
1247
|
+
— new `masonry` flag). JS bucket-fill fallback with `ResizeObserver`.
|
|
1248
|
+
Responsive columns via container-query breakpoints. `animated` prop.
|
|
1249
|
+
`tokens/component/masonry.json` (`animation-duration`,
|
|
1250
|
+
`animation-easing`) (commit `2691c4e5`).
|
|
1251
|
+
- `OrigamEmptyState` — placeholder for absent data. 5 presets
|
|
1252
|
+
(`no-data` / `no-results` / `error` / `offline` / `locked`) with auto
|
|
1253
|
+
icon + intent mapping. Three sizes, two alignments. ARIA `role="status"`
|
|
1254
|
+
+ `aria-live="polite"`. `tokens/component/empty-state.json` (commit
|
|
1255
|
+
`abaca302`).
|
|
1256
|
+
- `OrigamClipboard` + `useClipboard` — copy-to-clipboard helper.
|
|
1257
|
+
`navigator.clipboard.writeText` + `execCommand` fallback. Scoped
|
|
1258
|
+
`#default` slot exposes `{ copy, copied, error }`. Auto-resetting
|
|
1259
|
+
feedback state. ARIA `aria-live="polite"`. SSR-safe.
|
|
1260
|
+
`tokens/component/clipboard.json` (commit `d93c2957`).
|
|
1261
|
+
- `OrigamInlineEdit` + `useInlineEdit` — edit-in-place pattern. Click
|
|
1262
|
+
display → input prefilled → Enter confirms / Escape cancels. Async
|
|
1263
|
+
`validate` callback. Multiline textarea mode. Custom slots
|
|
1264
|
+
`#display` / `#edit` / `#actions`. ARIA `aria-invalid` +
|
|
1265
|
+
`aria-describedby`. `tokens/component/inline-edit.json` (commit
|
|
1266
|
+
`d4a95557`).
|
|
1267
|
+
- `OrigamNumberFormat` + `useNumberFormat` — i18n number formatting via
|
|
1268
|
+
`Intl.NumberFormat`. 7 formats, full locale support with auto-resolution
|
|
1269
|
+
chain, LRU-cached `Intl` instances. Scoped `#default` slot exposes
|
|
1270
|
+
`{ formatted, parts, value }`. ARIA `aria-label` expansion for compact
|
|
1271
|
+
notation (commit `dd8bfe3c`).
|
|
1272
|
+
- `OrigamWatermark` + `useWatermark` — diagonal repeating overlay. SVG
|
|
1273
|
+
data-URL (no canvas). Text or image mode. Anti-tamper MutationObserver.
|
|
1274
|
+
`pointer-events: none`. `tokens/component/watermark.json`. SSR-safe
|
|
1275
|
+
(commit `cc715c38`).
|
|
1276
|
+
- `OrigamQRCode` + `useQRCode` — SVG QR code rendering via
|
|
1277
|
+
`qrcode-generator` (~5 kB). 4 ECC levels. Optional logo overlay.
|
|
1278
|
+
Rounded modules. LRU cache. ARIA `role="img"`. Renamed from
|
|
1279
|
+
`OrigamQRCode` → `OrigamQrCode` (Vue style guide — commits `9f5a4eea`,
|
|
1280
|
+
`eabb92a3`, `1ee2acf6`, `da34f20d`, multiple QrCode fixes).
|
|
1281
|
+
- `OrigamCalendar` + `useCalendar` — full calendar. 4 views
|
|
1282
|
+
(month / week / day / agenda), navigation, events with
|
|
1283
|
+
start / end / color / category, range select with drag-to-create,
|
|
1284
|
+
RRULE recurring events (`DAILY | WEEKLY | MONTHLY` + `INTERVAL` /
|
|
1285
|
+
`COUNT` / `UNTIL` / `BYDAY`). Toolbar with view switcher. Locale-aware
|
|
1286
|
+
via `Intl.DateTimeFormat`. Zero external dep. ARIA
|
|
1287
|
+
`application / gridcell / toolbar` + keyboard navigation. SSR-safe
|
|
1288
|
+
(commit `8b5d7f0a`).
|
|
1289
|
+
- `OrigamTextMask` + gradient color props — text reveals an animated
|
|
1290
|
+
background via `background-clip: text`. 4 animation types
|
|
1291
|
+
(`pan` / `rotate` / `pulse` / `zoom`) with `prefers-reduced-motion`.
|
|
1292
|
+
Zero JS (pure CSS keyframes). SSR-safe (commit `31f67d37`).
|
|
1293
|
+
- Gradient support for `color` / `bgColor` / `textColor` props. Three
|
|
1294
|
+
input formats: raw CSS gradient string, `IGradient` structured object
|
|
1295
|
+
(`{ from, to, via?, direction?, type? }` or `{ stops: [...] }`), or
|
|
1296
|
+
preset name (`color="gradient-sunset"`). 5 built-in semantic presets
|
|
1297
|
+
(`sunset`, `ocean`, `forest`, `fire`, `midnight`) with light + dark
|
|
1298
|
+
variants. 100 % backward-compatible (commit `c922fbff`).
|
|
1299
|
+
- `SliderField` — native HTML `<input type="range">` implementation
|
|
1300
|
+
(commit `d3781288`).
|
|
1301
|
+
|
|
1302
|
+
### Changed
|
|
1303
|
+
|
|
1304
|
+
- DS-wide reuse-interfaces audit — 9 batches (commits `d0afd731`,
|
|
1305
|
+
`2c6e3aab`, `325c4df1`, `5f1abaf8`, and earlier in the cycle).
|
|
1306
|
+
Every component that declared `height` / `width` / `margin` / etc.
|
|
1307
|
+
inline now `extends IDimensionProps` / `IMarginProps` / etc. and
|
|
1308
|
+
consumes the matching composable. Eliminates half-implemented
|
|
1309
|
+
surfaces and drift from the standard `convertToUnit` helper.
|
|
1310
|
+
- All ~28 inline composable constants extracted to `src/consts/`
|
|
1311
|
+
(commits `7cd6ff81`, `de48f7da`).
|
|
1312
|
+
- Story Playground variants universally renamed to `Default` across all
|
|
1313
|
+
177 stories (commits `cfeaa682`, `ace53342`, `f2e89284`).
|
|
1314
|
+
|
|
1315
|
+
### Fixed
|
|
1316
|
+
|
|
1317
|
+
- `OrigamChart` — area fill previously overridden by the SCSS
|
|
1318
|
+
`fill: none` cascade (commit `ed1c4610`); scatter points overflowing
|
|
1319
|
+
the plot zone (commit `ba51275b`); horizontal bar — category/value
|
|
1320
|
+
axis swapped (commit `f8ec65db`); legend click filtered wrong series
|
|
1321
|
+
index (commit `d25eae00`); `legendPosition` not moving the legend
|
|
1322
|
+
(commit `082d053b`); column/bar slots overlapping value axis on first
|
|
1323
|
+
index (commit `4406e92d`); stepped-line tail cut off (commit
|
|
1324
|
+
`ee45357a`); pie/donut legend showing wrong labels (commit `4406e92d`).
|
|
1325
|
+
- `OrigamVideo` — double-click skip on desktop (`f50ccbdb`); controls bar
|
|
1326
|
+
clicks restored after overlay removal (`4fd5f375`); skip ripple sizing
|
|
1327
|
+
cascade (`80e2a9c0`, `9bbbea96`, `75b0779f`); cross-origin download
|
|
1328
|
+
via blob (`73c2e2a4`, `d84fa9bc`).
|
|
1329
|
+
- `OrigamCalendar` — Calendar loading shape + active toolbar button
|
|
1330
|
+
contrast (`55e58b3d`).
|
|
1331
|
+
- `OrigamQrCode` — intent-to-paint mapping, SVG host sizing, title
|
|
1332
|
+
centring (commits `c1823057`, `dceb4cfe`).
|
|
1333
|
+
- Link composable — `ComputedRef` for `tag` and `href` unwrapped in
|
|
1334
|
+
templates; previously caused a `[object Object]` render (commit
|
|
1335
|
+
`9822c47b`, reverted and re-landed as `3f79d0c0`).
|
|
1336
|
+
- `withDefaults()` inline literal rule enforced — `Grid`, `Masonry`,
|
|
1337
|
+
`Blockquote` were referencing `XXX_DEFAULTS` objects statically
|
|
1338
|
+
unresolvable by the SFC compiler, causing `undefined` prop crashes
|
|
1339
|
+
(commit `276fff1e`).
|
|
1340
|
+
- `OrigamSnackbar` — `roundedClasses` `ReferenceError` at mount (commit
|
|
1341
|
+
`aa86f93c`).
|
|
1342
|
+
|
|
1343
|
+
---
|
|
1344
|
+
|
|
1345
|
+
## [2.3.0] — 2026-05-15
|
|
1346
|
+
|
|
1347
|
+
> **The features release.** Four new components, four major
|
|
1348
|
+
> enrichments, an official Nuxt module, and a comprehensive SSR
|
|
1349
|
+
> safety audit. All additions are backward-compatible — drop-in
|
|
1350
|
+
> upgrade from 2.2.x. 378 unit tests (+158 vs 2.2.1), 0 lint errors.
|
|
1351
|
+
|
|
1352
|
+
### Added
|
|
1353
|
+
|
|
1354
|
+
- `origam/nuxt` sub-export — official Nuxt 3 / Nuxt 4 module. Auto-imports
|
|
1355
|
+
components and composables. SSR-safe theme resolution via cookie +
|
|
1356
|
+
`Sec-CH-Prefers-Color-Scheme` header (no FOUC, no hydration mismatch).
|
|
1357
|
+
Auto-injects token CSS files (primitive + selected themes + utilities).
|
|
1358
|
+
Configurable via `origam: {}` in `nuxt.config.ts`. Resolves through
|
|
1359
|
+
`modules: ['origam/nuxt']`. New `IOrigamNuxtModuleOptions` and
|
|
1360
|
+
`IOrigamNuxtRuntimeConfig` interfaces; new theme constants
|
|
1361
|
+
(`ORIGAM_THEME_AUTO`, `ORIGAM_THEME_LIGHT`, `ORIGAM_THEME_DARK`,
|
|
1362
|
+
`ORIGAM_THEME_ATTR`, `ORIGAM_THEME_STORAGE_KEY`). Reference
|
|
1363
|
+
documentation at `docs/integrations/nuxt.md`.
|
|
1364
|
+
|
|
1365
|
+
### Changed
|
|
1366
|
+
|
|
1367
|
+
- `OrigamTextField` — new `mask` prop with built-in patterns
|
|
1368
|
+
(`phone:fr`, `phone:us`, `phone:international`, `iban`, `siret`,
|
|
1369
|
+
`creditcard`, `date:iso`, `date:fr`, `date:us`, `time`, `time:12h`,
|
|
1370
|
+
`postcode:fr`, `postcode:us`) plus a custom pattern syntax
|
|
1371
|
+
(`#` = digit, `A` = letter, `*` = any, anything else is a literal).
|
|
1372
|
+
In-house mask engine — zero external dependency (no `imask.js` /
|
|
1373
|
+
`cleave.js` / `vue-the-mask`). Reactive validation pipeline with
|
|
1374
|
+
built-in `luhn` (credit card), `iban` (mod-97) and date parsers
|
|
1375
|
+
(`date:iso` / `date:fr` / `date:us`); custom validators accepted as
|
|
1376
|
+
`(unmasked) => boolean`. New emits `@valid(boolean)` and
|
|
1377
|
+
`@complete({ complete, unmasked })` fire on every value change. The
|
|
1378
|
+
v-model exposes the **unmasked** value while the DOM input displays
|
|
1379
|
+
the formatted (masked) one — paste handling strips literals and
|
|
1380
|
+
reformats, `aria-invalid` toggles on touched fields, and the engine
|
|
1381
|
+
auto-promotes phone-shaped patterns to `type="tel"` for mobile
|
|
1382
|
+
keyboard hints. New `useMask` composable, `applyMask` / `unmaskValue`
|
|
1383
|
+
/ `resolveMaskConfig` / `validatePattern` utils, new `IMaskOptions`
|
|
1384
|
+
interface and `TMask` / `TBuiltInPattern` / `TPatternValidator`
|
|
1385
|
+
types.
|
|
1386
|
+
- `OrigamTextareaField` — new `mode="rich"` enabling a lightweight
|
|
1387
|
+
HTML / Markdown editor based on `contenteditable`. Built in-house
|
|
1388
|
+
with zero external dependencies (no TipTap, ProseMirror, Quill).
|
|
1389
|
+
9 toolbar commands (`bold`, `italic`, `underline`, `link`,
|
|
1390
|
+
`list-bullet`, `list-ordered`, `heading`, `code-inline`,
|
|
1391
|
+
`clear-format`), customisable via the new `toolbar` prop (or
|
|
1392
|
+
`toolbar: false` to hide). Keyboard shortcuts (Cmd/Ctrl+B/I/U/K/E
|
|
1393
|
+
and Cmd/Ctrl+Shift+7/8 for the two list modes). New `output` prop
|
|
1394
|
+
switches the v-model serialisation between `'html'` (sanitised) and
|
|
1395
|
+
`'markdown'` (CommonMark-flavoured subset). New `toolbarPosition`
|
|
1396
|
+
prop (`'top' | 'bottom' | 'floating'`). New `format` emit fired on
|
|
1397
|
+
every toolbar click or keyboard shortcut with the command id (and
|
|
1398
|
+
the URL for link insertion). New slots `#toolbar` and
|
|
1399
|
+
`#toolbar-item` allow replacing the default UI entirely. Internal
|
|
1400
|
+
sub-component `OrigamRichToolbar.vue` + composable
|
|
1401
|
+
`useTextareaRich` own the contenteditable contract. In-house HTML
|
|
1402
|
+
sanitiser with allowlist on tags (`p`, `br`, `strong`, `b`, `em`,
|
|
1403
|
+
`i`, `u`, `a`, `ul`, `ol`, `li`, `h1`, `h2`, `h3`, `code`),
|
|
1404
|
+
attributes (`href` restricted to `http:` / `https:` / `mailto:` /
|
|
1405
|
+
`tel:` plus relative URLs; `class` restricted to the
|
|
1406
|
+
`origam-rich--*` prefix), and stripping every `on*` event handler
|
|
1407
|
+
before per-tag filtering. External links are auto-hardened with
|
|
1408
|
+
`rel="noopener noreferrer nofollow" target="_blank"`. ARIA:
|
|
1409
|
+
`role="toolbar" + aria-label` on the toolbar, real `<button>` per
|
|
1410
|
+
command with `aria-label` + `aria-pressed`, the editing surface
|
|
1411
|
+
carries `role="textbox" + aria-multiline="true"`. New tokens under
|
|
1412
|
+
`component/textarea-field/rich-*` (toolbar surface, button states,
|
|
1413
|
+
content padding, inline-code colors, link color, heading sizes).
|
|
1414
|
+
The plain-mode (`mode="plain"`, default) API is fully
|
|
1415
|
+
backward-compatible — passing nothing keeps the previous
|
|
1416
|
+
`<textarea>` behaviour.
|
|
1417
|
+
|
|
1418
|
+
- `OrigamCode` — major enrichment via shiki integration. Syntax
|
|
1419
|
+
highlighting for 13 languages (vue, ts, js, tsx, jsx, scss, css, json,
|
|
1420
|
+
bash, html, xml, yaml, md) plus `plaintext`. New props: `lineNumbers`,
|
|
1421
|
+
`highlightLines` (accepts both `number[]` and the range syntax
|
|
1422
|
+
`'2,5-7'`), `copyable`, `maxHeight`, `theme` (`'auto' | 'light' | 'dark'`),
|
|
1423
|
+
`wrap`, `filename`. Copy button with `navigator.clipboard` and an
|
|
1424
|
+
`execCommand('copy')` fallback for legacy WebViews. Lazy-init shiki
|
|
1425
|
+
highlighter cached as a module-level singleton across instances; an
|
|
1426
|
+
LRU (max 64 entries) caches highlighted HTML by `(code, lang, theme)`
|
|
1427
|
+
so re-renders never re-tokenise. Theme defaults to `auto` and tracks
|
|
1428
|
+
the host `<html data-theme>` attribute. New `useCode` composable
|
|
1429
|
+
exposing `{ highlight, prime, isReady, resetCacheForTesting }`. New
|
|
1430
|
+
utility `parseHighlightLines()` shared with stories/tests. Pure-CSS
|
|
1431
|
+
line-numbers gutter (CSS counter, no JS layout) and line-highlight
|
|
1432
|
+
swap (class toggle on already-rendered rows, no re-tokenisation).
|
|
1433
|
+
ARIA: `role="region"` on the surface, `aria-live="polite"` on the
|
|
1434
|
+
copy feedback, hidden line numbers. `shiki` (`^3.8.1`) promoted from
|
|
1435
|
+
`devDependencies` to `dependencies` (it's a runtime dep now); the
|
|
1436
|
+
bundle adds ~3 MB to installed `node_modules` for the curated subset.
|
|
1437
|
+
New tokens under `component/code` (35 vars: surface, header, filename,
|
|
1438
|
+
copy button, line-number gutter, line-highlight, scrollbar). The v2.x
|
|
1439
|
+
plain-text `<pre>` API is fully backward-compatible — passing just
|
|
1440
|
+
`code` and `lang` keeps the previous behaviour.
|
|
1441
|
+
|
|
1442
|
+
- `OrigamParallax` — major enrichment. Multi-layer support via new
|
|
1443
|
+
`OrigamParallaxLayer` subcomponent (`speed`, `offsetX`, `offsetY`,
|
|
1444
|
+
`zIndex` props; layers register themselves into the host runtime and
|
|
1445
|
+
receive direct DOM mutations of `transform` outside Vue reactivity).
|
|
1446
|
+
Host gains `direction` (`'vertical' | 'horizontal' | 'both'`),
|
|
1447
|
+
`easing` (`'linear' | 'ease-out' | 'spring'`, in addition to the
|
|
1448
|
+
legacy raw CSS timing-function string), `disabled`, `speed`,
|
|
1449
|
+
`threshold` props. New emits: `@enter`, `@leave`,
|
|
1450
|
+
`@scroll-progress(0→1)` driven by `IntersectionObserver` +
|
|
1451
|
+
`requestAnimationFrame`. `prefers-reduced-motion: reduce` is honoured
|
|
1452
|
+
natively — layers stay at `translate3d(offsetX, offsetY, 0)` and the
|
|
1453
|
+
rAF loop short-circuits. CSS-first scroll-driven animations
|
|
1454
|
+
(`animation-timeline: view()`) when `view-timeline` is supported
|
|
1455
|
+
(Chrome 115+, Edge 115+) AND `easing === 'linear'`; JS fallback
|
|
1456
|
+
otherwise. Spring easing implemented as a damped lerp in the JS path.
|
|
1457
|
+
Existing single-layer / `<OrigamParallaxElement>` API preserved (the
|
|
1458
|
+
two layer kinds use independent injection contexts and can coexist
|
|
1459
|
+
inside the same host). New tokens: `parallax.transition-duration-spring`,
|
|
1460
|
+
`parallax.transition-easing-default` / `-spring`,
|
|
1461
|
+
`parallax.layer.will-change` / `.transform-origin`.
|
|
1462
|
+
|
|
1463
|
+
### Added
|
|
1464
|
+
|
|
1465
|
+
- `OrigamCommandPalette` — ⌘K command launcher. Built on a teleported
|
|
1466
|
+
dialog with focus trap + focus restoration. Custom subsequence-based
|
|
1467
|
+
fuzzy-match algorithm (no external dep) ranks results by
|
|
1468
|
+
consecutive-run + label-prefix + first-position bonuses. Composable
|
|
1469
|
+
`useCommand` exposes a process-wide command registry — entries
|
|
1470
|
+
registered inside a Vue effect scope auto-unregister on dispose.
|
|
1471
|
+
Reuses `OrigamKbd` for inline shortcut display. Hotkey listener
|
|
1472
|
+
built on `useHotkey` (default `⌘+K` on macOS, `Ctrl+K` on
|
|
1473
|
+
Windows / Linux, configurable per combination or disabled with
|
|
1474
|
+
`:hotkey="null"`). ARIA combobox pattern (`role="combobox"` on the
|
|
1475
|
+
input, `role="listbox"` on the result list, `role="option"` per
|
|
1476
|
+
item, `aria-activedescendant` tracking the keyboard cursor) +
|
|
1477
|
+
`role="dialog"` + `aria-modal="true"` on the surface. Tokens exposed
|
|
1478
|
+
under `tokens/component/command-palette.json`
|
|
1479
|
+
(`--origam-command-palette---*`,
|
|
1480
|
+
`--origam-command-palette__input---*`,
|
|
1481
|
+
`--origam-command-palette__item---*`,
|
|
1482
|
+
`--origam-command-palette__group-title---*`,
|
|
1483
|
+
`--origam-command-palette__empty---*`,
|
|
1484
|
+
`--origam-command-palette__footer---*`,
|
|
1485
|
+
`--origam-command-palette--backdrop---*`).
|
|
1486
|
+
|
|
1487
|
+
- `OrigamBracket` — e-sport tournament tree. Supports single-elimination,
|
|
1488
|
+
double-elimination and round-robin variants. SVG connectors
|
|
1489
|
+
auto-computed from `nextMatchId` (with positional fallback). Slots for
|
|
1490
|
+
custom match / competitor / round-title / connector rendering. ARIA
|
|
1491
|
+
`role="region"` with per-round `role="group"` + `aria-labelledby`
|
|
1492
|
+
pointing at title headings. Tokens exposed under
|
|
1493
|
+
`tokens/component/bracket.json` (`--origam-bracket---*`,
|
|
1494
|
+
`--origam-bracket-match---*`, `--origam-bracket-competitor---*`,
|
|
1495
|
+
`--origam-bracket-connector---*`, `--origam-bracket-round-robin---*`).
|
|
1496
|
+
|
|
1497
|
+
- `OrigamSnackbarStack` — multi-toast notification system. Reuses
|
|
1498
|
+
`OrigamSnackbar` styling vocabulary for rendering. Composable
|
|
1499
|
+
`useSnackbarStack({ id })` exposes `notify` / `dismiss` /
|
|
1500
|
+
`dismissAll`. 8 anchor locations, max stack size with FIFO eviction,
|
|
1501
|
+
per-item auto-dismiss (or `0` for sticky), action buttons with
|
|
1502
|
+
optional `keepOpen`, ARIA `role="region"` on the stack root +
|
|
1503
|
+
`role="status"` / `"alert"` per intent on each item with matching
|
|
1504
|
+
`aria-live`. Slide-in / slide-out transitions degrade to a fade under
|
|
1505
|
+
`prefers-reduced-motion`. Tokens exposed under
|
|
1506
|
+
`tokens/component/snackbar-stack.json`
|
|
1507
|
+
(`--origam-snackbar-stack---*`, `--origam-snackbar-stack__item---*`).
|
|
1508
|
+
|
|
1509
|
+
- `OrigamTabs` / `OrigamTab` / `OrigamTabPanels` / `OrigamTabPanel` —
|
|
1510
|
+
full tab system with horizontal / vertical orientation, three visual
|
|
1511
|
+
variants (`default` / `pills` / `underline`), ARIA `role="tablist"` +
|
|
1512
|
+
`role="tab"` + `role="tabpanel"` wiring, full keyboard navigation
|
|
1513
|
+
(`←`/`→`/`↑`/`↓`/`Home`/`End`/`Enter`/`Space`), lazy or eager panel
|
|
1514
|
+
mounting, optional touch-swipeable panels. Reuses the shared
|
|
1515
|
+
`useGroup` orchestration so the selection state, mandatory behaviour
|
|
1516
|
+
and disabled-tab semantics align with the rest of the system
|
|
1517
|
+
(`OrigamBtnToggle`, `OrigamCarousel`, `OrigamBottomNav`). Tokens
|
|
1518
|
+
exposed under `tokens/component/tabs.json` (item color, indicator
|
|
1519
|
+
color, panel padding, transition duration).
|
|
1520
|
+
|
|
1521
|
+
- `OrigamClientOnly` — SSR helper component that renders its default
|
|
1522
|
+
slot only after `onMounted`. Optional `#fallback` slot (or
|
|
1523
|
+
`placeholder-tag` / `placeholder-class` props) reserves layout space
|
|
1524
|
+
during SSR to avoid CLS. Use to wrap fragments whose markup truly must
|
|
1525
|
+
differ between server and client (audio, deviceorientation,
|
|
1526
|
+
IntersectionObserver-driven features, …) without triggering hydration
|
|
1527
|
+
mismatches.
|
|
1528
|
+
|
|
1529
|
+
- `useCssSupportClient(feature, { defaultValue })` — hydration-safe
|
|
1530
|
+
feature-gate helper. Returns a `Ref<boolean>` that starts at
|
|
1531
|
+
`defaultValue` (default `false`) on both SSR and first client render,
|
|
1532
|
+
then flips to the real `CSS.supports()` result inside `onMounted`.
|
|
1533
|
+
Use to gate **markup** branches (template `v-if`) when the regular
|
|
1534
|
+
`useCssSupport().css.value.X` would produce a hydration mismatch
|
|
1535
|
+
(class-only branches keep using the existing API — Vue 3 reconciles
|
|
1536
|
+
class diffs fine).
|
|
1537
|
+
|
|
1538
|
+
### Fixed
|
|
1539
|
+
|
|
1540
|
+
- SSR safety — comprehensive audit of all composables and components
|
|
1541
|
+
that previously could crash on server render (`window is not defined`,
|
|
1542
|
+
`document is not defined`). `useCssSupport` already returned all-false
|
|
1543
|
+
flags during SSR; the rest of the surface (`useTheme`, `useCommand`,
|
|
1544
|
+
`useSnackbarStack`, `useCode`, `useMask`, `useTouch`, `useHotkey`,
|
|
1545
|
+
`useSticky`, `useSheetSwipe`, `useScroll`, `useParallax`, `useStyleTag`,
|
|
1546
|
+
`useTeleport`, `useLocationStrategies`, `useScrollStrategies`,
|
|
1547
|
+
`useDisplay`) was confirmed safe via the audit and patched where a
|
|
1548
|
+
composable's public method or a `computed` could be evaluated during
|
|
1549
|
+
SSR. Specifically: `useAspectRatio` no longer dereferences
|
|
1550
|
+
`window.innerWidth/Height` when no explicit `aspectRatio` prop is
|
|
1551
|
+
given; `useVirtual`'s `viewportHeight` computed guards
|
|
1552
|
+
`document.documentElement`; `useSnackbarStack.dismiss()` guards
|
|
1553
|
+
`window.clearTimeout`. Overlay components (Dialog, Drawer, Menu,
|
|
1554
|
+
Tooltip, Snackbar, ContextualMenu, SnackbarStack, CommandPalette)
|
|
1555
|
+
confirmed SSR-safe via `<Teleport>` (Vue defers the mount until the
|
|
1556
|
+
client). New guide `docs/guide/ssr.md`. New `src/__tests__/ssr-smoke.spec.ts`
|
|
1557
|
+
exercises every refactored composable in a simulated SSR environment
|
|
1558
|
+
(window/document/CSS stripped) **and** through `@vue/server-renderer`'s
|
|
1559
|
+
real `renderToString()`.
|
|
1560
|
+
|
|
1561
|
+
---
|
|
1562
|
+
|
|
1563
|
+
## [2.2.1] — 2026-05-14
|
|
1564
|
+
|
|
1565
|
+
### Fixed
|
|
1566
|
+
|
|
1567
|
+
- Expose `./package.json` explicitly in the `exports` map. The catch-all
|
|
1568
|
+
`"./*": "./dist/src/*"` previously intercepted `import 'origam/package.json'`
|
|
1569
|
+
and re-routed it to a non-existent file inside `dist/`. Standard
|
|
1570
|
+
consumer pattern (reading the version from the package metadata) was
|
|
1571
|
+
broken — fixed by adding `"./package.json": "./package.json"` ahead
|
|
1572
|
+
of the catch-all so it matches first.
|
|
1573
|
+
- 2.2.0 was tagged but never published to npm. 2.2.1 is the first
|
|
1574
|
+
version that lands on the registry.
|
|
1575
|
+
|
|
1576
|
+
---
|
|
1577
|
+
|
|
1578
|
+
## [2.2.0] — 2026-05-14
|
|
1579
|
+
|
|
1580
|
+
> **The "ready for npm" release.** Package metadata, peer dependencies,
|
|
1581
|
+
> tree-shaking signals and a real README are all in. Tarball preview
|
|
1582
|
+
> shrunk from 5.6 MB to **867.9 kB** (2 343 files, zero suspect entry).
|
|
1583
|
+
> No public API change vs 2.1.0 — every consumer upgrade is a
|
|
1584
|
+
> drop-in.
|
|
1585
|
+
|
|
1586
|
+
### Added — stories, slots, emits coverage
|
|
1587
|
+
|
|
1588
|
+
- 525+ missing `Slot` / `Emit` Variants across 113 component stories
|
|
1589
|
+
(`feat(stories)`). Every documented slot now has a dedicated Variant
|
|
1590
|
+
with a custom-content example, and every emit a Variant that logs
|
|
1591
|
+
to a live counter.
|
|
1592
|
+
- `OrigamSwitchTrack` extracted as a standalone primitive (track-only)
|
|
1593
|
+
so consumers can build switch-like compounds without rewriting the
|
|
1594
|
+
thumb logic.
|
|
1595
|
+
- Tooling: `useStateEffect` now reacts to every per-axis composable
|
|
1596
|
+
(`useHover` / `useActive` / `useFocus`) in a single call — collapses
|
|
1597
|
+
the 14 components that historically wired them axis by axis.
|
|
1598
|
+
|
|
1599
|
+
### Fixed
|
|
1600
|
+
|
|
1601
|
+
- `useStyle` now instrumented across the 124 components that
|
|
1602
|
+
previously inlined `*Styles` arrays — single source of truth for the
|
|
1603
|
+
inline-style escape hatch.
|
|
1604
|
+
- Carousel — `progress` prop renders a real-time progress bar wired to
|
|
1605
|
+
the cycle timer (was rendering a static "step / total" bar).
|
|
1606
|
+
- Carousel — `hideDelimiterBackground` finally has a background to
|
|
1607
|
+
hide (default `__controls` bg = `rgba(0, 0, 0, 0.4)`).
|
|
1608
|
+
- Histoire sandbox/panel sash now resizes the iframe in **both
|
|
1609
|
+
directions** (was capped at the 720 px responsive-preset width when
|
|
1610
|
+
dragging right).
|
|
1611
|
+
- `useRounded` — utility variants (`xs|sm|md|lg|xl|none|full`) now
|
|
1612
|
+
emit BOTH the `.origam--rounded-*` class AND an inline
|
|
1613
|
+
`border-radius` declaration as a specificity escape hatch (Strategy
|
|
1614
|
+
A documented in `CLAUDE.md`).
|
|
1615
|
+
- 130 unused-vars cleared from `src/`, 39 ESLint warnings fixed.
|
|
1616
|
+
|
|
1617
|
+
### Changed — package for npm
|
|
1618
|
+
|
|
1619
|
+
- `peerDependencies` introduced: `vue ^3.5`, `vue-i18n ^11`,
|
|
1620
|
+
`vue-router ^4.5` (last two `optional` via `peerDependenciesMeta`).
|
|
1621
|
+
They are no longer auto-installed as `dependencies` — consumers
|
|
1622
|
+
bring their own versions.
|
|
1623
|
+
- `sideEffects: ["**/*.css", "**/*.scss", "**/*.vue"]` for downstream
|
|
1624
|
+
tree-shaking.
|
|
1625
|
+
- `engines.node: ">=22"` (matches `.nvmrc`).
|
|
1626
|
+
- `prepublishOnly` script chains `tokens:build` → `server:build` →
|
|
1627
|
+
unit tests. Every `npm publish` rebuilds from scratch with green
|
|
1628
|
+
tests.
|
|
1629
|
+
- `files` whitelist tightened to `dist/src/`, `dist/tokens/`, LICENSE,
|
|
1630
|
+
README, CHANGELOG. The Histoire bundle (`dist/stories/`, ~13 MB) is
|
|
1631
|
+
no longer shipped to consumers.
|
|
1632
|
+
- `build.config.ts` `externals` extended to `['vue', 'vue-i18n',
|
|
1633
|
+
'vue-router', '@mdi/font']` so peer deps don't get re-bundled.
|
|
1634
|
+
- mkdist exclusion patterns expanded: `.spec.ts`, `__tests__/**`,
|
|
1635
|
+
`.cy.ts`, `.story.vue` are stripped from `dist/`.
|
|
1636
|
+
- ESLint config ignores `docs/.vitepress/cache/**` and
|
|
1637
|
+
`figma-plugin/**` (these aren't part of the published library).
|
|
1638
|
+
|
|
1639
|
+
### Documentation
|
|
1640
|
+
|
|
1641
|
+
- Full `README.md` written from scratch (253 lines) — install,
|
|
1642
|
+
peer deps, plugin registration, theming (`data-theme` +
|
|
1643
|
+
`useTheme()` + `<OrigamThemeProvider>`), token tiers, component
|
|
1644
|
+
families, composable table, CSS-first principle.
|
|
1645
|
+
|
|
1646
|
+
### Internal
|
|
1647
|
+
|
|
1648
|
+
- ESLint rule `no-restricted-imports` blocks `@origam` /
|
|
1649
|
+
`@stories` / `@docs` / `@cypress` aliases inside `src/` — once
|
|
1650
|
+
published, those aliases can't be resolved by consumers.
|
|
1651
|
+
- 124 components instrumented with `useStyle` following the
|
|
1652
|
+
canonical pattern.
|
|
1653
|
+
- `.tsbuildinfo` and other transient artefacts removed from the tree.
|
|
1654
|
+
|
|
1655
|
+
---
|
|
1656
|
+
|
|
1657
|
+
## [2.1.0] — 2026-05-07
|
|
1658
|
+
|
|
1659
|
+
> **The classes-first release.** The 13 transversal composables
|
|
1660
|
+
> (`useColor`, `useBackgroundColor`, `useTextColor`, `useColorEffect`,
|
|
1661
|
+
> `useElevation`, `useRounded`, `useBorder`, `useMargin`, `usePadding`,
|
|
1662
|
+
> `useSize`) now emit utility classes (e.g. `.origam--bg-primary`,
|
|
1663
|
+
> `.origam--shadow-md`) when the consumer passes a tokenised value. The
|
|
1664
|
+
> existing `*Styles` outputs stay populated only when the value is
|
|
1665
|
+
> non-tokenisable (legacy hex, custom dimensions) — the inline style
|
|
1666
|
+
> stack on a typical button drops from ~12 to ~6 declarations.
|
|
1667
|
+
>
|
|
1668
|
+
> **Non-breaking.** Every composable keeps its previous return shape;
|
|
1669
|
+
> the new `*Classes` keys are additive. Components have been migrated
|
|
1670
|
+
> to read both shapes in parallel (transition strategy A).
|
|
1671
|
+
|
|
1672
|
+
### Migrating from v2.0 to v2.1
|
|
1673
|
+
|
|
1674
|
+
Nothing is required. The release is additive; existing consumers keep
|
|
1675
|
+
working unchanged. To start using the new path:
|
|
1676
|
+
|
|
1677
|
+
```vue
|
|
1678
|
+
<!-- v2.0 — still works, still emits inline style -->
|
|
1679
|
+
<OrigamBtn color="primary">Click</OrigamBtn>
|
|
1680
|
+
|
|
1681
|
+
<!-- v2.1 — same code, but the emitted DOM now also carries the
|
|
1682
|
+
`.origam--bg-primary` utility class instead of inline
|
|
1683
|
+
`background-color: var(...)`. Inspecting the DOM is much cleaner. -->
|
|
1684
|
+
```
|
|
1685
|
+
|
|
1686
|
+
If you write your own components on top of `useColor*` / `useElevation`
|
|
1687
|
+
/ `useRounded` / etc., you can now destructure the new `*Classes`
|
|
1688
|
+
return:
|
|
1689
|
+
|
|
1690
|
+
```ts
|
|
1691
|
+
const { colorClasses, colorStyles } = useColorEffect(props, isHover, isActive, isDisabled)
|
|
1692
|
+
// colorClasses: ['origam--bg-primary'] when intent
|
|
1693
|
+
// colorStyles : [] when intent
|
|
1694
|
+
// colorClasses: [] when '#7c3aed'
|
|
1695
|
+
// colorStyles : ['background-color: ...']when '#7c3aed'
|
|
1696
|
+
```
|
|
1697
|
+
|
|
1698
|
+
Bind both — `:class="[..., colorClasses]"` AND `:style="[..., colorStyles]"`.
|
|
1699
|
+
The hover/active/disabled state still flows through `colorStyles` (utility
|
|
1700
|
+
classes are static, by design).
|
|
1701
|
+
|
|
1702
|
+
### Added
|
|
1703
|
+
|
|
1704
|
+
- **66 utility classes** generated by Style Dictionary, exposed at
|
|
1705
|
+
`origam/tokens/css/utilities` and forwarded by `origam/styles`:
|
|
1706
|
+
- `.origam--color-{primary|secondary|success|warning|danger|info|neutral}`
|
|
1707
|
+
- `.origam--bg-{primary|secondary|success|warning|danger|info|neutral}`
|
|
1708
|
+
- `.origam--shadow-{none|xs|sm|md|lg|xl}`
|
|
1709
|
+
- `.origam--rounded-{none|xs|sm|md|lg|xl|full}`
|
|
1710
|
+
- `.origam--border-{none|thin|thick}`
|
|
1711
|
+
- `.origam--p-{0..12}`, `.origam--m-{0..12}`, `.origam--gap-{0..12}`
|
|
1712
|
+
- `.origam--text-{xs|sm|md|lg|xl|2xl}`
|
|
1713
|
+
- New return keys on transversal composables:
|
|
1714
|
+
`colorClasses`, `backgroundColorClasses`, `textColorClasses`,
|
|
1715
|
+
`elevationClasses` (extended), `roundedClasses` (extended),
|
|
1716
|
+
`borderClasses` (extended), `marginClasses`, `paddingClasses`,
|
|
1717
|
+
`sizeClasses`.
|
|
1718
|
+
- `tests/e2e/utilities.spec.ts` — 66 Playwright tests, one per
|
|
1719
|
+
utility class, asserting both class presence and `getComputedStyle`
|
|
1720
|
+
resolution against the CSS var pipeline.
|
|
1721
|
+
- `tests/e2e/prop-audit-phase4.spec.ts` — DOM audit on representative
|
|
1722
|
+
components confirming the inline-style pile reduction.
|
|
1723
|
+
- 79 new Vitest unit specs in `src/composables/Commons/__tests__/`
|
|
1724
|
+
covering the classes-first branch of every refactored composable.
|
|
1725
|
+
|
|
1726
|
+
### Changed
|
|
1727
|
+
|
|
1728
|
+
- ~54 components migrated to consume `*Classes` in parallel with
|
|
1729
|
+
`*Styles`. Notable surface-bearing children: Menu/Tooltip/Picker/
|
|
1730
|
+
Snackbar/Badge — utility class lands on the `__content` / `__pill` /
|
|
1731
|
+
`__wrapper` BEM child, never on the teleport root.
|
|
1732
|
+
- `OrigamSelectionControl.__wrapper` now carries
|
|
1733
|
+
`useTextColor(color)`'s class + style on its root element. This
|
|
1734
|
+
re-instates the Switch thumb tinting (`currentColor`) for tokenised
|
|
1735
|
+
intents, which had silently broken when `OrigamSwitchTrack` was
|
|
1736
|
+
extracted earlier in the cycle.
|
|
1737
|
+
- `OrigamSwitch` SCSS — the legacy `[style*="color:"]` selector is
|
|
1738
|
+
joined by a class-driven set
|
|
1739
|
+
(`.origam-selection-control__wrapper.origam--color-{intent} &__thumb`)
|
|
1740
|
+
so both the new tokenised path and the legacy hex path tint the thumb
|
|
1741
|
+
via `currentColor`.
|
|
1742
|
+
|
|
1743
|
+
### Deprecated
|
|
1744
|
+
|
|
1745
|
+
- `*Styles` returns on the 10 refactored composables — prefer the
|
|
1746
|
+
matching `*Classes` for tokenised values. Both are kept for one
|
|
1747
|
+
major cycle; removal scheduled for v3.0.0.
|
|
1748
|
+
|
|
1749
|
+
### Fixed
|
|
1750
|
+
|
|
1751
|
+
- `OrigamSwitch` thumb stayed white when `color="primary"` (or any
|
|
1752
|
+
tokenised intent) — regression from the `OrigamSwitchTrack`
|
|
1753
|
+
extraction. Re-introduced via classes-first.
|
|
1754
|
+
- `OrigamSnackbar` `__wrapper` no longer duplicates the
|
|
1755
|
+
`roundedClasses`/`borderClasses` already applied at the root.
|
|
1756
|
+
|
|
1757
|
+
### Known limits — planned for v2.2 (Phase 1.5)
|
|
1758
|
+
|
|
1759
|
+
- No utility for margin / padding axes (`mx`, `my`, `mt`, `mb`, `ml`,
|
|
1760
|
+
`mr`, `px`, `py`, `pt`, `pb`, `pl`, `pr`). Components passing
|
|
1761
|
+
axis-specific values fall back to inline styles for now.
|
|
1762
|
+
- No `2xl` / `3xl` shadow utilities (the rungs exist as primitives but
|
|
1763
|
+
are off the manifest).
|
|
1764
|
+
- Legacy `ROUNDED` enum (`x-small | small | default | medium | large
|
|
1765
|
+
| x-large | shaped | shaped-invert`) does not bridge to the
|
|
1766
|
+
`none|xs|sm|md|lg|xl|full` utility taxonomy — components passing a
|
|
1767
|
+
legacy value get their existing component-scoped BEM modifier and an
|
|
1768
|
+
inline style fallback.
|
|
1769
|
+
- `useColorEffect` does NOT emit a `*Classes` value when `isHover` /
|
|
1770
|
+
`isActive` / `isDisabled` is true (states are inline-only by design).
|
|
1771
|
+
Components that bind `useActive(props, 'modelValue')` (Alert, Badge,
|
|
1772
|
+
BottomNav) therefore never carry a utility class while visible — the
|
|
1773
|
+
inline style still paints them correctly. This is intentional; do not
|
|
1774
|
+
rely on the utility class for state-dependent styling.
|
|
1775
|
+
|
|
1776
|
+
---
|
|
1777
|
+
|
|
1778
|
+
## [2.0.0] — 2026-04-26
|
|
1779
|
+
|
|
1780
|
+
> **The design tokens release.** Every component now resolves its colors,
|
|
1781
|
+
> spacing, typography, and motion through a centralised, theme-aware
|
|
1782
|
+
> token pipeline (Style Dictionary v4 + Tokens Studio for Figma). 50+
|
|
1783
|
+
> components migrated; 18 of them also picked up real bug fixes from the
|
|
1784
|
+
> companion `optimus-design-system` codebase. Multi-theme (light / dark)
|
|
1785
|
+
> works out of the box; `brand-X` themes are an additive layer.
|
|
1786
|
+
|
|
1787
|
+
### Migrating from v0.x to v2.0.0
|
|
1788
|
+
|
|
1789
|
+
This is a major bump because three things change:
|
|
1790
|
+
|
|
1791
|
+
1. **The CSS variables that components read are now generated.** The old
|
|
1792
|
+
`<style>:root{}` blocks that each component shipped have been removed.
|
|
1793
|
+
Consumers MUST load the generated token CSS — either:
|
|
1794
|
+
|
|
1795
|
+
```ts
|
|
1796
|
+
import 'origam/styles' // primitive + light + dark + helpers
|
|
1797
|
+
```
|
|
1798
|
+
or pick the layers separately:
|
|
1799
|
+
```ts
|
|
1800
|
+
import 'origam/tokens/css/primitive'
|
|
1801
|
+
import 'origam/tokens/css/light'
|
|
1802
|
+
import 'origam/tokens/css/dark' // applied via [data-theme="dark"]
|
|
1803
|
+
```
|
|
1804
|
+
|
|
1805
|
+
If you were overriding origam vars at the document root (e.g.
|
|
1806
|
+
`:root { --origam-btn---background-color: red }`), that still works —
|
|
1807
|
+
the generated CSS is just a default. But if you depended on the
|
|
1808
|
+
per-component `:root{}` block being injected when the component
|
|
1809
|
+
mounted, that's gone. The vars are now set once globally.
|
|
1810
|
+
|
|
1811
|
+
2. **`useColorEffect` is intent-aware.** The `color` / `bgColor` props on
|
|
1812
|
+
`<OrigamBtn>`, `<OrigamChip>`, `<OrigamAvatar>`, etc. now expect a
|
|
1813
|
+
semantic intent (`'primary'`, `'success'`, `'danger'`, …) rather than
|
|
1814
|
+
a raw hex. Raw hex still works but emits a one-shot `console.warn`
|
|
1815
|
+
per `(prop, value)` pair (full removal in v3.0.0).
|
|
1816
|
+
|
|
1817
|
+
```vue
|
|
1818
|
+
<!-- v0.x -->
|
|
1819
|
+
<OrigamBtn color="#7c3aed">Click</OrigamBtn>
|
|
1820
|
+
|
|
1821
|
+
<!-- v2.0 -->
|
|
1822
|
+
<OrigamBtn color="primary">Click</OrigamBtn>
|
|
1823
|
+
|
|
1824
|
+
<!-- One-off custom color -->
|
|
1825
|
+
<OrigamBtn :style="{ '--origam-btn---background-color': '#7c3aed' }">…</OrigamBtn>
|
|
1826
|
+
```
|
|
1827
|
+
|
|
1828
|
+
3. **`useElevation` no longer computes shadows in JS.** The `bgColor`
|
|
1829
|
+
parameter is accepted for signature compat but ignored. The composable
|
|
1830
|
+
now emits `box-shadow: var(--origam-shadow-{rung})` and the rung is
|
|
1831
|
+
themed at the token level (different shadow recipes for light vs dark).
|
|
1832
|
+
|
|
1833
|
+
The legacy `formatElevationStyle(level, bgColor)` utility is still
|
|
1834
|
+
exported but `@deprecated` — it will be removed in v3.0.0.
|
|
1835
|
+
|
|
1836
|
+
### Added
|
|
1837
|
+
|
|
1838
|
+
- **Multi-tier design tokens** (`tokens/`):
|
|
1839
|
+
- Primitive: 12 color ramps, 12 spacing steps, full font / radius /
|
|
1840
|
+
shadow / motion / zIndex / opacity / border ladders.
|
|
1841
|
+
- Semantic: `surface`, `text`, `border`, `action.{primary,secondary,
|
|
1842
|
+
ghost}`, `feedback.{success,warning,danger,info}`, `overlay`. Per
|
|
1843
|
+
theme (light + dark), with hooks for brand-X.
|
|
1844
|
+
- Component: ~60 files, one per component, in DTCG / Tokens Studio
|
|
1845
|
+
format — editable from the Figma plugin.
|
|
1846
|
+
- **Pipeline**: Style Dictionary v4 + sd-transforms. Outputs CSS,
|
|
1847
|
+
SCSS partials, and TypeScript union types. `npm run tokens:build`,
|
|
1848
|
+
`tokens:watch`, `tokens:lint`.
|
|
1849
|
+
- **GitHub Action** (`.github/workflows/tokens-sync.yml`): consumes
|
|
1850
|
+
Figma → Tokens Studio → `tokens-sync` branch, rebuilds artifacts,
|
|
1851
|
+
opens a PR to `develop` automatically.
|
|
1852
|
+
- **Multi-theme runtime**:
|
|
1853
|
+
- `useTheme()` composable — singleton ref, persistence, prefers-
|
|
1854
|
+
color-scheme fallback, toggle helper.
|
|
1855
|
+
- `<OrigamThemeProvider theme="dark">` for sub-tree overrides.
|
|
1856
|
+
- **CSS-first / JS-fallback principle**:
|
|
1857
|
+
- `useCssSupport()` composable — feature detection layer wrapping
|
|
1858
|
+
`CSS.supports()` with caching for 20 modern features (subgrid,
|
|
1859
|
+
container queries, `:has()`, aspect-ratio, color-mix, anchor
|
|
1860
|
+
positioning, view transitions, …). Components now branch via
|
|
1861
|
+
this composable instead of calling `CSS.supports()` directly.
|
|
1862
|
+
- **Defaults system** (ported from optimus):
|
|
1863
|
+
- `useDefaults()` composable + `<OrigamDefaultsProvider>` for
|
|
1864
|
+
cascading default props (mirrors Vuetify's `<v-defaults-provider>`).
|
|
1865
|
+
- `IDefault`, `IDefaultProviderProps`, `IDefaultProviderSlots`.
|
|
1866
|
+
- **`<OrigamConfirmWrapper>`** — type-it-twice form helper with
|
|
1867
|
+
auto-injected validation, two render modes (slot-based / `field=`
|
|
1868
|
+
shortcut), and bidirectional defaults forwarding.
|
|
1869
|
+
- **`SCSS helpers`** (`src/assets/scss/_helpers.scss`): `ds-intent`,
|
|
1870
|
+
`ds-elevation`, `ds-text-style`, `ds-space`, `ds-focus-ring`,
|
|
1871
|
+
`ds-visually-hidden`.
|
|
1872
|
+
- **VARIANT / VARIANT_INPUT enums** + `TVariant` / `TVariantInput`
|
|
1873
|
+
types.
|
|
1874
|
+
- Common emit / slot interfaces: `IFieldEmits`, `IFieldSlots`,
|
|
1875
|
+
`IFieldDefaultSlotProps`, `IInputEmits`, `IInputSlots`,
|
|
1876
|
+
`IAdjacentEmits`, `IAdjacentSlots`, `IAdjacentInnerEmits`,
|
|
1877
|
+
`IAdjacentInnerSlots`, `IActiveEmits`, `IFocusEmits`,
|
|
1878
|
+
`ICommonsComponentEmits`, `ICommonsComponentSlots`.
|
|
1879
|
+
|
|
1880
|
+
### Changed
|
|
1881
|
+
|
|
1882
|
+
- **Every component** with chrome (~50) now consumes design tokens
|
|
1883
|
+
rather than hardcoded values. The per-component `<style>:root{}`
|
|
1884
|
+
blocks are gone.
|
|
1885
|
+
- **`OrigamPasswordField`** rebuilt from the optimus version (629
|
|
1886
|
+
vs 399 lines). New features: strength-requirements popup
|
|
1887
|
+
(`requirements` + `need*` flags + `minLength`), auto-injected
|
|
1888
|
+
validation rules, show/hide toggle, intersect-driven autofocus,
|
|
1889
|
+
click:control / mousedown:control emits.
|
|
1890
|
+
- **`OrigamFileField`** split into 3 files (FileField + DragNDropItem
|
|
1891
|
+
+ ListItem) for clearer responsibility boundaries; drag-and-drop
|
|
1892
|
+
mode reworked, `maxFileSize` validation added, typed emits.
|
|
1893
|
+
- **`OrigamForm`** grew form-level validation, `scrollToError`,
|
|
1894
|
+
global `messages` rendering through OrigamMessages.
|
|
1895
|
+
- **`OrigamField`** now exposes the `outline__notch` BEM child for
|
|
1896
|
+
the floating-label rendering, slot-based prefix/suffix detection,
|
|
1897
|
+
and proper focus↔active synchronisation.
|
|
1898
|
+
- **Snackbar z-index** normalised from `10000` to `1060` via
|
|
1899
|
+
`{zIndex.toast}`. Consumers stacking custom overlays on top must
|
|
1900
|
+
verify their stacking context.
|
|
1901
|
+
- **`color.action.primary.bgSubtle / fgSubtle`** added to the
|
|
1902
|
+
semantic layer (was missing — Select selected-item background and
|
|
1903
|
+
Slider thumb focus ring needed it).
|
|
1904
|
+
|
|
1905
|
+
### Fixed
|
|
1906
|
+
|
|
1907
|
+
- **OrigamMessages**: `:id` was bound to the entire messages array
|
|
1908
|
+
instead of the current message. Fixed by using a kebab-cased
|
|
1909
|
+
per-message key.
|
|
1910
|
+
- **OrigamNumberField**: `watchEffect` → `watch(props.modelValue)` —
|
|
1911
|
+
the eager mode was causing reactive write loops while the user
|
|
1912
|
+
typed. Increment / decrement handlers split.
|
|
1913
|
+
- **OrigamOtpInputField**: undefined-current crash guard;
|
|
1914
|
+
`isValidNumber` → `isInvalidValue` (semantic was inverted);
|
|
1915
|
+
double `update:focused` emit prevented; handleClear added.
|
|
1916
|
+
- **OrigamFileField**: `@clik:append` and `@lick:append-inner` typo
|
|
1917
|
+
fixes; drag&drop append mode no longer overwrites existing files;
|
|
1918
|
+
locale arg shape `t(key, [arg])` corrected.
|
|
1919
|
+
- **OrigamMenu**: stray `console.log()` removed.
|
|
1920
|
+
- **OrigamOverlayScrim**: `<style scoped>` block was missing
|
|
1921
|
+
entirely — scrim wasn't rendering.
|
|
1922
|
+
- **OrigamProgressCircular**: `backgroundColorClasses` /
|
|
1923
|
+
`loaderColorClasses` were missing on the SVG `<circle>` elements.
|
|
1924
|
+
- **OrigamProgressLinear**: `useBackgroundColor` → `useTextColor`
|
|
1925
|
+
(the bar's color was being applied as background, washing it out).
|
|
1926
|
+
- **OrigamListSubheader**: vuetify-specific
|
|
1927
|
+
`rgba(var(--v-theme-on-surface), …)` references replaced with
|
|
1928
|
+
origam-native tokens. Style block converted from `lang="css"` to
|
|
1929
|
+
`lang="scss"`.
|
|
1930
|
+
- **OrigamExpansionPanel**: vuetify shadow var leak
|
|
1931
|
+
(`var(--v-shadow-key-umbra-opacity, …)`) removed; selector
|
|
1932
|
+
`:not(.v-expansion-panel-title--static)` matched a vuetify class
|
|
1933
|
+
that never renders in origam — corrected to the origam class.
|
|
1934
|
+
- **OrigamSlideGroup**: `<style scoped>` block was missing entirely.
|
|
1935
|
+
- **OrigamCheckbox / OrigamCheckboxBtn / OrigamSelectionControl**:
|
|
1936
|
+
`handleClickLabel` argument typed `MouseEvent` (was `Event` —
|
|
1937
|
+
caused TS strict failures).
|
|
1938
|
+
- **OrigamSelectionControlGroup**: `item` slot now exposes
|
|
1939
|
+
`{ item, index }` (was `{ item }` only).
|
|
1940
|
+
|
|
1941
|
+
### Deprecated
|
|
1942
|
+
|
|
1943
|
+
- `formatElevationStyle(level, bgColor)` — replaced by the
|
|
1944
|
+
`--origam-shadow-{rung}` token ladder. Kept exported for one
|
|
1945
|
+
major version; full removal in v3.0.0.
|
|
1946
|
+
- Raw hex / rgb passed to `useColorEffect` color props — pass a
|
|
1947
|
+
`TIntent` value or use `:style` for one-off custom colors. Removal
|
|
1948
|
+
in v3.0.0.
|
|
1949
|
+
|
|
1950
|
+
### Outstanding (deferred to v2.x or v3.0.0)
|
|
1951
|
+
|
|
1952
|
+
- Several form components still carry hardcoded hex inside their
|
|
1953
|
+
scoped styles (Switch 11, Select 8, DatePickerField 5,
|
|
1954
|
+
ColorPickerField 2, Img 2, Highlight 3). The token JSONs are in
|
|
1955
|
+
place; the `var(--origam-…)` references need to be wired in a
|
|
1956
|
+
follow-up. Fallback-only behaviour ensures consumers see the
|
|
1957
|
+
intended design today.
|
|
1958
|
+
- Outstanding token-naming gaps: `color.surface.chrome` (SystemBar),
|
|
1959
|
+
`color.overlay.backdrop` (Drawer / Overlay scrim), `color.surface
|
|
1960
|
+
.inverse` (Tooltip), `opacity.20` / `opacity.30`, `radius.xs2: 6px`,
|
|
1961
|
+
`font.size.6xl: 45px`, `font.letterSpacing.widish`. Promote at
|
|
1962
|
+
next ui-designer review.
|
|
1963
|
+
- `OrigamMain` uses `--origam-main--{prop}` (double-tiret) instead
|
|
1964
|
+
of the canonical `---` convention. Cosmetic, breaks consumer
|
|
1965
|
+
overrides. To be aligned at v3.
|
|
1966
|
+
|
|
1967
|
+
---
|
|
1968
|
+
|
|
1969
|
+
## Pre-2.0 history
|
|
1970
|
+
|
|
1971
|
+
The `[WIP]` commits before this release were the foundation work
|
|
1972
|
+
(audit, Figma integration spike, package layout). The design-token
|
|
1973
|
+
migration started at commit `2124ab8` (Lot 0) and shipped over
|
|
1974
|
+
ten incremental commits visible in `git log --oneline main..HEAD`.
|
|
1975
|
+
|