@reliability-design/web 1.3.1 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/components/rel-accordion/README.md +13 -13
  3. package/dist/components/rel-accordion/rel-accordion.ts +80 -45
  4. package/dist/components/rel-alert/README.md +15 -15
  5. package/dist/components/rel-alert/rel-alert.ts +149 -158
  6. package/dist/components/rel-avatar/README.md +15 -15
  7. package/dist/components/rel-avatar/rel-avatar.ts +42 -38
  8. package/dist/components/rel-badge/README.md +5 -5
  9. package/dist/components/rel-badge/rel-badge.ts +46 -11
  10. package/dist/components/rel-breadcrumb/README.md +7 -7
  11. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +16 -13
  12. package/dist/components/rel-button/README.md +20 -20
  13. package/dist/components/rel-button/rel-button.ts +292 -105
  14. package/dist/components/rel-calendar/README.md +5 -5
  15. package/dist/components/rel-calendar/rel-calendar.ts +68 -45
  16. package/dist/components/rel-card/README.md +6 -6
  17. package/dist/components/rel-card/rel-card.ts +88 -35
  18. package/dist/components/rel-cardmedia/README.md +9 -9
  19. package/dist/components/rel-cardmedia/rel-cardmedia.ts +27 -20
  20. package/dist/components/rel-carousel/README.md +3 -3
  21. package/dist/components/rel-carousel/rel-carousel.ts +174 -90
  22. package/dist/components/rel-chart/README.md +8 -8
  23. package/dist/components/rel-chart/rel-chart.ts +59 -41
  24. package/dist/components/rel-checkbox/README.md +7 -7
  25. package/dist/components/rel-checkbox/rel-checkbox.ts +61 -61
  26. package/dist/components/rel-chip/README.md +16 -16
  27. package/dist/components/rel-chip/rel-chip.ts +143 -111
  28. package/dist/components/rel-container/README.md +11 -11
  29. package/dist/components/rel-container/rel-container.ts +35 -9
  30. package/dist/components/rel-date-picker/README.md +43 -7
  31. package/dist/components/rel-date-picker/date-format.test.ts +43 -0
  32. package/dist/components/rel-date-picker/date-format.ts +47 -0
  33. package/dist/components/rel-date-picker/rel-date-picker.ts +154 -82
  34. package/dist/components/rel-divider/README.md +9 -9
  35. package/dist/components/rel-divider/rel-divider.ts +10 -9
  36. package/dist/components/rel-drawer/README.md +1 -1
  37. package/dist/components/rel-drawer/rel-drawer-footer.ts +1 -1
  38. package/dist/components/rel-drawer/rel-drawer.ts +88 -25
  39. package/dist/components/rel-kbd/README.md +20 -20
  40. package/dist/components/rel-kbd/rel-kbd.ts +119 -25
  41. package/dist/components/rel-layout/README.md +1 -1
  42. package/dist/components/rel-layout/rel-layout.ts +2 -2
  43. package/dist/components/rel-menu/README.md +15 -15
  44. package/dist/components/rel-menu/rel-menu.ts +155 -88
  45. package/dist/components/rel-menubar/README.md +20 -20
  46. package/dist/components/rel-menubar/rel-menubar.ts +47 -31
  47. package/dist/components/rel-nav-menu/README.md +21 -21
  48. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +17 -14
  49. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +33 -14
  50. package/dist/components/rel-nav-menu/rel-nav-menu.ts +14 -7
  51. package/dist/components/rel-navbar/README.md +7 -7
  52. package/dist/components/rel-navbar/rel-navbar.ts +12 -11
  53. package/dist/components/rel-otp/README.md +3 -3
  54. package/dist/components/rel-otp/rel-otp.ts +46 -30
  55. package/dist/components/rel-pagination/README.md +18 -18
  56. package/dist/components/rel-pagination/rel-pagination.ts +141 -90
  57. package/dist/components/rel-popover/README.md +13 -13
  58. package/dist/components/rel-popover/rel-popover-content.ts +39 -14
  59. package/dist/components/rel-popover/rel-popover.ts +18 -7
  60. package/dist/components/rel-progress/README.md +5 -5
  61. package/dist/components/rel-progress/rel-progress.ts +16 -12
  62. package/dist/components/rel-radio/README.md +9 -9
  63. package/dist/components/rel-radio/rel-radio.ts +64 -50
  64. package/dist/components/rel-range-picker/rel-range-picker.ts +120 -117
  65. package/dist/components/rel-resizable/README.md +4 -4
  66. package/dist/components/rel-resizable/rel-resizable-group.ts +15 -4
  67. package/dist/components/rel-resizable/rel-resizable-handle.ts +13 -9
  68. package/dist/components/rel-resizable/rel-resizable-panel.ts +11 -0
  69. package/dist/components/rel-segmented-button/README.md +10 -10
  70. package/dist/components/rel-segmented-button/rel-segmented-button.ts +39 -40
  71. package/dist/components/rel-select/README.md +14 -14
  72. package/dist/components/rel-select/rel-select.ts +120 -188
  73. package/dist/components/rel-sheet/README.md +10 -10
  74. package/dist/components/rel-sheet/rel-sheet.ts +82 -23
  75. package/dist/components/rel-sidebar/README.md +5 -5
  76. package/dist/components/rel-sidebar/rel-sidebar.ts +75 -60
  77. package/dist/components/rel-skeleton/rel-skeleton.ts +8 -13
  78. package/dist/components/rel-slider/README.md +10 -10
  79. package/dist/components/rel-slider/rel-slider.ts +230 -57
  80. package/dist/components/rel-snackbar/README.md +9 -9
  81. package/dist/components/rel-snackbar/rel-snackbar.ts +44 -32
  82. package/dist/components/rel-stepper/README.md +10 -10
  83. package/dist/components/rel-stepper/rel-stepper.ts +110 -46
  84. package/dist/components/rel-switch/README.md +5 -5
  85. package/dist/components/rel-switch/rel-switch.ts +23 -12
  86. package/dist/components/rel-tab/README.md +13 -13
  87. package/dist/components/rel-tab/rel-tab.ts +63 -19
  88. package/dist/components/rel-table/README.md +7 -7
  89. package/dist/components/rel-table/rel-table-body.ts +2 -1
  90. package/dist/components/rel-table/rel-table-caption.ts +10 -7
  91. package/dist/components/rel-table/rel-table-cell.ts +7 -6
  92. package/dist/components/rel-table/rel-table-footer.ts +4 -3
  93. package/dist/components/rel-table/rel-table-head.ts +11 -9
  94. package/dist/components/rel-table/rel-table-header.ts +2 -1
  95. package/dist/components/rel-table/rel-table-row.ts +5 -4
  96. package/dist/components/rel-table/rel-table.ts +16 -7
  97. package/dist/components/rel-textfield/README.md +11 -11
  98. package/dist/components/rel-textfield/rel-textfield.ts +218 -92
  99. package/dist/components/rel-toast/README.md +11 -11
  100. package/dist/components/rel-toast/rel-toast.ts +33 -30
  101. package/dist/components/rel-tooltip/README.md +7 -7
  102. package/dist/components/rel-tooltip/rel-tooltip.ts +160 -123
  103. package/dist/components/rel-topbar/rel-topbar-actions.ts +1 -2
  104. package/dist/components/rel-topbar/rel-topbar-brand.ts +8 -5
  105. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +10 -8
  106. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +4 -5
  107. package/dist/components/rel-topbar/rel-topbar-item.ts +23 -22
  108. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -1
  109. package/dist/components/rel-topbar/rel-topbar-profile.ts +68 -50
  110. package/dist/components/rel-topbar/rel-topbar-utilities.ts +1 -2
  111. package/dist/components/rel-topbar/rel-topbar.ts +31 -29
  112. package/dist/index.d.mts +159 -39
  113. package/dist/index.d.ts +159 -39
  114. package/dist/index.js +3600 -2269
  115. package/dist/index.js.map +1 -1
  116. package/dist/index.mjs +3930 -2600
  117. package/dist/index.mjs.map +1 -1
  118. package/dist/styles/vars.css +866 -363
  119. package/dist/vars-BYCEEKWJ.css +866 -0
  120. package/package.json +5 -3
  121. package/dist/components/rel-range-picker/rel-range-picker.css +0 -349
  122. package/dist/styles/vars-v2.css +0 -525
  123. package/dist/vars-F54UGCHM.css +0 -363
  124. package/dist/vars-v2-VMGWTFJZ.css +0 -525
@@ -1,6 +1,5 @@
1
1
  import { LitElement, html, css, nothing } from "lit";
2
2
  import { customElement, property, state } from "lit/decorators.js";
3
- import "../../styles/vars-v2.css";
4
3
  import "@reliability-design/icons/rel-icon";
5
4
 
6
5
  export type TextFieldState = "default" | "error" | "disabled";
@@ -15,6 +14,11 @@ export class RelTextfield extends LitElement {
15
14
  @property({ type: String }) value: string = "";
16
15
  @property({ type: String }) leftIcon?: string;
17
16
  @property({ type: String }) rightIcon?: string;
17
+ /** Makes the trailing icon interactive (pointer + focusable) and emits
18
+ * `rel-right-icon-click` — e.g. a password show/hide toggle or clear button. */
19
+ @property({ type: Boolean, attribute: "clickable-right-icon" }) clickableRightIcon = false;
20
+ /** Accessible label for the trailing icon when it is clickable. */
21
+ @property({ type: String, attribute: "right-icon-aria-label" }) rightIconAriaLabel?: string;
18
22
  @property({ type: String }) supportingText?: string;
19
23
  @property({ type: String }) state: TextFieldState = "default";
20
24
  @property({ type: String }) size: TextFieldSize = "medium";
@@ -63,27 +67,37 @@ export class RelTextfield extends LitElement {
63
67
 
64
68
  static styles = css`
65
69
  :host {
70
+ color: var(--rel-text-default);
66
71
  display: block;
67
- font-family: var(--rel-fontFamilies-primary);
72
+ font-family: var(--rel-fonts-font-family);
68
73
  }
69
74
 
70
75
  /* Wrapper */
71
76
  .textfield-wrapper {
72
77
  display: flex;
73
78
  flex-direction: column;
74
- gap: var(--rel-spacing-space-2xs);
79
+ gap: var(--rel-spacing-2xs);
75
80
  width: 100%;
76
81
  }
77
82
 
78
83
  /* Label */
79
84
  .textfield-label {
80
- font-size: var(--rel-fontSizes-sm);
81
- font-weight: var(--rel-fontWeights-medium);
82
- color: var(--rel-color-text-heading);
85
+ color: var(--rel-text-label);
86
+
87
+ font-family: var(--rel-body-sm-medium-font-family);
88
+
89
+ font-weight: var(--rel-body-sm-medium-font-weight);
90
+
91
+ font-size: var(--rel-body-sm-medium-font-size);
92
+
93
+ line-height: var(--rel-body-sm-medium-line-height);
94
+
95
+ letter-spacing: var(--rel-body-sm-medium-letter-spacing);
96
+
83
97
  }
84
98
 
85
99
  .required-mark {
86
- color: var(--rel-error-surface-default, #CC0000);
100
+ color: var(--rel-text-danger);
87
101
  margin-left: 2px;
88
102
  }
89
103
 
@@ -100,24 +114,26 @@ export class RelTextfield extends LitElement {
100
114
 
101
115
  :host([floatinglabel]) .textfield-label {
102
116
  position: absolute;
103
- left: var(--rel-spacing-space-sm);
117
+ left: var(--rel-spacing-sm);
104
118
  top: 50%;
105
119
  transform: translateY(-50%);
106
- font-size: var(--rel-fontSizes-md);
107
- font-weight: var(--rel-fontWeights-regular);
108
- color: var(--rel-color-text-placeholder);
120
+ color: var(--rel-text-placeholder);
109
121
  pointer-events: none;
110
122
  transition: top 0.15s ease, font-size 0.15s ease, color 0.15s ease, transform 0.15s ease;
111
- background: var(--rel-color-bg-primary);
123
+ background: var(--rel-bg-neutral);
112
124
  padding: 0 2px;
113
125
  z-index: 1;
114
- line-height: 1;
115
126
  white-space: nowrap;
127
+ font-family: var(--rel-body-md-regular-font-family);
128
+ font-weight: var(--rel-body-md-regular-font-weight);
129
+ font-size: var(--rel-body-md-regular-font-size);
130
+ line-height: var(--rel-body-md-regular-line-height);
131
+ letter-spacing: var(--rel-body-md-regular-letter-spacing);
116
132
  }
117
133
 
118
134
  /* Floating label in multiline mode anchors to top instead of vertical center */
119
135
  :host([floatinglabel][multiline]) .textfield-label {
120
- top: var(--rel-spacing-space-sm);
136
+ top: var(--rel-spacing-sm);
121
137
  transform: none;
122
138
  }
123
139
 
@@ -125,46 +141,54 @@ export class RelTextfield extends LitElement {
125
141
  :host([floatinglabel]) .textfield-wrapper.has-value .textfield-label {
126
142
  top: 0;
127
143
  transform: translateY(-50%);
128
- font-size: var(--rel-fontSizes-xs);
129
- color: var(--rel-color-text-primary);
144
+ color: var(--rel-text-default);
145
+ font-family: var(--rel-body-xs-regular-font-family);
146
+ font-weight: var(--rel-body-xs-regular-font-weight);
147
+ font-size: var(--rel-body-xs-regular-font-size);
148
+ line-height: var(--rel-body-xs-regular-line-height);
149
+ letter-spacing: var(--rel-body-xs-regular-letter-spacing);
130
150
  }
131
151
 
132
152
  :host([floatinglabel]) .textfield-wrapper.error .textfield-label {
133
- color: var(--rel-error-text);
153
+ color: var(--rel-text-danger);
134
154
  }
135
155
 
136
156
  :host([floatinglabel]) .textfield-wrapper.focused:not(.error) .textfield-label {
137
- color: var(--rel-color-text-primary);
157
+ color: var(--rel-text-default);
138
158
  }
139
159
 
140
160
  :host([floatinglabel]) .textfield-wrapper.focused.error .textfield-label,
141
161
  :host([floatinglabel]) .textfield-wrapper.has-value.error .textfield-label {
142
162
  top: 0;
143
163
  transform: translateY(-50%);
144
- font-size: var(--rel-fontSizes-xs);
145
- color: var(--rel-error-text);
164
+ color: var(--rel-text-danger);
165
+ font-family: var(--rel-body-xs-regular-font-family);
166
+ font-weight: var(--rel-body-xs-regular-font-weight);
167
+ font-size: var(--rel-body-xs-regular-font-size);
168
+ line-height: var(--rel-body-xs-regular-line-height);
169
+ letter-spacing: var(--rel-body-xs-regular-letter-spacing);
146
170
  }
147
171
 
148
172
  :host([floatinglabel]) .textfield-input {
149
- padding-top: var(--rel-spacing-space-sm);
150
- padding-bottom: var(--rel-spacing-space-sm);
173
+ padding-top: var(--rel-spacing-sm);
174
+ padding-bottom: var(--rel-spacing-sm);
151
175
  }
152
176
 
153
177
  :host([floatinglabel]) .textfield-input.has-left-icon {
154
- padding-left: var(--rel-spacing-space-2xl);
178
+ padding-left: var(--rel-spacing-2xl);
155
179
  }
156
180
 
157
181
  :host([floatinglabel]) .textfield-label.has-left-icon {
158
- left: var(--rel-spacing-space-2xl);
182
+ left: var(--rel-spacing-2xl);
159
183
  }
160
184
 
161
185
  :host([floatinglabel]) .textfield-wrapper.focused .textfield-label.has-left-icon,
162
186
  :host([floatinglabel]) .textfield-wrapper.has-value .textfield-label.has-left-icon {
163
- left: var(--rel-spacing-space-sm);
187
+ left: var(--rel-spacing-sm);
164
188
  }
165
189
 
166
190
  :host([floatinglabel]) .textfield-wrapper.disabled .textfield-label {
167
- background: var(--rel-color-bg-tertiary);
191
+ background: var(--rel-bg-neutral-elevated-1);
168
192
  }
169
193
 
170
194
  /* Container */
@@ -172,15 +196,15 @@ export class RelTextfield extends LitElement {
172
196
  display: flex;
173
197
  align-items: center;
174
198
  position: relative;
175
- border: 1px solid var(--rel-color-border-default);
176
- border-radius: var(--rel-borders-radius-border-radius-100);
177
- background: var(--rel-color-bg-primary);
199
+ border: 1px solid var(--rel-border-default);
200
+ border-radius: var(--rel-border-radius-xs);
201
+ background: var(--rel-bg-neutral);
178
202
  overflow: hidden;
179
203
  transition: border 0.2s;
180
204
  }
181
205
 
182
206
  .textfield-container.disabled {
183
- background: var(--rel-color-bg-tertiary);
207
+ background: var(--rel-bg-neutral-elevated-1);
184
208
  cursor: not-allowed;
185
209
  }
186
210
 
@@ -194,16 +218,19 @@ export class RelTextfield extends LitElement {
194
218
  flex: 1;
195
219
  border: none;
196
220
  outline: none;
197
- font-size: var(--rel-fontSizes-md);
198
- padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-sm);
221
+ padding: var(--rel-spacing-xs) var(--rel-spacing-sm);
199
222
  background: transparent;
200
- font-family: var(--rel-fontFamilies-primary);
201
- color: var(--rel-color-text-primary);
223
+ color: var(--rel-text-body);
224
+ font-family: var(--rel-body-md-regular-font-family);
225
+ font-weight: var(--rel-body-md-regular-font-weight);
226
+ font-size: var(--rel-body-md-regular-font-size);
227
+ line-height: var(--rel-body-md-regular-line-height);
228
+ letter-spacing: var(--rel-body-md-regular-letter-spacing);
202
229
  }
203
230
 
204
231
  .textfield-input:disabled {
205
232
  cursor: not-allowed;
206
- color: var(--rel-color-text-disabled);
233
+ color: var(--rel-text-disabled);
207
234
  }
208
235
 
209
236
  /* Textarea */
@@ -221,7 +248,7 @@ export class RelTextfield extends LitElement {
221
248
  background: transparent;
222
249
  }
223
250
  textarea.textfield-input::-webkit-scrollbar-thumb {
224
- background: var(--rel-color-text-placeholder);
251
+ background: var(--rel-text-placeholder);
225
252
  border-radius: 2px;
226
253
  }
227
254
 
@@ -229,7 +256,7 @@ export class RelTextfield extends LitElement {
229
256
  position: absolute;
230
257
  display: flex;
231
258
  pointer-events: none;
232
- color: var(--rel-color-text-placeholder);
259
+ color: var(--rel-text-placeholder);
233
260
  }
234
261
 
235
262
  .icon.left {
@@ -240,33 +267,68 @@ export class RelTextfield extends LitElement {
240
267
  right: 8px;
241
268
  }
242
269
 
270
+ /* Interactive trailing icon (e.g. password show/hide) */
271
+ .icon.right.clickable {
272
+ pointer-events: auto;
273
+ cursor: pointer;
274
+ border-radius: var(--rel-border-radius-xs, 4px);
275
+ }
276
+ .icon.right.clickable:hover {
277
+ color: var(--rel-text-body);
278
+ }
279
+ .icon.right.clickable:focus-visible {
280
+ outline: 2px solid var(--rel-border-focus);
281
+ outline-offset: 2px;
282
+ }
283
+
284
+ .textfield-wrapper.small .textfield-support {
285
+ font-weight: var(--rel-body-xs-medium-font-weight);
286
+ }
287
+
243
288
  .textfield-wrapper.small .textfield-input {
244
- padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-sm);
245
- font-size: var(--rel-fontSizes-sm);
289
+ padding: var(--rel-spacing-xs) var(--rel-spacing-sm);
290
+ font-family: var(--rel-body-sm-regular-font-family);
291
+ font-weight: var(--rel-body-sm-regular-font-weight);
292
+ font-size: var(--rel-body-sm-regular-font-size);
293
+ line-height: var(--rel-body-sm-regular-line-height);
294
+ letter-spacing: var(--rel-body-sm-regular-letter-spacing);
246
295
  }
247
296
 
248
297
  .textfield-wrapper.medium .textfield-input {
249
- padding: var(--rel-spacing-space-sm) var(--rel-spacing-space-md);
250
- font-size: var(--rel-fontSizes-md);
298
+ padding: var(--rel-spacing-sm) var(--rel-spacing-md);
299
+ font-family: var(--rel-body-md-regular-font-family);
300
+ font-weight: var(--rel-body-md-regular-font-weight);
301
+ font-size: var(--rel-body-md-regular-font-size);
302
+ line-height: var(--rel-body-md-regular-line-height);
303
+ letter-spacing: var(--rel-body-md-regular-letter-spacing);
251
304
  }
252
305
 
253
306
  .textfield-wrapper.large .textfield-input {
254
- padding: var(--rel-spacing-space-md) var(--rel-spacing-space-md);
255
- font-size: var(--rel-fontSizes-lg);
307
+ padding: var(--rel-spacing-md) var(--rel-spacing-md);
308
+ font-family: var(--rel-body-lg-regular-font-family);
309
+ font-weight: var(--rel-body-lg-regular-font-weight);
310
+ font-size: var(--rel-body-lg-regular-font-size);
311
+ line-height: var(--rel-body-lg-regular-line-height);
312
+ letter-spacing: var(--rel-body-lg-regular-letter-spacing);
256
313
  }
257
314
 
258
315
  /* Adjust padding when icons are present */
259
316
  .textfield-wrapper .textfield-input.has-left-icon {
260
- padding-left: var(--rel-spacing-space-2xl);
317
+ padding-left: var(--rel-spacing-2xl);
261
318
  }
262
319
 
263
320
  .textfield-wrapper .textfield-input.has-right-icon {
264
- padding-right: var(--rel-spacing-space-2xl);
321
+ padding-right: var(--rel-spacing-2xl);
265
322
  }
266
323
 
267
324
  /* States */
325
+ /* Hover (Figma State=Hover): border-strong at 1px — no focus ring */
326
+ .textfield-wrapper:not(.focused):not(.error):not(.disabled) .textfield-container:hover {
327
+ border-color: var(--rel-border-strong);
328
+ }
329
+
268
330
  .textfield-wrapper.focused .textfield-container {
269
- border-color: var(--rel-color-text-primary);
331
+ border-color: var(--rel-text-default);
270
332
  }
271
333
 
272
334
  .textfield-input:focus-visible {
@@ -275,37 +337,47 @@ export class RelTextfield extends LitElement {
275
337
 
276
338
  .textfield-wrapper.focused .textfield-container,
277
339
  .textfield-container:focus-within {
278
- border-color: var(--rel-color-text-primary);
279
- box-shadow: 0 0 0 1px var(--rel-color-text-primary);
340
+ border-color: var(--rel-border-strong);
341
+ box-shadow: 0 0 0 1px var(--rel-border-strong);
280
342
  }
281
343
 
282
344
  .textfield-wrapper.error .textfield-container,
283
345
  .textfield-wrapper.error .textfield-container:focus-within {
284
- border-color: var(--rel-error-surface-default);
346
+ border-color: var(--rel-border-danger);
285
347
  box-shadow: none;
286
348
  }
287
349
 
288
350
  .textfield-wrapper.disabled .textfield-container {
289
- border-color: var(--rel-color-border-default);
351
+ border-color: var(--rel-border-default);
290
352
  }
291
353
 
292
354
  .textfield-wrapper.disabled .textfield-label {
293
- color: var(--rel-color-text-disabled);
355
+ color: var(--rel-text-disabled);
294
356
  }
295
357
 
296
358
  /* Supporting text */
297
359
  .textfield-support {
298
- font-size: var(--rel-fontSizes-xs);
299
- color: var(--rel-color-text-placeholder);
360
+ color: var(--rel-text-caption);
361
+
362
+ font-family: var(--rel-body-xs-regular-font-family);
363
+
364
+ font-weight: var(--rel-body-xs-regular-font-weight);
365
+
366
+ font-size: var(--rel-body-xs-regular-font-size);
367
+
368
+ line-height: var(--rel-body-xs-regular-line-height);
369
+
370
+ letter-spacing: var(--rel-body-xs-regular-letter-spacing);
371
+
300
372
  }
301
373
 
302
374
  .textfield-support.error {
303
- color: var(--rel-error-surface-default, #CC0000);
375
+ color: var(--rel-text-danger);
304
376
  }
305
377
 
306
378
  /* Placeholder */
307
379
  .textfield-input::placeholder {
308
- color: var(--rel-color-text-placeholder);
380
+ color: var(--rel-text-placeholder);
309
381
  }
310
382
 
311
383
  :host([floatinglabel]) .textfield-input::placeholder {
@@ -320,34 +392,38 @@ export class RelTextfield extends LitElement {
320
392
  .textfield-input:-webkit-autofill,
321
393
  .textfield-input:-webkit-autofill:hover,
322
394
  .textfield-input:-webkit-autofill:focus {
323
- -webkit-box-shadow: 0 0 0px 1000px var(--rel-color-bg-primary) inset;
324
- -webkit-text-fill-color: var(--rel-color-text-primary);
395
+ -webkit-box-shadow: 0 0 0px 1000px var(--rel-bg-surface) inset;
396
+ -webkit-text-fill-color: var(--rel-text-default);
325
397
  }
326
398
 
327
399
  /* ── Underline variant ── */
328
400
  :host([variant="underline"]) .textfield-container {
329
401
  border: none;
330
- border-bottom: 2px solid var(--rel-color-border-default);
402
+ border-bottom: 2px solid var(--rel-border-default);
331
403
  border-radius: 0;
332
- background: var(--rel-color-bg-tertiary, #f5f5f5);
404
+ background: var(--rel-bg-neutral-elevated-1);
333
405
  box-shadow: none;
334
406
  overflow: visible;
335
407
  }
336
408
 
409
+ :host([variant="underline"]) .textfield-wrapper:not(.focused):not(.error):not(.disabled) .textfield-container:hover {
410
+ border-bottom-color: var(--rel-border-strong);
411
+ }
412
+
337
413
  :host([variant="underline"]) .textfield-wrapper.focused .textfield-container,
338
414
  :host([variant="underline"]) .textfield-container:focus-within {
339
- border-bottom: 2px solid var(--rel-color-text-primary);
415
+ border-bottom: 2px solid var(--rel-text-default);
340
416
  box-shadow: none;
341
417
  }
342
418
 
343
419
  :host([variant="underline"]) .textfield-wrapper.error .textfield-container {
344
- border-bottom: 2px solid var(--rel-error-surface-default, #CC0000);
420
+ border-bottom: 2px solid var(--rel-border-danger);
345
421
  box-shadow: none;
346
422
  }
347
423
 
348
424
  :host([variant="underline"]) .textfield-wrapper.disabled .textfield-container {
349
- border-bottom: 2px solid var(--rel-color-border-default);
350
- background: var(--rel-color-bg-tertiary);
425
+ border-bottom: 2px solid var(--rel-border-default);
426
+ background: var(--rel-bg-neutral-elevated-1);
351
427
  }
352
428
 
353
429
  /* Remove border radius on input for underline variant */
@@ -358,8 +434,8 @@ export class RelTextfield extends LitElement {
358
434
  /* Dark mode — underline variant uses same border colors as default */
359
435
  :host-context([data-theme="dark"]) :host([variant="underline"]) .textfield-container,
360
436
  :host-context(.dark) :host([variant="underline"]) .textfield-container {
361
- background: var(--rel-color-bg-tertiary);
362
- border-bottom-color: var(--rel-color-border-default);
437
+ background: var(--rel-bg-neutral-elevated-1);
438
+ border-bottom-color: var(--rel-border-default);
363
439
  }
364
440
 
365
441
  /* ── Full-width control (fullWidth defaults true → block, fills parent) ── */
@@ -379,19 +455,21 @@ export class RelTextfield extends LitElement {
379
455
  margin: 0;
380
456
  min-inline-size: 0;
381
457
  padding: 0;
382
- border: 1px solid var(--rel-color-border-default);
383
- border-radius: var(--rel-borders-radius-border-radius-100);
384
- background: var(--rel-color-bg-primary);
458
+ border: 1px solid var(--rel-border-default);
459
+ border-radius: var(--rel-border-radius-xs);
460
+ background: var(--rel-bg-neutral);
385
461
  transition: border-color 0.2s;
386
462
  }
387
463
 
388
464
  :host([variant="legend"]) .field-legend {
389
- margin-left: var(--rel-spacing-space-sm);
390
- padding: 0 var(--rel-spacing-space-2xs);
391
- font-size: var(--rel-fontSizes-sm);
392
- font-weight: var(--rel-fontWeights-medium);
393
- line-height: 1;
394
- color: var(--rel-color-text-heading);
465
+ margin-left: var(--rel-spacing-sm);
466
+ padding: 0 var(--rel-spacing-2xs);
467
+ color: var(--rel-text-label);
468
+ font-family: var(--rel-body-sm-medium-font-family);
469
+ font-weight: var(--rel-body-sm-medium-font-weight);
470
+ font-size: var(--rel-body-sm-medium-font-size);
471
+ line-height: var(--rel-body-sm-medium-line-height);
472
+ letter-spacing: var(--rel-body-sm-medium-letter-spacing);
395
473
  }
396
474
 
397
475
  :host([variant="legend"]) .textfield-input {
@@ -402,17 +480,18 @@ export class RelTextfield extends LitElement {
402
480
  /* Prefix icon (legend): vertically centered; input inset via has-left-icon */
403
481
  :host([variant="legend"]) .icon.left {
404
482
  top: 50%;
405
- left: var(--rel-spacing-space-sm);
483
+ left: var(--rel-spacing-sm);
406
484
  transform: translateY(-50%);
407
485
  }
408
486
  :host([variant="legend"]) .field-fieldset.multiline .icon.left {
409
- top: var(--rel-spacing-space-sm);
487
+ top: var(--rel-spacing-sm);
410
488
  transform: none;
411
489
  }
412
490
 
413
491
  /* Hover */
414
492
  :host([variant="legend"]) .field-fieldset:hover {
415
- border-color: var(--rel-color-text-placeholder);
493
+ border-color: var(--rel-border-accent);
494
+ border-color: var(--rel-text-placeholder);
416
495
  }
417
496
 
418
497
  /* Focus — border-color only. A box-shadow/outline ring hugs the full
@@ -420,31 +499,31 @@ export class RelTextfield extends LitElement {
420
499
  strike through the legend. The legend also recolors on focus (below). */
421
500
  :host([variant="legend"]) .textfield-wrapper.focused .field-fieldset,
422
501
  :host([variant="legend"]) .field-fieldset:focus-within {
423
- border-color: var(--rel-color-border-focus);
502
+ border-color: var(--rel-border-focus);
424
503
  box-shadow: none;
425
504
  }
426
505
  :host([variant="legend"]) .textfield-wrapper.focused .field-legend,
427
506
  :host([variant="legend"]) .field-fieldset:focus-within .field-legend {
428
- color: var(--rel-color-border-focus);
507
+ color: var(--rel-border-focus);
429
508
  }
430
509
 
431
510
  /* Error */
432
511
  :host([variant="legend"]) .textfield-wrapper.error .field-fieldset {
433
- border-color: var(--rel-error-surface-default);
512
+ border-color: var(--rel-border-danger);
434
513
  box-shadow: none;
435
514
  }
436
515
  :host([variant="legend"]) .textfield-wrapper.error .field-legend {
437
- color: var(--rel-error-surface-default);
516
+ color: var(--rel-text-danger);
438
517
  }
439
518
 
440
519
  /* Disabled */
441
520
  :host([variant="legend"]) .textfield-wrapper.disabled .field-fieldset {
442
- background: var(--rel-color-bg-tertiary);
443
- border-color: var(--rel-color-border-default);
521
+ background: var(--rel-bg-neutral-elevated-1);
522
+ border-color: var(--rel-border-default);
444
523
  cursor: not-allowed;
445
524
  }
446
525
  :host([variant="legend"]) .textfield-wrapper.disabled .field-legend {
447
- color: var(--rel-color-text-disabled);
526
+ color: var(--rel-text-disabled);
448
527
  }
449
528
 
450
529
  /* Readonly */
@@ -454,10 +533,30 @@ export class RelTextfield extends LitElement {
454
533
 
455
534
  /* Legend font tracks size */
456
535
  :host([variant="legend"]) .textfield-wrapper.small .field-legend {
457
- font-size: var(--rel-fontSizes-xs);
536
+
537
+ font-family: var(--rel-body-xs-regular-font-family);
538
+
539
+ font-weight: var(--rel-body-xs-regular-font-weight);
540
+
541
+ font-size: var(--rel-body-xs-regular-font-size);
542
+
543
+ line-height: var(--rel-body-xs-regular-line-height);
544
+
545
+ letter-spacing: var(--rel-body-xs-regular-letter-spacing);
546
+
458
547
  }
459
548
  :host([variant="legend"]) .textfield-wrapper.large .field-legend {
460
- font-size: var(--rel-fontSizes-md);
549
+
550
+ font-family: var(--rel-body-md-regular-font-family);
551
+
552
+ font-weight: var(--rel-body-md-regular-font-weight);
553
+
554
+ font-size: var(--rel-body-md-regular-font-size);
555
+
556
+ line-height: var(--rel-body-md-regular-line-height);
557
+
558
+ letter-spacing: var(--rel-body-md-regular-letter-spacing);
559
+
461
560
  }
462
561
  `;
463
562
 
@@ -481,6 +580,22 @@ export class RelTextfield extends LitElement {
481
580
  }
482
581
  }
483
582
 
583
+ private handleRightIconClick(e: Event) {
584
+ if (!this.clickableRightIcon) return;
585
+ e.stopPropagation();
586
+ this.dispatchEvent(
587
+ new CustomEvent("rel-right-icon-click", { bubbles: true, composed: true })
588
+ );
589
+ }
590
+
591
+ private handleRightIconKeydown(e: KeyboardEvent) {
592
+ if (!this.clickableRightIcon) return;
593
+ if (e.key === "Enter" || e.key === " ") {
594
+ e.preventDefault();
595
+ this.handleRightIconClick(e);
596
+ }
597
+ }
598
+
484
599
  private handleInput(e: Event) {
485
600
  const input = e.target as HTMLInputElement;
486
601
  this.value = input.value;
@@ -532,6 +647,7 @@ export class RelTextfield extends LitElement {
532
647
  const labelTemplate = (extraClass = "") => {
533
648
  if (!this.label) return "";
534
649
  return html`<label
650
+ part="label"
535
651
  class="textfield-label${extraClass}"
536
652
  for="${inputId}"
537
653
  >${this.label}${this.required ? html`<span class="required-mark" aria-hidden="true">*</span>` : ""}</label>`;
@@ -540,7 +656,7 @@ export class RelTextfield extends LitElement {
540
656
  const ariaLabelledby = this.variant === "legend" && this.label ? legendId : undefined;
541
657
 
542
658
  const inputTemplate = this.multiline
543
- ? html`<textarea
659
+ ? html`<textarea part="input"
544
660
  id="${inputId}"
545
661
  class="${inputClasses}"
546
662
  placeholder="${this.placeholder}"
@@ -559,7 +675,7 @@ export class RelTextfield extends LitElement {
559
675
  @blur="${this.handleBlur}"
560
676
  @input="${this.handleInput}"
561
677
  ></textarea>`
562
- : html`<input
678
+ : html`<input part="input"
563
679
  type="${this.type}"
564
680
  id="${inputId}"
565
681
  class="${inputClasses}"
@@ -591,7 +707,7 @@ export class RelTextfield extends LitElement {
591
707
  : "";
592
708
 
593
709
  const belowTemplate = belowText
594
- ? html`<div class="textfield-support ${isError ? "error" : ""}" id="${describedById}">
710
+ ? html`<div part="helper" class="textfield-support ${isError ? "error" : ""}" id="${describedById}">
595
711
  ${belowText}
596
712
  </div>`
597
713
  : "";
@@ -604,7 +720,7 @@ export class RelTextfield extends LitElement {
604
720
  // is always present (only its content is dynamic).
605
721
  return html`
606
722
  <div class="${wrapperClasses}">
607
- <fieldset class="${fieldsetClass}"><legend class="field-legend" id="${legendId}">${this.label ?? ""}${this.required ? html`<span class="required-mark" aria-hidden="true">*</span>` : ""}</legend>
723
+ <fieldset part="control" class="${fieldsetClass}"><legend class="field-legend" id="${legendId}">${this.label ?? ""}${this.required ? html`<span class="required-mark" aria-hidden="true">*</span>` : ""}</legend>
608
724
  ${!this.multiline ? leadingIconTemplate : ""}
609
725
  ${inputTemplate}
610
726
  </fieldset>
@@ -617,7 +733,7 @@ export class RelTextfield extends LitElement {
617
733
  <div class="${wrapperClasses}">
618
734
  ${!this.floatingLabel ? labelTemplate() : ""}
619
735
 
620
- <div class="${["textfield-container", this.isDisabled ? "disabled" : "", this.multiline ? "multiline" : ""].filter(Boolean).join(" ")}">
736
+ <div part="control" class="${["textfield-container", this.isDisabled ? "disabled" : "", this.multiline ? "multiline" : ""].filter(Boolean).join(" ")}">
621
737
  ${this.floatingLabel
622
738
  ? labelTemplate(leadingIcon && !this.multiline ? " has-left-icon" : "")
623
739
  : ""}
@@ -626,7 +742,17 @@ export class RelTextfield extends LitElement {
626
742
  ${inputTemplate}
627
743
 
628
744
  ${!this.multiline && this.rightIcon
629
- ? html`<rel-icon name="${this.rightIcon}" size="sm" class="icon right"></rel-icon>`
745
+ ? html`<rel-icon
746
+ part="right-icon"
747
+ name="${this.rightIcon}"
748
+ size="${this.clickableRightIcon ? "md" : "sm"}"
749
+ class="icon right ${this.clickableRightIcon ? "clickable" : ""}"
750
+ role="${this.clickableRightIcon ? "button" : nothing}"
751
+ tabindex="${this.clickableRightIcon ? "0" : nothing}"
752
+ aria-label="${this.clickableRightIcon ? (this.rightIconAriaLabel ?? nothing) : nothing}"
753
+ @click="${(e: Event) => this.handleRightIconClick(e)}"
754
+ @keydown="${(e: KeyboardEvent) => this.handleRightIconKeydown(e)}"
755
+ ></rel-icon>`
630
756
  : ""}
631
757
  </div>
632
758
 
@@ -98,25 +98,25 @@ None exposed.
98
98
  ## Tokens / CSS Variables
99
99
 
100
100
  ### Semantic Tokens
101
- - `--rel-fontFamilies-primary` - Font family
102
- - `--rel-fontSizes-md` - Font size
101
+ - `--rel-fonts-font-family` - Font family
102
+ - `--rel-body-md-regular-font-size` - Font size
103
103
 
104
104
  ### Spacing Tokens
105
- - `--rel-spacing-space-sm` - Gap between elements
106
- - `--rel-spacing-space-md` - Padding
107
- - `--rel-spacing-space-2xs` - Close button padding and margin
105
+ - `--rel-spacing-sm` - Gap between elements
106
+ - `--rel-spacing-md` - Padding
107
+ - `--rel-spacing-2xs` - Close button padding and margin
108
108
 
109
109
  ### Color Tokens
110
- - `--rel-surface-toast` - Default background color (dark gray)
111
- - `--rel-colors-red-secondary` - Error background color
112
- - `--rel-colors-white` - Text and focus outline color
113
- - `--rel-colors-green-primary` - Action button text color
110
+ - `--rel-bg-neutral-inverse-1` - Default background color (dark gray)
111
+ - `--rel-text-danger` - Error background color
112
+ - `--rel-bg-surface` - Text and focus outline color
113
+ - `--rel-bg-brand` - Action button text color
114
114
 
115
115
  ### Shadow Tokens
116
116
  - `--rel-shadows-shadow-300` - Drop shadow
117
117
 
118
118
  ### Border Tokens
119
- - `--rel-borders-radius-border-radius-200` - Border radius
119
+ - `--rel-border-radius-sm` - Border radius
120
120
 
121
121
  ## Accessibility
122
122
  - Uses `role="status"` and `aria-live="polite"` for screen reader announcements
@@ -144,5 +144,5 @@ None exposed.
144
144
  - The component includes a `fadeInUp` animation (20px translateY → 0, opacity 0 → 1) on appearance
145
145
  - Animation disabled when `prefers-reduced-motion: reduce` is set
146
146
  - When `visible` is false, `hidden` class applies `display: none`
147
- - **Type variants**: `default` uses `--rel-surface-toast`, `error` uses `--rel-colors-red-secondary`
147
+ - **Type variants**: `default` uses `--rel-bg-neutral-inverse-1`, `error` uses `--rel-text-danger`
148
148
  - The toast appears inline-flex, so it sizes to content width