@reliability-design/web 1.1.1 → 1.2.0

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 (64) hide show
  1. package/dist/components/rel-accordion/rel-accordion.ts +17 -32
  2. package/dist/components/rel-alert/rel-alert.ts +34 -34
  3. package/dist/components/rel-avatar/rel-avatar.ts +5 -3
  4. package/dist/components/rel-badge/rel-badge.ts +2 -1
  5. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +6 -6
  6. package/dist/components/rel-button/rel-button.ts +67 -21
  7. package/dist/components/rel-calendar/rel-calendar.ts +15 -8
  8. package/dist/components/rel-card/rel-card.ts +9 -17
  9. package/dist/components/rel-cardmedia/rel-cardmedia.ts +20 -23
  10. package/dist/components/rel-carousel/rel-carousel.ts +596 -468
  11. package/dist/components/rel-checkbox/rel-checkbox.ts +68 -16
  12. package/dist/components/rel-chip/rel-chip.ts +291 -244
  13. package/dist/components/rel-container/rel-container.ts +2 -2
  14. package/dist/components/rel-date-picker/rel-date-picker.ts +23 -19
  15. package/dist/components/rel-divider/rel-divider.ts +3 -3
  16. package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -2
  17. package/dist/components/rel-drawer/rel-drawer.ts +41 -88
  18. package/dist/components/rel-kbd/rel-kbd.ts +94 -118
  19. package/dist/components/rel-layout/rel-layout.ts +49 -58
  20. package/dist/components/rel-menu/rel-menu.ts +359 -359
  21. package/dist/components/rel-menubar/rel-menubar-menu.css +3 -0
  22. package/dist/components/rel-menubar/rel-menubar-menu.ts +2 -1
  23. package/dist/components/rel-menubar/rel-menubar.ts +602 -605
  24. package/dist/components/rel-otp/rel-otp.ts +22 -25
  25. package/dist/components/rel-pagination/rel-pagination.ts +101 -57
  26. package/dist/components/rel-popover/rel-popover-content.ts +6 -5
  27. package/dist/components/rel-popover/rel-popover.ts +26 -7
  28. package/dist/components/rel-progress/rel-progress.ts +10 -9
  29. package/dist/components/rel-radio/rel-radio.ts +228 -172
  30. package/dist/components/rel-range-picker/rel-range-picker.css +349 -0
  31. package/dist/components/rel-range-picker/rel-range-picker.ts +1079 -0
  32. package/dist/components/rel-resizable/rel-resizable-handle.ts +8 -7
  33. package/dist/components/rel-segmented-button/rel-segmented-button.ts +41 -20
  34. package/dist/components/rel-select/rel-select.ts +103 -32
  35. package/dist/components/rel-sheet/rel-sheet.ts +362 -684
  36. package/dist/components/rel-slider/rel-slider.ts +49 -27
  37. package/dist/components/rel-snackbar/rel-snackbar.ts +28 -28
  38. package/dist/components/rel-stepper/rel-stepper.ts +11 -10
  39. package/dist/components/rel-switch/rel-switch.ts +7 -6
  40. package/dist/components/rel-tab/rel-tab.ts +15 -29
  41. package/dist/components/rel-textfield/rel-textfield.ts +144 -35
  42. package/dist/components/rel-toast/rel-toast.ts +25 -12
  43. package/dist/components/rel-tooltip/rel-tooltip.ts +123 -123
  44. package/dist/components/rel-topbar/rel-topbar-actions.ts +1 -0
  45. package/dist/components/rel-topbar/rel-topbar-brand.ts +1 -0
  46. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +32 -2
  47. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +1 -1
  48. package/dist/components/rel-topbar/rel-topbar-item.ts +15 -10
  49. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +1 -0
  50. package/dist/components/rel-topbar/rel-topbar-profile.ts +30 -56
  51. package/dist/components/rel-topbar/rel-topbar-utilities.ts +1 -0
  52. package/dist/components/rel-topbar/rel-topbar.ts +137 -28
  53. package/dist/index.d.mts +153 -178
  54. package/dist/index.d.ts +153 -178
  55. package/dist/index.js +4711 -3875
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.mjs +4047 -3202
  58. package/dist/index.mjs.map +1 -1
  59. package/dist/rel-menubar-menu-BEEQDAXW.css +3 -0
  60. package/dist/styles/vars-v2.css +525 -0
  61. package/dist/styles/vars.css +346 -346
  62. package/dist/{vars-TBB4BMSD.css → vars-I2PC74XD.css} +346 -346
  63. package/dist/vars-v2-VMGWTFJZ.css +525 -0
  64. package/package.json +2 -1
@@ -47,12 +47,13 @@ export class RelCheckbox extends LitElement {
47
47
  pointer-events: none;
48
48
  }
49
49
 
50
+ /* Unchecked — transparent fill, gray border */
50
51
  .box {
51
52
  width: 18px;
52
53
  height: 18px;
53
54
  border-radius: 4px;
54
- border: 2px solid var(--rel-text-heading, #2b2b2b);
55
- background: var(--rel-colors-white, #fff);
55
+ border: 2px solid var(--rel-gray-text-primary);
56
+ background: transparent;
56
57
  display: flex;
57
58
  align-items: center;
58
59
  justify-content: center;
@@ -61,7 +62,7 @@ export class RelCheckbox extends LitElement {
61
62
  }
62
63
 
63
64
  input:focus-visible + .box {
64
- outline: 2px solid var(--rel-border-info, #0091ea);
65
+ outline: 2px solid var(--rel-color-border-focus);
65
66
  outline-offset: 2px;
66
67
  }
67
68
 
@@ -71,36 +72,43 @@ export class RelCheckbox extends LitElement {
71
72
  display: none;
72
73
  }
73
74
 
74
- .checked .box,
75
- .indeterminate .box {
76
- background: var(--rel-text-heading, #2b2b2b);
77
- border-color: var(--rel-text-heading, #2b2b2b);
75
+ /* Checked — filled box, transparent checkmark (bg shows through) */
76
+ .checked .box {
77
+ background: var(--rel-gray-text-primary);
78
+ border-color: var(--rel-gray-text-primary);
78
79
  }
79
80
 
80
81
  .checked .check-icon {
81
82
  display: block;
83
+ fill: #ffffff;
82
84
  }
83
85
 
86
+ /* Indeterminate — transparent fill, dash inherits border color */
84
87
  .indeterminate .indeterminate-icon {
85
88
  display: block;
89
+ fill: var(--rel-gray-text-primary);
86
90
  }
87
91
 
92
+ /* Error unchecked — transparent fill, error border */
88
93
  .error .box {
89
- border-color: var(--rel-colors-red-primary);
94
+ border-color: var(--rel-error-surface-default);
90
95
  }
91
96
 
92
- .error.checked .box,
93
- .error.indeterminate .box {
94
- background: var(--rel-colors-red-primary);
95
- border-color: var(--rel-colors-red-primary);
97
+ /* Error checked — error fill, transparent checkmark */
98
+ .error.checked .box {
99
+ background: var(--rel-error-surface-default);
100
+ border-color: var(--rel-error-surface-default);
96
101
  }
97
102
 
98
- /* Pin checkmark/dash to white on red background — correct in both themes */
99
- .error.checked svg,
100
- .error.indeterminate svg {
103
+ .error.checked .check-icon {
101
104
  fill: #ffffff;
102
105
  }
103
106
 
107
+ /* Error indeterminate — transparent fill, dash is error color */
108
+ .error.indeterminate .indeterminate-icon {
109
+ fill: var(--rel-error-surface-default);
110
+ }
111
+
104
112
  .disabled {
105
113
  opacity: 0.55;
106
114
  cursor: not-allowed;
@@ -114,10 +122,54 @@ export class RelCheckbox extends LitElement {
114
122
  pointer-events: none;
115
123
  }
116
124
 
125
+ .disabled .label,
126
+ .disabled .text {
127
+ color: var(--rel-color-text-disabled);
128
+ }
129
+
130
+ /* Dark mode — tokens auto-flip via vars-v2, declared explicitly for clarity */
131
+ :host-context([data-theme="dark"]) .box {
132
+ border-color: var(--rel-gray-text-primary);
133
+ }
134
+
135
+ :host-context([data-theme="dark"]) .checked .box {
136
+ background: var(--rel-gray-text-primary);
137
+ border-color: var(--rel-gray-text-primary);
138
+ }
139
+
140
+ :host-context([data-theme="dark"]) .checked .check-icon {
141
+ fill: var(--rel-color-bg-primary);
142
+ }
143
+
144
+ :host-context([data-theme="dark"]) .indeterminate .indeterminate-icon {
145
+ fill: var(--rel-gray-text-primary);
146
+ }
147
+
148
+ :host-context([data-theme="dark"]) .error .box {
149
+ border-color: var(--rel-error-surface-default);
150
+ }
151
+
152
+ :host-context([data-theme="dark"]) .error.checked .box {
153
+ background: var(--rel-error-surface-default);
154
+ border-color: var(--rel-error-surface-default);
155
+ }
156
+
157
+ :host-context([data-theme="dark"]) .error.checked .check-icon {
158
+ fill: var(--rel-color-bg-primary);
159
+ }
160
+
161
+ :host-context([data-theme="dark"]) .error.indeterminate .indeterminate-icon {
162
+ fill: var(--rel-error-surface-default);
163
+ }
164
+
165
+ :host-context([data-theme="dark"]) .label {
166
+ color: var(--rel-gray-text-primary);
167
+ }
168
+
117
169
  .label {
118
170
  font-size: var(--rel-fontSizes-md, 14px);
119
171
  font-weight: var(--rel-fontWeights-medium, 500);
120
- color: var(--rel-text-primary, #333);
172
+ color: var(--rel-gray-text-primary);
121
173
  }
122
174
 
123
175
  .text {
@@ -1,244 +1,291 @@
1
- import { LitElement, html, css } from "lit";
2
- import { customElement, property } from "lit/decorators.js";
3
-
4
- @customElement("rel-chip")
5
- export class RelChip extends LitElement {
6
- @property({ type: String }) label = "Label";
7
-
8
- @property({ type: String })
9
- tone: "default" | "blue" | "yellow" | "red" | "green" = "default";
10
-
11
- @property({ type: String }) leadingIcon?: string;
12
- @property({ type: String }) trailingIcon?: string;
13
- @property({ type: String }) avatar?: string;
14
-
15
- @property({ type: Boolean }) removable = false;
16
- @property({ type: Boolean }) outline = false;
17
-
18
- /** IMPORTANT: reflected so CSS + Angular can see it */
19
- @property({ type: Boolean, reflect: true }) removed = false;
20
-
21
- static styles = css`
22
- :host {
23
- display: inline-block;
24
- }
25
-
26
- :host([removed]) {
27
- display: none;
28
- }
29
-
30
- .chip {
31
- display: inline-flex;
32
- align-items: center;
33
- font-family: var(--rel-fontFamilies-primary);
34
- font-size: var(--rel-fontSizes-md);
35
- font-weight: var(--rel-fontWeights-medium);
36
- border-radius: var(--rel-borders-radius-border-radius-500);
37
- padding: var(--rel-spacing-space-2xs) var(--rel-spacing-space-sm);
38
- gap: var(--rel-spacing-space-2xs);
39
- cursor: pointer;
40
- border: var(--rel-borders-width-stroke-100) solid transparent;
41
- user-select: none;
42
- white-space: nowrap;
43
- background: transparent;
44
- }
45
-
46
- .chip:hover {
47
- filter: brightness(0.92);
48
- box-shadow: var(--rel-shadows-shadow-100);
49
- }
50
-
51
- .chip:focus-visible {
52
- outline: 2px solid var(--rel-colors-blue-primary, #0091ea);
53
- outline-offset: 2px;
54
- }
55
-
56
- /* TONES */
57
- .chip-default {
58
- background: var(--rel-colors-gray-border);
59
- color: #000000;
60
- }
61
-
62
- .chip-blue {
63
- background: var(--rel-colors-blue-tertiary);
64
- color: #ffffff;
65
- }
66
-
67
- .chip-yellow {
68
- background: var(--rel-colors-yellow-pending);
69
- color: #000000;
70
- }
71
-
72
- .chip-red {
73
- background: var(--rel-colors-red-secondary);
74
- color: #ffffff;
75
- }
76
-
77
- .chip-green {
78
- background: var(--rel-colors-green-success);
79
- color: #ffffff;
80
- }
81
-
82
- /* OUTLINE */
83
- .chip-outline {
84
- background: transparent;
85
- border-color: var(--rel-color-border-default);
86
- }
87
-
88
- .chip-blue.chip-outline {
89
- color: #000000;
90
- background: transparent;
91
- border-color: #0059F4;
92
- }
93
-
94
- .chip-red.chip-outline {
95
- color: #9C1E33;
96
- background: transparent;
97
- border-color: #9C1E33;
98
- }
99
-
100
- .chip-green.chip-outline {
101
- color: #00A86B;
102
- background: transparent;
103
- border-color: #00A86B;
104
- }
105
-
106
- .chip-yellow.chip-outline {
107
- color: #92400E;
108
- background: transparent;
109
- border-color: #F2915C;
110
- }
111
-
112
- .chip-avatar {
113
- width: 20px;
114
- height: 20px;
115
- border-radius: 50%;
116
- object-fit: cover;
117
- }
118
-
119
- .chip-icon {
120
- display: inline-flex;
121
- align-items: center;
122
- justify-content: center;
123
- width: 14px;
124
- height: 14px;
125
- flex-shrink: 0;
126
- }
127
-
128
- .chip-icon * {
129
- width: 100%;
130
- height: 100%;
131
- }
132
-
133
- .chip-icon ::slotted(svg),
134
- .chip-icon svg {
135
- width: 16px;
136
- height: 16px;
137
- fill: currentColor;
138
- }
139
-
140
- .chip-remove {
141
- margin-left: var(--rel-spacing-space-3xs);
142
- cursor: pointer;
143
- opacity: 0.7;
144
- background: none;
145
- border: none;
146
- color: inherit;
147
- font: inherit;
148
- padding: 0;
149
- line-height: 1;
150
- }
151
-
152
- .chip-remove:hover {
153
- opacity: 1;
154
- }
155
-
156
- .chip-remove:focus-visible {
157
- outline: 2px solid var(--rel-colors-white, #fff);
158
- outline-offset: 1px;
159
- border-radius: 2px;
160
- }
161
-
162
- /* Dark mode overrides */
163
- :host-context([data-theme="dark"]) .chip-default,
164
- :host-context(.dark) .chip-default {
165
- color: #ffffff;
166
- background: var(--rel-color-bg-secondary);
167
- }
168
-
169
- :host-context([data-theme="dark"]) .chip-default.chip-outline,
170
- :host-context(.dark) .chip-default.chip-outline {
171
- color: #ffffff;
172
- border-color: #ffffff;
173
- }
174
-
175
- :host-context([data-theme="dark"]) .chip-outline,
176
- :host-context(.dark) .chip-outline {
177
- color: #ffffff;
178
- border-color: currentColor;
179
- }
180
- `;
181
-
182
- private get classes() {
183
- return [
184
- "chip",
185
- `chip-${this.tone}`,
186
- this.outline ? "chip-outline" : "",
187
- ].join(" ");
188
- }
189
-
190
- private handleRemove(event: Event) {
191
- event.stopPropagation();
192
- this.removed = true;
193
-
194
- this.dispatchEvent(
195
- new CustomEvent("removed", {
196
- bubbles: true,
197
- composed: true,
198
- })
199
- );
200
- }
201
-
202
- render() {
203
- return html`
204
- <span
205
- class="${this.classes}"
206
- role="button"
207
- tabindex="0"
208
- aria-label="${this.label}"
209
- >
210
- ${this.avatar
211
- ? html`<img src=${this.avatar} alt="" class="chip-avatar" />`
212
- : null}
213
- ${this.leadingIcon
214
- ? html`<span class="chip-icon">
215
- ${this.renderIcon(this.leadingIcon)}
216
- </span>`
217
- : null}
218
-
219
- <span class="chip-label">${this.label}</span>
220
-
221
- ${this.trailingIcon
222
- ? html`<span class="chip-icon">
223
- ${this.renderIcon(this.trailingIcon)}
224
- </span>`
225
- : null}
226
- ${this.removable
227
- ? html`<button
228
- class="chip-remove"
229
- aria-label="Remove ${this.label}"
230
- @click=${this.handleRemove}
231
- >
232
- ✕
233
- </button>`
234
- : null}
235
- </span>
236
- `;
237
- }
238
-
239
- private renderIcon(iconString: string) {
240
- const template = document.createElement("template");
241
- template.innerHTML = iconString.trim();
242
- return template.content.cloneNode(true);
243
- }
244
- }
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+ import "../rel-avatar/rel-avatar.js";
4
+
5
+ @customElement("rel-chip")
6
+ export class RelChip extends LitElement {
7
+ @property({ type: String }) label = "Label";
8
+
9
+ // "yellow" renamed to "orange" — existing serialized "yellow" values will fall through to chip-yellow class (no match) and render unstyled
10
+ @property({ type: String })
11
+ tone: "default" | "blue" | "orange" | "red" | "green" = "default";
12
+
13
+ @property({ type: String }) leadingIcon?: string;
14
+ @property({ type: String }) trailingIcon?: string;
15
+ /** Initials text for the avatar (e.g. "JD"). Mutually exclusive with leadingIcon. */
16
+ @property({ type: String }) avatar?: string;
17
+
18
+ @property({ type: Boolean }) removable = false;
19
+
20
+ /** IMPORTANT: reflected so CSS + Angular can see it */
21
+ @property({ type: Boolean, reflect: true }) removed = false;
22
+
23
+ static styles = css`
24
+ :host {
25
+ display: inline-flex;
26
+ width: auto;
27
+ flex: 0 0 auto;
28
+ }
29
+
30
+ :host([removed]) {
31
+ display: none;
32
+ }
33
+
34
+ .chip {
35
+ display: inline-flex;
36
+ align-items: center;
37
+ font-family: var(--rel-fontFamilies-primary);
38
+ font-size: var(--rel-fontSizes-md);
39
+ font-weight: var(--rel-fontWeights-medium);
40
+ border-radius: var(--rel-borders-radius-border-radius-100);
41
+ padding: var(--rel-spacing-space-2xs) var(--rel-spacing-space-xs);
42
+ gap: var(--rel-spacing-space-2xs);
43
+ cursor: pointer;
44
+ border: var(--rel-borders-width-stroke-100) solid transparent;
45
+ user-select: none;
46
+ white-space: nowrap;
47
+ background: transparent;
48
+ }
49
+
50
+ .chip:hover {
51
+ filter: brightness(0.88);
52
+ box-shadow: var(--rel-shadows-shadow-100);
53
+ }
54
+
55
+ .chip:focus-visible {
56
+ outline: 2px solid var(--rel-color-border-focus);
57
+ outline-offset: 2px;
58
+ }
59
+
60
+ .chip:active {
61
+ filter: brightness(0.80);
62
+ box-shadow: var(--rel-shadows-shadow-200);
63
+ }
64
+
65
+ /* TONES — light (default) */
66
+ /* NOTE: #717171 has no exact vars-v2 token; nearest candidates are
67
+ --rel-colors-gray-toast-bg (#404040) and --rel-colors-gray-divider (#BDBDBD) */
68
+ .chip-default {
69
+ background: #717171;
70
+ color: var(--rel-colors-white);
71
+ }
72
+
73
+ .chip-blue {
74
+ background: var(--rel-colors-blue-tertiary);
75
+ color: var(--rel-colors-white);
76
+ }
77
+
78
+ .chip-orange {
79
+ background: var(--rel-colors-yellow-pending);
80
+ color: var(--rel-colors-white);
81
+ }
82
+
83
+ .chip-red {
84
+ background: var(--rel-colors-red-primary);
85
+ color: var(--rel-colors-white);
86
+ }
87
+
88
+ .chip-green {
89
+ background: var(--rel-colors-green-tertiary);
90
+ color: var(--rel-colors-white);
91
+ }
92
+
93
+ /* AVATAR — light mode (all tones)
94
+ rel-avatar uses background-color: var(--rel-colors-gray-disabled-text).
95
+ Overriding that custom property here pins avatar bg to white across all tones.
96
+ NOTE: rel-avatar hardcodes color: #ffffff — text color (#000000) cannot be
97
+ overridden from outside the shadow DOM without ::part() or a custom property
98
+ in rel-avatar itself. */
99
+ .chip rel-avatar {
100
+ display: inline-flex;
101
+ width: 20px !important;
102
+ height: 20px !important;
103
+ flex-shrink: 0;
104
+ font-size: 10px;
105
+ }
106
+
107
+ .chip-default rel-avatar,
108
+ .chip-blue rel-avatar,
109
+ .chip-orange rel-avatar,
110
+ .chip-red rel-avatar,
111
+ .chip-green rel-avatar {
112
+ --rel-colors-gray-disabled-text: #ffffff;
113
+ --rel-avatar-color: #000000;
114
+ }
115
+
116
+ .chip-icon {
117
+ display: inline-flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ width: 16px;
121
+ height: 16px;
122
+ flex-shrink: 0;
123
+ }
124
+
125
+ .chip-icon * {
126
+ width: 100%;
127
+ height: 100%;
128
+ }
129
+
130
+ .chip-icon ::slotted(svg),
131
+ .chip-icon svg {
132
+ width: 16px;
133
+ height: 16px;
134
+ fill: currentColor;
135
+ }
136
+
137
+ .chip-remove {
138
+ margin-left: var(--rel-spacing-space-3xs);
139
+ cursor: pointer;
140
+ opacity: 0.7;
141
+ background: none;
142
+ border: none;
143
+ color: inherit;
144
+ font: inherit;
145
+ padding: 0;
146
+ line-height: 1;
147
+ }
148
+
149
+ .chip-remove:hover {
150
+ opacity: 1;
151
+ }
152
+
153
+ .chip-remove:focus-visible {
154
+ outline: 2px solid var(--rel-colors-white);
155
+ outline-offset: 1px;
156
+ border-radius: 2px;
157
+ }
158
+
159
+ /* DARK THEME */
160
+ /* NOTE: #717171 (chip-default dark color) has no exact vars-v2 token */
161
+ /* NOTE: #FFFBF5 (chip-orange dark bg) has no exact vars-v2 token;
162
+ nearest is --rel-colors-gray-light (#FAFAFA) */
163
+
164
+ /* Reinforce layout — external dark-mode stylesheets can override display/width on the host */
165
+ :host-context([data-theme="dark"]) .chip {
166
+ display: inline-flex;
167
+ width: auto;
168
+ }
169
+
170
+ :host-context([data-theme="dark"]) .chip-default {
171
+ /* --rel-colors-gray-screen-bg flips to #262626 in dark — hardcoded to preserve #EEEEEE */
172
+ background: #EEEEEE;
173
+ color: #717171;
174
+ }
175
+
176
+ :host-context([data-theme="dark"]) .chip-blue {
177
+ /* --rel-colors-blue-bg flips to #0f1e2c in dark mode — hardcoded to preserve #E1F2FF */
178
+ background: #E1F2FF;
179
+ color: var(--rel-colors-blue-tertiary);
180
+ }
181
+
182
+ :host-context([data-theme="dark"]) .chip-orange {
183
+ background: #FFFBF5;
184
+ color: var(--rel-colors-yellow-pending);
185
+ }
186
+
187
+ :host-context([data-theme="dark"]) .chip-red {
188
+ background: var(--rel-colors-red-light);
189
+ color: var(--rel-colors-red-primary);
190
+ }
191
+
192
+ :host-context([data-theme="dark"]) .chip-green {
193
+ background: var(--rel-colors-green-bg-light);
194
+ color: var(--rel-colors-green-tertiary);
195
+ }
196
+
197
+ /* AVATAR — dark mode (per tone: bg = light fill color, text = white) */
198
+ :host-context([data-theme="dark"]) .chip-default rel-avatar {
199
+ --rel-colors-gray-disabled-text: #717171;
200
+ --rel-avatar-color: #ffffff;
201
+ }
202
+
203
+ :host-context([data-theme="dark"]) .chip-blue rel-avatar {
204
+ --rel-colors-gray-disabled-text: #0059F4;
205
+ --rel-avatar-color: #ffffff;
206
+ }
207
+
208
+ :host-context([data-theme="dark"]) .chip-orange rel-avatar {
209
+ --rel-colors-gray-disabled-text: #FFBF43;
210
+ --rel-avatar-color: #ffffff;
211
+ }
212
+
213
+ :host-context([data-theme="dark"]) .chip-red rel-avatar {
214
+ --rel-colors-gray-disabled-text: #CC0000;
215
+ --rel-avatar-color: #ffffff;
216
+ }
217
+
218
+ :host-context([data-theme="dark"]) .chip-green rel-avatar {
219
+ --rel-colors-gray-disabled-text: #00A86B;
220
+ --rel-avatar-color: #ffffff;
221
+ }
222
+ `;
223
+
224
+ private get classes() {
225
+ return ["chip", `chip-${this.tone}`].join(" ");
226
+ }
227
+
228
+ private handleRemove(event: Event) {
229
+ event.stopPropagation();
230
+ this.removed = true;
231
+
232
+ this.dispatchEvent(
233
+ new CustomEvent("removed", {
234
+ bubbles: true,
235
+ composed: true,
236
+ })
237
+ );
238
+ }
239
+
240
+ render() {
241
+ const showAvatar = !!this.avatar;
242
+ const showLeadingIcon = !showAvatar && !!this.leadingIcon;
243
+
244
+ if (this.avatar && this.leadingIcon) {
245
+ console.warn(
246
+ "[rel-chip] leadingIcon and avatar are mutually exclusive. avatar takes precedence."
247
+ );
248
+ }
249
+
250
+ return html`
251
+ <span
252
+ class="${this.classes}"
253
+ role="button"
254
+ tabindex="0"
255
+ aria-label="${this.label}"
256
+ >
257
+ ${showAvatar
258
+ ? html`<rel-avatar type="text" text=${this.avatar} size="xs"></rel-avatar>`
259
+ : null}
260
+ ${showLeadingIcon
261
+ ? html`<span class="chip-icon">
262
+ ${this.renderIcon(this.leadingIcon!)}
263
+ </span>`
264
+ : null}
265
+
266
+ <span class="chip-label">${this.label}</span>
267
+
268
+ ${this.trailingIcon
269
+ ? html`<span class="chip-icon">
270
+ ${this.renderIcon(this.trailingIcon)}
271
+ </span>`
272
+ : null}
273
+ ${this.removable
274
+ ? html`<button
275
+ class="chip-remove"
276
+ aria-label="Remove ${this.label}"
277
+ @click=${this.handleRemove}
278
+ >
279
+ ✕
280
+ </button>`
281
+ : null}
282
+ </span>
283
+ `;
284
+ }
285
+
286
+ private renderIcon(iconString: string) {
287
+ const template = document.createElement("template");
288
+ template.innerHTML = iconString.trim();
289
+ return template.content.cloneNode(true);
290
+ }
291
+ }