@reliability-design/web 1.4.6 → 1.4.7

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.
Files changed (146) hide show
  1. package/CHANGELOG.md +211 -49
  2. package/dist/components/rel-accordion/README.md +132 -132
  3. package/dist/components/rel-alert/README.md +145 -141
  4. package/dist/components/rel-autocomplete/README.md +156 -61
  5. package/dist/components/rel-avatar/README.md +116 -130
  6. package/dist/components/rel-badge/README.md +98 -93
  7. package/dist/components/rel-breadcrumb/README.md +96 -102
  8. package/dist/components/rel-button/README.md +160 -130
  9. package/dist/components/rel-calendar/README.md +109 -109
  10. package/dist/components/rel-card/README.md +75 -94
  11. package/dist/components/rel-cardmedia/README.md +100 -127
  12. package/dist/components/rel-carousel/README.md +184 -166
  13. package/dist/components/rel-checkbox/README.md +93 -75
  14. package/dist/components/rel-chip/README.md +132 -121
  15. package/dist/components/rel-container/README.md +107 -99
  16. package/dist/components/rel-date-picker/README.md +200 -289
  17. package/dist/components/rel-divider/README.md +78 -100
  18. package/dist/components/rel-drawer/README.md +187 -200
  19. package/dist/components/rel-kbd/README.md +141 -151
  20. package/dist/components/rel-menu/README.md +178 -151
  21. package/dist/components/rel-menubar/README.md +218 -329
  22. package/dist/components/rel-otp/README.md +170 -440
  23. package/dist/components/rel-pagination/README.md +100 -424
  24. package/dist/components/rel-popover/README.md +203 -568
  25. package/dist/components/rel-progress/README.md +88 -110
  26. package/dist/components/rel-radio/README.md +131 -138
  27. package/dist/components/rel-range-picker/README.md +162 -0
  28. package/dist/components/rel-resizable/README.md +199 -140
  29. package/dist/components/rel-segmented-button/README.md +155 -141
  30. package/dist/components/rel-select/README.md +154 -93
  31. package/dist/components/rel-sheet/README.md +168 -224
  32. package/dist/components/rel-skeleton/README.md +103 -0
  33. package/dist/components/rel-slider/README.md +130 -135
  34. package/dist/components/rel-snackbar/README.md +162 -134
  35. package/dist/components/rel-stepper/README.md +158 -160
  36. package/dist/components/rel-switch/README.md +108 -102
  37. package/dist/components/rel-tab/README.md +171 -163
  38. package/dist/components/rel-textfield/README.md +159 -69
  39. package/dist/components/rel-time-picker/README.md +122 -157
  40. package/dist/components/rel-toast/README.md +157 -148
  41. package/dist/components/rel-tooltip/README.md +108 -111
  42. package/dist/components/rel-upload/README.md +220 -0
  43. package/dist/index.d.mts +1147 -340
  44. package/dist/index.d.ts +1147 -340
  45. package/dist/index.js +3451 -3163
  46. package/dist/index.js.map +1 -1
  47. package/dist/index.mjs +3416 -3118
  48. package/dist/index.mjs.map +1 -1
  49. package/dist/styles/vars.css +877 -866
  50. package/dist/{vars-XNMTSRVN.css → vars-JHTUGNRG.css} +877 -866
  51. package/package.json +3 -2
  52. package/dist/components/rel-accordion/rel-accordion.ts +0 -336
  53. package/dist/components/rel-alert/rel-alert.ts +0 -305
  54. package/dist/components/rel-autocomplete/rel-autocomplete.ts +0 -720
  55. package/dist/components/rel-avatar/rel-avatar.ts +0 -142
  56. package/dist/components/rel-badge/rel-badge.ts +0 -175
  57. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +0 -106
  58. package/dist/components/rel-button/rel-button.ts +0 -560
  59. package/dist/components/rel-calendar/index.ts +0 -1
  60. package/dist/components/rel-calendar/rel-calendar.ts +0 -565
  61. package/dist/components/rel-card/rel-card.ts +0 -88
  62. package/dist/components/rel-cardmedia/rel-cardmedia.ts +0 -88
  63. package/dist/components/rel-carousel/index.ts +0 -1
  64. package/dist/components/rel-carousel/rel-carousel.ts +0 -723
  65. package/dist/components/rel-chart/README.md +0 -286
  66. package/dist/components/rel-chart/index.ts +0 -1
  67. package/dist/components/rel-chart/rel-chart.ts +0 -754
  68. package/dist/components/rel-checkbox/rel-checkbox.ts +0 -382
  69. package/dist/components/rel-chip/rel-chip.ts +0 -483
  70. package/dist/components/rel-container/rel-container.ts +0 -95
  71. package/dist/components/rel-date-picker/date-format.test.ts +0 -43
  72. package/dist/components/rel-date-picker/date-format.ts +0 -47
  73. package/dist/components/rel-date-picker/date-parse.test.ts +0 -116
  74. package/dist/components/rel-date-picker/date-parse.ts +0 -178
  75. package/dist/components/rel-date-picker/index.ts +0 -1
  76. package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1676
  77. package/dist/components/rel-divider/rel-divider.ts +0 -54
  78. package/dist/components/rel-drawer/index.ts +0 -1
  79. package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
  80. package/dist/components/rel-drawer/rel-drawer.ts +0 -607
  81. package/dist/components/rel-kbd/rel-kbd.ts +0 -188
  82. package/dist/components/rel-layout/rel-layout.ts +0 -49
  83. package/dist/components/rel-menu/rel-menu.ts +0 -541
  84. package/dist/components/rel-menubar/index.ts +0 -2
  85. package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
  86. package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
  87. package/dist/components/rel-menubar/rel-menubar.ts +0 -777
  88. package/dist/components/rel-nav-menu/README.md +0 -289
  89. package/dist/components/rel-nav-menu/index.ts +0 -3
  90. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
  91. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
  92. package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
  93. package/dist/components/rel-navbar/README.md +0 -126
  94. package/dist/components/rel-navbar/rel-navbar.ts +0 -105
  95. package/dist/components/rel-otp/index.ts +0 -1
  96. package/dist/components/rel-otp/rel-otp.ts +0 -527
  97. package/dist/components/rel-pagination/index.ts +0 -1
  98. package/dist/components/rel-pagination/rel-pagination.ts +0 -522
  99. package/dist/components/rel-popover/index.ts +0 -2
  100. package/dist/components/rel-popover/rel-popover-content.ts +0 -81
  101. package/dist/components/rel-popover/rel-popover.ts +0 -475
  102. package/dist/components/rel-progress/rel-progress.ts +0 -234
  103. package/dist/components/rel-radio/rel-radio.ts +0 -481
  104. package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1688
  105. package/dist/components/rel-resizable/index.ts +0 -3
  106. package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
  107. package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
  108. package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
  109. package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -217
  110. package/dist/components/rel-select/rel-select.ts +0 -1416
  111. package/dist/components/rel-sheet/rel-sheet.ts +0 -610
  112. package/dist/components/rel-sidebar/README.md +0 -209
  113. package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1191
  114. package/dist/components/rel-skeleton/rel-skeleton.ts +0 -143
  115. package/dist/components/rel-slider/rel-slider.ts +0 -673
  116. package/dist/components/rel-snackbar/rel-snackbar.ts +0 -329
  117. package/dist/components/rel-stepper/rel-stepper.ts +0 -567
  118. package/dist/components/rel-switch/rel-switch.ts +0 -199
  119. package/dist/components/rel-tab/rel-tab.ts +0 -264
  120. package/dist/components/rel-table/README.md +0 -178
  121. package/dist/components/rel-table/rel-table-body.ts +0 -22
  122. package/dist/components/rel-table/rel-table-caption.ts +0 -30
  123. package/dist/components/rel-table/rel-table-cell.ts +0 -43
  124. package/dist/components/rel-table/rel-table-footer.ts +0 -24
  125. package/dist/components/rel-table/rel-table-head.ts +0 -47
  126. package/dist/components/rel-table/rel-table-header.ts +0 -22
  127. package/dist/components/rel-table/rel-table-row.ts +0 -37
  128. package/dist/components/rel-table/rel-table.ts +0 -62
  129. package/dist/components/rel-textfield/rel-textfield.ts +0 -1054
  130. package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1482
  131. package/dist/components/rel-time-picker/time-parse.test.ts +0 -67
  132. package/dist/components/rel-time-picker/time-parse.ts +0 -85
  133. package/dist/components/rel-toast/rel-toast.ts +0 -206
  134. package/dist/components/rel-tooltip/rel-tooltip.ts +0 -193
  135. package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
  136. package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
  137. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
  138. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
  139. package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
  140. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
  141. package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
  142. package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
  143. package/dist/components/rel-topbar/rel-topbar.ts +0 -446
  144. package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
  145. package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
  146. package/dist/components/rel-upload/rel-upload.ts +0 -968
@@ -1,122 +1,183 @@
1
1
  # rel-select
2
2
 
3
- ## Overview
4
- A custom combobox-style select component built on the same textfield visual language (sizes, states, border styles). Renders a typeable text trigger with a custom-styled dropdown listbox (no native `<select>`/`<option>` rendering), so the dropdown is fully themeable in both light and dark mode. Supports icons, multiple states, and sizes, with built-in keyboard navigation, type-to-filter, and an inline "ghost text" autocomplete suggestion.
3
+ `<rel-select>` is the combobox-style dropdown from the Figma "Dropdown" component: a text-field-styled trigger button that opens a custom listbox (never a native `<select>`, so it is fully themeable in light and dark mode). It supports single- and multi-select, an optional in-panel search field, a Select-all row in multi mode, and width-adaptive selection chips that collapse into a "+N" chip instead of wrapping. Use it to pick one or several values from a known list. For free text use `rel-textfield`; for type-ahead against a large or remote list use `rel-autocomplete`; for two or three mutually exclusive options `rel-radio` is usually clearer.
5
4
 
6
5
  ## Usage
6
+
7
7
  ```html
8
- <!-- Basic example -->
9
- <rel-select id="countrySelect" label="Country" selected="USA"></rel-select>
8
+ <!-- Single select -->
9
+ <rel-select id="country" label="Country" placeholder="Select a country"></rel-select>
10
10
  <script>
11
- const select = document.getElementById('countrySelect');
12
- select.options = ['USA', 'Canada', 'Mexico'];
11
+ const country = document.getElementById("country");
12
+ country.options = ["USA", "Canada", "Mexico"];
13
+ country.addEventListener("changed", (e) => console.log(e.detail.value)); // "Canada"
13
14
  </script>
14
15
 
15
- <!-- Example with common options -->
16
+ <!-- Object options: value / label / icon / supportingText (supportingText shows in multi-select rows only) -->
17
+ <script>
18
+ country.options = [
19
+ { value: "air", label: "Air freight", icon: "air" },
20
+ { value: "sea", label: "Sea freight", icon: "ship", supportingText: "4-6 weeks" },
21
+ ];
22
+ </script>
23
+
24
+ <!-- Preselected value, helper text, icons -->
25
+ <rel-select label="Email preference" selected="weekly" supporting-text="How often we email you" left-icon="mail"></rel-select>
26
+ <rel-select label="Custom chevron" right-icon="expand-more"></rel-select>
27
+
28
+ <!-- Sizes, corners, label styles -->
29
+ <rel-select label="Small" size="small"></rel-select>
30
+ <rel-select label="Large" size="large"></rel-select>
31
+ <rel-select label="Sharp corners" border="sharp"></rel-select>
32
+ <rel-select label="Floating label" label-style="floating"></rel-select>
33
+ <rel-select label-style="none" placeholder="Filter by status" field-aria-label="Filter by status"></rel-select>
34
+
35
+ <!-- States -->
36
+ <rel-select label="Region" state="error" supporting-text="Pick a region to continue"></rel-select>
37
+ <rel-select label="Locked" state="disabled" selected="USA"></rel-select>
38
+
39
+ <!-- Short list without a search field (Figma "Single Option" dropdown) -->
40
+ <rel-select label="Priority" no-search></rel-select>
41
+
42
+ <!-- Multi-select with chips, Select-all and a search placeholder -->
16
43
  <rel-select
17
- id="emailPreference"
18
- label="Email Preference"
19
- selected="Weekly"
20
- size="medium"
21
- state="default"
22
- supportingText="Choose how often you want to receive emails"
23
- leftIcon="📧">
44
+ id="tags"
45
+ label="Tags"
46
+ multiple
47
+ selected-values='["urgent","fragile"]'
48
+ select-all-label="Select all tags"
49
+ search-placeholder="Search tags"
50
+ max-visible-chips="3">
24
51
  </rel-select>
25
52
  <script>
26
- const emailPref = document.getElementById('emailPreference');
27
- emailPref.options = ['Daily', 'Weekly', 'Monthly', 'Never'];
53
+ const tags = document.getElementById("tags");
54
+ tags.options = ["urgent", "fragile", "hazmat", "oversize", "refrigerated"];
55
+ tags.addEventListener("changed", (e) => console.log(e.detail.value)); // ["urgent", "fragile", ...]
28
56
  </script>
29
57
  ```
30
58
 
59
+ <!-- readme-gen:start -->
60
+
61
+ <!-- Generated from rel-select.ts — do not edit; run readme-generate.mjs -->
62
+
31
63
  ## API
32
64
 
33
- ### Attributes/Properties
34
- | Name | Type | Default | Description |
35
- |------|------|---------|-------------|
36
- | `label` | `string` | `""` | Label text displayed above the select |
37
- | `label-style` | `"default" \| "floating" \| "none"` | `"default"` | Label presentation. `"default"` sits above the trigger, `"floating"` rests over the placeholder and animates onto the border line, `"none"` renders no label at all |
38
- | `field-aria-label` | `string` | - | Accessible name for the trigger. Required with `label-style="none"` |
39
- | `field-aria-labelledby` | `string` | - | IDREF list of external element(s) naming the trigger. Wins over `field-aria-label` |
40
- | `options` | `(string \| SelectOptionObject)[]` | `[]` | Options to display in the dropdown. Each entry is either a plain string or an object: `{ value, label?, supportingText?, icon? }`. `icon` is a `rel-icon` name rendered as a prefix (leading icon) on the menu item — before the label in single-select rows, and between the checkbox and label in multi-select rows |
41
- | `selected` | `string` | `""` | Currently selected option value |
42
- | `state` | `"default" \| "error" \| "disabled"` | `"default"` | Visual and interaction state of the select |
43
- | `supportingText` | `string` | `""` | Helper or error text displayed below the select |
44
- | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Size variant affecting padding and font size |
45
- | `border` | `"rounded" \| "sharp"` | `"rounded"` | Border radius style |
46
- | `leftIcon` | `string` | `""` | `rel-icon` name displayed on the left side |
47
- | `rightIcon` | `string` | `""` | `rel-icon` name to override the default right-side icon. When unset, a chevron is shown that rotates 180° on open; a custom `rightIcon` replaces the chevron entirely and does not rotate |
48
- | `placeholder` | `string` | `"Select option"` | Placeholder text shown when nothing is selected |
65
+ ### Attributes / Properties
66
+
67
+ | Property | Attribute | Type | Default | Description |
68
+ | --- | --- | --- | --- | --- |
69
+ | `label` | `label` | `string` | `""` | Visible label. Rendered above the trigger (`labelStyle="default"`) or floating inside it; omitted under `labelStyle="none"`. |
70
+ | `labelStyle` | `label-style` | `"default" \| "floating" \| "none"` | `"default"` | Label presentation: `default` static label above the trigger; `floating` label rests in the value area and floats onto the border when focused, open or filled; `none` renders no label (supply `fieldAriaLabel` / `fieldAriaLabelledby`). Reflected. |
71
+ | `fieldAriaLabel` | `field-aria-label` | `string` | `undefined` | Accessible name for the trigger. Required when `labelStyle="none"`, since no `<label>` renders and a placeholder is not a valid naming mechanism. |
72
+ | `fieldAriaLabelledby` | `field-aria-labelledby` | `string` | `undefined` | IDREF list of external element(s) naming the trigger. Wins over `fieldAriaLabel`. |
73
+ | `options` | `options` | `(string \| SelectOptionObject)[]` | `[]` | Options to list. Each entry is a plain string (used as both value and label) or `{ value, label?, supportingText?, icon? }`; `icon` is a `rel-icon` name rendered before the label, `supportingText` shows only in multi-select rows. |
74
+ | `multiple` | `multiple` | `boolean` | `false` | Enables multi-select: selected values render as removable chips, options as checkboxes, and a Select-all row appears in the panel. |
75
+ | `selected` | `selected` | `string` | `""` | Selected option value in single-select mode. Ignored when `multiple` is set. |
76
+ | `selectedValues` | `selected-values` | `string[]` | `[]` | Selected option values in multi-select mode. Reset to `[]` when `multiple` is turned off. |
77
+ | `state` | `state` | `"default" \| "error" \| "disabled"` | `"default"` | Visual / interaction state. `error` colours the border and supporting text and clears itself on the next selection; `disabled` blocks interaction and dims the whole field. |
78
+ | `supportingText` | `supporting-text` | `string` | `""` | Helper line below the trigger; coloured as an error while `state="error"`. |
79
+ | `supportingIcon` | `supporting-icon` | `string` | `""` | `rel-icon` name shown before the supporting text (16px, 14px at `small`). Optional: the design pairs the helper line with an icon, but existing fields without one keep their current single-line look. |
80
+ | `size` | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Field height — `small` 32px, `medium` 40px, `large` 48px. The whole component rides this one axis: label and supporting type, trigger padding, icons (20 / 18 / 16), selection chips, and the panel's rows, search field and checkboxes all scale with it. Reflected. |
81
+ | `border` | `border` | `"rounded" \| "sharp"` | `"rounded"` | Trigger corners: `rounded` applies the corner radius, `sharp` renders square corners. |
82
+ | `leftIcon` | `left-icon` | `string` | `""` | `rel-icon` name rendered at the left edge of the trigger. |
83
+ | `rightIcon` | `right-icon` | `string` | `""` | `rel-icon` name replacing the default chevron at the right edge of the trigger. A custom icon does not rotate when the panel opens. |
84
+ | `placeholder` | `placeholder` | `string` | `"Select option"` | Text shown in the trigger while nothing is selected. |
85
+ | `searchPlaceholder` | `search-placeholder` | `string` | `"Search option"` | Placeholder of the in-panel search field (the field is hidden when `noSearch` is set). |
86
+ | `selectAllLabel` | `select-all-label` | `string` | `"Select all"` | Label of the Select-all row shown at the top of the panel in multi-select mode. |
87
+ | `maxVisibleChips` | `max-visible-chips` | `number` | `Infinity` | Optional hard cap on visible chips. By default (no cap) the visible count adapts to the trigger's width: chips collapse into the "+N" badge one by one instead of wrapping to a second line. |
88
+ | `noSearch` | `no-search` | `boolean` | `false` | Hides the in-panel search field. Figma's "Single Option" dropdown has no search bar at all — use this for short, non-searchable lists. |
49
89
 
50
90
  ## Events
51
- | Event | Detail | Description |
52
- |-------|--------|-------------|
53
- | `changed` | `{ value: string }` | Fired when the selected value changes |
54
91
 
55
- ## Slots
56
- Default slot not used.
57
-
58
- ## CSS Parts
59
- None exposed.
92
+ | Event | Detail | Bubbles / composed | Description |
93
+ | --- | --- | --- | --- |
94
+ | `changed` | `{ value: this.multiple ? this.selectedValues : this.selected }` | bubbles / composed | Fired after any selection change (pick, checkbox toggle, Select-all, chip removal). Detail: `{ value }` — the selected value string in single mode, or the array of selected values when `multiple`. |
60
95
 
61
- ## Tokens / CSS Variables
96
+ ## Slots
62
97
 
63
- ### Semantic Tokens
64
- - `--rel-fonts-font-family` - Font family
65
- - `--rel-body-xs-regular-font-size`, `--rel-body-sm-regular-font-size`, `--rel-body-md-regular-font-size` - Font sizes for different size variants
66
- - `--rel-fonts-weight-body-medium` - Font weight for label
98
+ | Slot | Description |
99
+ | --- | --- |
100
+ | — | This element has no slots. |
67
101
 
68
- ### Spacing Tokens
69
- - `--rel-spacing-3xs`, `--rel-spacing-2xs`, `--rel-spacing-xs` - Internal padding
70
- - `--rel-spacing-sm`, `--rel-spacing-md`, `--rel-spacing-xl`, `--rel-spacing-2xl` - Padding and icon positioning
102
+ ## CSS Parts
71
103
 
72
- ### Color Tokens
73
- - `--rel-text-label` - Label and selected-value text color
74
- - `--rel-text-default` - Icon color, focus border/shadow color
75
- - `--rel-text-placeholder` - Placeholder, supporting text, and ghost-suggestion text color
76
- - `--rel-text-disabled` - Disabled text/icon color
77
- - `--rel-border-default` - Default border color
78
- - `--rel-bg-surface` - Background color (trigger and dropdown panel)
79
- - `--rel-bg-neutral-elevated-1` - Disabled background, hovered/highlighted option background
80
- - `--rel-bg-danger` - Error state border, text, and icon color (light: `#D50000`, dark: `#FF5252`)
81
- - `--rel-shadows-shadow-200` - Dropdown panel shadow
104
+ | Part | Description |
105
+ | --- | --- |
106
+ | `label` | The visible label above the trigger (default label style) |
107
+ | `trigger` | The button that opens the panel; styled like a text field |
108
+ | `value` | The value area inside the trigger (selected label, placeholder or chips) |
109
+ | `helper` | The supporting / error text below the trigger |
110
+ | `panel` | The dropdown listbox container (same node as `list`) |
111
+ | `list` | Alias of `panel` |
112
+ | `input` | The search input inside the panel |
113
+ | `option` | A single-select option row |
82
114
 
83
- ### Border Tokens
84
- - `--rel-border-radius-xs` - Rounded border radius (default `border="rounded"`)
115
+ ## Tokens / CSS Variables
85
116
 
86
- ### Layout Tokens
87
- - `--rel-field-label-reserve` - Height held for the absent label row under `label-style="none"`, so the trigger bottom-aligns with labelled siblings. Defaults to the label line-height plus the wrapper gap; set to `0` to collapse the row entirely in compact contexts (toolbars, table cells)
117
+ ### Component hooks
118
+
119
+ Set these on the host (or an ancestor) to customise the element without touching design tokens.
120
+
121
+ | Custom property | Default | Description |
122
+ | --- | --- | --- |
123
+ | `--rel-field-label-reserve` | `calc(var(--rel-body-md-regular-line-height) + var(--rel-spacing-2xs))` | Height held for the absent label row under `labelStyle="none"` so the trigger bottom-aligns with labelled siblings; defaults to the label line-height plus the wrapper gap. Set to `0` to collapse the row entirely (toolbars, table cells). |
124
+ | `--rel-select-bg` | `var(--rel-bg-neutral)` | Background of the trigger, the floating label, the panel and its sticky header |
125
+ | `--rel-select-bg-disabled` | `var(--rel-bg-neutral-elevated-2)` | Trigger background when `state="disabled"` |
126
+ | `--rel-select-border-default` | `var(--rel-border-default)` | Trigger border colour at rest |
127
+ | `--rel-select-border-disabled` | `var(--rel-border-accent)` | Trigger border colour when `state="disabled"` |
128
+ | `--rel-select-border-error` | `var(--rel-border-danger)` | Trigger border colour when `state="error"` |
129
+ | `--rel-select-border-focus` | `var(--rel-border-strong)` | Trigger border colour on hover, while focused (where it also thickens to 2px) and while the panel is open |
130
+ | `--rel-select-divider` | `var(--rel-border-subtle)` | Hairline under the search field, the Select-all row and every option row |
131
+ | `--rel-select-icon-color` | `var(--rel-text-default)` | Colour of the trigger icons, the search icon and option prefix icons |
132
+ | `--rel-select-label-color` | `var(--rel-text-label)` | Colour of the static label and of the floated label |
133
+ | `--rel-select-menu-border` | `var(--rel-border-default)` | Panel border colour. The panel is borderless by design and only draws this on dark surfaces, where its shadow alone can't separate it from the page. |
134
+ | `--rel-select-menu-radius` | `var(--rel-border-radius-sm)` | Panel corner radius |
135
+ | `--rel-select-menu-shadow` | `var(--rel-shadows-md)` | Panel box-shadow |
136
+ | `--rel-select-option-hover` | `var(--rel-action-overlay-hover)` | Background of the hovered / keyboard-highlighted / selected option and Select-all row |
137
+ | `--rel-select-option-pressed` | `var(--rel-action-overlay-pressed)` | Background of an option row while it is being pressed |
138
+ | `--rel-select-placeholder-color` | `var(--rel-text-placeholder)` | Placeholder colour (trigger, resting floating label, search field, empty-list message) |
139
+ | `--rel-select-placeholder-disabled-color` | `var(--rel-text-caption)` | Placeholder colour when disabled |
140
+ | `--rel-select-radius` | `var(--rel-border-radius-xs)` | Trigger corner radius when `border="rounded"` |
141
+ | `--rel-select-search-border` | `var(--rel-border-default)` | Border colour of the search field inside the panel |
142
+ | `--rel-select-supporting-color` | `var(--rel-text-body)` | Supporting text colour (non-error) |
143
+ | `--rel-select-value-color` | `var(--rel-text-default)` | Colour of the selected value, the search text, option labels and the check mark |
144
+
145
+ <!-- readme-gen:end -->
88
146
 
89
147
  ## Accessibility
90
- - Trigger input uses `role="combobox"` with `aria-haspopup="listbox"`, `aria-expanded`, and `aria-controls`
91
- - Dropdown panel uses `role="listbox"`; each option uses `role="option"` with `aria-selected`
92
- - `aria-activedescendant` tracks the keyboard-highlighted option
93
- - Label properly associated with the trigger via `for`/`id`
94
- - Disabled state prevents interaction and reduces opacity
95
- - Error state communicated through color and supporting text
96
-
97
- ### Keyboard Interactions
98
- - Typing - Filters the dropdown to matching options and shows an inline "ghost text" suggestion for the best prefix match
99
- - `→ (Arrow Right)` - When the cursor is at the end of the input, accepts the current ghost-text suggestion
100
- - `Enter` - Opens the dropdown (if closed); if open, selects the highlighted option, or commits the typed text if it exactly matches an option
101
- - `Arrow Up/Down` - Open dropdown (if closed) or move the highlighted option
102
- - `Home/End` - Jump to first/last filtered option (when open)
103
- - `Escape` - Revert input text to the committed value and close the dropdown
104
- - `Tab` - Accept any ghost suggestion, commit or revert the typed text, close the dropdown, and move focus to the next element
105
-
106
- ### Focus Behavior
107
- - Clear focus ring with primary color via `box-shadow` on the container (`:focus-within`)
108
- - Trigger input is a normal editable text field with a visible caret
148
+
149
+ - The trigger is a native `<button role="combobox">` with `aria-haspopup="listbox"`, `aria-expanded`, `aria-controls` (the listbox id) and `aria-invalid` (true in the error state). Its accessible name is composed as `"{label}, {selected label}"` in single mode and `"{label}, a, b, c, plus N more"` in multi mode (first three labels), so the current selection is always announced with the name. `field-aria-labelledby` replaces that computed name entirely.
150
+ - The static label (`label-style="default"`) is a `<label for>` linked to the trigger. The floating label is a visual `<span>`; the trigger's `aria-label` still carries the name. With `label-style="none"` the name comes from `field-aria-label` and a console warning is logged once if neither `field-aria-label` nor `field-aria-labelledby` is set.
151
+ - The panel is `role="listbox"` with `aria-multiselectable` and an `aria-label` of the field name (or "Options"). Every row is `role="option"` with `aria-selected`; multi-select rows and the Select-all row carry an explicit `aria-label` and contain an `inert`, `aria-hidden` `rel-checkbox` used purely as the visual.
152
+ - The in-panel search input is itself a `role="combobox"` with `aria-expanded`, `aria-controls` and `aria-activedescendant` tracking the highlighted row. With `no-search` the trigger keeps focus while open and carries `aria-activedescendant` instead.
153
+ - Screen-reader announcements via the shared `announce()` helper: `"{label} selected"` / `"{label} deselected"` on a checkbox toggle, `"All options selected"` / `"All options deselected"`, `"{label} removed"` when a chip is removed, and `"N options available"` / `"No matches found"` / `"No options available"` while typing in the search field.
154
+ - Focus: opening the panel moves focus to the search input (with `preventScroll`) unless `no-search`; closing always returns focus to the trigger. Chips render inside the trigger `<button>`, so their remove buttons are not Tab stops — Backspace / Delete is the keyboard path.
155
+
156
+ | Key | Action |
157
+ |-----|--------|
158
+ | `ArrowDown` / `ArrowUp` / `Enter` / `Space` (closed) | Open the panel |
159
+ | `Backspace` / `Delete` (closed, `multiple`) | Remove the most recently selected chip |
160
+ | `ArrowDown` / `ArrowUp` (open) | Move the highlight; in multi mode the Select-all row is a virtual first row above the options |
161
+ | `Home` / `End` (open) | Jump to the first / last filtered option |
162
+ | `Enter` (open) | Select the highlighted option (single), toggle it (multi) or toggle Select-all |
163
+ | `Space` (open, `no-search` only) | Same as Enter; with a search field Space types into it |
164
+ | `Escape` (open) | Close the panel and return focus to the trigger |
165
+ | `Tab` (open) | Close the panel, then focus moves on normally |
166
+ | `Backspace` in an empty search field (`multiple`) | Remove the most recently selected chip |
167
+ | Typing (search field) | Filters options by case-insensitive substring; the first match is highlighted |
168
+ | Printable keys (`no-search`) | APG type-ahead: keys accumulate for 500 ms and jump to the next option whose label starts with the buffer |
109
169
 
110
170
  ## Notes / Edge Cases
111
- - When `state="disabled"`, the select becomes non-interactive with reduced opacity and cursor indication
112
- - Empty `selected` value shows the `placeholder` text ("Select option" by default)
113
- - Icons (left/right) adjust internal padding automatically to accommodate icon space
114
- - The chevron is always visible on the far right and rotates 180° when the dropdown is open; a custom `rightIcon` replaces it entirely (no chevron) and does not rotate
115
- - In error state, supporting text is styled with error color for visual consistency; the error state automatically clears once a valid option is selected
116
- - Options accept plain strings or `{ value, label?, supportingText?, icon? }` objects; string entries use the same text for value and label
117
- - In multi-select, selected chips stay on a single line: the number of visible chips adapts to the field's width and the rest collapse into a trailing "+N" chip (recomputed on selection changes and via `ResizeObserver` on resize). At least one chip is always shown. `max-visible-chips` is an optional additional hard cap (uncapped by default)
118
- - An option's `icon` renders only when set — options without one simply omit the prefix icon (no reserved empty space), and an unknown icon name logs a `rel-icon` console warning and renders nothing
119
- - Typed text that doesn't exactly match (case-insensitive) any option reverts to the last committed `selected` value on blur, Escape, or Tab
120
- - The ghost-text suggestion shows the remainder of the first option whose name starts with the typed text (case-insensitive); it has no effect on filtering, which matches substrings anywhere in an option
121
- - Dropdown panel is positioned via `position: fixed` and flips above the trigger if there isn't enough viewport space below
122
- - The open listbox is promoted to the browser **top layer** (native Popover API, `popover="manual"`), so it renders correctly inside transformed / `overflow: hidden` containers — a centered `rel-modal`, a bottom `rel-drawer`. Engines without the Popover API fall back to `position: fixed` with a measure-and-cancel correction for transformed ancestors
171
+
172
+ - The change event is named `changed` (not `rel-change`); `detail.value` is a string in single mode and an array of strings when `multiple`.
173
+ - Opening the panel does not pre-highlight any row; the highlight appears on the first hover or arrow key so nothing reads as an unintended default.
174
+ - `state="error"` clears itself to `"default"` on the next selection, toggle, Select-all or chip removal. `state="disabled"` dims the whole field to 50% opacity, makes chips non-removable and blocks pointer events on them.
175
+ - Turning `multiple` off resets `selectedValues` to `[]`. `selected` is ignored in multi mode and `selectedValues` in single mode.
176
+ - Chips never wrap: the number shown adapts to the trigger width (measured through a hidden copy of every chip and a `ResizeObserver`), with the remainder collapsed into a trailing "+N" chip. At least one chip always stays visible; `max-visible-chips` is an extra hard cap. A selected value with no matching option is shown as its raw value.
177
+ - Option `icon` renders in both single and multi rows; `supportingText` only in multi rows. An unknown icon name logs a `rel-icon` warning and renders nothing (no reserved space).
178
+ - A custom `right-icon` replaces the chevron and does not rotate when the panel opens; the default chevron rotates 180°.
179
+ - The search field uses the small field sizing for both `small` and `medium` selects; only `large` bumps it to medium. Empty results show "No matches found" (or "No options available" when `options` is empty).
180
+ - The `helper` part exists only while `supporting-text` is non-empty.
181
+ - The open listbox is promoted to the browser top layer (native Popover API, `popover="manual"`) so it renders correctly inside transformed or `overflow: hidden` containers such as a centered `rel-modal` or a `rel-drawer`; engines without the Popover API fall back to `position: fixed` with a measure-and-cancel correction. The panel matches the trigger width, flips above the trigger when there is not enough room below, is capped at 360px with internal scrolling, and closes on any outside pointerdown or outside scroll (scrolling the list itself does not close it).
182
+ - `--rel-field-label-reserve` (see Component hooks) keeps a `label-style="none"` select bottom-aligned with labelled siblings; set it to `0` in toolbars or table cells.
183
+ - The trigger heights (32 / 40 / 48px) match `rel-textfield` and the date / time / range picker triggers so mixed form rows line up.