@reliability-design/web 1.4.8 → 1.4.10
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 +214 -0
- package/custom-elements.json +18600 -0
- package/dist/components/rel-accordion/README.md +9 -2
- package/dist/components/rel-alert/README.md +5 -8
- package/dist/components/rel-autocomplete/README.md +209 -208
- package/dist/components/rel-avatar/README.md +228 -118
- package/dist/components/rel-breadcrumb/README.md +1 -0
- package/dist/components/rel-button/README.md +9 -9
- package/dist/components/rel-calendar/README.md +111 -109
- package/dist/components/rel-cardmedia/README.md +1 -1
- package/dist/components/rel-carousel/README.md +187 -186
- package/dist/components/rel-checkbox/README.md +159 -146
- package/dist/components/rel-chip/README.md +141 -138
- package/dist/components/rel-container/README.md +1 -1
- package/dist/components/rel-date-picker/README.md +221 -200
- package/dist/components/rel-drawer/README.md +4 -4
- package/dist/components/rel-kbd/README.md +188 -141
- package/dist/components/rel-layout/README.md +34 -34
- package/dist/components/rel-menu/README.md +17 -10
- package/dist/components/rel-menubar/README.md +218 -218
- package/dist/components/rel-otp/README.md +4 -8
- package/dist/components/rel-pagination/README.md +141 -100
- package/dist/components/rel-popover/README.md +220 -203
- package/dist/components/rel-radio/README.md +142 -131
- package/dist/components/rel-range-picker/README.md +194 -165
- package/dist/components/rel-resizable/README.md +220 -199
- package/dist/components/rel-segmented-button/README.md +158 -156
- package/dist/components/rel-select/README.md +22 -16
- package/dist/components/rel-sheet/README.md +3 -2
- package/dist/components/rel-signature-pad/README.md +161 -0
- package/dist/components/rel-slider/README.md +140 -131
- package/dist/components/rel-snackbar/README.md +170 -168
- package/dist/components/rel-split-button/README.md +129 -0
- package/dist/components/rel-stepper/README.md +171 -162
- package/dist/components/rel-switch/README.md +122 -117
- package/dist/components/rel-tab/README.md +184 -173
- package/dist/components/rel-textfield/README.md +23 -30
- package/dist/components/rel-time-picker/README.md +188 -164
- package/dist/components/rel-toast/README.md +20 -11
- package/dist/components/rel-tooltip/README.md +5 -4
- package/dist/components/rel-tree/README.md +157 -0
- package/dist/components/rel-upload/README.md +8 -5
- package/dist/index.d.mts +1698 -607
- package/dist/index.d.ts +1698 -607
- package/dist/index.js +12276 -6347
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12218 -6296
- package/dist/index.mjs.map +1 -1
- package/dist/styles/motion.css +31 -0
- package/dist/styles/motion.tokens.json +38 -0
- package/dist/styles/vars.css +88 -64
- package/dist/{vars-DXX6QOAG.css → vars-E22LYFMV.css} +88 -64
- package/package.json +60 -37
- package/dist/styles/focus-ring.ts +0 -84
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,219 @@
|
|
|
1
1
|
# Changelog — @reliability-design/web
|
|
2
2
|
|
|
3
|
+
## 1.5.0 (TBD)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
React 19, naming and accessibility release. Several defaults change behaviour without a rename — they are listed under [Changed](#changed-150), each with what to do. The release notes and migration checklist are on the docs site at `/docs/migration`.
|
|
7
|
+
|
|
8
|
+
Paired releases: `@reliability-design/angular` 1.5.0, which now requires web `^1.5.0` — install both together. `@reliability-design/icons` 1.5.0 ships alongside: 224 new icons (121 from the design file, 103 FO icons redrawn in the DS style), 65 existing icons redrawn from the design file, `caret-left` / `caret-right` / `arrow-from-left` / `go-back` now point the way their names say, and name aliases (see its changelog). Web keeps accepting any icons version.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`rel-toast` `tone="success"` and `tone="info"`**, on `rel-alert`'s solid fill and text tokens, so a toast matches an alert of the same tone. Announced politely; they show a leading icon, as `destructive` now does (see Changed). The design file's Toast has both tones.
|
|
13
|
+
- **`rel-accordion` `content-type`** — `text` (default, unchanged) | `custom`: no body padding, type or colour, 8px radius on the body wrapper (Figma Content Type=Custom).
|
|
14
|
+
- **`rel-segmented-button` `disabled`** disables the whole group (click, keyboard, Tab stop); per-option `disabled` is kept.
|
|
15
|
+
- **`rel-chip` `field-aria-label`** names an icon-only chip and its remove button; the remove button is exposed as **`::part(remove)`**.
|
|
16
|
+
- **`rel-breadcrumbs` `aria-label`** names the navigation (default "Breadcrumb").
|
|
17
|
+
- **`rel-range-picker` editable From / To boxes** in the panel: labelled inputs over the draft range, with inline errors; nothing commits until Apply.
|
|
18
|
+
- **An outer `<label>` works for `rel-switch`, `rel-checkbox` and `rel-radio`**, wrapping or `for=`. The three are form-associated; see Changed.
|
|
19
|
+
- **Motion v1 tokens** — 19 `--rel-motion-*` properties (6 durations, 4 easings, 4 duration + easing recipes, a loading cycle) in `vars.css`, plus the new exports `@reliability-design/web/motion.css` and `@reliability-design/web/motion.tokens.json`. The recipe durations drop to 0ms under `prefers-reduced-motion`. Opt-in: no component reads them yet.
|
|
20
|
+
- **Kebab-case attribute spellings** for 33 attributes on 13 components (`full-width`, `error-message`, `total-pages`, …) — see Deprecated.
|
|
21
|
+
- **`rel-checkbox` `supportingText`** (camelCase property) now renders; it silently did nothing.
|
|
22
|
+
- **`unavailable` CSS part** on unavailable day cells — `rel-calendar` (`part="item unavailable"`), `rel-date-picker` and `rel-range-picker` (`part="unavailable"`). Use it in place of `::part(item):disabled`; see Changed.
|
|
23
|
+
- **`rel-checkbox` `disabled`** (property and attribute), ORed with `state="disabled"`, which stays the documented spelling.
|
|
24
|
+
- **`rel-kbd` `key-name` and `platform`** — named keys in the platform's convention (Mac symbols ⌘ ⌥ ⇧ …, short words elsewhere) and a `mod` key (⌘ on Mac, Ctrl elsewhere); `platform="auto|mac|other"` also on `rel-kbd-group`. Screen readers hear the full key name.
|
|
25
|
+
- **`rel-resizable-panel` `panel-label`** names a panel while its content overflows and it is a focusable region (default "Panel N"); read-only `scrollable`.
|
|
26
|
+
- **`rel-chip` `presentational`** — the chip body is plain text (no button role, Tab stop or key handling); the remove button stays a real button.
|
|
27
|
+
- **`rel-tree`** (new, Figma Nested Tree) — an `items` tree with hierarchy guides, `selection="single" | "none" | "multiple"` (multiple: cascading checkboxes with indeterminate parents), controlled `selected` / `selected-values` / `expanded-values`, `expandAll()` / `collapseAll()`, lazy children (`rel-load-children`), `rel-change` and `rel-expanded-change`, and the full WAI-ARIA tree keyboard (arrows, Home / End, `*`, type-ahead), RTL and forced colours.
|
|
28
|
+
- **`rel-avatar-group`** (new, Figma Avatar Group) — slotted avatars get the group's `size` and a `ring` and overlap by 10 / 8 / 6 / 4px; `max` and `total` produce a "+N" circle (named "{n} more", `overflow-label`); `role="group"` named by `label`.
|
|
29
|
+
- **`rel-avatar` `ring`, `badge`, `badge-icon`, `badge-label`, `icon`** — a 2px page-colour ring outside the circle; a 12 / 10 / 8 / 6px status badge (`dot`: green; `icon`: neutral disc with `badge-icon`), read as `badge-label` or hidden without one; `icon` names a rel-icon for `type="icon"`. New hooks `--rel-avatar-ring-color`, `--rel-avatar-badge-bg`, part `badge`.
|
|
30
|
+
- **`rel-pagination` `type="page-select"` and `show-rows-per-page`** — a "Page [dropdown] of N" jump-to-page layout, and a "Results per Page" dropdown after the navigation with any type (`rows-per-page-options`, default `[10, 20, 50, 100]`; `rows-per-page-label`). A rows pick sets `per-page`, fires `rel-per-page-change` (`{ perPage }`) and returns to page 1. New parts `page-select`, `rows-per-page`.
|
|
31
|
+
- **`custom-elements.json`** — a Custom Elements Manifest of every element's API (`customElements` field; `@reliability-design/web/custom-elements.json`), with deprecations, status, `since` and accessibility notes under `rds`.
|
|
32
|
+
- **`rel-upload` `max-files`** (property `maxFiles`, `0` = no limit) — with `multiple`, files beyond the limit become error rows ("only 5 files allowed") and `rel-invalid` rejections with the new `reason: "count"`; rows already in the list count first, then new files in order; `retry()` re-checks the limit.
|
|
33
|
+
- **`rel-upload` `rel-file-replaced`** (`{ name, previous, next }`) — picking a file whose name is already in the list still replaces that row, and now also fires this event, announces "report.pdf replaced" and shows an info notice in the alert slot (the delay warning and the failure alert take the slot first).
|
|
34
|
+
- **`rel-upload` `rel-upload-complete`** (`{ succeeded, failed }`, this batch's rows) — once per batch when nothing is uploading any more, in both modes: in controlled mode it follows the statuses the app writes. Not after `cancel()`. Announced politely; no built-in toast (the docs show a `rel-toast` recipe). `rel-complete` (self-driving only) is unchanged.
|
|
35
|
+
- **`rel-tab` `orientation="vertical"`** — the tab list sits in a column beside the panel (`--rel-tab-list-width`), with `aria-orientation="vertical"`, tabs 24px apart along a rule on the list's inline-start edge with the active bar on that edge, and Up / Down instead of Left / Right. Long labels wrap; no built-in breakpoint (switch to horizontal on small screens).
|
|
36
|
+
- **`rel-tab` `icon-placement="top"`** — stacks each tab's icon above its label, with the badge beside the label; stacked tabs are 76 / 64 / 52px tall at large / medium / small. Works in both orientations.
|
|
37
|
+
- **`rel-signature-pad`** (new, status stable) — captures a handwritten signature with a mouse, pen or finger on a 160px pad that fills its container (`--rel-signature-pad-height`; focus, drawing and error draw a 2px border inside the pad edge, and focus in error adds a 2px danger ring outside), or a typed name: the "Type your name instead" link switches to `mode="type"` (Poppins italic), the keyboard alternative to drawing (WCAG 2.2 SC 2.5.7). `value` is a trimmed PNG data URL (2×, black ink in every theme) and the **form value**: the pad is form-associated and submits it under `name`, is invalid (`valueMissing`) when `required` and empty, empties on form reset and comes back on state restore (decision 0006; switch, checkbox and radio still set no form value). Also `strokes` (the vector record), `signedAt`, `typed-name`, `toDataURL(type)`, `toSVG()`, `isEmpty()`, `undo()` / `clear()`. Undo is stroke level and also reverses Clear, so Clear asks no confirmation; Ctrl/Cmd+Z undoes inside the field; the helper row shows "Signed {date, time, time zone}". Label, `helper-text`, `error` / `error-message`, `disabled` and `readonly` work as on `rel-textfield`. `rel-change` (`{ value, strokes, signedAt, mode }`, user actions only) and `rel-begin` / `rel-end`.
|
|
38
|
+
- **`rel-split-button`** (new, status stable) — the Combo Button: a main action and a chevron that opens a `rel-menu` of `items` (`{ value, label, icon?, disabled? }`) below the pill, end-aligned and at least as wide. Both segments are drawn with `rel-button`'s own styles, so `variant` (primary | secondary, the default | ghost | static), `tone` (neutral | brand | destructive) and `size` (32 / 40 / 48px) match `rel-button` exactly, including hover, pressed, focus and disabled; outer corners keep the pill radius and the seam is square. While the menu is open the chevron keeps its pressed look. Also `disabled`, `loading` (a spinner only on the main action, which keeps its accessible name; the chevron is disabled), `icon-only` with `aria-label` (the main action is a square too), `icon`, `menu-label` (the chevron's name, default "More options") and `open`. The host's `click` is the main action; `rel-select` (`{ value, item }`) and `rel-open-change` (`{ open }`). WAI-ARIA menu button: two Tab stops; Enter, Space or Down opens on the first entry and Up on the last; Escape or a choice returns focus to the chevron; Tab closes; a mouse open shows no ring. Divider: its own 1px column, in the outline border (secondary; the hover colour while the main action is hovered or pressed), the label colour (primary), white (static) or `--rel-border-subtle` (ghost).
|
|
39
|
+
- **`rel-popover` `has-popup`** (property `hasPopup`) — the value written to the trigger's `aria-haspopup`: `dialog` (default, unchanged), or `menu` for a panel holding a `rel-menu` (also `listbox`, `tree`, `grid`, `true`).
|
|
40
|
+
- **`rel-menu` item icons and `focusItem(index)`** — `MenuItem.icon` draws a `rel-icon` before the label on `list` and `arrow` rows (20 / 18 / 16px by size, hidden from screen readers); `focusItem()` moves the virtual focus (`aria-activedescendant`), clamped, a negative index counting from the end, for menu buttons that open on the last row.
|
|
41
|
+
- **`createGridNavigation(grid, options)`** (a utility, exported from the main entry) — the WAI-ARIA grid keyboard for plain markup (`[role="row"]` > `[role="gridcell"]`): a roving Tab stop, arrows, Home / End, Ctrl+Home / Ctrl+End, PageUp / PageDown with `pageSize`, right-to-left, `disabledCells` (`"focus"`, the default, or `"skip"`), `wrap`, `onActivate` (Enter, Space, click), `onMove`, a custom `resolve` key map, and a handle with `active`, `focusCell()`, `refresh()` and `destroy()`. Framework-free, so recipes can use it; the Rate Calendar recipe does.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
<a id="changed-150"></a>Visible or behavioural, with no rename to warn you:
|
|
46
|
+
|
|
47
|
+
- **`="false"` turns a Boolean attribute off.** Presence and `""` stay true. Before, any value read as true. Default-true props (`dismissible`, `icon-close`, `show-separator`, `pause-on-hover`, `close-on-select`, `close-on-escape`, `close-on-outside-click`, `responsive`) can now be switched off from HTML. Markup writing `="false"` — including Angular `[attr.x]="false"` and React 18 `x={false}` — now reads false: React 18 `<rel-alert dismissible={false}>` writes `dismissible="false"`, which was still dismissible in 1.4.9 and is not in 1.5.0.
|
|
48
|
+
- **A string assigned as a property is converted** for Array, Object, Number and Boolean props (React 19 sets custom-element props as properties). Unparseable JSON warns once and falls back to `[]` / `{}` instead of `null`. Every component now extends the new `RelElement` base.
|
|
49
|
+
- **`rel-switch`, `rel-checkbox`, `rel-radio` are form-associated.** They appear in `form.elements` and `el.click()` toggles a switch or checkbox. Form submission is unchanged (no form value). With an outer label on a checkbox, set `label=""`.
|
|
50
|
+
- **The same three behave disabled inside a `<fieldset disabled>`** (no click, label click or key; out of the Tab order; disabled styling). Their own `disabled` / `state` is untouched, so re-enabling the fieldset restores it. They now match `:disabled` when disabled, which they never did in 1.4.9. Known limit: a host with `disabled="false"` is enabled but still matches `:disabled`.
|
|
51
|
+
- **Popups stay open on an outside scroll while their field is visible** (select, autocomplete, date / range / time picker, menu submenus) and close once it scrolls out of view or under a sticky header; 1.4.9 closed on any scroll. A wheel over an open panel no longer scrolls the page.
|
|
52
|
+
- **`rel-popover` moves focus into the panel on open and back to the trigger's control on close**; `trap-focus` now wraps. With nothing focusable, `rel-popover-content`'s dialog takes focus.
|
|
53
|
+
- **Unavailable days are `aria-disabled` (focusable), not `disabled`**, in `rel-date-picker` and `rel-calendar`, as in `rel-range-picker`. **Breaking for custom CSS:** `rel-calendar::part(item):disabled` no longer matches them (only a wholly disabled calendar); style them with `::part(unavailable)`.
|
|
54
|
+
- **Out-of-month days are interactive** in the date and range pickers; min / max (and `isDateDisabled` on the date picker) apply as usual.
|
|
55
|
+
- **`rel-radio` and `rel-checkbox` geometry.** Radio follows the rebuilt design-file control (wall 1.6px small / medium; large ring 19.2px, dot 9.6px). Both paint the same size wherever they sit. In forced colors the checked radio dot and the checkbox tick / dash are now visible. Disabled labels lose subpixel anti-aliasing in Chromium.
|
|
56
|
+
- **`rel-upload`:** inside strokes per the design file — icon badge 46 → 44px, file rows 70 → 68px, dropzone 2px shorter, 6/4 dashes; the file row's progress track on `--rel-border-subtle` (dark `#404040` → `#2B2B2B`).
|
|
57
|
+
- **`rel-drawer`** renders its footer only when the `footer` slot has content, and the footer divider (drawer and `rel-modal`) now tracks content that grows after opening.
|
|
58
|
+
- **`rel-toast`:** an unknown `tone` resolves to `neutral`; it used to be added as a raw class (`tone="hidden"` hid the toast).
|
|
59
|
+
- **`rel-pagination`** `total-pages`, `default-page`, `total-items`, `per-page` are observed (were read once on connect); `show-label` and `href-template` now work.
|
|
60
|
+
- **`rel-menu`:** the row focus ring shows for keyboard focus only; `type="arrow"` flyouts open in the top layer, so containers no longer clip them, and they flip at the viewport edge.
|
|
61
|
+
- **`rel-range-picker`** colours and radii follow the design file's tokens (8px period cells, outlined switchers, darker From / To label in light mode, full-pill lone endpoint, scrim backdrop).
|
|
62
|
+
- **`rel-select`:** `role="listbox"` moves from the panel to the options container; the panel is a named group. **`rel-tooltip`:** text is set as `aria-description` on the focused control; `aria-describedby` is no longer set.
|
|
63
|
+
- **Pickers:** the error border beats the filled border; 24 × 24 icon targets (heights unchanged).
|
|
64
|
+
- **`rel-accordion`:** open bodies are no longer capped at 1000px.
|
|
65
|
+
- **`rel-select` multi-select chips sit in an overlay beside the trigger, not inside the button.** Same look and position; a click on a chip label or "+N" opens the panel; Tab goes trigger → each "Remove {label}" (no dead stops); remove targets ≥ 24 × 24px; a keyboard removal moves focus to the next remove button; "+N" is `aria-hidden`. `::part(value)` in multi mode with chips is now the overlay; CSS that shifted chips through `::part(trigger)` padding no longer moves them.
|
|
66
|
+
- **Day tones:** out-of-month and weekend days in `rel-calendar`, `rel-date-picker` and `rel-range-picker` use `--rel-text-caption` instead of a 40% / 70% fade; unavailable days use `--rel-text-disabled` at full opacity, with no extra fade; days inside a selected range are full strength; the range panel binds `--rel-bg-neutral` (same value). In `rel-calendar` and `rel-date-picker`, today keeps its `--rel-border-brand` ring when it is unavailable or the calendar is disabled, as in the design file (it used to switch to a faint `--rel-border-subtle` ring; `rel-range-picker` already kept it).
|
|
67
|
+
- **24px targets:** `rel-carousel` dot buttons are ≥ 24 × 24px cells (visible dot unchanged; the row is 24px tall; the cells touch, so the dots sit 24px apart centre to centre, 16px apart edge to edge). **Breaking for custom CSS:** `::part(dot)` is now the transparent cell — style the visible dot with `::part(dot)::before`. `rel-slider`'s rail is ≥ 24px tall (Small 16 → 24, Medium 20 → 24; track and thumb unchanged).
|
|
68
|
+
- **`rel-button`:** Pressed is exactly the Hover fill in every style, also for a keyboard or touch press; only the scale is added.
|
|
69
|
+
- **`rel-tab`:** a disabled tab keeps the enabled badge colours (was white on white in dark mode). **`rel-slider`:** fixed bubble height 18 / 22 / 24px. **`rel-menu`:** keyboard navigation rings only the current row (no ring around the whole menu).
|
|
70
|
+
- **`rel-tab` follows the updated design file (sandbox Tabs):** every tab is at least 80px wide; an inactive label uses `--rel-text-caption` (was `--rel-text-body`); hover darkens the label to `--rel-text-default` with no fill (`--rel-tab-hover-color` now defaults to `transparent`; set it to bring a fill back); icons stay `--rel-text-default`; the strip is `--rel-border-subtle` (the same in light, `#2B2B2B` instead of `#404040` in dark). The active label keeps its semibold `--rel-text-default`.
|
|
71
|
+
- **`rel-range-picker`:** Apply stays disabled while only a start day is picked (Reset → Apply still clears a committed range); a preset whose range equals the picked days shows as selected; after a mouse click on the start day the To box shows its hover border as the next field, while keyboard focus stays in the grid; day hover uses `--rel-bg-neutral-elevated-2`; the error line gains a 14px error icon.
|
|
72
|
+
- **`rel-autocomplete`:** 12px between a row's icon and its text (was 8); a disabled row keeps its icon and shows its text in `--rel-text-disabled` instead of fading the whole row to 40%; the matched characters in the supporting line are semibold, like the label's.
|
|
73
|
+
- **`rel-kbd-group`** `items` entries are named keys: on a Mac `"Ctrl"` shows ⌃; off-Mac `"Escape"` shows Esc. Use `"mod"` for the primary modifier, or `platform="other"`.
|
|
74
|
+
- **`rel-resizable-panel`:** an overflowing panel is a named, focusable `role="region"` with a focus ring until its content fits again.
|
|
75
|
+
- **`rel-switch` follows the updated design file** (API and defaults unchanged): the label is one step smaller (12 / 14 / 16px, was 14 / 16 / 20); one square 1.5px focus ring around control and label (Pill loses its inner ring); a disabled label uses `--rel-text-disabled` instead of 40% opacity, with the dulled handle on every disabled switch; hover and pressed cover the whole component.
|
|
76
|
+
- **`rel-carousel` dot colours:** inactive dots use `--rel-bg-neutral-elevated-3` (was elevated-2); the active pill is `--rel-bg-surface-brand` with a 1px `--rel-text-default` edge.
|
|
77
|
+
- **`rel-button`:** the legacy `variant="icon"` Neutral button darkens on hover (the Icon Only hover over its grey fill); its hover used to equal its rest fill.
|
|
78
|
+
- **Colours follow the design file's contrast update** (WCAG AA in light and dark; no token added, removed or renamed):
|
|
79
|
+
- **Borders:** `--rel-border-default` goes light `#E5E5E5` → `#707070`, dark `#2B2B2B` → `#707070` (3:1). `--rel-border-accent` goes light `#C2C2C2` → `#575757`, dark `#525252` → `#989898`. `--rel-border-subtle` goes light `#F7F7F7` → `#E5E5E5`, dark `#1B1B1B` → `#2B2B2B`.
|
|
80
|
+
- **Solid status fills:** danger `#FF5252` → `#CE3131`; info `#0091EA` → `#00528D` (dark too); success `#00A86B` → `#008655`.
|
|
81
|
+
- **Hover and dragged:** hover is lighter than dragged in every tone (neutral hover `#2B2B2B` → `#404040`).
|
|
82
|
+
- **Light status text:** danger → `#942323`, success → `#006440`, info → `#00528D`.
|
|
83
|
+
- **Placeholder:** light → `#707070`, dark → `#989898`.
|
|
84
|
+
- **Dark text:** a step lighter (label `#F7F7F7`, body `#E5E5E5`, caption `#C2C2C2`).
|
|
85
|
+
- **Dark `--rel-bg-surface-elevated`:** `#111111` → `#2B2B2B`. This changes `rel-container surface="elevated"`, disabled picker triggers, picker icon-button hover and time-picker shortcut keys.
|
|
86
|
+
- **Link hover:** the light destructive link hover goes to `#3E0E0E` and the dark neutral link hover to `#C2C2C2`.
|
|
87
|
+
- **Primitives:** gray-300 / 400 / 500 → `#989898` / `#707070` / `#575757`, and green-300 → `#60C9A3`.
|
|
88
|
+
- **Dividers and decorative edges** move to `--rel-border-subtle`, so they stay soft. This covers drawer and sheet dividers, the neutral tooltip edge, the menubar separator, picker shortcut keys, the range presets divider, `rel-card-media`, `rel-kbd`, the `rel-textfield` prefix and suffix divider and the `rel-upload` rows.
|
|
89
|
+
- **Fills:**
|
|
90
|
+
- the time picker's column scrollbar thumb is `--rel-bg-neutral-elevated-3`: light `#E5E5E5` → `#989898`, dark `#2B2B2B` → `#575757`;
|
|
91
|
+
- an inset muted `rel-kbd` is `--rel-bg-neutral-elevated-2`: dark `#2B2B2B` → `#404040`, light unchanged.
|
|
92
|
+
- **The `rel-upload` dropzone dash** moves to `--rel-border-default`.
|
|
93
|
+
- **What to do:** update screenshot tests, and replace `--rel-border-default` with `--rel-border-subtle` wherever your own CSS uses it as a divider or background.
|
|
94
|
+
- **`rel-kbd`:** a single-symbol key is a square cap, 20 × 20 / 24 × 24 / 28 × 28px at small / medium / large, with the symbol centred. This applies whether the symbol is slotted or comes from `key-name`: ⌘ ⌥ ⇧ ⌃, `mod` when it shows ⌘, the arrows, and ↩ ⎋ ⇥ ⌫. A small ⌘ used to be about 30px wide. Letters, digits and words are unchanged.
|
|
95
|
+
- **`rel-toast`:** `destructive`, `success` and `info` show a 20px leading icon (`error`, `check-circle`, `info`) in the static-light colour. It is `::part(icon)` and is hidden from screen readers. The gap is 8px, or 12px at `size="large"`. Neutral toasts are unchanged.
|
|
96
|
+
- **`rel-upload` same-name replace is no longer silent:** an info notice shows where nothing did, and screen readers hear it (see Added). `UploadRejection.reason` gains `"count"`; an exhaustive TypeScript `switch` over it needs the new case.
|
|
97
|
+
|
|
98
|
+
- **`rel-upload` success state and image previews:** when a batch finishes with no failures, a success alert shows in the alert slot ("3 files uploaded"); the delay warning and the failure alert come first. Image files show a 40×40 preview in place of the file icon (object URLs revoked when the row leaves the list or the element disconnects); an image that cannot be decoded keeps the icon.
|
|
99
|
+
- **`rel-kbd` `variant="muted"`:** the label moves to `--rel-text-caption` and now passes AA (5.74:1 light, 5.82:1 dark; it was 3.9 / 3.6 on placeholder).
|
|
100
|
+
- **Disabled fields are readable** and follow the design file's TextField Disabled frame: the whole field at 0.65 opacity, an elevated-2 box with the accent border, the label in `--rel-text-label` and the value and placeholder in `--rel-text-caption`. The text used to be `--rel-text-disabled` under the 0.65, which painted about 1.2–1.4:1. This covers `rel-textfield` (every variant, floating and legend labels included), `rel-autocomplete`, `rel-date-picker`, `rel-time-picker` (both were 0.4 / 0.6 before, now 0.65) and `rel-range-picker` (which was the enabled look at 0.6). `rel-select` already looked this way; `rel-otp` and `rel-signature-pad` keep their own disabled looks.
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
|
|
104
|
+
- **Calendar keyboard:** `rel-calendar`, `rel-date-picker` and `rel-range-picker` move by date, not grid position (Sep 27 + ArrowDown went to Nov 1); Home / End honour `week-start`; PageUp / PageDown (Shift: year) clamp to the month's end; the Tab stop follows the last-used day.
|
|
105
|
+
- **Panels closed within their opening frame** could stay painted or stick open on `rel-select`, `rel-autocomplete` and `rel-popover`. `rel-select` also ignored Escape / Tab pressed just after opening.
|
|
106
|
+
- **`rel-tooltip` was never announced**: its `aria-describedby` pointed into a shadow root.
|
|
107
|
+
- **`rel-drawer` / `rel-modal`** share one page scroll lock (closing one no longer unlocks the page under another); no more "ResizeObserver loop" error events; the drawer no longer leaks an observer per open.
|
|
108
|
+
- **Dialog focus** skips inert, disabled and `visibility: hidden` elements.
|
|
109
|
+
- **`rel-button`** keeps its accessible name while loading.
|
|
110
|
+
- **`rel-autocomplete`** multi rows and Select-all are named; **`rel-select`**'s listbox no longer fails `aria-required-children`.
|
|
111
|
+
- **`rel-carousel`** keeps measuring after a DOM move; **`rel-pagination`**'s page buttons are natively disabled with the host; **`rel-upload-actions`** no longer triggers an unfixable `rel-button` "no tone" notice.
|
|
112
|
+
- Pagination, segmented-button and tooltip transitions respect `prefers-reduced-motion`.
|
|
113
|
+
- **`rel-select`:** Enter or Space on a multi-select chip's remove button did nothing (it sat inside the trigger button); a keyboard removal dropped focus to `<body>`.
|
|
114
|
+
- **`rel-switch`:** the pressed state never showed (mouse or Space); a disabled checked Pill painted with the checked fills; forced colours painted nothing.
|
|
115
|
+
- **`rel-carousel`:** the dots were invisible in forced colours.
|
|
116
|
+
- **`rel-popover` / `rel-menu`:** a mouse open no longer draws a focus ring in the panel (or, after a mouse close, on the trigger); keyboard opens still do, and in a menu opened with the mouse the first arrow key brings the row ring back.
|
|
117
|
+
|
|
118
|
+
- **Fields in error lost their focus ring:** a focused `rel-textfield` (and `rel-autocomplete`) in error showed only the caret. Error + focus now draws the 2px ring outside the danger border in `--rel-border-danger` on the textfield (underline: a 2px danger line below; legend: the danger outline doubles), `rel-select` and the date, time and range pickers (WCAG 2.4.7).
|
|
119
|
+
- **`rel-popover` panel sat at a stale spot until the next frame:** it is now placed in the same task that opens it. Before, for one frame it stayed at its previous position, or at 0,0 on a first open; nothing painted there, but a quick pointer release could land on the unplaced panel instead of the trigger.
|
|
120
|
+
- **`rel-button` `variant="static" icon-only` was not square:** the static style's 40 / 50 / 60px minimum width outranked the icon-only reset, so a static icon-only button was 40 / 50 / 60 wide instead of a 32 / 40 / 48 square. Static label buttons keep their minimum width; no other style changes.
|
|
121
|
+
- **`rel-popover` panel text followed the `align` attribute:** Chromium maps an element's `align` attribute to `text-align`, and rel-popover reflects `align` (default `center`), so every popover centred its panel text (and its trigger's inline content) and `align="end"` right-aligned it. The host now takes its parent's alignment, as if the attribute were not there. If you relied on the centring, set `text-align` on your panel content.
|
|
122
|
+
|
|
123
|
+
### Known issues
|
|
124
|
+
|
|
125
|
+
- **`disabled="false"` still matches `:disabled`** on `rel-switch`, `rel-checkbox` and `rel-radio`: the control is enabled, but the browser counts the attribute's presence. Remove the attribute instead of writing `"false"`.
|
|
126
|
+
|
|
127
|
+
### Deprecated (still supported — removal targeted for 3.0)
|
|
128
|
+
|
|
129
|
+
The old lowercase-joined attribute spellings below log one notice per (component, attribute): `[rel-textfield] "fullwidth" is deprecated and will be removed in 3.0 — use "full-width" instead. (attribute spelling only; the fullWidth property is unchanged)`. Property names are unchanged. Reflected props (marked †) still write the old name in 1.x, so `[fullwidth]`-style CSS selectors keep matching. React 18 JSX writes camelCase props as these lowercase attributes, so `fullWidth` in JSX logs the notice — write `full-width`.
|
|
130
|
+
|
|
131
|
+
| Component | Old → new |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
| `rel-checkbox` | `supportingtext` → `supporting-text` |
|
|
134
|
+
| `rel-date-picker`, `rel-range-picker`, `rel-time-picker` | `fullwidth`† → `full-width` |
|
|
135
|
+
| `rel-pagination` | `defaultpage`, `totalpages`, `totalitems`, `perpage`, `showlabel`, `hreftemplate` → `default-page`, `total-pages`, `total-items`, `per-page`, `show-label`, `href-template` |
|
|
136
|
+
| `rel-popover` | `defaultopen`, `sideoffset`, `alignoffset`, `trapfocus`, `closeonescape`, `closeonoutsideclick` → `default-open`, `side-offset`, `align-offset`, `trap-focus`, `close-on-escape`, `close-on-outside-click` |
|
|
137
|
+
| `rel-radio` | `selectedvalue`†, `errormessage` → `selected-value`, `error-message` |
|
|
138
|
+
| `rel-resizable-panel` | `defaultsize`, `minsize`, `maxsize` → `default-size`, `min-size`, `max-size` |
|
|
139
|
+
| `rel-slider` | `showticklabels`†, `showbubble` → `show-tick-labels`, `show-bubble` |
|
|
140
|
+
| `rel-snackbar` | `iconclose` → `icon-close` |
|
|
141
|
+
| `rel-tab` | `activeindex`† → `active-index` |
|
|
142
|
+
| `rel-textfield` | `lefticon`, `righticon`, `prefixicon`, `prefixiconarialabel`, `errormessage`, `helpertext`, `fullwidth`† → `left-icon`, `right-icon`, `prefix-icon`, `prefix-icon-aria-label`, `error-message`, `helper-text`, `full-width` |
|
|
143
|
+
| `rel-toast` | `actionlabel` → `action-label` |
|
|
144
|
+
|
|
145
|
+
Not aliased: `arialabel` (badge, pagination), native-mirror `maxlength`, and attributes of props that are already deprecated.
|
|
146
|
+
|
|
147
|
+
**Events:** `rel-upload`'s `rel-complete` is deprecated, with removal in 3.0. Use `rel-upload-complete`, which fires once per batch in both modes (self-driving and controlled). `rel-complete` still fires exactly as before (self-driving mode only). Adding a listener for it on the element logs a one-time console warning, and `custom-elements.json` marks the event deprecated.
|
|
148
|
+
|
|
149
|
+
### Package hygiene
|
|
150
|
+
|
|
151
|
+
- `exports["."]` carries per-condition types (`import` → `index.d.mts`, `require` → `index.d.ts`); no consumer change expected. New exports `./motion.css`, `./motion.tokens.json`.
|
|
152
|
+
- **The package no longer ships `dist/styles/focus-ring.ts`**, a TypeScript source file; `dist/styles` holds only `vars.css`, `motion.css` and `motion.tokens.json`.
|
|
153
|
+
- The build fails if the icons package is unbuilt, a published entry file is missing, or a non-declaration `.ts` lands in `dist`; `prepublishOnly` builds.
|
|
154
|
+
|
|
155
|
+
## 1.4.9 (2026-09-26)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
Bug-fix release from a twenty-one item report against 1.4.8. Mostly geometry: things the token and
|
|
159
|
+
variant gates cannot see, because those gates read source text and bound token names while every one
|
|
160
|
+
of these defects is about what the browser actually *paints*. Two reported items turned out not to
|
|
161
|
+
be defects at all and are noted under [Not changed](#notchanged-149) so they are not re-filed.
|
|
162
|
+
|
|
163
|
+
Paired releases: `@reliability-design/angular` 1.4.9 — install it together with this version. (Its
|
|
164
|
+
published peer range still reads `^1.4.8`; the move to `^1.4.9` lands in the next release. See the
|
|
165
|
+
Angular changelog.) `@reliability-design/icons` is unchanged and stays on 1.4.4.
|
|
166
|
+
|
|
167
|
+
Three changes are visible without a rename to warn you; they are listed under
|
|
168
|
+
[Changed](#changed-149).
|
|
169
|
+
|
|
170
|
+
### Fixed
|
|
171
|
+
|
|
172
|
+
- **`rel-textfield` `variant="legend"` was broken at every size.** It painted a 23 / 30 / 37px outline against the 32 / 40 / 48 ladder, sat its value 4–7.5px low and overflowed the bottom border by up to 6px at `small` — while `getBoundingClientRect()` reported the correct height, which is why nothing caught it. Two Blink fieldset behaviours caused it: a fieldset's border box *includes* the legend's protruding top half, and the legend's full height is subtracted from the content area (the intended remedy, `flex: 1` on the row, is inert — a fieldset's anonymous content box does not take a fixed height). The fieldset is now a decorative, absolutely-positioned outline layer and the content rides the ordinary container row, so the variant measures identically to `variant="default"`. Also fixed in the same pass: the legend's text sat 4px right of the value, its inline inset was frozen at 12px and could not see the size ramp, and the default size rendered a heavier legend than either neighbour.
|
|
173
|
+
- **The floating label was struck through by the field's own border.** The label masks the border with an opaque strip rather than cutting a notch, and the strip was positioned against the wrong reference, leaving part of the painted band crossing the label text. Affects `rel-textfield`, `rel-select` and — through composition — `rel-autocomplete`. The two components need *different* corrections because their containing blocks differ; both are now derived from the border and ring widths rather than restated.
|
|
174
|
+
- **`rel-select`'s floating label painted an opaque block over the field.** It filled the label's whole ~20px line box to hide a 1px border, erasing roughly 10px of the trigger's interior and 10px above it. Figma specifies a strip whose height *equals the border it masks* — 1px at rest, 2px focused — which `rel-textfield` already used. Two further defects fixed with it: there was no disabled fill swap, so a disabled select painted a lighter block over its own trigger; and a hard-coded `top: -2px` nudge applied to `.focused` but not `.has-value`, so the label **jumped 2px** when focus arrived on a filled select.
|
|
175
|
+
- **`rel-autocomplete` lit three suggestion rows at once.** The committed selection, the keyboard cursor and a stale CSS `:hover` all painted the same wash, so arrowing through a list with the mouse resting on it left no way to tell which row `Enter` would commit. `:hover` was redundant in that rule — `pointerenter` already moves the keyboard cursor onto the hovered row — and it was the only thing keeping a passed-over row lit. Every individual state was, and remains, pixel-correct against the design file.
|
|
176
|
+
- **`rel-accordion` appeared to gain a border on hover.** There was no hover border rule: `.accordion` always carried a 1px border and `appearance="shadow"` merely made it transparent, so the header was inset 1px on all four sides and the hover wash stopped short of the card edge, leaving a ring of untinted surface. The stroke is now an `outline` with a negative offset, which is what Figma's inside-aligned stroke means and costs no layout.
|
|
177
|
+
- **`rel-upload`'s disabled cursor never appeared.** `cursor: not-allowed` was set on the dropzone, but an ancestor carried `pointer-events: none`, and an element that is not a hit target never has its cursor consulted. `getComputedStyle` reported `not-allowed` while the pointer showed an arrow. The cursor now sits on the host. Separately, the file list failed `aria-required-children`: its container has `role="list"` and its rows carried no `role="listitem"`.
|
|
178
|
+
- **`rel-menu`'s submenu chevron was dulled to 60% opacity**, where the design file has it at full strength on the same token as the row label beside it. Its colour is now declared rather than inherited — `rel-menu` renders to the light DOM, so an inherited colour travelled through the consumer's page cascade.
|
|
179
|
+
- **`rel-carousel`'s vertical orientation put the arrows on the horizontal axis.** A vertical carousel got a left-pointing chevron at mid-left and a right-pointing one at mid-right, flanking the caption while the motion ran up and down. The arrows now ride the vertical axis with rotated chevrons. Vertical slides also centre their content instead of stretching it and leaving the caption top-anchored in dead space.
|
|
180
|
+
- **`rel-checkbox`'s indeterminate dash rendered 1.6× too thin.** An 8:1 viewBox was being letterboxed into a square box, so the dash painted at 6.875% of the frame where the design file has 11.11% — and at a fractional thickness at every size, which is what made it look soft. Both marks now use the design file's own 16-unit geometry. Corner radius was hand-written per size and *omitted* for `large` and `extra-large`, so a 24px box and an 18px box shared a corner; radius and border are now derived from the drawn square.
|
|
181
|
+
- **All three pickers left their panel floating over sticky page furniture.** `rel-date-picker`, `rel-range-picker` and `rel-time-picker` repositioned their panel on scroll, tracking a trigger that had already scrolled out of view — and because the panel is promoted to the browser top layer it kept painting above everything. They now **close on an outside scroll**, matching `rel-select` and `rel-autocomplete`. Scrolling *inside* a panel does not close it, including the time picker's hour, minute and period columns, which are each their own scroller.
|
|
182
|
+
- **`rel-date-picker` and `rel-range-picker` drew a hand-written calendar glyph** that matched no icon in the set. Both triggers now render the design system's `calendar-month`.
|
|
183
|
+
- **`rel-alert` reserved a pixel no variant used.** A 1px transparent border sat on the shared base, so every appearance's content box was 1px tighter than the design file — only `outline` has a stroke there, and it is inside-aligned, which overlays rather than insets. The content column also hugged its text instead of filling the row it is specified to fill. Both fixed; every appearance keeps a visible boundary in forced-colors mode.
|
|
184
|
+
- **`rel-radio` warned about a value you never set.** `density="compact"` with `alignment="trailing"` logged a notice — but `compact` is the default, so setting only `alignment` produced a warning about a coercion of a value the author never wrote. It now warns only when `density` was explicitly chosen.
|
|
185
|
+
|
|
186
|
+
### Added
|
|
187
|
+
|
|
188
|
+
- **`rel-stepper` `connector`.** `solid` (default, unchanged) or `dot` — a 1px connector dashed 2px on / 2px off, per the design file's `.Line Types`. Note `connector="dot"` is the **line between steps** while the existing `type="dot"` is the **step indicator disc**; they are independent axes that both use the word.
|
|
189
|
+
- **`rel-checkbox` `field-aria-label`**, joining `rel-switch`, `rel-radio`, `rel-segmented-button` and `rel-autocomplete`. It was the only control in that family without one.
|
|
190
|
+
- **`rel-change` as an alias on the last three components that lacked it.** `rel-select` and `rel-segmented-button` emitted only `changed`; `rel-tab` emitted only `rel-tab-change`. All three now emit `rel-change` *alongside* their existing event, with the same detail and timing. **Both fire — neither replaces the other**, and the legacy names are kept for as long as 1.x. Every interactive component in the library now emits `rel-change`.
|
|
191
|
+
- **`--rel-overlay-fallback-z`** (default `1001`), shared by `rel-select`, `rel-autocomplete` and the three pickers. Consulted **only** on the no-Popover-API fallback path: wherever the browser top layer is available the panel is promoted into it and z-index is inert, because top-layer elements are not in the page stacking order at all.
|
|
192
|
+
- **`--rel-select-surface`** and **`--rel-select-surface-disabled`**, mirroring `--rel-textfield-surface` — the colour of the strip the floating label lays over the trigger's border. Set them when the field sits on a surface that is not the trigger's own fill.
|
|
193
|
+
- **`--rel-carousel-slide-display`** (default `flex`), the escape hatch for the vertical slide centring above. Set it to `block` if forcing flex reflows your slide's own children.
|
|
194
|
+
- **`rel-stepper` `textalign` now logs its deprecation.** It has been a documented alias of `label-placement` for some time but said nothing at runtime. The notice fires once, only for a non-default value, and only when `label-placement` is unset.
|
|
195
|
+
|
|
196
|
+
### Changed
|
|
197
|
+
|
|
198
|
+
<a id="changed-149"></a>Three changes are visible with no rename to warn you:
|
|
199
|
+
|
|
200
|
+
- **`rel-radio` `size="small"` renders larger again.** 1.4.8 gave Small its own 16px control on the premise that the ramp was 16/20/24. That premise was never read off the design file, which pins Small **and** Medium to one 20px control and separates them by type alone — verified across all forty-five variants. Small returns to a 20px control, 16px ring and 8px dot, keeping its smaller label type. This reverts a deliberate 1.4.8 change; the component's own README had said so correctly the whole time.
|
|
201
|
+
- **`rel-textfield`'s `::part(control)` is a `div` for `variant="legend"`,** where it used to be the `<fieldset>`. The fieldset became a decorative outline layer so the variant could sit on the size ladder. `::part(control)` still matches; only rules that depended on it *being* a fieldset do not.
|
|
202
|
+
- **`rel-alert` has no minimum width.** It carried `min-width: 360px`, which was code-invented — the design file's Alert is a fixed 400 with no minimum — and it stopped the alert fitting any column narrower than 360px. Set a floor on the host if you want one.
|
|
203
|
+
|
|
204
|
+
Also changed, but only observable on the fallback path: the picker panels' fallback `z-index` drops
|
|
205
|
+
from `2147483647` to the shared `--rel-overlay-fallback-z` (default `1001`). This value is consulted
|
|
206
|
+
only in browsers without the Popover API and has no effect wherever the top layer is available. The
|
|
207
|
+
old value unconditionally beat consumer application chrome.
|
|
208
|
+
|
|
209
|
+
### Not changed
|
|
210
|
+
|
|
211
|
+
<a id="notchanged-149"></a>Two reported items were investigated and found correct, recorded here so
|
|
212
|
+
they are not re-filed:
|
|
213
|
+
|
|
214
|
+
- **`rel-alert`'s colours and tones match the design file.** All twelve style × tone cells bind exactly the token the design file binds. The report came from comparing against a dark-mode rendering; the REST API resolves variable-bound fills in whichever mode is default, so a raw hex from it names no token and cannot be compared to a light-mode value.
|
|
215
|
+
- **`rel-checkbox`'s four sizes are the design file's own ramp.** The drawn squares land 1.6px apart at the lower steps, which does read as tight, but 16 / 18 / 20 / 24 is what the file specifies and the code already matched it.
|
|
216
|
+
|
|
3
217
|
## 1.4.8 (2026-09-21)
|
|
4
218
|
|
|
5
219
|
|