@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,481 +0,0 @@
|
|
|
1
|
-
import { LitElement, html, css, nothing, type PropertyValues } from "lit";
|
|
2
|
-
import { customElement, property } from "lit/decorators.js";
|
|
3
|
-
import "@reliability-design/icons/rel-icon";
|
|
4
|
-
import type { Orientation } from "../rel-stepper/rel-stepper.js";
|
|
5
|
-
|
|
6
|
-
export interface RadioOption {
|
|
7
|
-
value: string;
|
|
8
|
-
label: string;
|
|
9
|
-
supportingText?: string;
|
|
10
|
-
disabled?: boolean;
|
|
11
|
-
/** rel-icon name rendered before the label (Figma Has Icon/Avatar, Type=Icon). */
|
|
12
|
-
icon?: string;
|
|
13
|
-
/** 1–2 initials rendered as a circular chip before the label (Type=Avatar).
|
|
14
|
-
* Ignored when `icon` is also set. */
|
|
15
|
-
avatar?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type RadioSize = "small" | "medium" | "large";
|
|
19
|
-
type RadioDensity = "compact" | "comfortable";
|
|
20
|
-
type RadioAlignment = "leading" | "trailing";
|
|
21
|
-
|
|
22
|
-
@customElement("rel-radio")
|
|
23
|
-
export class RelRadio extends LitElement {
|
|
24
|
-
@property({ type: Array }) options: RadioOption[] = [];
|
|
25
|
-
|
|
26
|
-
@property({ type: String }) name = "radio-group";
|
|
27
|
-
|
|
28
|
-
/** Layout axis of the option list. `"vertical"` (default) stacks options in
|
|
29
|
-
* a column; `"horizontal"` lays them out in a wrapping row. */
|
|
30
|
-
@property({ type: String, reflect: true }) orientation: Orientation = "vertical";
|
|
31
|
-
|
|
32
|
-
/** Control scale (Figma Size). `"medium"` (default, Figma M) = 20px control
|
|
33
|
-
* with body-lg labels; `"large"` (Figma L) = 24px control with body-xl
|
|
34
|
-
* labels; `"small"` (Figma S) = 20px control with body-md labels — S and M
|
|
35
|
-
* share the control size in the spec, only typography steps down. */
|
|
36
|
-
@property({ type: String, reflect: true }) size: RadioSize = "medium";
|
|
37
|
-
|
|
38
|
-
/** Supporting-text layout (Figma Density). `"compact"` (default) puts the
|
|
39
|
-
* supporting text on its own line under the row, indented past the control;
|
|
40
|
-
* `"comfortable"` stacks label + supporting text beside the control. */
|
|
41
|
-
@property({ type: String, reflect: true }) density: RadioDensity = "compact";
|
|
42
|
-
|
|
43
|
-
/** Control position (Figma Layout). `"leading"` (default) renders the
|
|
44
|
-
* control before the label; `"trailing"` pushes it to the far edge of the
|
|
45
|
-
* row. Trailing has no compact layout in the spec, so it always renders
|
|
46
|
-
* with comfortable density. Meant for vertical orientation — trailing
|
|
47
|
-
* options stretch to the group's full width. */
|
|
48
|
-
@property({ type: String, reflect: true }) alignment: RadioAlignment = "leading";
|
|
49
|
-
|
|
50
|
-
@property({ type: String, reflect: true })
|
|
51
|
-
selectedValue: string | null = null;
|
|
52
|
-
|
|
53
|
-
@property({ type: Boolean })
|
|
54
|
-
disabled = false;
|
|
55
|
-
|
|
56
|
-
@property({ type: Boolean }) error = false;
|
|
57
|
-
|
|
58
|
-
@property({ type: String }) errorMessage = "";
|
|
59
|
-
|
|
60
|
-
/** Accessible name for the radiogroup (it renders no visible group label). */
|
|
61
|
-
@property({ type: String, attribute: "field-aria-label" }) fieldAriaLabel?: string;
|
|
62
|
-
|
|
63
|
-
@property({ type: String }) value = "";
|
|
64
|
-
|
|
65
|
-
checked = false;
|
|
66
|
-
|
|
67
|
-
private _onChange: (value: string) => void = () => {};
|
|
68
|
-
private _onTouched: () => void = () => {};
|
|
69
|
-
|
|
70
|
-
static styles = css`
|
|
71
|
-
:host {
|
|
72
|
-
color: var(--rel-text-default);
|
|
73
|
-
display: block;
|
|
74
|
-
font-family: var(--rel-fonts-font-family);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.rel-radio-group {
|
|
78
|
-
display: flex;
|
|
79
|
-
flex-direction: column;
|
|
80
|
-
align-items: flex-start;
|
|
81
|
-
gap: var(--rel-spacing-xs);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/* Horizontal orientation — options flow in a wrapping row. Wider column
|
|
85
|
-
gap than the vertical rhythm so adjacent option labels read as separate
|
|
86
|
-
choices; row gap keeps the vertical value for wrapped lines. */
|
|
87
|
-
:host([orientation="horizontal"]) .rel-radio-group {
|
|
88
|
-
flex-direction: row;
|
|
89
|
-
flex-wrap: wrap;
|
|
90
|
-
gap: var(--rel-spacing-xs) var(--rel-spacing-xl);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/* Trailing alignment — options stretch so the control can sit on the far
|
|
94
|
-
edge of the group's width. */
|
|
95
|
-
:host([alignment="trailing"]) .rel-radio-group {
|
|
96
|
-
align-items: stretch;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.rel-radio-option {
|
|
100
|
-
display: inline-flex;
|
|
101
|
-
flex-direction: column;
|
|
102
|
-
gap: var(--rel-spacing-3xs);
|
|
103
|
-
cursor: pointer;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.rel-radio-option.disabled {
|
|
107
|
-
/* Figma State=Disabled: whole option at 40% opacity, colors unchanged. */
|
|
108
|
-
opacity: 0.4;
|
|
109
|
-
cursor: not-allowed !important;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.rel-radio-option:focus-within:has(input:focus-visible) {
|
|
113
|
-
outline: 1.5px solid var(--rel-border-focus);
|
|
114
|
-
outline-offset: 1px;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.radio-main {
|
|
118
|
-
/* Containing block for the hidden input below — without this the
|
|
119
|
-
absolutely-positioned input resolves against the document (or any
|
|
120
|
-
positioned ancestor in the consumer page), where it neither moves
|
|
121
|
-
with intermediate scroll containers nor stays aligned with the
|
|
122
|
-
visible radio. Tabbing to it then makes the browser scroll the
|
|
123
|
-
WRONG scroller, shoving the whole page up (same bug as
|
|
124
|
-
rel-checkbox — keep the two fixes in sync). */
|
|
125
|
-
position: relative;
|
|
126
|
-
display: flex;
|
|
127
|
-
align-items: center;
|
|
128
|
-
/* Compact row rhythm (control ↔ label). Comfortable widens to 12px. */
|
|
129
|
-
gap: var(--rel-spacing-xs);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.rel-radio-option.comfortable .radio-main {
|
|
133
|
-
gap: var(--rel-spacing-sm);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
:host([alignment="trailing"]) .radio-main {
|
|
137
|
-
flex-direction: row-reverse;
|
|
138
|
-
justify-content: space-between;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
input {
|
|
142
|
-
position: absolute;
|
|
143
|
-
inset: 0;
|
|
144
|
-
width: 100%;
|
|
145
|
-
height: 100%;
|
|
146
|
-
margin: 0;
|
|
147
|
-
opacity: 0;
|
|
148
|
-
pointer-events: none;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/* Control box (Figma .Radio Control) — the drawn ring is inset inside a
|
|
152
|
-
larger hit/spacing box: 16px ring in a 20px box (M/S), 20px ring in a
|
|
153
|
-
24px box (L). Indent math below uses the BOX size. */
|
|
154
|
-
.radio-custom {
|
|
155
|
-
width: 20px;
|
|
156
|
-
height: 20px;
|
|
157
|
-
display: inline-flex;
|
|
158
|
-
align-items: center;
|
|
159
|
-
justify-content: center;
|
|
160
|
-
position: relative;
|
|
161
|
-
flex-shrink: 0;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.radio-custom::before {
|
|
165
|
-
content: "";
|
|
166
|
-
box-sizing: border-box;
|
|
167
|
-
width: 16px;
|
|
168
|
-
height: 16px;
|
|
169
|
-
border: 2px solid var(--rel-text-default);
|
|
170
|
-
border-radius: 50%;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.radio-custom::after {
|
|
174
|
-
content: "";
|
|
175
|
-
position: absolute;
|
|
176
|
-
width: 8px;
|
|
177
|
-
height: 8px;
|
|
178
|
-
border-radius: 50%;
|
|
179
|
-
background: var(--rel-text-default);
|
|
180
|
-
display: none;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
input:checked + .radio-custom::after {
|
|
184
|
-
display: block;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/* Comfortable density — label and supporting text stack beside the control. */
|
|
188
|
-
.stack {
|
|
189
|
-
display: flex;
|
|
190
|
-
flex-direction: column;
|
|
191
|
-
min-width: 0;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.label-line {
|
|
195
|
-
display: flex;
|
|
196
|
-
align-items: center;
|
|
197
|
-
gap: var(--rel-spacing-xs);
|
|
198
|
-
min-width: 0;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/* Optional label prefix — icon tracks the label's color in every state
|
|
202
|
-
(rel-icon inherits currentColor). */
|
|
203
|
-
.radio-prefix {
|
|
204
|
-
flex-shrink: 0;
|
|
205
|
-
color: var(--rel-text-default);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.radio-avatar {
|
|
209
|
-
flex-shrink: 0;
|
|
210
|
-
width: 20px;
|
|
211
|
-
height: 20px;
|
|
212
|
-
border-radius: 50%;
|
|
213
|
-
display: inline-flex;
|
|
214
|
-
align-items: center;
|
|
215
|
-
justify-content: center;
|
|
216
|
-
background: var(--rel-bg-neutral-inverse-2);
|
|
217
|
-
color: var(--rel-text-inverse);
|
|
218
|
-
font-family: var(--rel-body-xs-semibold-font-family);
|
|
219
|
-
font-weight: var(--rel-body-xs-semibold-font-weight);
|
|
220
|
-
font-size: var(--rel-body-xs-semibold-font-size);
|
|
221
|
-
line-height: 1;
|
|
222
|
-
letter-spacing: var(--rel-body-xs-semibold-letter-spacing);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
.radio-label {
|
|
226
|
-
color: var(--rel-text-default);
|
|
227
|
-
font-family: var(--rel-body-lg-regular-font-family);
|
|
228
|
-
font-weight: var(--rel-body-lg-regular-font-weight);
|
|
229
|
-
font-size: var(--rel-body-lg-regular-font-size);
|
|
230
|
-
line-height: var(--rel-body-lg-regular-line-height);
|
|
231
|
-
letter-spacing: var(--rel-body-lg-regular-letter-spacing);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.radio-supporting {
|
|
235
|
-
color: var(--rel-text-caption);
|
|
236
|
-
font-family: var(--rel-body-sm-regular-font-family);
|
|
237
|
-
font-weight: var(--rel-body-sm-regular-font-weight);
|
|
238
|
-
font-size: var(--rel-body-sm-regular-font-size);
|
|
239
|
-
line-height: var(--rel-body-sm-regular-line-height);
|
|
240
|
-
letter-spacing: var(--rel-body-sm-regular-letter-spacing);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/* Compact density — supporting text sits under the whole row, indented
|
|
244
|
-
past the control box (box width + row gap). */
|
|
245
|
-
.radio-supporting.indent {
|
|
246
|
-
padding-left: 28px;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/* Hover (Figma State=Hover) — ring, dot, label, and prefix icon shift
|
|
250
|
-
text-default → text-body; supporting text stays caption. Scoped away
|
|
251
|
-
from disabled and error so those keep their own colors. */
|
|
252
|
-
.rel-radio-option:not(.disabled):not(.error-unchecked):not(.error-checked):hover .radio-custom::before {
|
|
253
|
-
border-color: var(--rel-text-body);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
.rel-radio-option:not(.disabled):not(.error-unchecked):not(.error-checked):hover .radio-custom::after {
|
|
257
|
-
background: var(--rel-text-body);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.rel-radio-option:not(.disabled):not(.error-unchecked):not(.error-checked):hover .radio-label,
|
|
261
|
-
.rel-radio-option:not(.disabled):not(.error-unchecked):not(.error-checked):hover .radio-prefix {
|
|
262
|
-
color: var(--rel-text-body);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/* Size variants (medium is the base scale above). */
|
|
266
|
-
:host([size="large"]) .radio-custom {
|
|
267
|
-
width: 24px;
|
|
268
|
-
height: 24px;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
:host([size="large"]) .radio-custom::before {
|
|
272
|
-
width: 20px;
|
|
273
|
-
height: 20px;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
:host([size="large"]) .radio-custom::after {
|
|
277
|
-
width: 10px;
|
|
278
|
-
height: 10px;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
:host([size="large"]) .radio-label {
|
|
282
|
-
font-family: var(--rel-body-xl-regular-font-family);
|
|
283
|
-
font-weight: var(--rel-body-xl-regular-font-weight);
|
|
284
|
-
font-size: var(--rel-body-xl-regular-font-size);
|
|
285
|
-
line-height: var(--rel-body-xl-regular-line-height);
|
|
286
|
-
letter-spacing: var(--rel-body-xl-regular-letter-spacing);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
:host([size="large"]) .radio-supporting {
|
|
290
|
-
font-family: var(--rel-body-md-regular-font-family);
|
|
291
|
-
font-weight: var(--rel-body-md-regular-font-weight);
|
|
292
|
-
font-size: var(--rel-body-md-regular-font-size);
|
|
293
|
-
line-height: var(--rel-body-md-regular-line-height);
|
|
294
|
-
letter-spacing: var(--rel-body-md-regular-letter-spacing);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
:host([size="large"]) .radio-supporting.indent {
|
|
298
|
-
padding-left: 32px;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
:host([size="large"]) .radio-avatar {
|
|
302
|
-
width: 24px;
|
|
303
|
-
height: 24px;
|
|
304
|
-
font-family: var(--rel-body-sm-semibold-font-family);
|
|
305
|
-
font-weight: var(--rel-body-sm-semibold-font-weight);
|
|
306
|
-
font-size: var(--rel-body-sm-semibold-font-size);
|
|
307
|
-
letter-spacing: var(--rel-body-sm-semibold-letter-spacing);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
:host([size="small"]) .radio-label {
|
|
311
|
-
font-family: var(--rel-body-md-regular-font-family);
|
|
312
|
-
font-weight: var(--rel-body-md-regular-font-weight);
|
|
313
|
-
font-size: var(--rel-body-md-regular-font-size);
|
|
314
|
-
line-height: var(--rel-body-md-regular-line-height);
|
|
315
|
-
letter-spacing: var(--rel-body-md-regular-letter-spacing);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
:host([size="small"]) .radio-supporting {
|
|
319
|
-
font-family: var(--rel-body-xs-regular-font-family);
|
|
320
|
-
font-weight: var(--rel-body-xs-regular-font-weight);
|
|
321
|
-
font-size: var(--rel-body-xs-regular-font-size);
|
|
322
|
-
line-height: var(--rel-body-xs-regular-line-height);
|
|
323
|
-
letter-spacing: var(--rel-body-xs-regular-letter-spacing);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/* Error state (Figma State=Error) — ring, dot, and supporting text go
|
|
327
|
-
danger; the label (and prefix) keep their default color. */
|
|
328
|
-
.rel-radio-option.error-unchecked .radio-custom::before,
|
|
329
|
-
.rel-radio-option.error-checked .radio-custom::before {
|
|
330
|
-
border-color: var(--rel-border-danger);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
.rel-radio-option.error-checked .radio-custom::after {
|
|
334
|
-
background: var(--rel-text-danger);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
.rel-radio-option.error-unchecked .radio-supporting,
|
|
338
|
-
.rel-radio-option.error-checked .radio-supporting {
|
|
339
|
-
color: var(--rel-text-danger);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/* Error message below group */
|
|
343
|
-
.error-message {
|
|
344
|
-
color: var(--rel-text-danger);
|
|
345
|
-
margin-top: var(--rel-spacing-2xs, 4px);
|
|
346
|
-
|
|
347
|
-
font-family: var(--rel-body-sm-regular-font-family);
|
|
348
|
-
|
|
349
|
-
font-weight: var(--rel-body-sm-regular-font-weight);
|
|
350
|
-
|
|
351
|
-
font-size: var(--rel-body-sm-regular-font-size);
|
|
352
|
-
|
|
353
|
-
line-height: var(--rel-body-sm-regular-line-height);
|
|
354
|
-
|
|
355
|
-
letter-spacing: var(--rel-body-sm-regular-letter-spacing);
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
.error-message.empty {
|
|
360
|
-
margin-top: 0;
|
|
361
|
-
}
|
|
362
|
-
`;
|
|
363
|
-
|
|
364
|
-
protected willUpdate(changed: PropertyValues<this>) {
|
|
365
|
-
if (
|
|
366
|
-
(changed.has("alignment") || changed.has("density")) &&
|
|
367
|
-
this.alignment === "trailing" &&
|
|
368
|
-
this.density === "compact"
|
|
369
|
-
) {
|
|
370
|
-
console.warn(
|
|
371
|
-
'[rel-radio] density="compact" has no trailing layout; rendering comfortable density.'
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
/** Trailing has no compact layout in the spec — trailing wins. */
|
|
377
|
-
private get effectiveDensity(): RadioDensity {
|
|
378
|
-
return this.alignment === "trailing" ? "comfortable" : this.density;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
private onChange(value: string) {
|
|
382
|
-
if (this.disabled) return;
|
|
383
|
-
|
|
384
|
-
this.selectedValue = value;
|
|
385
|
-
this.dispatchEvent(
|
|
386
|
-
new CustomEvent("rel-change", {
|
|
387
|
-
detail: { value, checked: true },
|
|
388
|
-
bubbles: true,
|
|
389
|
-
composed: true,
|
|
390
|
-
})
|
|
391
|
-
);
|
|
392
|
-
this._onChange(this.value);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
registerOnChange(fn: (value: string) => void): void { this._onChange = fn; }
|
|
396
|
-
registerOnTouched(fn: () => void): void { this._onTouched = fn; }
|
|
397
|
-
writeValue(value: string): void { this.checked = value === this.value; }
|
|
398
|
-
|
|
399
|
-
private get hasSelection(): boolean {
|
|
400
|
-
return this.selectedValue !== null && this.selectedValue !== "";
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
private renderPrefix(option: RadioOption) {
|
|
404
|
-
if (option.icon) {
|
|
405
|
-
return html`<rel-icon
|
|
406
|
-
name="${option.icon}"
|
|
407
|
-
size="${this.size === "large" ? "lg" : "md"}"
|
|
408
|
-
class="radio-prefix"
|
|
409
|
-
></rel-icon>`;
|
|
410
|
-
}
|
|
411
|
-
if (option.avatar) {
|
|
412
|
-
return html`<span class="radio-avatar" aria-hidden="true">${option.avatar}</span>`;
|
|
413
|
-
}
|
|
414
|
-
return null;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
private renderOption(option: RadioOption) {
|
|
418
|
-
const isChecked = this.selectedValue === option.value;
|
|
419
|
-
const isDisabled = this.disabled || option.disabled;
|
|
420
|
-
const comfortable = this.effectiveDensity === "comfortable";
|
|
421
|
-
const classes = [
|
|
422
|
-
"rel-radio-option",
|
|
423
|
-
comfortable ? "comfortable" : "compact",
|
|
424
|
-
isDisabled ? "disabled" : "",
|
|
425
|
-
this.error && !this.hasSelection ? "error-unchecked" : "",
|
|
426
|
-
this.error && isChecked ? "error-checked" : "",
|
|
427
|
-
]
|
|
428
|
-
.filter(Boolean)
|
|
429
|
-
.join(" ");
|
|
430
|
-
|
|
431
|
-
const labelLine = html`
|
|
432
|
-
<span class="label-line">
|
|
433
|
-
${this.renderPrefix(option)}
|
|
434
|
-
<span part="label" class="radio-label">${option.label}</span>
|
|
435
|
-
</span>
|
|
436
|
-
`;
|
|
437
|
-
|
|
438
|
-
const supporting = option.supportingText
|
|
439
|
-
? html`<div class="radio-supporting ${comfortable ? "" : "indent"}">
|
|
440
|
-
${option.supportingText}
|
|
441
|
-
</div>`
|
|
442
|
-
: null;
|
|
443
|
-
|
|
444
|
-
return html`
|
|
445
|
-
<label class="${classes}">
|
|
446
|
-
<div class="radio-main">
|
|
447
|
-
<input
|
|
448
|
-
type="radio"
|
|
449
|
-
name="${this.name}"
|
|
450
|
-
.checked="${isChecked}"
|
|
451
|
-
?disabled="${isDisabled}"
|
|
452
|
-
@change="${() => this.onChange(option.value)}"
|
|
453
|
-
@blur="${() => this._onTouched()}"
|
|
454
|
-
/>
|
|
455
|
-
<span class="radio-custom"></span>
|
|
456
|
-
${comfortable
|
|
457
|
-
? html`<span class="stack">${labelLine}${supporting}</span>`
|
|
458
|
-
: labelLine}
|
|
459
|
-
</div>
|
|
460
|
-
|
|
461
|
-
${comfortable ? null : supporting}
|
|
462
|
-
</label>
|
|
463
|
-
`;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
render() {
|
|
467
|
-
return html`
|
|
468
|
-
<div
|
|
469
|
-
part="base"
|
|
470
|
-
class="rel-radio-group"
|
|
471
|
-
role="radiogroup"
|
|
472
|
-
aria-orientation="${this.orientation}"
|
|
473
|
-
aria-label="${this.fieldAriaLabel ?? nothing}"
|
|
474
|
-
aria-describedby="radio-error"
|
|
475
|
-
>
|
|
476
|
-
${this.options.map((o) => this.renderOption(o))}
|
|
477
|
-
</div>
|
|
478
|
-
<div class="${this.error && this.errorMessage ? "error-message" : "error-message empty"}" id="radio-error" aria-live="polite">${this.error && this.errorMessage ? this.errorMessage : ""}</div>
|
|
479
|
-
`;
|
|
480
|
-
}
|
|
481
|
-
}
|