@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,141 +1,145 @@
1
- # rel-alert
2
-
3
- ## Overview
4
- A versatile alert component for displaying informational, success, warning, error, or neutral messages. Features built-in icons, optional dismissibility, secondary message text, and inline links. Automatically hides when dismissed via the `dismissed` reflected attribute.
5
-
6
- ## Usage
7
- ```html
8
- <!-- Basic neutral alert -->
9
- <rel-alert
10
- message1="This is a neutral alert"
11
- type="neutral">
12
- </rel-alert>
13
-
14
- <!-- Info alert with secondary message -->
15
- <rel-alert
16
- type="info"
17
- message1="System Notification"
18
- message2="Your settings have been updated successfully.">
19
- </rel-alert>
20
-
21
- <!-- Success alert -->
22
- <rel-alert
23
- type="success"
24
- message1="Operation Completed"
25
- message2="Your data has been saved.">
26
- </rel-alert>
27
-
28
- <!-- Warning alert -->
29
- <rel-alert
30
- type="warning"
31
- message1="Warning"
32
- message2="Please verify your input before continuing.">
33
- </rel-alert>
34
-
35
- <!-- Error alert -->
36
- <rel-alert
37
- type="error"
38
- message1="Error Occurred"
39
- message2="Unable to process your request.">
40
- </rel-alert>
41
-
42
- <!-- With action link -->
43
- <rel-alert
44
- type="info"
45
- message1="Update Available"
46
- message2="A new version is ready."
47
- urlText="Learn More"
48
- urlHref="https://example.com/release-notes">
49
- </rel-alert>
50
-
51
- <!-- Non-dismissible -->
52
- <rel-alert
53
- type="warning"
54
- message1="Required Action"
55
- dismissible="false">
56
- </rel-alert>
57
-
58
- <!-- Listen for dismiss -->
59
- <rel-alert id="myAlert" type="success" message1="Success!"></rel-alert>
60
- <script>
61
- const alert = document.getElementById('myAlert');
62
- alert.addEventListener('dismiss', () => {
63
- console.log('Alert was dismissed');
64
- });
65
- </script>
66
- ```
67
-
68
- ## API
69
-
70
- ### Attributes/Properties
71
- | Name | Type | Default | Description |
72
- |------|------|---------|-------------|
73
- | `type` | `"info" \| "success" \| "warning" \| "error" \| "neutral"` | `"neutral"` | Alert type determining icon and color scheme |
74
- | `message1` | `string` | `""` | Primary message text (bold) |
75
- | `message2` | `string` | - | Optional secondary message text (smaller, slightly transparent) |
76
- | `urlText` | `string` | - | Link text (shown below messages) |
77
- | `urlHref` | `string` | - | Link URL (both `urlText` and `urlHref` required for link to show) |
78
- | `dismissible` | `boolean` | `true` | Whether to show the close (✕) button |
79
- | `dismissed` | `boolean` (reflected) | `false` | When true, hides the component via `:host([dismissed])` |
80
-
81
- ## Events
82
- | Event | Detail | Description |
83
- |-------|--------|-------------|
84
- | `dismiss` | None | Fired when the close button is clicked (sets `dismissed` to true) |
85
-
86
- ## Slots
87
- Default slot not used.
88
-
89
- ## CSS Parts
90
- None exposed.
91
-
92
- ## Tokens / CSS Variables
93
-
94
- ### Semantic Tokens
95
- - `--rel-fonts-font-family` - Font family
96
- - `--rel-body-md-regular-font-size` - Primary message font size
97
- - `--rel-body-sm-regular-font-size` - Secondary message and link font size
98
- - `--rel-fonts-weight-body-medium` - Primary message and link font weight
99
- - `--rel-fonts-weight-body-semibold` - Used implicitly in link styling
100
-
101
- ### Spacing Tokens
102
- - `--rel-spacing-xs` - Gap between icon and content
103
- - `--rel-spacing-sm` - Vertical padding
104
- - `--rel-spacing-md` - Horizontal padding
105
- - `--rel-spacing-2xs` - Close button padding
106
-
107
- ### Color Tokens (by type)
108
- - **info**: `--rel-bg-info-light` (background), `--rel-text-info` (text), `--rel-text-info` (icon)
109
- - **success**: `--rel-bg-success-light`, `--rel-text-success`, `--rel-text-success`
110
- - **warning**: `--rel-bg-warning-light`, `--rel-text-warning`, `--rel-text-warning`
111
- - **error**: `--rel-bg-danger-light`, `--rel-text-error`, `--rel-text-danger`
112
- - **neutral**: `--rel-bg-surface` (background), `--rel-text-default` (text), `--rel-text-default` (icon), `--rel-border-default` (border)
113
-
114
- ### Border Tokens
115
- - `--rel-border-radius-sm` - Border radius
116
-
117
- ## Accessibility
118
- - Uses `role="alert"` for screen reader announcements
119
- - Close button has `aria-label="Dismiss"`
120
- - Focus visible states on close button with 2px outline
121
- - Secondary message has reduced opacity for visual hierarchy
122
-
123
- ### Keyboard Interactions
124
- - `Tab` - Focus the close button (if dismissible)
125
- - `Space/Enter` - Dismiss the alert (when close button focused)
126
-
127
- ### Focus Behavior
128
- - Close button shows 2px outline matching the alert's text color with 2px offset
129
- - Border radius applied to maintain visual consistency
130
-
131
- ## Notes / Edge Cases
132
- - Icons are built-in SVG graphics that change based on `type` (info: ℹ️, success: ✓, warning: ⚠️, error: ❗, neutral: ℹ️)
133
- - Icon colors are controlled by type-specific `--rel-icon-*` tokens
134
- - The alert has a minimum width of `360px`
135
- - Both `urlText` and `urlHref` must be set for the link to appear
136
- - Links inherit the alert's text color and are underlined
137
- - `message2` has `opacity: 0.9` for subtle contrast with `message1`
138
- - When `dismissed` is set to `true`, the component applies `display: none` via `:host([dismissed])`
139
- - `dismissed` is a reflected attribute, meaning it appears in the HTML when true
140
- - The close button is always positioned at the right edge via `margin-left: auto`
141
- - Neutral type includes a 1px border while colored types do not
1
+ # rel-alert
2
+
3
+ `<rel-alert>` is the inline status banner of the Reliability Design System (Figma "Alert"). It renders a tone-coloured box with a leading status icon, a bold title (`message1`), optional supporting text (`message2`), an optional inline link and an optional dismiss button, in the Figma Tone (neutral / info / success / warning / destructive) and Style (subtle / solid / outline) variants. Use it for persistent, in-flow messages about a page or section — form-level validation, degraded-service notices, onboarding hints. For transient feedback that disappears on its own use `<rel-toast>` or `<rel-snackbar>`; for blocking decisions use `<rel-modal>`.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Neutral (default tone, subtle appearance) -->
9
+ <rel-alert message1="Scheduled maintenance on Sunday 02:00–04:00 UTC"></rel-alert>
10
+
11
+ <!-- Tones -->
12
+ <rel-alert tone="info" message1="Update available" message2="Version 2.3 adds offline mode."></rel-alert>
13
+ <rel-alert tone="success" message1="Changes saved" message2="Your profile is up to date."></rel-alert>
14
+ <rel-alert tone="warning" message1="Storage almost full" message2="You have used 95% of your quota."></rel-alert>
15
+ <rel-alert tone="destructive" message1="Upload failed" message2="The file exceeds the 25 MB limit."></rel-alert>
16
+
17
+ <!-- Appearance: subtle (default) | solid | outline -->
18
+ <rel-alert tone="info" appearance="solid" message1="Solid alert"></rel-alert>
19
+ <rel-alert tone="info" appearance="outline" message1="Outline alert"></rel-alert>
20
+
21
+ <!-- Inline link: both url-text and url-href are required for it to render -->
22
+ <rel-alert
23
+ tone="info"
24
+ message1="Release notes"
25
+ message2="See what changed in this version."
26
+ url-text="Read more"
27
+ url-href="https://example.com/release-notes"
28
+ ></rel-alert>
29
+
30
+ <!-- Non-dismissible: the boolean must be cleared from script (see the js block) -->
31
+ <rel-alert id="locked" tone="warning" message1="Action required"></rel-alert>
32
+
33
+ <!-- Listen for dismissal -->
34
+ <rel-alert id="saved" tone="success" message1="Saved"></rel-alert>
35
+ ```
36
+
37
+ ```js
38
+ // A Lit boolean attribute is true whenever present, so dismissible="false" does NOT work.
39
+ document.getElementById("locked").dismissible = false;
40
+
41
+ const saved = document.getElementById("saved");
42
+ saved.addEventListener("dismiss", () => {
43
+ saved.dismissed; // true — the host is now display: none
44
+ });
45
+ // Show it again later:
46
+ saved.dismissed = false;
47
+ ```
48
+
49
+ ### Deprecated aliases
50
+
51
+ ```html
52
+ <!-- type= is the deprecated alias of tone= (tone wins when both are set). Logs once per page:
53
+ [rel-alert] "type" is deprecated and will be removed in 3.0 — use "tone" instead. Note: tone="destructive" replaces type="error". -->
54
+ <rel-alert type="error" message1="Upload failed"></rel-alert>
55
+
56
+ <!-- tone="error" | "danger" | "critical" are deprecated spellings of tone="destructive". Logs once per spelling:
57
+ [rel-alert] "tone="error"" is deprecated and will be removed in 3.0 — use "tone="destructive"" instead. -->
58
+ <rel-alert tone="error" message1="Upload failed"></rel-alert>
59
+ <rel-alert tone="critical" message1="Upload failed"></rel-alert>
60
+
61
+ <!-- appearance="filled" is the deprecated alias of appearance="solid" (no console notice). -->
62
+ <rel-alert tone="info" appearance="filled" message1="Solid alert"></rel-alert>
63
+ ```
64
+
65
+ <!-- readme-gen:start -->
66
+
67
+ <!-- Generated from rel-alert.ts — do not edit; run readme-generate.mjs -->
68
+
69
+ ## API
70
+
71
+ ### Attributes / Properties
72
+
73
+ | Property | Attribute | Type | Default | Description |
74
+ | --- | --- | --- | --- | --- |
75
+ | `tone` | `tone` | `"neutral" \| "info" \| "success" \| "warning" \| "destructive" \| "error" \| "danger" \| "critical"` | `undefined` | Semantic tone (Figma "Tone"): `"neutral"` (default) \| `"info"` \| `"success"` \| `"warning"` \| `"destructive"`. Drives the fill/border colour, the title colour and the leading icon (info, check-circle, alert-circle, error). `"error"`, `"danger"` and `"critical"` are deprecated aliases of `"destructive"` and log a one-time console notice. Takes precedence over the deprecated `type` prop. |
76
+ | `appearance` | `appearance` | `"solid" \| "subtle" \| "outline" \| "filled"` | `"subtle"` | Visual treatment (Figma "Style"): `"subtle"` (default: tone-light fill, no border) \| `"solid"` (tone fill, inverse text, `--rel-shadows-md` elevation) \| `"outline"` (transparent fill, tone border). `"filled"` is a deprecated alias of `"solid"` (no console notice). Reflected. |
77
+ | `message1` | `message1` | `string` | `""` | Primary message (title), rendered in body-lg medium weight in the tone colour. |
78
+ | `message2` | `message2` | `string` | `undefined` | Optional secondary message rendered under the title in body-md at 90% opacity; omitted when unset. |
79
+ | `urlText` | `url-text` | `string` | `undefined` | Text of the inline link rendered under the messages. The link appears only when both `urlText` and `urlHref` are set. |
80
+ | `urlHref` | `url-href` | `string` | `undefined` | `href` of the inline link. The link appears only when both `urlText` and `urlHref` are set. |
81
+ | `dismissible` | `dismissible` | `boolean` | `true` | Shows the dismiss (✕) button. Defaults to true; because it is a Lit boolean, `dismissible="false"` is still true — set the property to `false` from script to hide the button. |
82
+ | `dismissed` | `dismissed` | `boolean` | `false` | True once the alert has been dismissed; hides the host via `:host([dismissed]) { display: none }`. Set it back to `false` to show the alert again. Reflected. |
83
+
84
+ #### Deprecated (still supported — removal targeted for 3.0)
85
+
86
+ | Property | Attribute | Type | Use instead |
87
+ | --- | --- | --- | --- |
88
+ | `type` | `type` | `"neutral" \| "info" \| "success" \| "warning" \| "destructive" \| "error" \| "danger" \| "critical"` | Deprecated since 1.4.7 — alias of `tone`; use `tone`. Same values as `tone`; `type="error"` maps to `tone="destructive"`. Ignored when `tone` is set. Logs a one-time console notice. |
89
+
90
+ ### Public fields / accessors
91
+
92
+ | Name | Type | Description |
93
+ | --- | --- | --- |
94
+ | `resolvedTone` | `AlertTone` | Read-only canonical tone actually rendered: explicit `tone` wins, else `type`, else `"neutral"`; deprecated aliases are resolved to `"destructive"`. |
95
+
96
+ ## Events
97
+
98
+ | Event | Detail | Bubbles / composed | Description |
99
+ | --- | --- | --- | --- |
100
+ | `dismiss` | — | bubbles / composed | Fired when the user clicks the dismiss button, after `dismissed` has been set to true. No detail. |
101
+
102
+ ## Slots
103
+
104
+ | Slot | Description |
105
+ | --- | --- |
106
+ | — | This element has no slots. |
107
+
108
+ ## CSS Parts
109
+
110
+ | Part | Description |
111
+ | --- | --- |
112
+ | `base` | The `role="alert"` container that carries the tone and appearance styling |
113
+ | `icon` | Wrapper around the leading status `<rel-icon>` |
114
+ | `content` | Column that stacks the title, helper text and link |
115
+ | `label` | The primary message (`message1`) paragraph |
116
+ | `helper` | The secondary message (`message2`) paragraph; rendered only when `message2` is set |
117
+ | `action` | The inline link; rendered only when both `url-text` and `url-href` are set |
118
+ | `close-button` | The dismiss (✕) button; rendered only while `dismissible` is true |
119
+
120
+ <!-- readme-gen:end -->
121
+
122
+ ## Accessibility
123
+
124
+ - The container (part `base`) has `role="alert"` and `aria-atomic="true"`, so screen readers announce the whole message assertively when the element enters the DOM or its text changes. Because of that, reserve it for messages that warrant an interruption; render a `<rel-alert>` only when there is something to say rather than keeping an empty one mounted.
125
+ - The leading status `<rel-icon>` renders `aria-hidden="true"`; the tone is not conveyed to assistive technology except through the text, so put the meaning in `message1` / `message2`.
126
+ - The dismiss control is a native `<button>` with `aria-label="Dismiss"`. The inline link is a plain `<a href>`. Both are in the Tab order; the component adds no key handlers of its own:
127
+
128
+ | Key | Action |
129
+ | --- | --- |
130
+ | Tab / Shift + Tab | Move between the inline link (if any) and the dismiss button (if any) |
131
+ | Enter / Space | Activate the focused dismiss button (fires `dismiss`, sets `dismissed`) |
132
+ | Enter | Follow the focused link |
133
+
134
+ - Keyboard focus on the dismiss button is a 2px `currentColor` outline with 2px offset (`:focus-visible` only).
135
+ - Dismissing hides the host with `display: none`; focus is not moved, so if the dismiss button had focus the browser drops focus to `<body>`. Move focus yourself in the `dismiss` handler when the alert sits in the middle of a form.
136
+
137
+ ## Notes / Edge Cases
138
+
139
+ - `tone` and `appearance` are independent axes; every tone renders in every appearance. Solid uses inverse text and carries the `--rel-shadows-md` elevation; subtle and outline have no shadow.
140
+ - The status icon is fixed per tone (`info` for neutral and info, `check-circle`, `alert-circle`, `error`) and cannot be replaced or removed — there are no slots.
141
+ - The alert has `min-width: 360px`; it stretches to its container (`display: block`) but never shrinks below that.
142
+ - The link renders only when both `url-text` and `url-href` are set; it opens in the same tab (no `target`).
143
+ - `dismissible` and `dismissed` are Lit booleans: any attribute value (including `"false"`) counts as true. Toggle them as properties from script.
144
+ - `dismissed` only hides the host; the element stays in the DOM and keeps its state. Resetting `dismissed = false` shows it again without re-firing `dismiss`.
145
+ - `resolvedTone` is the tone actually rendered after alias resolution; use it (not `tone` / `type`) if you branch on tone in script.
@@ -1,97 +1,192 @@
1
1
  # rel-autocomplete
2
2
 
3
- ## Overview
4
-
5
- A searchable single-select type-ahead field ("autocomplete") for searchable-dropdown and searchbar scenarios. Composes `rel-textfield` for all field chrome (label, sizes, variants, states, icons) and adds a suggestion panel with keyboard navigation, loading / no-results states, and clear/reset.
6
-
7
- Two data modes:
8
-
9
- - **Local** — provide `items`; typing filters them client-side (`filter` mode).
10
- - **Remote** — provide a `searchFn`; input is debounced (`debounce-ms`), queries are latest-wins (stale responses are discarded), and local filtering is bypassed (results arrive pre-filtered).
3
+ `<rel-autocomplete>` is a searchable single-select type-ahead field. It composes `rel-textfield` for all field chrome (label, sizes, variants, states, prefix icon, helper / error text) and adds a suggestion panel with keyboard navigation, loading and no-results rows, and an optional clear affordance. Two data modes: **local** — set `items` and typing filters them client-side (`filter`); **remote** — set `searchFn` and input is debounced (`debounce-ms`), queries are latest-wins and local filtering is bypassed. Use it for searchable dropdowns and search bars over lists too long for `rel-select`; for a short fixed list use `rel-select`, and for plain free text use `rel-textfield`.
11
4
 
12
5
  ## Usage
13
6
 
14
7
  ```html
15
8
  <!-- Local items (strings) -->
16
- <rel-autocomplete id="carrier" label="Carrier" prefix-icon="search" clearable></rel-autocomplete>
9
+ <rel-autocomplete id="carrier" label="Carrier" prefix-icon="search" placeholder="Start typing" clearable></rel-autocomplete>
17
10
  <script>
18
11
  const ac = document.getElementById("carrier");
19
12
  ac.items = ["FedEx Freight", "UPS Freight", "XPO Logistics", "Estes Express"];
20
13
  ac.addEventListener("changed", (e) => console.log(e.detail.value, e.detail.item));
14
+ ac.addEventListener("rel-change", (e) => console.log("typed:", e.detail));
21
15
  </script>
22
16
 
23
- <!-- Object items with icons -->
17
+ <!-- Object items with icons, read through display-field / value-field -->
18
+ <rel-autocomplete id="mode" label="Mode" display-field="name" value-field="id"></rel-autocomplete>
24
19
  <script>
25
- ac.items = [
26
- { value: "air", label: "Air", icon: "air" },
27
- { value: "sea", label: "Sea", icon: "ship" },
20
+ document.getElementById("mode").items = [
21
+ { id: "air", name: "Air", icon: "air" },
22
+ { id: "sea", name: "Sea", icon: "ship" },
23
+ // dulled, skipped by arrow keys, ignores clicks
24
+ { id: "rail", name: "Rail", icon: "intermodal", disabled: true },
28
25
  ];
29
26
  </script>
30
27
 
31
- <!-- Custom fields for arbitrary API shapes -->
32
- <rel-autocomplete display-field="name" value-field="id"></rel-autocomplete>
28
+ <!-- Filtering and limits -->
29
+ <rel-autocomplete label="City" filter="starts-with" max-suggestions="8" min-search-length="2"></rel-autocomplete>
33
30
 
34
- <!-- Remote data -->
31
+ <!-- Remote data: debounced, latest-wins -->
32
+ <rel-autocomplete id="remote" label="Customer" debounce-ms="250" loading-text="Searching…" no-results-text="No customers match"></rel-autocomplete>
35
33
  <script>
36
- ac.searchFn = async (query) => {
37
- const res = await fetch(`/api/carriers?q=${encodeURIComponent(query)}`);
34
+ const remote = document.getElementById("remote");
35
+ remote.searchFn = async (query) => {
36
+ const res = await fetch(`/api/customers?q=${encodeURIComponent(query)}`);
38
37
  return res.json(); // (string | object)[]
39
38
  };
39
+ remote.addEventListener("rel-search-error", (e) => console.warn(e.detail.query, e.detail.error));
40
40
  </script>
41
+
42
+ <!-- Field chrome passthroughs -->
43
+ <rel-autocomplete label="Small underline" size="small" variant="underline"></rel-autocomplete>
44
+ <rel-autocomplete label="Floating label" label-style="floating" helper-text="Pick a carrier"></rel-autocomplete>
45
+ <rel-autocomplete label-style="none" placeholder="Search orders" field-aria-label="Search orders"></rel-autocomplete>
46
+ <rel-autocomplete label="Required" required error error-message="Choose a carrier from the list"></rel-autocomplete>
47
+ <rel-autocomplete label="Read only" value="UPS Freight" readonly></rel-autocomplete>
48
+ <rel-autocomplete label="Disabled" disabled></rel-autocomplete>
49
+ <rel-autocomplete label="Inline width" full-width name="carrier"></rel-autocomplete>
50
+ ```
51
+
52
+ ### Deprecated aliases
53
+
54
+ ```html
55
+ <!-- floating-label → label-style="floating" (kept permanently as an alias; no console notice) -->
56
+ <rel-autocomplete label="Old spelling" floating-label></rel-autocomplete>
57
+ <rel-autocomplete label="Canonical" label-style="floating"></rel-autocomplete>
41
58
  ```
42
59
 
60
+ <!-- readme-gen:start -->
61
+
62
+ <!-- Generated from rel-autocomplete.ts — do not edit; run readme-generate.mjs -->
63
+
43
64
  ## API
44
65
 
45
- ### Attributes/Properties
46
-
47
- | Name | Type | Default | Description |
48
- |------|------|---------|-------------|
49
- | `items` | `(string \| object)[]` | `[]` | Local suggestion list. Objects are read through `display-field` / `value-field`; an `icon` field renders a leading `rel-icon` on the row |
50
- | `value` | `string` | `""` | Committed value — the selected item's `value-field` string. Typing alone does not change it; selection (or an exact label/value match on Enter/blur) does. Settable externally: the field shows the matching item's label, or the raw string when unknown |
51
- | `display-field` | `string` | `"label"` | Object key used as the row label |
52
- | `value-field` | `string` | `"value"` | Object key used as the committed value |
53
- | `filter` | `"contains" \| "starts-with" \| "none"` | `"contains"` | Local filtering mode. `"none"` shows `items` as-is (use when the app pre-filters). Ignored when `searchFn` is set |
54
- | `searchFn` | `(query: string) => Promise<items>` | — | Property-only. Async data source; enables debounce + loading + latest-wins handling |
55
- | `debounce-ms` | `number` | `300` | Debounce before `searchFn` fires |
56
- | `min-search-length` | `number` | `1` | Minimum typed characters before the panel opens / `searchFn` fires. `0` opens on focus showing all items |
57
- | `max-suggestions` | `number` | `Infinity` | Optional cap on rendered rows (the panel scrolls regardless) |
58
- | `clearable` | `boolean` | `false` | Trailing ✕ clears text + value, emits `rel-clear` and `changed` |
59
- | `loading` | `boolean` | `false` | Externally-controlled loading row (internal `searchFn` loading is automatic) |
60
- | `no-results-text` | `string` | `"No results found"` | Row shown when a query yields nothing |
61
- | `loading-text` | `string` | `"Loading…"` | Text next to the loading spinner |
62
- | `label`, `placeholder`, `size`, `variant`, `label-style`, `floating-label`, `field-aria-label`, `field-aria-labelledby`, `prefix-icon`, `disabled`, `readonly`, `required`, `error`, `error-message`, `helper-text`, `name`, `full-width` | — | — | Passed through to the inner `rel-textfield` unchanged |
63
- | `label-style` | `"default" \| "floating" \| "none"` | — | Label presentation. `"none"` renders no label — pair it with `field-aria-label`. Unset, the deprecated `floating-label` boolean decides |
66
+ ### Attributes / Properties
67
+
68
+ | Property | Attribute | Type | Default | Description |
69
+ | --- | --- | --- | --- | --- |
70
+ | `items` | `items` | `(string \| Record<string, unknown>)[]` | `[]` | Local (or fallback initial) suggestion list. Ignored while searchFn drives results. Object items read two keys directly whatever `display-field` / `value-field` are set to: `icon` (a `rel-icon` name shown before the label) and `disabled` (`true` dulls the row and makes it unselectable by click or keyboard). |
71
+ | `value` | `value` | `string` | `""` | Committed value — the selected item's valueField string ("" = none). |
72
+ | `displayField` | `display-field` | `string` | `"label"` | Object key read for the row label when items are objects. |
73
+ | `valueField` | `value-field` | `string` | `"value"` | Object key read for the committed value when items are objects. |
74
+ | `filter` | `filter` | `"contains" \| "starts-with" \| "none"` | `"contains"` | Local filtering mode. Ignored when searchFn is set (results arrive pre-filtered). |
75
+ | `searchFn` | — | `(query: string) => Promise<AutocompleteItem[]>` | `undefined` | Async data source. When set, local filtering is bypassed entirely. Property only. |
76
+ | `debounceMs` | `debounce-ms` | `number` | `300` | Debounce for searchFn calls, in ms. |
77
+ | `minSearchLength` | `min-search-length` | `number` | `1` | Minimum typed characters before the panel opens / searchFn fires. 0 = open on focus. |
78
+ | `maxSuggestions` | `max-suggestions` | `number` | `Infinity` | Optional cap on rendered suggestions (panel scrolls regardless). |
79
+ | `clearable` | `clearable` | `boolean` | `false` | Shows a trailing ✕ that clears the text and the committed value. |
80
+ | `loading` | `loading` | `boolean` | `false` | Externally-controlled loading state (internal searchFn loading is automatic). |
81
+ | `noResultsText` | `no-results-text` | `string` | `"No results found"` | Row shown when a query yields nothing. |
82
+ | `loadingText` | `loading-text` | `string` | `"Loading…"` | Text shown next to the spinner while suggestions load. |
83
+ | `label` | `label` | `string` | `undefined` | Visible label, forwarded to the inner `rel-textfield`. Also names the suggestion panel. |
84
+ | `placeholder` | `placeholder` | `string` | `""` | Placeholder of the input, forwarded to the inner `rel-textfield`. |
85
+ | `size` | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Field height — `small` 32px, `medium` 40px, `large` 48px — forwarded to the inner `rel-textfield`. |
86
+ | `variant` | `variant` | `"default" \| "underline" \| "legend"` | `"default"` | Field chrome (`default` outlined, `underline`, `legend` notched outline), forwarded to the inner `rel-textfield`. |
87
+ | `labelStyle` | `label-style` | `"default" \| "floating" \| "none"` | `undefined` | Label presentation (`default` / `floating` / `none`), forwarded to the inner field. Left `undefined`, the deprecated `floatingLabel` decides. Reflected. |
88
+ | `fieldAriaLabel` | `field-aria-label` | `string` | `undefined` | Accessible name for the input. Required when `labelStyle="none"`. |
89
+ | `fieldAriaLabelledby` | `field-aria-labelledby` | `string` | `undefined` | IDREF list of external element(s) naming the input. Wins over `fieldAriaLabel`. |
90
+ | `prefixIcon` | `prefix-icon` | `string` | `undefined` | Leading `rel-icon` name in the field's prefix block, e.g. `search`. |
91
+ | `disabled` | `disabled` | `boolean` | `false` | Disables the field; the panel never opens and the clear affordance is hidden. |
92
+ | `readonly` | `readonly` | `boolean` | `false` | Read-only field: focusable but not editable; the panel never opens and the clear affordance is hidden. |
93
+ | `required` | `required` | `boolean` | `false` | Marks the input required (native `required` / `aria-required`, asterisk on the label). |
94
+ | `error` | `error` | `boolean` | `false` | Puts the field in the error state (danger border, `aria-invalid`); pair with `errorMessage`. |
95
+ | `errorMessage` | `error-message` | `string` | `undefined` | Text shown below the field instead of `helperText` while `error` is set. |
96
+ | `helperText` | `helper-text` | `string` | `undefined` | Helper line below the field, linked to the input via `aria-describedby`. |
97
+ | `name` | `name` | `string` | `undefined` | Form field name forwarded to the native input. |
98
+ | `fullWidth` | `full-width` | `boolean` | `true` | Fills the parent width as a block element (default). Unset it to render inline at the content's natural width. |
99
+
100
+ #### Deprecated (still supported — removal targeted for 3.0)
101
+
102
+ | Property | Attribute | Type | Use instead |
103
+ | --- | --- | --- | --- |
104
+ | `floatingLabel` | `floating-label` | `boolean` | Use `labelStyle="floating"`. Kept permanently as an alias. |
105
+
106
+ ### Methods
107
+
108
+ | Method | Signature | Description |
109
+ | --- | --- | --- |
110
+ | `focus` | `focus()` | Delegates focus to the inner textfield. |
64
111
 
65
112
  ## Events
66
113
 
67
- | Event | Detail | Description |
68
- |-------|--------|-------------|
69
- | `changed` | `{ value: string, item: object \| string \| null }` | An item was selected (or cleared — `value: ""`, `item: null`). This is the form-value event (Angular CVA binds it) |
70
- | `rel-change` | `string` | Fired on every keystroke with the raw text — use for the controlled/remote pattern (fetch, then set `.items`) |
71
- | `rel-clear` | — | The clear (✕) affordance was used |
72
- | `rel-search-error` | `{ query, error }` | `searchFn` rejected — the panel shows the no-results state |
114
+ | Event | Detail | Bubbles / composed | Description |
115
+ | --- | --- | --- | --- |
116
+ | `changed` | `{ value: this.value, item: item ? item.item : null }` | bubbles / composed | Fired when the committed value changes — an item was selected (click, Enter, or an exact text match on Enter / Tab / blur) or the field was cleared. Detail: `{ value, item }`, where `item` is the original string or object, or `null` after a clear. |
117
+ | `rel-change` | `inputText / ""` | bubbles / composed | Fired on every keystroke with the raw input text as the detail (and with `""` after a clear). The committed `value` does not change until an item is selected. |
118
+ | `rel-clear` | — | bubbles / composed | Fired when the clear icon empties a non-empty field (followed by `changed` and `rel-change`). No detail. |
119
+ | `rel-search-error` | `{ query, error: err }` | bubbles / composed | Fired when `searchFn` rejects; the panel then shows the no-results row. Detail: `{ query, error }`. |
120
+
121
+ ## Slots
122
+
123
+ | Slot | Description |
124
+ | --- | --- |
125
+ | — | This element has no slots. |
126
+
127
+ ## CSS Parts
128
+
129
+ | Part | Description |
130
+ | --- | --- |
131
+ | `panel` | The suggestion listbox container (same node as `list`) |
132
+ | `list` | Alias of `panel` |
133
+ | `option` | A suggestion row |
134
+ | `label` | The inner field's label (re-exported from `rel-textfield`) |
135
+ | `control` | The inner field's bordered control box (re-exported from `rel-textfield`) |
136
+ | `input` | The inner native input (re-exported from `rel-textfield`) |
137
+ | `helper` | The inner field's helper / error line (re-exported from `rel-textfield`) |
138
+ | `right-icon` | The clear icon shown when `clearable` (re-exported from `rel-textfield`) |
139
+
140
+ ## Tokens / CSS Variables
141
+
142
+ ### Component hooks
143
+
144
+ Set these on the host (or an ancestor) to customise the element without touching design tokens.
145
+
146
+ | Custom property | Default | Description |
147
+ | --- | --- | --- |
148
+ | `--rel-autocomplete-bg` | `var(--rel-bg-neutral)` | Panel and row background |
149
+ | `--rel-autocomplete-divider` | `var(--rel-border-subtle)` | Hairline between rows |
150
+ | `--rel-autocomplete-icon-color` | `var(--rel-text-default)` | Colour of a row's leading `icon` |
151
+ | `--rel-autocomplete-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. |
152
+ | `--rel-autocomplete-menu-radius` | `var(--rel-border-radius-xs)` | Panel corner radius |
153
+ | `--rel-autocomplete-menu-shadow` | `var(--rel-shadows-md)` | Panel box-shadow |
154
+ | `--rel-autocomplete-option-hover` | `var(--rel-action-overlay-hover)` | Background of the hovered / keyboard-highlighted / selected row |
155
+ | `--rel-autocomplete-option-pressed` | `var(--rel-action-overlay-pressed)` | Background of a row while it is being pressed |
156
+ | `--rel-autocomplete-status-color` | `var(--rel-text-body)` | Colour of the loading / no-results status rows |
157
+ | `--rel-autocomplete-value-color` | `var(--rel-text-default)` | Suggestion label colour |
158
+
159
+ <!-- readme-gen:end -->
73
160
 
74
- ## Keyboard Interactions
161
+ ## Accessibility
75
162
 
76
- - Typing — filters (local) or queries (remote) and opens the panel
77
- - `Arrow Down` / `Arrow Up` — open the panel / move the highlight
78
- - `Enter` — selects the highlighted row; with no highlight, commits an exact label/value match, otherwise keeps the free text and closes
79
- - `Escape` — closes the panel without touching the text
80
- - `Tab` — commits an exact match, closes, and moves on
163
+ - Combobox pattern: a wrapper around the inner field carries `role="combobox"`, `aria-haspopup="listbox"`, `aria-expanded`, `aria-controls` and `aria-activedescendant` (the highlighted row). The role sits on the wrapper rather than the `<input>` because the input lives in `rel-textfield`'s nested shadow root, which `aria-activedescendant` cannot reference across — the pragmatic pattern for composed shadow components.
164
+ - The panel is `role="listbox"` named by the visible `label` (or `field-aria-label` under `label-style="none"`, falling back to "Suggestions"); rows are `role="option"` with `aria-selected` on the committed value. The loading row is `role="status"`.
165
+ - Field-level semantics come from `rel-textfield`: `<label for>`, `aria-required`, `aria-invalid`, `aria-describedby` on the helper / error line. With `label-style="none"` the inner field logs a console warning once if neither `field-aria-label` nor `field-aria-labelledby` is set.
166
+ - The clear affordance (`clearable`) is the inner field's clickable trailing icon: `role="button"`, focusable, labelled "Clear".
167
+ - Screen-reader announcements via the shared `announce()` helper: `"Loading suggestions"` when the loading row appears, `"{label}, i of n"` while arrowing through rows, `"N results available"` when results change, and the `no-results-text` when a query yields nothing.
168
+ - Disabled and read-only fields never open the panel and hide the clear icon.
81
169
 
82
- ## Accessibility
170
+ | Key | Action |
171
+ |-----|--------|
172
+ | Typing | Filters local items or queries `searchFn`, and opens the panel once the query reaches `min-search-length` |
173
+ | `ArrowDown` | Open the panel (if the query is long enough) or move the highlight down |
174
+ | `ArrowUp` | Move the highlight up |
175
+ | `Enter` | Select the highlighted row; with no highlight, commit an exact label / value match, otherwise keep the free text and close |
176
+ | `Escape` | Close the panel without touching the text |
177
+ | `Tab` | Commit an exact match (if any), close, and move focus on |
83
178
 
84
- - Combobox pattern: `role="combobox"` with `aria-expanded`, `aria-controls`, and `aria-activedescendant`; panel is `role="listbox"` with `role="option"` rows
85
- - Known limitation: the combobox role sits on a wrapper around the field rather than on the `<input>` itself — the input lives in `rel-textfield`'s nested shadow root, which `aria-activedescendant` cannot reference across. This is the standard pragmatic pattern for composed shadow components
86
- - Loading row uses `role="status"`; disabled/readonly never open the panel
87
- - With `label-style="none"` no `<label>` renders, so `field-aria-label` (or `field-aria-labelledby`) must supply the accessible name — it also names the suggestion panel. A placeholder is not a valid naming mechanism; the inner field logs a console warning when both are missing
179
+ Focus: `focus()` on the host delegates to the inner field. Focusing the field with `min-search-length="0"` (or with a query already long enough and matching items) opens the panel. Focus leaving the component commits an exact match and closes the panel; the same happens on an outside pointerdown. After a clear, focus returns to the field.
88
180
 
89
181
  ## Notes / Edge Cases
90
182
 
91
- - The matched substring in each row renders bold
92
- - `value` set externally to a string not present in `items` displays the raw string (common with remote data on init); provide the item in `items` to show its label instead
93
- - `searchFn` rejection is treated as an empty result plus a `rel-search-error` event — the component never throws into the app
94
- - Form validation is *displayed* (`error`, `error-message`, `required`), not performed — validity logic belongs to the form layer (e.g. Angular validators)
95
- - CSS parts: `panel`, `list`, `option`, plus re-exported textfield parts (`label`, `control`, `input`, `helper`, `right-icon`)
96
- - Panel styling matches `rel-select`'s listbox; override via `--rel-autocomplete-bg`, `--rel-autocomplete-menu-border`, `--rel-autocomplete-menu-radius`, `--rel-autocomplete-menu-shadow`, `--rel-autocomplete-option-hover`
97
- - The open panel 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
183
+ - `value` and the visible text are separate: typing only emits `rel-change`; `value` (and `changed`) update when a row is picked, or when the text exactly matches an item's label or value (case-insensitive) on Enter, Tab, blur or outside click. Free text that matches nothing stays in the field but never becomes `value`.
184
+ - Setting `value` externally (attribute, property, Angular `writeValue`) shows the matching item's label, or the raw string when no item matches (common with remote data on init) — provide the item in `items` to show its label.
185
+ - Clearing emits, in order, `rel-clear`, `changed` (`value: ""`, `item: null`) and `rel-change` (`""`), and only when the field actually had text or a value.
186
+ - Remote mode: `items` is ignored while `searchFn` has produced results; a shorter-than-minimum query cancels any in-flight request and closes the panel; stale responses are discarded (latest-wins); a rejected `searchFn` is treated as an empty result plus `rel-search-error` — the component never throws into the app.
187
+ - `loading` is an external flag layered on top of the automatic `searchFn` loading state; the loading row is shown while either is true.
188
+ - `max-suggestions` caps rendered rows only; the panel scrolls (360px max height) regardless. The matched substring in each row renders bold.
189
+ - Validation is displayed (`error`, `error-message`, `required`) but not performed; validity logic belongs to the form layer.
190
+ - `full-width` layout is keyed off the **attribute** (`:host(:not([full-width]))` renders inline-block) even though the property defaults to `true` and is not reflected — add the `full-width` attribute in markup when you need the block layout. This differs from `rel-textfield`, whose `fullwidth` attribute is reflected.
191
+ - The suggestion panel mirrors `rel-select`'s listbox (same tokens, radius, shadow, row styling) and 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. It matches the field width, flips above when short on space, and closes on outside pointerdown or outside scroll.
192
+ - Only `label`, `control`, `input`, `helper` and `right-icon` are re-exported from the inner `rel-textfield`; its `prefix` / `suffix` parts and slots are not exposed.