@reliability-design/web 1.4.5 → 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 -135
- 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 -103
- package/dist/components/rel-upload/README.md +220 -0
- package/dist/index.d.mts +1387 -350
- package/dist/index.d.ts +1387 -350
- package/dist/index.js +5863 -3600
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5864 -3592
- 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 +4 -3
- 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 -689
- package/dist/components/rel-avatar/rel-avatar.ts +0 -142
- package/dist/components/rel-badge/rel-badge.ts +0 -170
- 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 -519
- 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 -700
- 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 -472
- 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/index.ts +0 -1
- package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1237
- 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 -604
- 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 -535
- 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 -517
- package/dist/components/rel-pagination/index.ts +0 -1
- package/dist/components/rel-pagination/rel-pagination.ts +0 -509
- 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 -444
- package/dist/components/rel-progress/rel-progress.ts +0 -225
- package/dist/components/rel-radio/rel-radio.ts +0 -305
- package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1331
- 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 -213
- package/dist/components/rel-select/rel-select.ts +0 -1385
- package/dist/components/rel-sheet/rel-sheet.ts +0 -465
- package/dist/components/rel-sidebar/README.md +0 -209
- package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1185
- package/dist/components/rel-skeleton/rel-skeleton.ts +0 -134
- package/dist/components/rel-slider/rel-slider.ts +0 -670
- package/dist/components/rel-snackbar/rel-snackbar.ts +0 -325
- package/dist/components/rel-stepper/rel-stepper.ts +0 -565
- package/dist/components/rel-switch/rel-switch.ts +0 -197
- 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 -866
- package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1126
- package/dist/components/rel-toast/rel-toast.ts +0 -204
- package/dist/components/rel-tooltip/rel-tooltip.ts +0 -190
- 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 -943
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# rel-range-picker
|
|
2
|
+
|
|
3
|
+
`<rel-range-picker>` is the date-range form field of the Reliability Design System (Figma "Date Range Picker"). It is a text field you can type a "from → to" range into, backed by a two-pane panel: quick-select presets with single-key shortcuts and From / To readouts on the left, a month grid with live range preview on the right, and a Reset / Cancel / Apply footer. The grid and presets edit a draft; only Apply (or typed entry / clear) commits `from`/`to` as ISO `YYYY-MM-DD` strings. Use it for filters and reports that need a start and an end. For a single date use `<rel-date-picker>`, for an always-visible grid use `<rel-calendar>`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<!-- Basic -->
|
|
9
|
+
<rel-range-picker placeholder="Select date range"></rel-range-picker>
|
|
10
|
+
|
|
11
|
+
<!-- Preselected range with a clear icon -->
|
|
12
|
+
<rel-range-picker from="2026-01-05" to="2026-01-09" clearable></rel-range-picker>
|
|
13
|
+
|
|
14
|
+
<!-- Bounded, Monday-first grid -->
|
|
15
|
+
<rel-range-picker min-date="2026-01-01" max-date="2026-12-31" week-start="mon"></rel-range-picker>
|
|
16
|
+
|
|
17
|
+
<!-- Centred popup with a dimmed backdrop instead of an anchored popover -->
|
|
18
|
+
<rel-range-picker mode="popup"></rel-range-picker>
|
|
19
|
+
|
|
20
|
+
<!-- Icon-only trigger (no typed entry, no clear icon) -->
|
|
21
|
+
<rel-range-picker trigger-variant="icon" placeholder="Filter by date"></rel-range-picker>
|
|
22
|
+
|
|
23
|
+
<!-- Sizing the host: explicit width, or fill the parent -->
|
|
24
|
+
<rel-range-picker width="320px" min-width="240px"></rel-range-picker>
|
|
25
|
+
<rel-range-picker fullwidth></rel-range-picker>
|
|
26
|
+
|
|
27
|
+
<!-- Disabled -->
|
|
28
|
+
<rel-range-picker from="2026-01-05" to="2026-01-09" disabled></rel-range-picker>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
const picker = document.querySelector("rel-range-picker");
|
|
33
|
+
|
|
34
|
+
picker.addEventListener("rel-change", (e) => {
|
|
35
|
+
e.detail.from; // "2026-01-05" ("" when cleared)
|
|
36
|
+
e.detail.to; // "2026-01-09"
|
|
37
|
+
e.detail.label; // "01/05/2026 → 01/09/2026"
|
|
38
|
+
});
|
|
39
|
+
picker.addEventListener("rel-open-change", (e) => e.detail.open);
|
|
40
|
+
picker.addEventListener("rel-blur", () => {/* run validation */});
|
|
41
|
+
|
|
42
|
+
picker.displayLabel; // same formatted label for the committed range
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Typed entry
|
|
46
|
+
|
|
47
|
+
With the default trigger the field is editable and commits on Enter or when focus leaves the component. Two dates are separated by `→`, `..`, a spaced `-`, or the word `to` (`2026-01-05 to 2026-01-09`, `21/7 .. 28/7`, `t - t+7`); a single date gives a one-day range and a reversed pair is normalised so `from` ≤ `to`. Each side accepts everything `rel-date-picker` parses — ISO, numeric, month names, partial `21/7` / `21`, and the `t` / `today` / `t±N` shortcuts — with ambiguous `a/b` always read as month/day, matching the `MM/DD/YYYY` display. Unparseable text shows "Invalid date range" and a date outside `min-date`/`max-date` shows "Date not available"; the text stays for correction and the committed range is untouched. Escape reverts the text; committing an empty field clears the range like the clear icon.
|
|
48
|
+
|
|
49
|
+
### Presets and shortcuts
|
|
50
|
+
|
|
51
|
+
The left pane lists Today (`T`), Tomorrow (`M`), Yesterday (`Y`), This Week (`W`), Next Week (`N`), Next 7 Days (`7`) and Next 30 Days (`3`), one per row. Weeks in the presets always run Sunday–Saturday regardless of `week-start`. While the panel is open, pressing the key (no modifier, focus not in an editable field) selects that preset; a preset only fills the draft — Apply still commits it. Following Figma's ".Suggested Range" row, the key is not printed on the row: each preset carries it as `aria-keyshortcuts` and a `title` tooltip instead.
|
|
52
|
+
|
|
53
|
+
> **Changed in this release.** The `Before Today` preset (`B`, `1970-01-01` → yesterday) has been replaced by `Yesterday` (`Y`, yesterday → yesterday) to match Figma. The `B` key no longer selects anything; use typed entry (for example `1970-01-01 to t-1`) if you need the old open-ended range.
|
|
54
|
+
|
|
55
|
+
<!-- readme-gen:start -->
|
|
56
|
+
|
|
57
|
+
<!-- Generated from rel-range-picker.ts — do not edit; run readme-generate.mjs -->
|
|
58
|
+
|
|
59
|
+
## API
|
|
60
|
+
|
|
61
|
+
### Attributes / Properties
|
|
62
|
+
|
|
63
|
+
| Property | Attribute | Type | Default | Description |
|
|
64
|
+
| --- | --- | --- | --- | --- |
|
|
65
|
+
| `from` | `from` | `string` | `""` | Committed range start as an ISO `YYYY-MM-DD` string; empty string when no range is set. |
|
|
66
|
+
| `to` | `to` | `string` | `""` | Committed range end as an ISO `YYYY-MM-DD` string; empty string when no range is set. Always ≥ `from`. |
|
|
67
|
+
| `locale` | `locale` | `string` | `"en-US"` | Locale used to match month names in typed input; the visible trigger text and calendar labels are always `en-US` (`MM/DD/YYYY`). |
|
|
68
|
+
| `weekStart` | `week-start` | `"mon" \| "sun"` | `"sun"` | First column of the calendar grid: `"sun"` (default) or `"mon"`. Presets always compute weeks Sunday–Saturday. |
|
|
69
|
+
| `minDate` | `min-date` | `string` | `""` | Earliest selectable date (ISO `YYYY-MM-DD`); earlier days are disabled and typed ranges starting before it are rejected. |
|
|
70
|
+
| `maxDate` | `max-date` | `string` | `""` | Latest selectable date (ISO `YYYY-MM-DD`); later days are disabled and typed ranges ending after it are rejected. |
|
|
71
|
+
| `disabled` | `disabled` | `boolean` | `false` | Disables the trigger, the icons and the panel controls; the host dims to 60% opacity. Reflected. |
|
|
72
|
+
| `open` | `open` | `boolean` | `false` | Whether the panel is open. Setting it directly shows/hides the panel but does not seed the draft from `from`/`to` or fire `rel-open-change` — user interaction does both. Reflected. |
|
|
73
|
+
| `mode` | `mode` | `"popover" \| "popup"` | `"popover"` | `popover` anchors the panel below the trigger; `popup` centres it in the viewport behind a dimmed backdrop (part `overlay`). |
|
|
74
|
+
| `width` | `width` | `string` | `""` | CSS width applied to the host (any CSS length, e.g. `320px`); empty leaves the intrinsic width. |
|
|
75
|
+
| `minWidth` | `min-width` | `string` | `""` | CSS `min-width` applied to the host. |
|
|
76
|
+
| `maxWidth` | `max-width` | `string` | `""` | CSS `max-width` applied to the host. |
|
|
77
|
+
| `height` | `height` | `string` | `""` | CSS height applied to the host. |
|
|
78
|
+
| `minHeight` | `min-height` | `string` | `""` | CSS `min-height` applied to the host. |
|
|
79
|
+
| `maxHeight` | `max-height` | `string` | `""` | CSS `max-height` applied to the host. |
|
|
80
|
+
| `placeholder` | `placeholder` | `string` | `"Select date range"` | Placeholder shown in the empty field; also the accessible name of the input (and of the icon trigger while no range is set). |
|
|
81
|
+
| `triggerVariant` | `trigger-variant` | `"default" \| "icon"` | `"default"` | `default` renders the text field; `icon` renders a single calendar icon button instead (no typed entry, no clear button, parts `trigger`/`value` absent). |
|
|
82
|
+
| `clearable` | `clearable` | `boolean` | `false` | Shows a clear (×) icon while a range is set; clearing fires `rel-change` with empty `from`/`to`. Only with the default trigger. |
|
|
83
|
+
| `fullWidth` | `fullwidth` | `boolean` | `false` | Stretches the host to fill its parent's width (attribute `fullwidth`), mirroring rel-time-picker / rel-date-picker. Off by default so the existing intrinsic-width (`inline-block`) rendering is unchanged. Reflected. |
|
|
84
|
+
|
|
85
|
+
### Public fields / accessors
|
|
86
|
+
|
|
87
|
+
| Name | Type | Description |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| `displayLabel` | `string` | Formatted "MM/DD/YYYY → MM/DD/YYYY" (or single date / "") for the current committed `from`/`to`. |
|
|
90
|
+
|
|
91
|
+
## Events
|
|
92
|
+
|
|
93
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
94
|
+
| --- | --- | --- | --- |
|
|
95
|
+
| `rel-blur` | — | bubbles / composed | Fired when the text input loses focus (before any typed text is committed). No detail. |
|
|
96
|
+
| `rel-change` | `{ from: this.from, to: this.to, label: this.displayLabel } / { from: "", to: "", label: "" }` | bubbles / composed | Fired when the committed range changes — Apply, typed entry, or clear. Detail: `{ from: string, to: string, label: string }` (ISO dates and the formatted `MM/DD/YYYY → MM/DD/YYYY` label; all empty strings when cleared). |
|
|
97
|
+
| `rel-open-change` | `{ open: true } / { open: false }` | bubbles / composed | Fired when the panel opens or closes (open, Cancel, Escape, outside click, Apply). Detail: `{ open: boolean }`. |
|
|
98
|
+
|
|
99
|
+
## Slots
|
|
100
|
+
|
|
101
|
+
| Slot | Description |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| — | This element has no slots. |
|
|
104
|
+
|
|
105
|
+
## CSS Parts
|
|
106
|
+
|
|
107
|
+
| Part | Description |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| `trigger` | The field box that wraps the text input and the clear/calendar icons (default trigger variant only) |
|
|
110
|
+
| `value` | The editable text input inside the trigger |
|
|
111
|
+
| `overlay` | The full-screen backdrop rendered in `mode="popup"` while open |
|
|
112
|
+
| `panel` | The floating panel (`role="dialog"`) holding presets and calendar |
|
|
113
|
+
| `list` | The preset column and the day grid |
|
|
114
|
+
| `option` | Each quick-select preset button |
|
|
115
|
+
| `action` | The previous-month and next-month buttons |
|
|
116
|
+
| `footer` | The Reset / Cancel / Apply button row |
|
|
117
|
+
|
|
118
|
+
<!-- readme-gen:end -->
|
|
119
|
+
|
|
120
|
+
## Accessibility
|
|
121
|
+
|
|
122
|
+
- Default trigger: the input is a `role="combobox"` with `aria-haspopup="dialog"`, `aria-expanded`, `aria-controls` pointing at the panel, `aria-label` = `placeholder`, `aria-invalid` while typed text is in error and `aria-describedby` pointing at the error line. The icon buttons are labelled "Clear date range" and "Open date range panel" (with `aria-expanded`).
|
|
123
|
+
- Icon trigger (`trigger-variant="icon"`): a `<rel-button>` with `aria-haspopup="dialog"`, `aria-expanded`, and an `aria-label` of the current range label or the `placeholder`.
|
|
124
|
+
- The panel is a `role="dialog"` named "Select date range". Presets sit in a `role="group"` named "Quick date selections"; each preset button carries `aria-pressed` plus an `aria-keyshortcuts` naming its single-key shortcut. The From / To readouts are groups named "From date" / "To date". Focus is not trapped inside the panel.
|
|
125
|
+
- The calendar is a `role="grid"` named "Select date range" with `role="columnheader"` weekday names, `role="row"` weeks and `role="gridcell"` days whose `aria-label` is the full long date plus ", range start" / ", range end" for the endpoints; `aria-selected` is true for the endpoints and every day between them, `aria-disabled` marks unavailable days. Exactly one cell is a Tab stop (last arrowed date → draft start → today → first enabled day).
|
|
126
|
+
- Focus: opening the panel does not move focus; Escape closes it and returns focus to the input. Keyboard navigation in the grid previews the range exactly like mouse hover does.
|
|
127
|
+
- Screen readers hear "<Month> <Year>" after every month change and "From date MM/DD/YYYY" / "To date MM/DD/YYYY" when an endpoint is chosen, through the shared `announce()` region (`utils/announce.ts`).
|
|
128
|
+
|
|
129
|
+
| Key (in the field) | Action |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| Enter | Nothing typed: open the panel. Text typed: commit it |
|
|
132
|
+
| ArrowDown | Open the panel |
|
|
133
|
+
| Escape | Revert uncommitted text; close the panel and refocus the input |
|
|
134
|
+
|
|
135
|
+
| Key (panel open, focus outside an editable field) | Action |
|
|
136
|
+
| --- | --- |
|
|
137
|
+
| T / M / Y / W / N / 7 / 3 | Select the matching preset into the draft |
|
|
138
|
+
| Escape | Cancel: discard the draft, close, refocus the input |
|
|
139
|
+
|
|
140
|
+
| Key (in the grid) | Action |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| ArrowLeft / ArrowRight | Previous / next day (switches month at the edge) |
|
|
143
|
+
| ArrowUp / ArrowDown | Same weekday one week earlier / later |
|
|
144
|
+
| Home / End | First / last day of the row, honouring `week-start` |
|
|
145
|
+
| PageUp / PageDown | Same day previous / next month |
|
|
146
|
+
| Shift + PageUp / Shift + PageDown | Same day previous / next year |
|
|
147
|
+
| Enter / Space | Pick the day as range start, then as range end |
|
|
148
|
+
|
|
149
|
+
## Notes / Edge Cases
|
|
150
|
+
|
|
151
|
+
- Draft vs committed: grid picks and presets only change the draft shown in the From / To readouts. Apply commits it (fires `rel-change`, closes); Cancel, Escape, an outside click, or the popup backdrop discard it; Reset empties the draft. Reset followed by Apply clears the committed range (`rel-change` with empty strings) — Apply is disabled only when both the draft and the committed range are empty.
|
|
152
|
+
- Second-click ordering: picking a day before the current draft start makes it the new start and the old start the end.
|
|
153
|
+
- Setting `open = true` from code shows the panel but neither seeds the draft from `from`/`to` nor fires `rel-open-change`; only user interaction does both.
|
|
154
|
+
- The trigger text, From / To readouts, month names and day labels are always rendered in `en-US` (`MM/DD/YYYY`); `locale` only affects month-name matching in typed input.
|
|
155
|
+
- Leading and trailing cells of adjacent months are visible but never selectable, and render at 40% label opacity (Figma "Day of a week = Other Month"). Today gets a 1 px brand ring; weekend cells render at 70% opacity (Figma "Day of a week = Weekend") unless they are range endpoints.
|
|
156
|
+
- Range styling follows Figma ".Date Range Days": the selected run is an `elevated-1` band across the full cell, rounded at the two ends (a one-day range is a single rounded pill), and the two endpoints are `inverse-2` discs with inverse semibold labels. Days between the endpoints keep their normal label on the band.
|
|
157
|
+
- The panel (and the popup backdrop) is promoted to the browser top layer (`popover="manual"`), so it works inside `rel-modal` / `rel-drawer` and above transformed or `overflow: hidden` ancestors. In `popover` mode it anchors below the host, flips above when there is no room, stays 8 px inside the viewport and repositions on scroll/resize; in `popup` mode it is fixed-centred behind a 40% black backdrop (part `overlay`) whose click cancels. It never exceeds the viewport and scrolls internally.
|
|
158
|
+
- `width`, `min-width`, `max-width`, `height`, `min-height` and `max-height` are copied to the host's inline style on every update, so they override stylesheet rules on the host.
|
|
159
|
+
- The icon trigger has no typed entry, no clear icon and no error line; parts `trigger` and `value` are not rendered in that variant.
|
|
160
|
+
- There is no helper-text or external error API; the only text below the field is the typed-entry error.
|
|
161
|
+
- The footer buttons are `<rel-button>` instances — `ghost` for Reset, `secondary` for Cancel and `primary tone="brand"` for Apply — and the icon trigger uses `<rel-button>` with `<rel-icon name="calendar-range">`, so `@reliability-design/icons` is loaded by this component.
|
|
162
|
+
- The host is `inline-block` with an intrinsic width by default; `fullwidth` switches it to a block that fills the parent.
|
|
@@ -1,140 +1,199 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<rel-resizable-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
</rel-resizable-panel>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
</rel-resizable-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
1
|
+
# rel-resizable
|
|
2
|
+
|
|
3
|
+
`rel-resizable` is a three-element split-pane system: `<rel-resizable-group>` lays out its direct-child `<rel-resizable-panel>`s along one axis (`direction="horizontal"` side by side, `"vertical"` stacked) and lets the user drag or keyboard-nudge the `<rel-resizable-handle>` between two neighbours to trade percentage size between them, within each panel's `minsize` / `maxsize`. Use it for editor / preview splits, sidebar + content layouts and inspector panes where the user should control the proportions. It has no Figma component of its own; it follows the WAI-ARIA window-splitter pattern. It is not a general grid or an accordion — every panel stays visible and cannot be collapsed below its `minsize`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<!-- Horizontal split (default direction) -->
|
|
9
|
+
<rel-resizable-group direction="horizontal" style="height: 320px;">
|
|
10
|
+
<rel-resizable-panel defaultsize="50">
|
|
11
|
+
<h3>Left</h3>
|
|
12
|
+
</rel-resizable-panel>
|
|
13
|
+
<rel-resizable-handle></rel-resizable-handle>
|
|
14
|
+
<rel-resizable-panel defaultsize="50">
|
|
15
|
+
<h3>Right</h3>
|
|
16
|
+
</rel-resizable-panel>
|
|
17
|
+
</rel-resizable-group>
|
|
18
|
+
|
|
19
|
+
<!-- Vertical split: the group needs an explicit height to divide -->
|
|
20
|
+
<rel-resizable-group direction="vertical" style="height: 480px;">
|
|
21
|
+
<rel-resizable-panel defaultsize="40">Top</rel-resizable-panel>
|
|
22
|
+
<rel-resizable-handle></rel-resizable-handle>
|
|
23
|
+
<rel-resizable-panel defaultsize="60">Bottom</rel-resizable-panel>
|
|
24
|
+
</rel-resizable-group>
|
|
25
|
+
|
|
26
|
+
<!-- Constraints: percentages of the group -->
|
|
27
|
+
<rel-resizable-group style="height: 320px;">
|
|
28
|
+
<rel-resizable-panel defaultsize="30" minsize="20" maxsize="50">Sidebar</rel-resizable-panel>
|
|
29
|
+
<rel-resizable-handle></rel-resizable-handle>
|
|
30
|
+
<rel-resizable-panel defaultsize="70">Main</rel-resizable-panel>
|
|
31
|
+
</rel-resizable-group>
|
|
32
|
+
|
|
33
|
+
<!-- Nested: a vertical group inside the right panel of a horizontal one -->
|
|
34
|
+
<rel-resizable-group direction="horizontal" style="height: 480px;">
|
|
35
|
+
<rel-resizable-panel defaultsize="33">Sidebar</rel-resizable-panel>
|
|
36
|
+
<rel-resizable-handle></rel-resizable-handle>
|
|
37
|
+
<rel-resizable-panel defaultsize="67">
|
|
38
|
+
<rel-resizable-group direction="vertical">
|
|
39
|
+
<rel-resizable-panel defaultsize="50">Editor</rel-resizable-panel>
|
|
40
|
+
<rel-resizable-handle></rel-resizable-handle>
|
|
41
|
+
<rel-resizable-panel defaultsize="50">Preview</rel-resizable-panel>
|
|
42
|
+
</rel-resizable-group>
|
|
43
|
+
</rel-resizable-panel>
|
|
44
|
+
</rel-resizable-group>
|
|
45
|
+
|
|
46
|
+
<!-- Listening for size changes -->
|
|
47
|
+
<rel-resizable-group id="split" style="height: 320px;">
|
|
48
|
+
<rel-resizable-panel>A</rel-resizable-panel>
|
|
49
|
+
<rel-resizable-handle></rel-resizable-handle>
|
|
50
|
+
<rel-resizable-panel>B</rel-resizable-panel>
|
|
51
|
+
</rel-resizable-group>
|
|
52
|
+
<script>
|
|
53
|
+
const split = document.getElementById('split');
|
|
54
|
+
// fires continuously while dragging
|
|
55
|
+
split.addEventListener('rel-resize', (e) => console.log(e.detail.sizes));
|
|
56
|
+
// fires once per drag, and after every keyboard step — good for persisting
|
|
57
|
+
split.addEventListener('rel-resize-end', (e) => localStorage.setItem('split', JSON.stringify(e.detail.sizes)));
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
<!-- readme-gen:start -->
|
|
62
|
+
|
|
63
|
+
<!-- Generated from rel-resizable-group.ts, rel-resizable-handle.ts, rel-resizable-panel.ts — do not edit; run readme-generate.mjs -->
|
|
64
|
+
|
|
65
|
+
## Elements
|
|
66
|
+
|
|
67
|
+
| Element | Class | Source |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `<rel-resizable-group>` | `RelResizableGroup` | `rel-resizable-group.ts` |
|
|
70
|
+
| `<rel-resizable-handle>` | `RelResizableHandle` | `rel-resizable-handle.ts` |
|
|
71
|
+
| `<rel-resizable-panel>` | `RelResizablePanel` | `rel-resizable-panel.ts` |
|
|
72
|
+
|
|
73
|
+
## API
|
|
74
|
+
|
|
75
|
+
### `<rel-resizable-group>`
|
|
76
|
+
|
|
77
|
+
#### Attributes / Properties
|
|
78
|
+
|
|
79
|
+
| Property | Attribute | Type | Default | Description |
|
|
80
|
+
| --- | --- | --- | --- | --- |
|
|
81
|
+
| `direction` | `direction` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout axis: `horizontal` places panels side by side and resizes widths, `vertical` stacks them and resizes heights; also pushed to every child handle's `orientation`. Reflected. |
|
|
82
|
+
|
|
83
|
+
### Events
|
|
84
|
+
|
|
85
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
86
|
+
| --- | --- | --- | --- |
|
|
87
|
+
| `rel-resize` | `{ direction: this.direction, sizes, }` | bubbles / composed | Fired continuously while a handle is dragged. Detail: `{ direction, sizes: number[] }` with one percentage per panel. |
|
|
88
|
+
| `rel-resize-end` | `{ direction: this.direction, sizes, }` | bubbles / composed | Fired once when a drag ends (pointerup) and after every keyboard resize step. Detail: `{ direction, sizes: number[] }` with one percentage per panel. |
|
|
89
|
+
|
|
90
|
+
### Slots
|
|
91
|
+
|
|
92
|
+
| Slot | Description |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| (default) | The panels and handles, as direct children in display order (panel, handle, panel, …) |
|
|
95
|
+
|
|
96
|
+
### CSS Parts
|
|
97
|
+
|
|
98
|
+
| Part | Description |
|
|
99
|
+
| --- | --- |
|
|
100
|
+
| — | None exposed. |
|
|
101
|
+
|
|
102
|
+
### `<rel-resizable-handle>`
|
|
103
|
+
|
|
104
|
+
#### Attributes / Properties
|
|
105
|
+
|
|
106
|
+
| Property | Attribute | Type | Default | Description |
|
|
107
|
+
| --- | --- | --- | --- | --- |
|
|
108
|
+
| `orientation` | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Axis the handle separates: `horizontal` = 8px-wide vertical bar with `col-resize` cursor, `vertical` = 8px-tall bar with `row-resize`; set automatically from the parent group's `direction` on first render and mirrored to `aria-orientation`. Reflected. |
|
|
109
|
+
|
|
110
|
+
#### Public fields / accessors
|
|
111
|
+
|
|
112
|
+
| Name | Type | Description |
|
|
113
|
+
| --- | --- | --- |
|
|
114
|
+
| `splitValue` | `number` | Current split of the two neighbouring panels as a percentage 0–100 (share held by the leading panel); read-only — the parent group updates it and mirrors it to `aria-valuenow`. |
|
|
115
|
+
|
|
116
|
+
### Events
|
|
117
|
+
|
|
118
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
119
|
+
| --- | --- | --- | --- |
|
|
120
|
+
| — | — | — | This element emits no custom events. |
|
|
121
|
+
|
|
122
|
+
### Slots
|
|
123
|
+
|
|
124
|
+
| Slot | Description |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| — | This element has no slots. |
|
|
127
|
+
|
|
128
|
+
### CSS Parts
|
|
129
|
+
|
|
130
|
+
| Part | Description |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| — | None exposed. |
|
|
133
|
+
|
|
134
|
+
### `<rel-resizable-panel>`
|
|
135
|
+
|
|
136
|
+
#### Attributes / Properties
|
|
137
|
+
|
|
138
|
+
| Property | Attribute | Type | Default | Description |
|
|
139
|
+
| --- | --- | --- | --- | --- |
|
|
140
|
+
| `defaultSize` | `defaultsize` | `number` | `undefined` | Initial size as a percentage of the group; panels without one share whatever is left of 100%, then all sizes are normalised to sum to 100. Attribute is `defaultsize`. |
|
|
141
|
+
| `minSize` | `minsize` | `number` | `10` | Smallest size (percentage) the panel can be resized to. Attribute is `minsize`. |
|
|
142
|
+
| `maxSize` | `maxsize` | `number` | `90` | Largest size (percentage) the panel can be resized to. Attribute is `maxsize`. |
|
|
143
|
+
|
|
144
|
+
#### Public fields / accessors
|
|
145
|
+
|
|
146
|
+
| Name | Type | Description |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `currentSize` | `number` | Current size as a percentage of the group (also written to the host's `flex-basis`); read-only — the parent group updates it on every resize. |
|
|
149
|
+
|
|
150
|
+
### Events
|
|
151
|
+
|
|
152
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
153
|
+
| --- | --- | --- | --- |
|
|
154
|
+
| — | — | — | This element emits no custom events. |
|
|
155
|
+
|
|
156
|
+
### Slots
|
|
157
|
+
|
|
158
|
+
| Slot | Description |
|
|
159
|
+
| --- | --- |
|
|
160
|
+
| (default) | The panel's content; slotted `h1`–`h4` get the headings-md role |
|
|
161
|
+
|
|
162
|
+
### CSS Parts
|
|
163
|
+
|
|
164
|
+
| Part | Description |
|
|
165
|
+
| --- | --- |
|
|
166
|
+
| — | None exposed. |
|
|
167
|
+
|
|
168
|
+
<!-- readme-gen:end -->
|
|
169
|
+
|
|
170
|
+
## Accessibility
|
|
171
|
+
|
|
172
|
+
- Each `<rel-resizable-handle>` makes itself focusable (`tabindex="0"`) and takes `role="separator"` with `aria-orientation` mirroring its `orientation`. The group writes `aria-valuenow` (the leading panel's share of the pair, rounded, 0–100), `aria-valuemin="0"` and `aria-valuemax="100"` on first render and after every resize, so assistive technology can read the current split before and after any interaction.
|
|
173
|
+
- Handles have no accessible name of their own; when several handles are on a page add `aria-label` to each (e.g. `aria-label="Resize sidebar"`).
|
|
174
|
+
- The group and the panels set no roles and are not focusable; panels are `overflow: auto`, so their content scrolls natively and any interactive content inside keeps its own tab order.
|
|
175
|
+
- A focused handle shows a 2px focus ring (`--rel-border-focus`) and a lighter background; hover and drag states change the background and grab-bar colours only.
|
|
176
|
+
- Keyboard resizing (handled by the group, on a focused handle):
|
|
177
|
+
|
|
178
|
+
| Key | Direction | Action |
|
|
179
|
+
| --- | --- | --- |
|
|
180
|
+
| `ArrowLeft` / `ArrowRight` | `horizontal` | Shrink / grow the leading panel by 2% (of the group). |
|
|
181
|
+
| `ArrowUp` / `ArrowDown` | `vertical` | Shrink / grow the leading panel by 2%. |
|
|
182
|
+
| `Shift` + arrow | either | Same, in 5% steps. |
|
|
183
|
+
| `Home` | either | Collapse the leading panel to its `minsize` (as far as the neighbour allows). |
|
|
184
|
+
| `End` | either | Grow the leading panel to its `maxsize` (as far as the neighbour allows). |
|
|
185
|
+
|
|
186
|
+
- Every keyboard step dispatches `rel-resize-end` (not `rel-resize`).
|
|
187
|
+
- Motion: the handle's background transitions are removed under `prefers-reduced-motion: reduce`.
|
|
188
|
+
|
|
189
|
+
## Notes / Edge Cases
|
|
190
|
+
|
|
191
|
+
- Panels and handles must be **direct children** of the group (`:scope > rel-resizable-panel`), alternating panel / handle / panel. A handle at the start or end, or two handles in a row, has no valid pair and does nothing.
|
|
192
|
+
- Layout is computed once in `firstUpdated`: panels without `defaultsize` share whatever remains of 100%, then all sizes are normalised to sum to exactly 100 (so `defaultsize="50"` + `defaultsize="70"` ends up as 41.7 / 58.3). Panels or handles added or removed later are **not** observed; re-attach the group to re-initialise.
|
|
193
|
+
- Sizes are always percentages of the group, applied as `flex-basis` with `flex-grow: 0; flex-shrink: 0`. The group itself is `display: flex; width: 100%; height: 100%`, so a `vertical` group needs an ancestor with a definite height or it has nothing to divide.
|
|
194
|
+
- Only the two panels adjacent to the dragged handle change; each is clamped to its own `minsize` / `maxsize`, then the pair is rescaled so their combined share stays constant. A panel therefore cannot go below its `minsize` (default 10) and never collapses to 0 unless you set `minsize="0"`.
|
|
195
|
+
- Attribute names are lowercase with no hyphen: `defaultsize`, `minsize`, `maxsize` (properties `defaultSize`, `minSize`, `maxSize`).
|
|
196
|
+
- While a drag is in progress the active handle carries a `data-dragging` attribute (the group sets and removes it) — the only hook for drag-specific styling from outside.
|
|
197
|
+
- Each handle's `orientation` is overwritten from the group's `direction` on first render; set `direction` on the group, not `orientation` on the handles.
|
|
198
|
+
- `rel-resize` fires on every pointer move during a drag; throttle any expensive listener. `rel-resize-end` fires once on pointer-up and after each keyboard step; both carry `{ direction, sizes }` where `sizes[i]` is panel *i*'s current percentage.
|
|
199
|
+
- Nested groups work because the inner group is ordinary panel content; pointer events are handled by the nearest group whose handle is in the event's composed path.
|