@reliability-design/web 1.4.6 → 1.4.8
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 +246 -49
- package/dist/components/rel-accordion/README.md +133 -132
- package/dist/components/rel-alert/README.md +145 -141
- package/dist/components/rel-autocomplete/README.md +172 -61
- package/dist/components/rel-avatar/README.md +118 -130
- package/dist/components/rel-badge/README.md +97 -93
- package/dist/components/rel-breadcrumb/README.md +96 -102
- package/dist/components/rel-button/README.md +190 -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 +186 -166
- package/dist/components/rel-checkbox/README.md +96 -75
- package/dist/components/rel-chip/README.md +138 -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 +88 -100
- package/dist/components/rel-drawer/README.md +187 -200
- package/dist/components/rel-kbd/README.md +141 -151
- package/dist/components/rel-layout/README.md +34 -0
- package/dist/components/rel-menu/README.md +180 -151
- package/dist/components/rel-menubar/README.md +218 -329
- package/dist/components/rel-otp/README.md +171 -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 +165 -0
- package/dist/components/rel-resizable/README.md +199 -140
- package/dist/components/rel-segmented-button/README.md +156 -141
- package/dist/components/rel-select/README.md +156 -93
- package/dist/components/rel-sheet/README.md +168 -224
- package/dist/components/rel-skeleton/README.md +104 -0
- package/dist/components/rel-slider/README.md +131 -135
- package/dist/components/rel-snackbar/README.md +168 -134
- package/dist/components/rel-stepper/README.md +162 -160
- package/dist/components/rel-switch/README.md +117 -102
- package/dist/components/rel-tab/README.md +173 -163
- package/dist/components/rel-textfield/README.md +176 -69
- package/dist/components/rel-time-picker/README.md +122 -157
- package/dist/components/rel-toast/README.md +165 -148
- package/dist/components/rel-tooltip/README.md +119 -111
- package/dist/components/rel-upload/README.md +220 -0
- package/dist/index.d.mts +1726 -447
- package/dist/index.d.ts +1726 -447
- package/dist/index.js +13715 -10870
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14018 -11163
- package/dist/index.mjs.map +1 -1
- package/dist/styles/focus-ring.ts +84 -0
- package/dist/styles/vars.css +892 -866
- package/dist/{vars-XNMTSRVN.css → vars-DXX6QOAG.css} +892 -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,130 +1,190 @@
|
|
|
1
|
-
# rel-button
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
```html
|
|
8
|
-
<!--
|
|
9
|
-
<rel-button variant="
|
|
10
|
-
<rel-button variant="
|
|
11
|
-
<rel-button variant="
|
|
12
|
-
<rel-button variant="
|
|
13
|
-
<rel-button variant="
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<!-- Tones (
|
|
19
|
-
<rel-button variant="primary" tone="
|
|
20
|
-
<rel-button variant="primary" tone="
|
|
21
|
-
<rel-button variant="primary" tone="
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<rel-button size="
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<rel-button border="
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<rel-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<rel-button
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
</
|
|
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
|
-
|
|
1
|
+
# rel-button
|
|
2
|
+
|
|
3
|
+
Action button implementing the Figma "Button" component: a native `<button>` with the Figma **Style** (`variant`), **Tone** (`tone`) and **Size** axes, an independent **Icon Only** mode, a **Loading** state and an optional corner badge. Use it for every clickable action (submit, confirm, open, delete). Do not use it for navigation to another page — use a link instead.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<!-- Styles (Figma "Style") -->
|
|
9
|
+
<rel-button variant="primary">Primary</rel-button>
|
|
10
|
+
<rel-button variant="secondary">Secondary</rel-button>
|
|
11
|
+
<rel-button variant="ghost">Ghost</rel-button>
|
|
12
|
+
<rel-button variant="link">Link style</rel-button>
|
|
13
|
+
<rel-button variant="default">Neutral fill</rel-button>
|
|
14
|
+
<div style="background: #1f2937; padding: 8px;">
|
|
15
|
+
<rel-button variant="static">Static (on dark surfaces)</rel-button>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<!-- Tones (Figma "Tone") -->
|
|
19
|
+
<rel-button variant="primary" tone="brand">Save</rel-button>
|
|
20
|
+
<rel-button variant="primary" tone="neutral">Cancel</rel-button>
|
|
21
|
+
<rel-button variant="primary" tone="destructive">Delete</rel-button>
|
|
22
|
+
<rel-button variant="secondary" tone="destructive">Remove</rel-button>
|
|
23
|
+
<rel-button variant="ghost" tone="destructive">Discard</rel-button>
|
|
24
|
+
|
|
25
|
+
<!-- Sizes: 32 / 40 / 48px -->
|
|
26
|
+
<rel-button size="small">Small</rel-button>
|
|
27
|
+
<rel-button size="medium">Medium</rel-button>
|
|
28
|
+
<rel-button size="large">Large</rel-button>
|
|
29
|
+
|
|
30
|
+
<!-- Corner radius -->
|
|
31
|
+
<rel-button border="corner-radius">Pill</rel-button>
|
|
32
|
+
<rel-button border="small-corner-radius">Small radius</rel-button>
|
|
33
|
+
<rel-button border="no-corner-radius">Square</rel-button>
|
|
34
|
+
|
|
35
|
+
<!-- Icon + label, and icon-only (needs an accessible name) -->
|
|
36
|
+
<rel-button variant="primary">
|
|
37
|
+
<rel-icon name="plus"></rel-icon>
|
|
38
|
+
Add item
|
|
39
|
+
</rel-button>
|
|
40
|
+
<rel-button variant="secondary" icon-only aria-label="Settings">
|
|
41
|
+
<rel-icon name="settings"></rel-icon>
|
|
42
|
+
</rel-button>
|
|
43
|
+
<rel-button variant="ghost" icon-only size="small" aria-label="Close">
|
|
44
|
+
<rel-icon name="x"></rel-icon>
|
|
45
|
+
</rel-button>
|
|
46
|
+
|
|
47
|
+
<!-- States -->
|
|
48
|
+
<rel-button variant="primary" loading>Saving</rel-button>
|
|
49
|
+
<rel-button variant="primary" disabled>Unavailable</rel-button>
|
|
50
|
+
|
|
51
|
+
<!-- Corner badges -->
|
|
52
|
+
<rel-button variant="secondary" badge="3">Inbox</rel-button>
|
|
53
|
+
<rel-button variant="ghost" icon-only badge-dot aria-label="Notifications">
|
|
54
|
+
<rel-icon name="bell"></rel-icon>
|
|
55
|
+
</rel-button>
|
|
56
|
+
|
|
57
|
+
<!-- Listen for clicks (native click bubbles through the shadow root) -->
|
|
58
|
+
<rel-button id="save" variant="primary">Save</rel-button>
|
|
59
|
+
<script>
|
|
60
|
+
document.getElementById('save').addEventListener('click', () => {
|
|
61
|
+
console.log('saved');
|
|
62
|
+
});
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<!-- Per-instance minimum width -->
|
|
66
|
+
<rel-button variant="primary" style="--rel-button-min-width: 160px;">Wide</rel-button>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Deprecated aliases
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<!-- Legacy Style spellings — still rendered identically, prefer the canonical names -->
|
|
73
|
+
<rel-button variant="outline">Outline</rel-button> <!-- → variant="secondary" -->
|
|
74
|
+
<rel-button variant="text">Text</rel-button> <!-- → variant="ghost" -->
|
|
75
|
+
<rel-button variant="icon" aria-label="Settings"> <!-- → icon-only + a variant -->
|
|
76
|
+
<rel-icon name="settings"></rel-icon>
|
|
77
|
+
</rel-button>
|
|
78
|
+
|
|
79
|
+
<!-- Legacy Tone spellings — each logs once per page:
|
|
80
|
+
[rel-button] "tone="critical"" is deprecated and will be removed in 3.0 — use "tone="destructive"" instead. -->
|
|
81
|
+
<rel-button variant="primary" tone="critical">Delete</rel-button> <!-- → tone="destructive" -->
|
|
82
|
+
<rel-button variant="primary" tone="danger">Delete</rel-button> <!-- → tone="destructive" -->
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
<!-- readme-gen:start -->
|
|
86
|
+
|
|
87
|
+
<!-- Generated from rel-button.ts — do not edit; run readme-generate.mjs -->
|
|
88
|
+
|
|
89
|
+
## API
|
|
90
|
+
|
|
91
|
+
### Attributes / Properties
|
|
92
|
+
|
|
93
|
+
| Property | Attribute | Type | Default | Description |
|
|
94
|
+
| --- | --- | --- | --- | --- |
|
|
95
|
+
| `variant` | `variant` | `"default" \| "primary" \| "secondary" \| "text" \| "link" \| "icon" \| "static" \| "outline" \| "ghost"` | `"default"` | Style axis (Figma "Style"). Canonical: `default` (legacy neutral fill), `primary`, `secondary` (outlined), `ghost` (text-only), `link` (underlined inline text), `static` (transparent, static-light label for dark/colored surfaces). Deprecated aliases still accepted: `outline` = secondary, `text` = ghost, and `icon` (pre-2.0 40px circular icon button — use `icon-only` with a style instead). |
|
|
96
|
+
| `tone` | `tone` | `"default" \| "primary" \| "secondary" \| "critical" \| "success" \| "neutral" \| "brand" \| "danger" \| "destructive"` | `undefined` | Tone axis (Figma "Tone"). Canonical: `neutral` (= `default`), `brand` (= `primary`), `destructive`. Deprecated aliases `critical` and `danger` map to destructive and log a one-time console notice. `secondary` and `success` are legacy extras with no Figma counterpart (secondary only affects the legacy `icon` variant). Left UNSET it means `neutral`, except on `variant="primary"`, where it still means `brand` for one release — see `effectiveTone`. Write the tone explicitly and you always get what you wrote. |
|
|
97
|
+
| `iconOnly` | `icon-only` | `boolean` | `false` | Figma "Type=Icon Only": renders a square button (32/40/48px per `size`) of the current style and tone with no padding or min-width. Composes with every `variant`; slot a single `rel-icon` and set `aria-label`. Reflected. |
|
|
98
|
+
| `loading` | `loading` | `boolean` | `false` | Figma "State=Loading": replaces the label with a spinner (`indicator` part), sets `aria-busy`, and blocks pointer and programmatic clicks. The button keeps its width. Reflected. |
|
|
99
|
+
| `size` | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Figma "Size": `small` = 32px, `medium` = 40px, `large` = 48px height, with matching padding, typography and minimum width. |
|
|
100
|
+
| `border` | `border` | `"corner-radius" \| "small-corner-radius" \| "no-corner-radius"` | `"corner-radius"` | Corner treatment: `corner-radius` = fully rounded pill, `small-corner-radius` = small radius token, `no-corner-radius` = square corners. |
|
|
101
|
+
| `disabled` | `disabled` | `boolean` | `false` | Figma "State=Disabled": dims the button to 50% opacity, flattens filled styles to the disabled fill, shows a `not-allowed` cursor and swallows every click (including programmatic `.click()`). Reflected. |
|
|
102
|
+
| `ariaLabel` | `aria-label` | `string \| null` | `null` | Accessible name forwarded to the inner native `<button>`. Required for `icon-only` buttons, whose slotted icon has no visible text. |
|
|
103
|
+
| `badge` | `badge` | `string` | `""` | Text for a small `rel-badge` anchored to the top-right corner (e.g. "3", "999+"). Empty string renders no badge. Ignored when `badge-dot` is set. |
|
|
104
|
+
| `badgeDot` | `badge-dot` | `boolean` | `false` | Renders a small dot badge in the top-right corner instead of a numbered badge; takes precedence over `badge`. The dot is inset 2px from the corner so it lands on a circular icon button's edge. |
|
|
105
|
+
|
|
106
|
+
## Events
|
|
107
|
+
|
|
108
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
109
|
+
| --- | --- | --- | --- |
|
|
110
|
+
| — | — | — | This element emits no custom events. |
|
|
111
|
+
|
|
112
|
+
## Slots
|
|
113
|
+
|
|
114
|
+
| Slot | Description |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| (default) | Button content: label text, a `rel-icon`, or icon + text (kept on one line with the size's gap). |
|
|
117
|
+
|
|
118
|
+
## CSS Parts
|
|
119
|
+
|
|
120
|
+
| Part | Description |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `base` | The inner native `<button>` element (padding, min-width, fill, border, focus ring). |
|
|
123
|
+
| `indicator` | The loading spinner, rendered only while `loading` is set. |
|
|
124
|
+
|
|
125
|
+
## Tokens / CSS Variables
|
|
126
|
+
|
|
127
|
+
### Component hooks
|
|
128
|
+
|
|
129
|
+
Set these on the host (or an ancestor) to customise the element without touching design tokens.
|
|
130
|
+
|
|
131
|
+
| Custom property | Default | Description |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| `--rel-button-min-width` | `80px` | Overrides the per-size minimum width (Figma small/medium/large = 80/100/120px, ghost small = 56px). Ignored by `icon-only` and `link`. |
|
|
134
|
+
|
|
135
|
+
<!-- readme-gen:end -->
|
|
136
|
+
|
|
137
|
+
## Accessibility
|
|
138
|
+
|
|
139
|
+
- Renders a native `<button>` (the `base` part), so it is focusable, announced as a button and activated with the keyboard without extra work.
|
|
140
|
+
- `aria-disabled` mirrors `disabled`; `aria-busy` mirrors `loading`. The spinner is `aria-hidden`, and the label stays in the DOM (visually hidden) while loading, so the accessible name does not change.
|
|
141
|
+
- `aria-label` is forwarded to the inner button. Always set it on `icon-only` buttons and on the legacy `icon` variant — a slotted icon has no text.
|
|
142
|
+
- Disabled and loading buttons swallow clicks in the capture phase on the host, so `el.click()` and delegated listeners never fire.
|
|
143
|
+
|
|
144
|
+
| Key | Action |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `Tab` / `Shift+Tab` | Move focus to / from the button |
|
|
147
|
+
| `Enter` / `Space` | Activate (native button behaviour) |
|
|
148
|
+
|
|
149
|
+
Focus: `:focus-visible` shows the shared 2px focus outline plus inner/outer halo on every style except `link`, which shows a 2px focus-coloured underline bar and the hover label colour instead (still a visible indicator per WCAG 2.4.7). Pressing scales the button to 97%; the spinner slows to 2s under `prefers-reduced-motion: reduce`.
|
|
150
|
+
|
|
151
|
+
## Notes / Edge Cases
|
|
152
|
+
|
|
153
|
+
### The `variant="primary"` tone transition
|
|
154
|
+
|
|
155
|
+
Figma's `Style=Primary` is the **filled** style, and `Tone` picks its colour — so Primary + Neutral is the neutral fill and Primary + Brand is the brand fill. This component's `variant="primary"` historically meant *both* "filled" and "brand-coloured", which left the Figma-canonical Primary/Neutral cell unreachable by its own names.
|
|
156
|
+
|
|
157
|
+
That cell now works: **`variant="primary" tone="neutral"` renders the neutral fill.**
|
|
158
|
+
|
|
159
|
+
For one release there is a deliberate wrinkle, and it is worth knowing before you debug it:
|
|
160
|
+
|
|
161
|
+
| Markup | Renders | Why |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| `<rel-button>` | neutral fill | Unchanged. `variant` defaults to `default`, which is Figma's Primary/Neutral. |
|
|
164
|
+
| `<rel-button variant="primary">` | **brand** fill | Unset tone still means brand *here only*, so existing brand buttons do not silently turn neutral. Logs a one-time console notice. |
|
|
165
|
+
| `<rel-button variant="primary" tone="brand">` | brand fill | The explicit form. **Write this.** |
|
|
166
|
+
| `<rel-button variant="primary" tone="neutral">` | neutral fill | The Figma-canonical cell, now reachable. |
|
|
167
|
+
|
|
168
|
+
So for this release, writing the default value explicitly changes the result: `variant="primary"` alone and `variant="primary" tone="neutral"` render differently. Setting `tone` explicitly always gives you exactly what you wrote. A future major will make an unset tone mean `neutral` everywhere, matching every other style.
|
|
169
|
+
|
|
170
|
+
### Tone × Style matrix
|
|
171
|
+
|
|
172
|
+
Figma populates only part of the grid. Combinations outside it have no design-system definition and fall back to the style's neutral treatment:
|
|
173
|
+
|
|
174
|
+
| Tone | Primary | Secondary | Ghost | Link | Static |
|
|
175
|
+
| --- | --- | --- | --- | --- | --- |
|
|
176
|
+
| Neutral | yes | yes | yes | yes | yes |
|
|
177
|
+
| Brand | yes | — | — | — | — |
|
|
178
|
+
| Destructive | yes | yes | yes | yes | — |
|
|
179
|
+
|
|
180
|
+
`Link` additionally has no icon-only and no loading state in the design.
|
|
181
|
+
|
|
182
|
+
- **Events.** The element dispatches no custom events. The native `click` is `composed`, so a listener on `<rel-button>` (or an ancestor) receives exactly one event per activation — do not re-dispatch it.
|
|
183
|
+
- **Minimum widths** come from the Figma master: small/medium/large = 80/100/120px, static = 40/50/60px. `link` has no minimum, `icon-only` is a fixed square (32/40/48px) and the legacy `icon` variant is always a 40px circle regardless of `size`. Override per instance with `--rel-button-min-width`.
|
|
184
|
+
- **`border`** exposes `small-corner-radius` and `no-corner-radius`, which have no design-system backing — every one of Figma's 624 button nodes is fully rounded. They are a code-only extension, kept for existing layouts.
|
|
185
|
+
- **Legacy `icon` variant vs `icon-only`.** `variant="icon"` keeps its pre-2.0 look (40px circle, tone-driven fill, `tone="secondary"` gives it an outline) and ignores `size` and `border`. `icon-only` is an axis that composes with any style and size — prefer it.
|
|
186
|
+
- **`tone` on `secondary` / `ghost` / `link`** changes the label, border or text colour only; the fill stays on the surface. The destructive outline border is deliberately subtle at rest and only goes solid on hover/pressed, matching Figma.
|
|
187
|
+
- **`static`** is a neutral-only style meant for coloured or dark backgrounds; other tones have no static treatment.
|
|
188
|
+
- **`success`** is a legacy tone without a Figma counterpart; it renders a green fill/outline/ghost tint but is not part of the current spec.
|
|
189
|
+
- **Badges** render a small `rel-badge` positioned outside the button's box (numbered) or 2px inside the corner (dot); give the button room in tight layouts. `badge-dot` wins when both are set.
|
|
190
|
+
- **Disabled styling**: only filled styles (`default`, `primary`, `icon`) flatten to the neutral disabled fill; `secondary`, `ghost`, `link` and `static` keep their shape at 50% opacity so they still read as their own style.
|
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
# rel-calendar
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
-
|
|
1
|
+
# rel-calendar
|
|
2
|
+
|
|
3
|
+
`<rel-calendar>` is the inline, always-visible month calendar of the Reliability Design System (Figma "Calendar"). It renders one month as a 7-column grid with previous/next navigation, a today ring, dimmed weekends and adjacent-month days, `min`/`max` bounds and a custom disabled-day predicate, and lets the user select a single date. Use it when the calendar itself is the interface — a scheduling sidebar, an inline availability view. For a form field that opens a calendar in a popover use `<rel-date-picker>`; for a from/to range use `<rel-range-picker>`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<!-- Default: today's month, nothing selected -->
|
|
9
|
+
<rel-calendar></rel-calendar>
|
|
10
|
+
|
|
11
|
+
<!-- Preselected date (ISO YYYY-MM-DD); the grid opens on that month -->
|
|
12
|
+
<rel-calendar value="2026-01-16"></rel-calendar>
|
|
13
|
+
|
|
14
|
+
<!-- Bounded: days outside min/max render disabled -->
|
|
15
|
+
<rel-calendar min="2026-01-01" max="2026-12-31"></rel-calendar>
|
|
16
|
+
|
|
17
|
+
<!-- Monday-first week with German month and weekday names -->
|
|
18
|
+
<rel-calendar week-start="mon" locale="de-DE"></rel-calendar>
|
|
19
|
+
|
|
20
|
+
<!-- Disabled: every cell and both navigation buttons are inert -->
|
|
21
|
+
<rel-calendar value="2026-01-16" disabled></rel-calendar>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
const calendar = document.querySelector("rel-calendar");
|
|
26
|
+
|
|
27
|
+
// Disable individual days on top of min/max (property only — there is no attribute)
|
|
28
|
+
calendar.isDateDisabled = (date) => date.getDay() === 0 || date.getDay() === 6;
|
|
29
|
+
|
|
30
|
+
calendar.addEventListener("rel-change", (e) => {
|
|
31
|
+
e.detail.value; // "2026-01-16"
|
|
32
|
+
e.detail.date; // Date at local midnight
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
<!-- readme-gen:start -->
|
|
37
|
+
|
|
38
|
+
<!-- Generated from rel-calendar.ts — do not edit; run readme-generate.mjs -->
|
|
39
|
+
|
|
40
|
+
## API
|
|
41
|
+
|
|
42
|
+
### Attributes / Properties
|
|
43
|
+
|
|
44
|
+
| Property | Attribute | Type | Default | Description |
|
|
45
|
+
| --- | --- | --- | --- | --- |
|
|
46
|
+
| `value` | `value` | `string \| null` | `null` | Selected date as an ISO `YYYY-MM-DD` string, or `null` for no selection; setting it also moves the visible month. Reflected. |
|
|
47
|
+
| `min` | `min` | `string \| null` | `null` | Earliest selectable date (ISO `YYYY-MM-DD`); earlier days render disabled. |
|
|
48
|
+
| `max` | `max` | `string \| null` | `null` | Latest selectable date (ISO `YYYY-MM-DD`); later days render disabled. |
|
|
49
|
+
| `disabled` | `disabled` | `boolean` | `false` | Disables every day cell and the month navigation; the host dims to 40% opacity (Figma State=Disabled). Reflected. |
|
|
50
|
+
| `weekStart` | `week-start` | `"sun" \| "mon"` | `"sun"` | First column of the week grid: `"sun"` (default) or `"mon"`. |
|
|
51
|
+
| `locale` | `locale` | `string` | `"en-US"` | BCP 47 locale for the month name, weekday headers and day cell labels (via `Intl.DateTimeFormat`). |
|
|
52
|
+
|
|
53
|
+
### Public fields / accessors
|
|
54
|
+
|
|
55
|
+
| Name | Type | Description |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `isDateDisabled` | `(date: Date) => boolean` | Custom predicate that disables individual days (return `true` to disable); applied on top of `min`/`max`. Property only — assign it from JavaScript. |
|
|
58
|
+
|
|
59
|
+
## Events
|
|
60
|
+
|
|
61
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
62
|
+
| --- | --- | --- | --- |
|
|
63
|
+
| `rel-change` | `{ value: newValue, date: new Date(day.date), }` | bubbles / composed | Fired when the user selects a day. Detail: `{ value: string, date: Date }` — the ISO `YYYY-MM-DD` string and a local-midnight Date. |
|
|
64
|
+
|
|
65
|
+
## Slots
|
|
66
|
+
|
|
67
|
+
| Slot | Description |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| — | This element has no slots. |
|
|
70
|
+
|
|
71
|
+
## CSS Parts
|
|
72
|
+
|
|
73
|
+
| Part | Description |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `header` | Month navigation row (previous button, month/year label, next button) |
|
|
76
|
+
| `action` | The previous-month and next-month buttons |
|
|
77
|
+
| `label` | The month/year heading and each weekday column header |
|
|
78
|
+
| `list` | The weekday-header row and the day grid |
|
|
79
|
+
| `item` | Each day cell button |
|
|
80
|
+
|
|
81
|
+
<!-- readme-gen:end -->
|
|
82
|
+
|
|
83
|
+
## Accessibility
|
|
84
|
+
|
|
85
|
+
- The day area is a `role="grid"` named "<Month> <Year>" (e.g. "January 2026"); the weekday header row and each week are `role="row"`, weekday names are `role="columnheader"`.
|
|
86
|
+
- Every day is a native `<button role="gridcell">` whose `aria-label` is the full long date in `locale` ("Friday, January 16, 2026"), with `aria-selected` for the selected day, `aria-current="date"` on today, and the native `disabled` attribute for days outside `min`/`max`, rejected by `isDateDisabled`, or when the host is `disabled`.
|
|
87
|
+
- The navigation buttons are labelled "Previous month" / "Next month".
|
|
88
|
+
- Roving tabindex: exactly one cell is a Tab stop — the last cell the user arrowed to, else the selected day, else today, else the first enabled day of the month — so Tab can always re-enter the grid.
|
|
89
|
+
- After every month or year change (buttons, PageUp/PageDown, or arrowing past the edge of the month) the new "<Month> <Year>" is read to screen readers through the shared `announce()` live region (`utils/announce.ts`).
|
|
90
|
+
|
|
91
|
+
| Key | Action |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| ArrowLeft / ArrowRight | Focus the previous / next day (crossing into the adjacent month switches the view) |
|
|
94
|
+
| ArrowUp / ArrowDown | Focus the same weekday one week earlier / later |
|
|
95
|
+
| Home / End | Focus the first / last cell of the current row |
|
|
96
|
+
| PageUp / PageDown | Show the previous / next month |
|
|
97
|
+
| Shift + PageUp / Shift + PageDown | Show the previous / next year |
|
|
98
|
+
| Enter / Space | Select the focused day (fires `rel-change`) |
|
|
99
|
+
|
|
100
|
+
## Notes / Edge Cases
|
|
101
|
+
|
|
102
|
+
- `value`, `min` and `max` must be `YYYY-MM-DD`; any other string is ignored (no selection, view unchanged). Setting `value` moves the visible month; clearing it to `null` leaves the view where it is.
|
|
103
|
+
- The grid always renders six weeks (42 cells). The leading/trailing cells belong to the adjacent months and, unlike in `rel-date-picker`, they are selectable (subject to `min`/`max`/`isDateDisabled`); picking one fires `rel-change` and the view jumps to that month.
|
|
104
|
+
- Comparisons happen at local midnight: the `Date` passed to `isDateDisabled` and returned in `rel-change` is `new Date(y, m, d)`, so read it with local getters, not `toISOString()`.
|
|
105
|
+
- `disabled` makes every day fail the disabled check and disables both navigation buttons; pointer events stay on the host so the `not-allowed` cursor shows.
|
|
106
|
+
- Each cell follows Figma ".Date Days": a 36 px full-rounded halo around a 28 px disc. The halo carries hover (`action/overlay/hover`), the focus ring and the selected day's `elevated-1` backing; the disc carries today's 1 px brand ring and the selected day's `inverse-2` fill with an inverse semibold label.
|
|
107
|
+
- Figma treats the cell tone as one axis, so exactly one applies per day: today beats weekend beats adjacent-month. Adjacent-month labels render at 40% and weekend labels at 70% — on the label only, so a *selected* weekend or adjacent-month day still reads at full contrast on the dark disc. A disabled day switches to the disabled text colour, and a disabled today swaps its brand ring for a neutral one.
|
|
108
|
+
- The month-navigation buttons are hand-rolled ghost buttons that bind the same action tokens as `<rel-button variant="ghost">` (audit 8b) — they are intentionally not `<rel-button>` instances.
|
|
109
|
+
- The host has a fixed `max-width: 320px`, its own radius, shadow and padding and no border (Figma draws the card with `shadow/xl`, approximated here by `--rel-shadows-shadow-400`, the nearest shipped step); wrap it or override on the host if you need a different footprint.
|