@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.
- package/CHANGELOG.md +211 -49
- package/dist/components/rel-accordion/README.md +132 -132
- package/dist/components/rel-alert/README.md +145 -141
- package/dist/components/rel-autocomplete/README.md +156 -61
- package/dist/components/rel-avatar/README.md +116 -130
- package/dist/components/rel-badge/README.md +98 -93
- package/dist/components/rel-breadcrumb/README.md +96 -102
- package/dist/components/rel-button/README.md +160 -130
- package/dist/components/rel-calendar/README.md +109 -109
- package/dist/components/rel-card/README.md +75 -94
- package/dist/components/rel-cardmedia/README.md +100 -127
- package/dist/components/rel-carousel/README.md +184 -166
- package/dist/components/rel-checkbox/README.md +93 -75
- package/dist/components/rel-chip/README.md +132 -121
- package/dist/components/rel-container/README.md +107 -99
- package/dist/components/rel-date-picker/README.md +200 -289
- package/dist/components/rel-divider/README.md +78 -100
- package/dist/components/rel-drawer/README.md +187 -200
- package/dist/components/rel-kbd/README.md +141 -151
- package/dist/components/rel-menu/README.md +178 -151
- package/dist/components/rel-menubar/README.md +218 -329
- package/dist/components/rel-otp/README.md +170 -440
- package/dist/components/rel-pagination/README.md +100 -424
- package/dist/components/rel-popover/README.md +203 -568
- package/dist/components/rel-progress/README.md +88 -110
- package/dist/components/rel-radio/README.md +131 -138
- package/dist/components/rel-range-picker/README.md +162 -0
- package/dist/components/rel-resizable/README.md +199 -140
- package/dist/components/rel-segmented-button/README.md +155 -141
- package/dist/components/rel-select/README.md +154 -93
- package/dist/components/rel-sheet/README.md +168 -224
- package/dist/components/rel-skeleton/README.md +103 -0
- package/dist/components/rel-slider/README.md +130 -135
- package/dist/components/rel-snackbar/README.md +162 -134
- package/dist/components/rel-stepper/README.md +158 -160
- package/dist/components/rel-switch/README.md +108 -102
- package/dist/components/rel-tab/README.md +171 -163
- package/dist/components/rel-textfield/README.md +159 -69
- package/dist/components/rel-time-picker/README.md +122 -157
- package/dist/components/rel-toast/README.md +157 -148
- package/dist/components/rel-tooltip/README.md +108 -111
- package/dist/components/rel-upload/README.md +220 -0
- package/dist/index.d.mts +1147 -340
- package/dist/index.d.ts +1147 -340
- package/dist/index.js +3451 -3163
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3416 -3118
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +877 -866
- package/dist/{vars-XNMTSRVN.css → vars-JHTUGNRG.css} +877 -866
- package/package.json +3 -2
- package/dist/components/rel-accordion/rel-accordion.ts +0 -336
- package/dist/components/rel-alert/rel-alert.ts +0 -305
- package/dist/components/rel-autocomplete/rel-autocomplete.ts +0 -720
- package/dist/components/rel-avatar/rel-avatar.ts +0 -142
- package/dist/components/rel-badge/rel-badge.ts +0 -175
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +0 -106
- package/dist/components/rel-button/rel-button.ts +0 -560
- package/dist/components/rel-calendar/index.ts +0 -1
- package/dist/components/rel-calendar/rel-calendar.ts +0 -565
- package/dist/components/rel-card/rel-card.ts +0 -88
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +0 -88
- package/dist/components/rel-carousel/index.ts +0 -1
- package/dist/components/rel-carousel/rel-carousel.ts +0 -723
- package/dist/components/rel-chart/README.md +0 -286
- package/dist/components/rel-chart/index.ts +0 -1
- package/dist/components/rel-chart/rel-chart.ts +0 -754
- package/dist/components/rel-checkbox/rel-checkbox.ts +0 -382
- package/dist/components/rel-chip/rel-chip.ts +0 -483
- package/dist/components/rel-container/rel-container.ts +0 -95
- package/dist/components/rel-date-picker/date-format.test.ts +0 -43
- package/dist/components/rel-date-picker/date-format.ts +0 -47
- package/dist/components/rel-date-picker/date-parse.test.ts +0 -116
- package/dist/components/rel-date-picker/date-parse.ts +0 -178
- package/dist/components/rel-date-picker/index.ts +0 -1
- package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1676
- package/dist/components/rel-divider/rel-divider.ts +0 -54
- package/dist/components/rel-drawer/index.ts +0 -1
- package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
- package/dist/components/rel-drawer/rel-drawer.ts +0 -607
- package/dist/components/rel-kbd/rel-kbd.ts +0 -188
- package/dist/components/rel-layout/rel-layout.ts +0 -49
- package/dist/components/rel-menu/rel-menu.ts +0 -541
- package/dist/components/rel-menubar/index.ts +0 -2
- package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
- package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
- package/dist/components/rel-menubar/rel-menubar.ts +0 -777
- package/dist/components/rel-nav-menu/README.md +0 -289
- package/dist/components/rel-nav-menu/index.ts +0 -3
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
- package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
- package/dist/components/rel-navbar/README.md +0 -126
- package/dist/components/rel-navbar/rel-navbar.ts +0 -105
- package/dist/components/rel-otp/index.ts +0 -1
- package/dist/components/rel-otp/rel-otp.ts +0 -527
- package/dist/components/rel-pagination/index.ts +0 -1
- package/dist/components/rel-pagination/rel-pagination.ts +0 -522
- package/dist/components/rel-popover/index.ts +0 -2
- package/dist/components/rel-popover/rel-popover-content.ts +0 -81
- package/dist/components/rel-popover/rel-popover.ts +0 -475
- package/dist/components/rel-progress/rel-progress.ts +0 -234
- package/dist/components/rel-radio/rel-radio.ts +0 -481
- package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1688
- package/dist/components/rel-resizable/index.ts +0 -3
- package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
- package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
- package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -217
- package/dist/components/rel-select/rel-select.ts +0 -1416
- package/dist/components/rel-sheet/rel-sheet.ts +0 -610
- package/dist/components/rel-sidebar/README.md +0 -209
- package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1191
- package/dist/components/rel-skeleton/rel-skeleton.ts +0 -143
- package/dist/components/rel-slider/rel-slider.ts +0 -673
- package/dist/components/rel-snackbar/rel-snackbar.ts +0 -329
- package/dist/components/rel-stepper/rel-stepper.ts +0 -567
- package/dist/components/rel-switch/rel-switch.ts +0 -199
- package/dist/components/rel-tab/rel-tab.ts +0 -264
- package/dist/components/rel-table/README.md +0 -178
- package/dist/components/rel-table/rel-table-body.ts +0 -22
- package/dist/components/rel-table/rel-table-caption.ts +0 -30
- package/dist/components/rel-table/rel-table-cell.ts +0 -43
- package/dist/components/rel-table/rel-table-footer.ts +0 -24
- package/dist/components/rel-table/rel-table-head.ts +0 -47
- package/dist/components/rel-table/rel-table-header.ts +0 -22
- package/dist/components/rel-table/rel-table-row.ts +0 -37
- package/dist/components/rel-table/rel-table.ts +0 -62
- package/dist/components/rel-textfield/rel-textfield.ts +0 -1054
- package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1482
- package/dist/components/rel-time-picker/time-parse.test.ts +0 -67
- package/dist/components/rel-time-picker/time-parse.ts +0 -85
- package/dist/components/rel-toast/rel-toast.ts +0 -206
- package/dist/components/rel-tooltip/rel-tooltip.ts +0 -193
- package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
- package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar.ts +0 -446
- package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
- package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
- package/dist/components/rel-upload/rel-upload.ts +0 -968
|
@@ -1,106 +1,196 @@
|
|
|
1
1
|
# rel-textfield
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
A text input field component with support for labels, icons, validation states, and supporting text. Used for single-line text entry in forms and user interfaces.
|
|
3
|
+
`<rel-textfield>` is the single-line and multi-line text input from the Figma "Text Field" component: a labelled control with three chromes (`default` outlined, `underline`, `legend` notched outline), three heights (32 / 40 / 48px), prefix and suffix blocks (icon, short text or slotted content), error / helper text and full-width or inline layout. Use it for free-text entry — names, emails, passwords, numbers, notes (`multiline`). For picking from a fixed list use `rel-select`; for type-ahead against a list use `rel-autocomplete`; for dates and times use the picker components, which reuse this field's chrome.
|
|
6
4
|
|
|
7
5
|
## Usage
|
|
8
6
|
|
|
9
7
|
```html
|
|
10
|
-
<!-- Basic
|
|
11
|
-
<rel-textfield label="Email" placeholder="
|
|
8
|
+
<!-- Basic field -->
|
|
9
|
+
<rel-textfield label="Email" placeholder="you@example.com" type="email"></rel-textfield>
|
|
10
|
+
|
|
11
|
+
<!-- Sizes and chromes -->
|
|
12
|
+
<rel-textfield label="Small" size="small"></rel-textfield>
|
|
13
|
+
<rel-textfield label="Large" size="large"></rel-textfield>
|
|
14
|
+
<rel-textfield label="Underline" variant="underline"></rel-textfield>
|
|
15
|
+
<rel-textfield label="Legend" variant="legend"></rel-textfield>
|
|
16
|
+
|
|
17
|
+
<!-- Label styles -->
|
|
18
|
+
<rel-textfield label="Floating label" label-style="floating"></rel-textfield>
|
|
19
|
+
<rel-textfield label-style="none" placeholder="Search orders" field-aria-label="Search orders"></rel-textfield>
|
|
20
|
+
|
|
21
|
+
<!-- Leading icon, helper text, required -->
|
|
22
|
+
<rel-textfield label="Search" prefixicon="search" helpertext="Type at least 3 characters" required></rel-textfield>
|
|
23
|
+
|
|
24
|
+
<!-- Prefix / suffix text (Figma .Preffix / .Suffix) -->
|
|
25
|
+
<rel-textfield label="Website" prefix-text="https://" prefix-style="fill"></rel-textfield>
|
|
26
|
+
<rel-textfield label="Weight" suffix-text="kg" suffix-divider></rel-textfield>
|
|
27
|
+
|
|
28
|
+
<!-- Slotted prefix / suffix content -->
|
|
29
|
+
<rel-textfield label="Amount">
|
|
30
|
+
<span slot="prefix">$</span>
|
|
31
|
+
<rel-button slot="suffix" variant="ghost" size="small">Max</rel-button>
|
|
32
|
+
</rel-textfield>
|
|
12
33
|
|
|
13
|
-
<!--
|
|
34
|
+
<!-- Clickable trailing icon (e.g. password toggle) -->
|
|
14
35
|
<rel-textfield
|
|
36
|
+
id="pw"
|
|
15
37
|
label="Password"
|
|
16
38
|
type="password"
|
|
17
|
-
|
|
18
|
-
|
|
39
|
+
righticon="eye"
|
|
40
|
+
clickable-right-icon
|
|
41
|
+
right-icon-aria-label="Show password">
|
|
19
42
|
</rel-textfield>
|
|
43
|
+
<script>
|
|
44
|
+
const pw = document.getElementById("pw");
|
|
45
|
+
pw.addEventListener("rel-right-icon-click", () => {
|
|
46
|
+
pw.type = pw.type === "password" ? "text" : "password";
|
|
47
|
+
});
|
|
48
|
+
pw.addEventListener("rel-change", (e) => console.log("typed:", e.detail));
|
|
49
|
+
</script>
|
|
20
50
|
|
|
21
|
-
<!--
|
|
22
|
-
<rel-textfield
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</rel-textfield>
|
|
51
|
+
<!-- Error state -->
|
|
52
|
+
<rel-textfield label="Username" value="a" error errormessage="Must be at least 3 characters"></rel-textfield>
|
|
53
|
+
|
|
54
|
+
<!-- Multiline (textarea) -->
|
|
55
|
+
<rel-textfield label="Notes" multiline rows="5" maxlength="500"></rel-textfield>
|
|
27
56
|
|
|
28
|
-
<!--
|
|
29
|
-
<rel-textfield
|
|
57
|
+
<!-- Read-only, disabled, inline width -->
|
|
58
|
+
<rel-textfield label="Order ID" value="SO-4821" readonly></rel-textfield>
|
|
59
|
+
<rel-textfield label="Disabled" disabled></rel-textfield>
|
|
60
|
+
<rel-textfield id="qty" label="Quantity" type="number"></rel-textfield>
|
|
30
61
|
<script>
|
|
31
|
-
|
|
32
|
-
|
|
62
|
+
// fullWidth defaults to true; a boolean attribute cannot express false, so unset it via the property
|
|
63
|
+
document.getElementById("qty").fullWidth = false;
|
|
33
64
|
</script>
|
|
34
65
|
```
|
|
35
66
|
|
|
67
|
+
### Deprecated aliases
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<!-- floatingLabel → label-style="floating" (kept permanently as an alias; no console notice) -->
|
|
71
|
+
<rel-textfield label="Old spelling" floatinglabel></rel-textfield>
|
|
72
|
+
<rel-textfield label="Canonical" label-style="floating"></rel-textfield>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
<!-- readme-gen:start -->
|
|
76
|
+
|
|
77
|
+
<!-- Generated from rel-textfield.ts — do not edit; run readme-generate.mjs -->
|
|
78
|
+
|
|
36
79
|
## API
|
|
37
80
|
|
|
38
|
-
### Attributes/Properties
|
|
39
|
-
|
|
40
|
-
|
|
|
41
|
-
|
|
42
|
-
| `label` | `string` |
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
81
|
+
### Attributes / Properties
|
|
82
|
+
|
|
83
|
+
| Property | Attribute | Type | Default | Description |
|
|
84
|
+
| --- | --- | --- | --- | --- |
|
|
85
|
+
| `label` | `label` | `string` | `undefined` | Visible label text. Rendered above the control (default), inside it as a floating label (`labelStyle="floating"`) or as the notch of the `legend` variant; omitted entirely under `labelStyle="none"`. |
|
|
86
|
+
| `placeholder` | `placeholder` | `string` | `""` | Placeholder shown while the field is empty. Under the floating label style it stays hidden until the field is focused. |
|
|
87
|
+
| `type` | `type` | `string` | `"text"` | Native input `type` (`text`, `email`, `password`, `number`, …). Ignored when `multiline` is set. |
|
|
88
|
+
| `value` | `value` | `string` | `""` | Current text. Updated on every keystroke; set it to control the field programmatically. |
|
|
89
|
+
| `leftIcon` | `lefticon` | `string` | `undefined` | Legacy name for the leading icon (a `rel-icon` name). `prefixIcon` wins when both are set. |
|
|
90
|
+
| `rightIcon` | `righticon` | `string` | `undefined` | Trailing `rel-icon` name rendered in the suffix block. Decorative unless `clickableRightIcon` is set. |
|
|
91
|
+
| `clickableRightIcon` | `clickable-right-icon` | `boolean` | `false` | Makes the trailing icon interactive (pointer + focusable) and emits `rel-right-icon-click` — e.g. a password show/hide toggle or clear button. |
|
|
92
|
+
| `rightIconAriaLabel` | `right-icon-aria-label` | `string` | `undefined` | Accessible label for the trailing icon when it is clickable. |
|
|
93
|
+
| `prefixText` | `prefix-text` | `string` | `undefined` | Short text rendered before the input, e.g. `"http://"` or `"$"`. Sits in the same prefix block as `prefixIcon` and is styled by `prefixStyle`. |
|
|
94
|
+
| `prefixStyle` | `prefix-style` | `"clear" \| "divider" \| "fill"` | `"clear"` | Visual treatment of the prefix block — applies to the prefix icon, text and slotted `prefix` content alike. See `TextFieldPrefixStyle`. |
|
|
95
|
+
| `suffixText` | `suffix-text` | `string` | `undefined` | Short text rendered after the input, e.g. `"kg"` or `".00"`. Shares the suffix block with `rightIcon` and slotted `suffix` content. |
|
|
96
|
+
| `suffixDivider` | `suffix-divider` | `boolean` | `false` | Draws a hairline between the input and the suffix block. |
|
|
97
|
+
| `supportingText` | `supportingtext` | `string` | `undefined` | Legacy name for the helper line below the control. `helperText` wins when both are set. |
|
|
98
|
+
| `state` | `state` | `"default" \| "error" \| "disabled"` | `"default"` | Legacy visual state. `"error"` / `"disabled"` behave like the `error` / `disabled` booleans, which are preferred and take precedence. Typing into a `state="error"` field resets it to `"default"` until the value is emptied again. |
|
|
99
|
+
| `size` | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Control height — `small` 32px, `medium` 40px, `large` 48px — which also scales the text and the affix icons. |
|
|
100
|
+
| `labelStyle` | `label-style` | `"default" \| "floating" \| "none"` | `undefined` | Label presentation. Left `undefined` the deprecated `floatingLabel` boolean decides, so existing markup keeps working; set explicitly and it wins. Declares `attribute` because Lit would otherwise only listen for the all-lowercase `labelstyle`. Reflected. |
|
|
101
|
+
| `fieldAriaLabel` | `field-aria-label` | `string` | `undefined` | Accessible name for the input. Required when `labelStyle="none"`, since no `<label>` renders and a placeholder is not a valid naming mechanism. |
|
|
102
|
+
| `fieldAriaLabelledby` | `field-aria-labelledby` | `string` | `undefined` | IDREF list of external element(s) naming the input. Wins over `fieldAriaLabel`. |
|
|
103
|
+
| `variant` | `variant` | `"default" \| "underline" \| "legend"` | `"default"` | Field chrome: `default` outlined box, `underline` bottom border only, `legend` notched outline with the label sitting in the top border (native fieldset/legend). Reflected. |
|
|
104
|
+
| `disabled` | `disabled` | `boolean` | `false` | Disables the input (not focusable, not editable) and dims the control. |
|
|
105
|
+
| `required` | `required` | `boolean` | `false` | Marks the input required: sets native `required` / `aria-required` and appends an asterisk to the label. |
|
|
106
|
+
| `multiline` | `multiline` | `boolean` | `false` | Renders a textarea instead of a single-line input (see `rows`). Prefix/suffix blocks and `type` are ignored in this mode. Reflected. |
|
|
107
|
+
| `rows` | `rows` | `number` | `3` | Visible text rows of the textarea when `multiline` is set. |
|
|
108
|
+
| `prefixIcon` | `prefixicon` | `string` | `undefined` | Leading `rel-icon` name rendered in the prefix block (preferred over the legacy `leftIcon`). |
|
|
109
|
+
| `prefixIconAriaLabel` | `prefixiconarialabel` | `string` | `undefined` | Accessible label for the leading icon. Without it the icon is `aria-hidden` (decorative). |
|
|
110
|
+
| `error` | `error` | `boolean` | `false` | Puts the field in the error state: danger border, `aria-invalid`, and `errorMessage` replacing the helper text. |
|
|
111
|
+
| `errorMessage` | `errormessage` | `string` | `undefined` | Text shown below the control instead of `helperText` while the field is in the error state. |
|
|
112
|
+
| `helperText` | `helpertext` | `string` | `undefined` | Helper line below the control (preferred over the legacy `supportingText`); linked to the input via `aria-describedby`. |
|
|
113
|
+
| `readonly` | `readonly` | `boolean` | `false` | Makes the input read-only: focusable and selectable but not editable. |
|
|
114
|
+
| `maxLength` | `maxlength` | `number` | `undefined` | Maximum number of characters (native `maxlength`). |
|
|
115
|
+
| `name` | `name` | `string` | `undefined` | Form field name forwarded to the native input, for form submission and autofill. |
|
|
116
|
+
| `fullWidth` | `fullwidth` | `boolean` | `true` | Fills the parent width as a block element (default). Unset it to render inline at the content's natural width. Reflected. |
|
|
117
|
+
|
|
118
|
+
#### Deprecated (still supported — removal targeted for 3.0)
|
|
119
|
+
|
|
120
|
+
| Property | Attribute | Type | Use instead |
|
|
121
|
+
| --- | --- | --- | --- |
|
|
122
|
+
| `floatingLabel` | `floatinglabel` | `boolean` | Use `labelStyle="floating"`. Kept permanently as an alias. |
|
|
123
|
+
|
|
124
|
+
### Methods
|
|
125
|
+
|
|
126
|
+
| Method | Signature | Description |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| `focus` | `focus(options?: FocusOptions)` | Focuses the inner input/textarea (the host itself is not focusable). |
|
|
55
129
|
|
|
56
130
|
## Events
|
|
57
131
|
|
|
58
|
-
| Event | Detail | Description |
|
|
59
|
-
|
|
60
|
-
| `
|
|
132
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
133
|
+
| --- | --- | --- | --- |
|
|
134
|
+
| `rel-change` | `value` | bubbles / composed | Fired on every keystroke. Detail: the current text (`value`). |
|
|
135
|
+
| `rel-right-icon-click` | — | bubbles / composed | Fired when the trailing icon is clicked or activated with Enter / Space while `clickableRightIcon` is set. No detail. |
|
|
61
136
|
|
|
62
137
|
## Slots
|
|
63
138
|
|
|
64
|
-
|
|
139
|
+
| Slot | Description |
|
|
140
|
+
| --- | --- |
|
|
141
|
+
| `prefix` | Custom content at the far left of the control (e.g. a unit dropdown); shares the prefix block with `prefixIcon` / `prefixText`. Hidden when `multiline` is set. |
|
|
142
|
+
| `suffix` | Custom content at the far right of the control (e.g. an action button); shares the suffix block with `rightIcon` / `suffixText`. Hidden when `multiline` is set. |
|
|
65
143
|
|
|
66
144
|
## CSS Parts
|
|
67
145
|
|
|
68
|
-
|
|
146
|
+
| Part | Description |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| `label` | The visible label element (default and floating label styles) |
|
|
149
|
+
| `input` | The native input / textarea |
|
|
150
|
+
| `right-icon` | The trailing `rel-icon` |
|
|
151
|
+
| `prefix` | The prefix block (leading icon, prefix text and the `prefix` slot) |
|
|
152
|
+
| `suffix` | The suffix block (suffix text, trailing icon and the `suffix` slot) |
|
|
153
|
+
| `helper` | The helper / error text line below the control |
|
|
154
|
+
| `control` | The bordered control box (the fieldset in the legend variant) |
|
|
69
155
|
|
|
70
156
|
## Tokens / CSS Variables
|
|
71
157
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- `--rel-border-danger`: Error state border color
|
|
82
|
-
- `--rel-bg-surface`: Input background (light mode)
|
|
83
|
-
- `--rel-bg-neutral-elevated-1`: Disabled background
|
|
84
|
-
- `--rel-spacing-*`: Spacing tokens
|
|
85
|
-
- `--rel-border-radius-sm`: Border radius
|
|
86
|
-
- `--rel-field-label-reserve`: Height held for the absent label row under `label-style="none"`, so the input 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)
|
|
158
|
+
### Component hooks
|
|
159
|
+
|
|
160
|
+
Set these on the host (or an ancestor) to customise the element without touching design tokens.
|
|
161
|
+
|
|
162
|
+
| Custom property | Default | Description |
|
|
163
|
+
| --- | --- | --- |
|
|
164
|
+
| `--rel-field-label-reserve` | `calc(var(--rel-body-sm-medium-line-height) + var(--rel-spacing-2xs))` | Height held for the absent label row under `labelStyle="none"` so the control 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). |
|
|
165
|
+
|
|
166
|
+
<!-- readme-gen:end -->
|
|
87
167
|
|
|
88
168
|
## Accessibility
|
|
89
169
|
|
|
90
|
-
-
|
|
91
|
-
- With `label-style="none"` no
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
170
|
+
- The visible `<label>` is linked to the native input via `for`/`id` (the host `id`, or a generated one). In the `legend` variant the input is instead named through `aria-labelledby` pointing at the `<legend>`.
|
|
171
|
+
- With `label-style="none"` no label renders: `field-aria-labelledby` (wins) or `field-aria-label` must supply the accessible name. The component logs a console warning once when neither is set, because a placeholder is not a valid naming mechanism.
|
|
172
|
+
- The input carries `aria-required`, `aria-invalid` (true in the error state) and `aria-describedby` pointing at the helper line. That line is always rendered with `aria-live="polite"`, so a change from helper text to `errorMessage` is announced.
|
|
173
|
+
- The leading icon is `aria-hidden` unless `prefixIconAriaLabel` is set, in which case it becomes `role="img"` with that label. The trailing icon is `aria-hidden` unless `clickable-right-icon` is set, in which case it is `role="button"`, `tabindex="0"` and named by `right-icon-aria-label`.
|
|
174
|
+
- No screen-reader announcements are made via `announce()`; the live helper region is the only announcement path.
|
|
175
|
+
|
|
176
|
+
| Key | Action |
|
|
177
|
+
|-----|--------|
|
|
178
|
+
| `Tab` | Focus the input; with `clickable-right-icon` the trailing icon is the next Tab stop |
|
|
179
|
+
| `Enter` / `Space` (on the trailing icon) | Fires `rel-right-icon-click` (default prevented) |
|
|
180
|
+
|
|
181
|
+
Focus behaviour: `focus()` on the host focuses the inner input / textarea (the host itself is not focusable). A mousedown anywhere on the control — border, legend notch, prefix / suffix padding — focuses the input like clicking a label would; presses on the input, a clickable icon or slotted content keep their native behaviour. The focused control shows a `--rel-border-strong` border plus a 1px ring; the `legend` variant recolours the border and legend only (a ring would strike through the notch).
|
|
99
182
|
|
|
100
183
|
## Notes / Edge Cases
|
|
101
184
|
|
|
102
|
-
- The `
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
-
|
|
106
|
-
-
|
|
185
|
+
- Attribute spellings: props declared with an explicit `attribute` use kebab-case (`label-style`, `prefix-text`, `clickable-right-icon`, `field-aria-label`, …). The others have Lit's default all-lowercase attribute — `prefixicon`, `righticon`, `helpertext`, `errormessage`, `maxlength`, `fullwidth`, `supportingtext`, `floatinglabel` — see the Attribute column above. HTML attribute names are case-insensitive, so `helperText="…"` in markup also works.
|
|
186
|
+
- Legacy names still work but the canonical ones win when both are set: `leftIcon` → `prefixIcon`, `supportingText` → `helperText`, `state="error"` → `error`, `state="disabled"` → `disabled`. `lefticon` / `righticon` attributes are also read once at connect time.
|
|
187
|
+
- `errorMessage` replaces the helper line only while the field is in the error state **and** the message is set; otherwise the helper text stays visible. There is no built-in validation — set `error` from your form layer.
|
|
188
|
+
- `state="error"` (legacy) auto-clears to `"default"` as soon as the user types a non-empty value and comes back once the value is emptied again; the `error` boolean never auto-clears.
|
|
189
|
+
- `multiline` renders a `<textarea>` (`rows`, vertical resize, 80px minimum height). `type`, the prefix / suffix blocks and their slots are ignored in this mode (the slots stay mounted but hidden).
|
|
190
|
+
- `fullWidth` defaults to `true` and reflects as `fullwidth`; without it the host becomes `inline-block` at its content width. To turn it off from HTML you must bind the property (`.fullWidth=${false}`), since a boolean attribute cannot express `false`.
|
|
191
|
+
- `label-style="floating"`: the placeholder is hidden until the field is focused; the label floats onto the border when focused or filled. Internally the deprecated `floatingLabel` boolean is kept in sync with `labelStyle` and its reflected `floatinglabel` attribute is the styling hook, so both spellings render identically. With a `prefix-style="clear"` prefix the floated label slides back over the control's left edge (Figma "Floating Label"); `divider` / `fill` prefixes keep it after the block.
|
|
192
|
+
- `variant="legend"` + `label-style="none"` drops the `<legend>` entirely so the top border runs continuous; a `fill` prefix is squared off in this variant because it cannot reach the notched top border.
|
|
193
|
+
- `--rel-field-label-reserve` (see Component hooks) keeps a `label-style="none"` field bottom-aligned with labelled siblings; set it to `0` in toolbars or table cells.
|
|
194
|
+
- Inside the prefix block the order is slotted content → icon → text (nearest the input); in the suffix block it is text → icon → slotted content. Clicking a non-interactive part of either block focuses the input.
|
|
195
|
+
- The control height (32 / 40 / 48px) is explicit so the field lines up with `rel-select` and the date / time / range picker triggers; the textarea keeps the padding model and grows with `rows`.
|
|
196
|
+
- In Figma, the `error` state's border has no focus ring; that matches the code (`box-shadow: none` in error).
|
|
@@ -1,199 +1,164 @@
|
|
|
1
1
|
# rel-time-picker
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Trigger button with time-column popover (Hour / Min / AM-PM)
|
|
8
|
-
- 12-hour and 24-hour display formats
|
|
9
|
-
- Configurable minute intervals (1, 5, 10, 15, 30, …)
|
|
10
|
-
- Draft state with Now / Cancel / Apply footer
|
|
11
|
-
- Min/max time constraints
|
|
12
|
-
- Optional clear button
|
|
13
|
-
- Label, placeholder, helper text and error states
|
|
14
|
-
- Standardized input API (mirrors rel-textfield / rel-date-picker)
|
|
15
|
-
- Keyboard navigation and full ARIA support
|
|
16
|
-
- Token-driven styling with `::part` hooks
|
|
17
|
-
|
|
18
|
-
## Value format
|
|
19
|
-
|
|
20
|
-
The committed `value` is **always 24-hour `"HH:mm"`** (e.g. `"09:30"`, `"17:05"`) regardless of the display `format`, so consumers get a consistent machine-readable string.
|
|
3
|
+
Time selection field implementing the Figma "Time Picker" component (Reliability DS V1.0, node 8301:3771): an editable text field with a clock icon that opens a panel of Hour / Minute (/ Second / AM-PM) columns and a Now / Cancel / OK footer. Column picks are held as a draft until OK; the field also accepts free-form typed times ("930", "9:30 pm", "n" for now). The committed `value` is always 24-hour `"HH:mm"` (or `"HH:mm:ss"` with `seconds`) regardless of the display `format`. Use it for a single time of day; use `rel-date-picker` for dates and `rel-range-picker` for date ranges.
|
|
21
4
|
|
|
22
5
|
## Usage
|
|
23
6
|
|
|
24
|
-
### Basic
|
|
25
|
-
|
|
26
7
|
```html
|
|
8
|
+
<!-- Basic (12-hour display, 5-minute steps) -->
|
|
27
9
|
<rel-time-picker></rel-time-picker>
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### With Value
|
|
31
10
|
|
|
32
|
-
|
|
33
|
-
<rel-time-picker value="09:30"></rel-time-picker>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
### With Label
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
<rel-time-picker label="Start time" placeholder="Select time"></rel-time-picker>
|
|
40
|
-
```
|
|
11
|
+
<!-- Value is always 24-hour HH:mm; the field shows it per `format` -->
|
|
12
|
+
<rel-time-picker value="09:30" label="Start time"></rel-time-picker>
|
|
13
|
+
<rel-time-picker value="17:05" format="24h"></rel-time-picker>
|
|
41
14
|
|
|
42
|
-
|
|
15
|
+
<!-- Seconds column; value becomes HH:mm:ss -->
|
|
16
|
+
<rel-time-picker seconds value="17:05:30" format="24h"></rel-time-picker>
|
|
43
17
|
|
|
44
|
-
|
|
45
|
-
<rel-time-picker format="24h" value="17:05"></rel-time-picker>
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Minute intervals
|
|
49
|
-
|
|
50
|
-
```html
|
|
18
|
+
<!-- Minute granularity of the column (typed entry still accepts any minute) -->
|
|
51
19
|
<rel-time-picker minute-step="15"></rel-time-picker>
|
|
52
|
-
<rel-time-picker minute-step="
|
|
53
|
-
```
|
|
20
|
+
<rel-time-picker minute-step="1"></rel-time-picker>
|
|
54
21
|
|
|
55
|
-
|
|
22
|
+
<!-- Constrain to business hours (inclusive, HH:mm) -->
|
|
23
|
+
<rel-time-picker min-time="09:00" max-time="17:30" placeholder="Business hours only"></rel-time-picker>
|
|
56
24
|
|
|
57
|
-
|
|
58
|
-
<rel-time-picker
|
|
59
|
-
min-time="09:00"
|
|
60
|
-
max-time="17:30"
|
|
61
|
-
placeholder="Business hours only"
|
|
62
|
-
></rel-time-picker>
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Clearable
|
|
66
|
-
|
|
67
|
-
```html
|
|
25
|
+
<!-- Clear button, helper / error text, required -->
|
|
68
26
|
<rel-time-picker value="09:30" clearable></rel-time-picker>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
27
|
+
<rel-time-picker label="Start time" helper-text="Local timezone"></rel-time-picker>
|
|
28
|
+
<rel-time-picker label="Start time" error error-message="Select a valid time"></rel-time-picker>
|
|
29
|
+
<rel-time-picker label="Start time" required></rel-time-picker>
|
|
72
30
|
|
|
73
|
-
|
|
31
|
+
<!-- States -->
|
|
74
32
|
<rel-time-picker value="09:30" disabled></rel-time-picker>
|
|
75
33
|
<rel-time-picker value="09:30" readonly></rel-time-picker>
|
|
76
|
-
<rel-time-picker error error-message="Select a valid time"></rel-time-picker>
|
|
77
|
-
<rel-time-picker helper-text="Local timezone"></rel-time-picker>
|
|
78
|
-
<rel-time-picker label="Start time" required></rel-time-picker>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Sizes / layout
|
|
82
34
|
|
|
83
|
-
|
|
35
|
+
<!-- Sizes (field 32 / 40 / 48px, panel 220 / 250 / 280px) and layout -->
|
|
84
36
|
<rel-time-picker size="small"></rel-time-picker>
|
|
37
|
+
<rel-time-picker size="medium"></rel-time-picker>
|
|
85
38
|
<rel-time-picker size="large"></rel-time-picker>
|
|
86
|
-
<rel-time-picker
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Form usage
|
|
39
|
+
<rel-time-picker fullwidth label="Full width"></rel-time-picker>
|
|
90
40
|
|
|
91
|
-
|
|
41
|
+
<!-- Form integration: `name` renders a hidden input carrying the value -->
|
|
92
42
|
<form>
|
|
93
43
|
<rel-time-picker name="startTime" label="Start time" required></rel-time-picker>
|
|
94
44
|
</form>
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
The value is mirrored onto a hidden `<input name="...">` so native form submission works.
|
|
98
|
-
|
|
99
|
-
### Programmatic Control (JavaScript)
|
|
100
45
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
picker.value = '14:30';
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
picker.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
picker.addEventListener('rel-change', (e) => {
|
|
112
|
-
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
picker.addEventListener('rel-open-change', (e) => {
|
|
116
|
-
console.log('Open:', e.detail.open);
|
|
117
|
-
});
|
|
46
|
+
<!-- Programmatic control -->
|
|
47
|
+
<rel-time-picker id="tp" clearable></rel-time-picker>
|
|
48
|
+
<script>
|
|
49
|
+
const picker = document.getElementById('tp');
|
|
50
|
+
picker.value = '14:30'; // always 24h
|
|
51
|
+
picker.open = true; // opens the panel and focuses the selected hour
|
|
52
|
+
|
|
53
|
+
picker.addEventListener('rel-change', (e) => {
|
|
54
|
+
console.log('time:', e.detail.value); // "14:30" | "14:30:00" | null (cleared)
|
|
55
|
+
});
|
|
56
|
+
picker.addEventListener('rel-open-change', (e) => {
|
|
57
|
+
console.log('open:', e.detail.open);
|
|
58
|
+
});
|
|
59
|
+
</script>
|
|
118
60
|
```
|
|
119
61
|
|
|
120
|
-
|
|
62
|
+
### Typed entry
|
|
121
63
|
|
|
122
|
-
-
|
|
123
|
-
- **Apply** commits the draft, emits `rel-change` and closes.
|
|
124
|
-
- **Cancel**, `Escape` or an outside click discards the draft (same as rel-range-picker).
|
|
125
|
-
- **Now** sets the draft to the current time, snapped to `minute-step` and clamped into `min-time`/`max-time`.
|
|
126
|
-
- Picking an hour with no minute selected defaults the minute to `00`.
|
|
64
|
+
Typing into the field and pressing `Enter` (or leaving the field) commits the text. Accepted forms are case- and whitespace-insensitive: `9` → 09:00, `930` / `0930` / `9:30` / `9.30` / `9 30` → 09:30, `093015` / `9:30:15` → 09:30:15, `9 pm` / `9:30p` → 21:00 / 21:30, `12am` → 00:00, `12 pm` → 12:00, and `n` / `now` → the current time. Unparseable text shows "Invalid time", a time outside `min-time` / `max-time` shows "Time out of range"; in both cases the text stays in the field for correction and the committed `value` is untouched.
|
|
127
65
|
|
|
128
|
-
|
|
66
|
+
<!-- readme-gen:start -->
|
|
129
67
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
| `ArrowUp` / `ArrowDown` | Column | Move and select the previous/next entry |
|
|
134
|
-
| `ArrowLeft` / `ArrowRight` | Column | Jump between Hour / Min / AM-PM columns |
|
|
135
|
-
| `Home` / `End` | Column | First / last entry |
|
|
136
|
-
| `Enter` | Column | Select the entry and Apply |
|
|
137
|
-
| `Escape` | Anywhere | Discard draft and close |
|
|
68
|
+
<!-- Generated from rel-time-picker.ts — do not edit; run readme-generate.mjs -->
|
|
69
|
+
|
|
70
|
+
## API
|
|
138
71
|
|
|
139
|
-
|
|
72
|
+
### Attributes / Properties
|
|
140
73
|
|
|
141
74
|
| Property | Attribute | Type | Default | Description |
|
|
142
75
|
| --- | --- | --- | --- | --- |
|
|
143
|
-
| `value` | `value` | `string \| null` | `null` | Committed time,
|
|
144
|
-
| `placeholder` | `placeholder` | `string` | `"Select time"` |
|
|
145
|
-
| `label` | `label` | `string \| null` | `null` | Field label |
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
| `open` | `open` | `boolean` | `false` |
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `variant` | `variant` | `"outlined"` | `"outlined"` | Visual style |
|
|
76
|
+
| `value` | `value` | `string \| null` | `null` | Committed time, 24-hour "HH:mm" or "HH:mm:ss" (e.g. "09:30", "17:05:30"). Reflected. |
|
|
77
|
+
| `placeholder` | `placeholder` | `string` | `"Select time"` | Placeholder shown in the field while no value is committed and nothing is typed. |
|
|
78
|
+
| `label` | `label` | `string \| null` | `null` | Field label rendered above the trigger; also the input's accessible name (unset → "Select time"). |
|
|
79
|
+
| `disabled` | `disabled` | `boolean` | `false` | Disables the field (0.6 opacity, no pointer events); the panel cannot open. Reflected. |
|
|
80
|
+
| `required` | `required` | `boolean` | `false` | Renders the `*` mark after the label and sets `aria-required`; not enforced by the component. |
|
|
81
|
+
| `readonly` | `readonly` | `boolean` | `false` | Shows the value but blocks typing and opening the panel. Reflected. |
|
|
82
|
+
| `format` | `format` | `"12h" \| "24h"` | `"12h"` | Display format of the trigger text and hour column. Value stays 24-hour. |
|
|
83
|
+
| `seconds` | `seconds` | `boolean` | `false` | Shows the seconds column; committed value becomes "HH:mm:ss". Reflected. |
|
|
84
|
+
| `minuteStep` | `minute-step` | `number` | `5` | Minute granularity of the minutes column (1, 5, 10, 15, 30, …). |
|
|
85
|
+
| `minTime` | `min-time` | `string \| null` | `null` | Earliest selectable time, "HH:mm" (inclusive). |
|
|
86
|
+
| `maxTime` | `max-time` | `string \| null` | `null` | Latest selectable time, "HH:mm" (inclusive). |
|
|
87
|
+
| `open` | `open` | `boolean` | `false` | Whether the panel is open. Settable from outside; opening resets the draft from `value` (programmatic changes do not fire `rel-open-change`). Reflected. |
|
|
88
|
+
| `clearable` | `clearable` | `boolean` | `false` | Shows a clear (×) button inside the field while a value is set; clearing commits `null`. |
|
|
89
|
+
| `error` | `error` | `boolean` | `false` | Error styling (danger border, `aria-invalid`) and shows `errorMessage` below the field. |
|
|
90
|
+
| `invalid` | `invalid` | `boolean` | `false` | Alias for `error` (requested-API compat); either flag applies error styling. |
|
|
91
|
+
| `errorMessage` | `error-message` | `string` | `undefined` | Text shown below the field while `error` / `invalid` is set (falls back to the typed-entry parse error, then `helperText`). |
|
|
92
|
+
| `helperText` | `helper-text` | `string` | `undefined` | Assistive text shown below the field when not in error. |
|
|
93
|
+
| `name` | `name` | `string` | `undefined` | When set, renders a hidden `<input name="…">` carrying `value` for native form submission. |
|
|
94
|
+
| `size` | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Trigger height on the shared field scale — small 32 / medium 40 / large 48px border-box; also sets the panel width (220 / 250 / 280px) and option row height (32 / 36 / 40px). Small lowers the trigger min-width from 160 to 128px. |
|
|
95
|
+
| `variant` | `variant` | `"outlined"` | `"outlined"` | Visual style; only `"outlined"` exists today. Reflected. |
|
|
96
|
+
| `fullWidth` | `fullwidth` | `boolean` | `false` | Fills the parent width (the host is inline-block with intrinsic width otherwise). The attribute is lowercase `fullwidth`. Reflected. |
|
|
163
97
|
|
|
164
98
|
## Events
|
|
165
99
|
|
|
166
|
-
| Event | Detail | Description |
|
|
167
|
-
| --- | --- | --- |
|
|
168
|
-
| `rel-
|
|
169
|
-
| `rel-
|
|
170
|
-
| `rel-focus` | — |
|
|
171
|
-
| `rel-
|
|
100
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
101
|
+
| --- | --- | --- | --- |
|
|
102
|
+
| `rel-blur` | — | bubbles / composed | Fired when the text input loses focus (before any typed text is committed). No detail. |
|
|
103
|
+
| `rel-change` | `{ value: newValue } / { value: null }` | bubbles / composed | Fired when a time is committed (OK, Enter / blur on typed text, the Now shortcut) or cleared. Detail: `{ value: string \| null }` — 24-hour "HH:mm" / "HH:mm:ss", or `null` after a clear. |
|
|
104
|
+
| `rel-focus` | — | bubbles / composed | Fired when the text input receives focus. No detail. |
|
|
105
|
+
| `rel-open-change` | `{ open: this.open } / { open: false }` | bubbles / composed | Fired whenever the panel opens or closes through user interaction. Detail: `{ open: boolean }`. |
|
|
172
106
|
|
|
173
|
-
##
|
|
107
|
+
## Slots
|
|
174
108
|
|
|
175
|
-
|
|
|
109
|
+
| Slot | Description |
|
|
176
110
|
| --- | --- |
|
|
177
|
-
|
|
|
178
|
-
| `label` | Field label |
|
|
179
|
-
| `trigger` | Trigger button |
|
|
180
|
-
| `value` | Trigger value/placeholder text |
|
|
181
|
-
| `icon` | Trailing clock icon |
|
|
182
|
-
| `panel` | Popover panel |
|
|
183
|
-
| `option` | Hour/minute/period entries |
|
|
184
|
-
| `footer` | Now / Cancel / Apply row |
|
|
185
|
-
| `helper` | Helper / error text |
|
|
186
|
-
|
|
187
|
-
```css
|
|
188
|
-
/* Example: widen the popover and restyle options */
|
|
189
|
-
rel-time-picker::part(panel) {
|
|
190
|
-
box-shadow: var(--rel-shadows-shadow-400);
|
|
191
|
-
}
|
|
192
|
-
rel-time-picker::part(option) {
|
|
193
|
-
border-radius: var(--rel-border-radius-xs);
|
|
194
|
-
}
|
|
195
|
-
```
|
|
111
|
+
| — | This element has no slots. |
|
|
196
112
|
|
|
197
|
-
##
|
|
113
|
+
## CSS Parts
|
|
198
114
|
|
|
199
|
-
|
|
115
|
+
| Part | Description |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| `base` | Outer wrapper; carries the size / error / readonly classes |
|
|
118
|
+
| `label` | The field label above the trigger |
|
|
119
|
+
| `trigger` | The field box that anchors the panel (wraps the text input and the icons) |
|
|
120
|
+
| `value` | The editable text input showing the formatted time |
|
|
121
|
+
| `icon` | The trailing clock icon |
|
|
122
|
+
| `panel` | The popover panel (`role="dialog"`) |
|
|
123
|
+
| `shortcuts` | The typed-shortcut chip row at the top of the panel (N → Now) |
|
|
124
|
+
| `option` | Each hour / minute / second / AM-PM entry button |
|
|
125
|
+
| `footer` | The Now / Cancel / OK row |
|
|
126
|
+
| `helper` | The helper / error text live region under the field |
|
|
127
|
+
|
|
128
|
+
<!-- readme-gen:end -->
|
|
129
|
+
|
|
130
|
+
## Accessibility
|
|
131
|
+
|
|
132
|
+
- The editable field is an `<input type="text" role="combobox">` with `aria-haspopup="dialog"`, `aria-expanded`, `aria-controls` pointing at the panel, `aria-required` (from `required`), `aria-invalid` (from `error` / `invalid` / a typed-entry error) and `aria-describedby` pointing at the helper / error text. Its accessible name is the `label` (via `aria-labelledby`), falling back to `aria-label="Select time"`.
|
|
133
|
+
- The clock icon is a button labelled "Open time panel" with its own `aria-expanded`; the optional clear button is labelled "Clear time". The required mark `*` is `aria-hidden`.
|
|
134
|
+
- The panel is `role="dialog"` `aria-label="Choose time"`, promoted to the browser top layer (`popover="manual"`) so a modal / drawer ancestor cannot clip it. Each column is a `role="listbox"` named "Hours", "Minutes", "Seconds" or "AM or PM"; entries are `role="option"` buttons with `aria-selected`, and out-of-range entries are native `disabled`. Each column uses a roving `tabindex` (the selected entry, else the first).
|
|
135
|
+
- The helper / error text (part `helper`) is a persistent `aria-live="polite"` region, so error messages and typed-entry errors are announced as they appear.
|
|
136
|
+
- Focus: opening with the clock icon, `ArrowDown`, `Enter` or by setting `open` moves focus to the selected (or first enabled) hour without scrolling the page; opening by clicking into the field keeps focus in the input so typing continues to work. Cancel, `Escape` and OK return focus to the field; an outside click closes without refocusing.
|
|
137
|
+
- Screen-reader announcement (shared `announce()` utility): "{formatted time} selected" when OK commits the draft.
|
|
138
|
+
|
|
139
|
+
| Key | Where | Action |
|
|
140
|
+
| --- | --- | --- |
|
|
141
|
+
| Typing | Field | Edits the free-form text (see Typed entry); clears any previous parse error |
|
|
142
|
+
| `Enter` | Field | Commit the typed text; if nothing was typed, open the panel (closed) or apply the draft (open) |
|
|
143
|
+
| `ArrowDown` | Field | Open the panel, or move focus into the columns when already open |
|
|
144
|
+
| `Escape` | Field | Revert uncommitted typed text; also closes the panel discarding the draft |
|
|
145
|
+
| Blur | Field | Commit the typed text when focus leaves the component (moving into the panel does not commit) |
|
|
146
|
+
| `ArrowUp` / `ArrowDown` | Column | Move to and select the previous / next enabled entry |
|
|
147
|
+
| `ArrowLeft` / `ArrowRight` | Column | Jump to the previous / next column (Hour → Minute → Second → AM/PM) |
|
|
148
|
+
| `Home` / `End` | Column | Select the first / last enabled entry |
|
|
149
|
+
| `Enter` | Column | Select the entry and apply (OK) |
|
|
150
|
+
| `N` | Panel | Commit the current time immediately (same as the "N → Now" chip) and close |
|
|
151
|
+
| `Escape` | Anywhere | Discard the draft and close |
|
|
152
|
+
|
|
153
|
+
## Notes / Edge Cases
|
|
154
|
+
|
|
155
|
+
- `value` is always 24-hour `"HH:mm"`, or `"HH:mm:ss"` when `seconds` is set; the `format` prop only changes the field text and the hour column (`12h` shows 01–12 plus an AM/PM column, `24h` shows 00–23). An unparseable `value` renders as empty.
|
|
156
|
+
- `min-time` / `max-time` are `"HH:mm"` (inclusive) and are compared at minute precision even with `seconds`. Hours with no in-range step minute and AM/PM periods with no enabled hour are disabled; picking an hour snaps the draft minute to the nearest in-range step.
|
|
157
|
+
- Draft model: column clicks only update the draft; **OK** commits and fires `rel-change`; **Cancel**, `Escape` or an outside click discard it (and fire `rel-open-change` with `open: false`). The OK button is disabled until an hour is chosen; picking an hour with no minute defaults the minute to `00`; picking a minute or second first defaults the hour to the first enabled one.
|
|
158
|
+
- Two "now" behaviours: the footer **Now** link sets the draft to the current time snapped to `minute-step` (and to the nearest enabled hour) — you still press OK; the `N` shortcut / typed `n` / the "N → Now" chip commit the current time immediately, clamped into `min-time` / `max-time`.
|
|
159
|
+
- Typed entry is not limited to `minute-step`: `9:07` commits `09:07` even with `minute-step="15"`. Typing an empty string and committing behaves like the clear button (`rel-change` with `value: null`).
|
|
160
|
+
- `minute-step` outside 1–60 falls back to 1; the seconds column is always step 1.
|
|
161
|
+
- `invalid` is a non-deprecated alias of `error`; either flag applies error styling. The text below the field is `error-message`, else the typed-entry error, else `helper-text`.
|
|
162
|
+
- Panel widths are fixed per `size` (220 / 250 / 280px, border-box) and capped to the viewport; it flips above the field when there is no room below and shrinks (columns scroll) rather than covering the field. Footer buttons are always small per the Figma spec; OK is narrowed to 60px min-width.
|
|
163
|
+
- Setting `open` programmatically opens the panel and resets the draft from `value`; it does not fire `rel-open-change` (only user interaction does).
|
|
164
|
+
- `fullWidth` reflects as the lowercase `fullwidth` attribute; the host is `inline-block` with intrinsic width otherwise.
|