@reliability-design/web 1.2.0 → 1.3.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.
- package/dist/components/rel-accordion/rel-accordion.ts +289 -135
- package/dist/components/rel-alert/rel-alert.ts +8 -1
- package/dist/components/rel-avatar/README.md +15 -4
- package/dist/components/rel-avatar/rel-avatar.ts +138 -96
- package/dist/components/rel-badge/README.md +7 -0
- package/dist/components/rel-badge/rel-badge.ts +61 -8
- package/dist/components/rel-button/rel-button.ts +64 -7
- package/dist/components/rel-chip/README.md +7 -0
- package/dist/components/rel-chip/rel-chip.ts +250 -130
- package/dist/components/rel-date-picker/rel-date-picker.ts +116 -14
- package/dist/components/rel-drawer/rel-drawer.ts +5 -2
- package/dist/components/rel-menubar/rel-menubar.ts +1 -0
- package/dist/components/rel-pagination/rel-pagination.ts +442 -425
- package/dist/components/rel-radio/rel-radio.ts +16 -16
- package/dist/components/rel-range-picker/rel-range-picker.css +349 -349
- package/dist/components/rel-range-picker/rel-range-picker.ts +1080 -1079
- package/dist/components/rel-select/README.md +34 -28
- package/dist/components/rel-select/rel-select.ts +1015 -346
- package/dist/components/rel-sheet/rel-sheet.ts +6 -3
- package/dist/components/rel-skeleton/rel-skeleton.ts +139 -0
- package/dist/components/rel-tab/rel-tab.ts +10 -4
- package/dist/components/rel-textfield/rel-textfield.ts +637 -349
- package/dist/components/rel-toast/rel-toast.ts +1 -6
- package/dist/components/rel-topbar/rel-topbar-actions.ts +4 -0
- package/dist/components/rel-topbar/rel-topbar-brand.ts +4 -0
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +4 -0
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +4 -0
- package/dist/components/rel-topbar/rel-topbar-item.ts +4 -0
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +4 -0
- package/dist/components/rel-topbar/rel-topbar-profile.ts +3 -0
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +4 -0
- package/dist/components/rel-topbar/rel-topbar.ts +6 -0
- package/dist/index.d.mts +239 -22
- package/dist/index.d.ts +239 -22
- package/dist/index.js +2609 -981
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2621 -994
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +17 -0
- package/dist/{vars-I2PC74XD.css → vars-F54UGCHM.css} +17 -0
- package/package.json +1 -1
|
@@ -1,96 +1,138 @@
|
|
|
1
|
-
import "../../styles/vars-v2.css";
|
|
2
|
-
import { LitElement, html, css } from "lit";
|
|
3
|
-
import { customElement, property } from "lit/decorators.js";
|
|
4
|
-
|
|
5
|
-
@customElement("rel-avatar")
|
|
6
|
-
export class RelAvatar extends LitElement {
|
|
7
|
-
@property({ type: String, reflect: true })
|
|
8
|
-
size: "lg" | "md" | "sm" | "xs" = "md";
|
|
9
|
-
|
|
10
|
-
@property({ type: String, reflect: true })
|
|
11
|
-
type: "image" | "text" | "icon" = "image";
|
|
12
|
-
|
|
13
|
-
@property({ type: String })
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@property({ type: String })
|
|
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
|
-
width:
|
|
81
|
-
height:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
1
|
+
import "../../styles/vars-v2.css";
|
|
2
|
+
import { LitElement, html, css } from "lit";
|
|
3
|
+
import { customElement, property } from "lit/decorators.js";
|
|
4
|
+
|
|
5
|
+
@customElement("rel-avatar")
|
|
6
|
+
export class RelAvatar extends LitElement {
|
|
7
|
+
@property({ type: String, reflect: true })
|
|
8
|
+
size: "lg" | "md" | "sm" | "xs" = "md";
|
|
9
|
+
|
|
10
|
+
@property({ type: String, reflect: true })
|
|
11
|
+
type: "image" | "text" | "icon" = "image";
|
|
12
|
+
|
|
13
|
+
@property({ type: String, reflect: true })
|
|
14
|
+
variant: "fill" | "subtle" | "outline" = "fill";
|
|
15
|
+
|
|
16
|
+
@property({ type: String }) src = "";
|
|
17
|
+
@property({ type: String }) text = "";
|
|
18
|
+
@property({ type: String }) alt = "Avatar";
|
|
19
|
+
@property({ type: String }) bg: string = "";
|
|
20
|
+
@property({ type: String }) color: string = "";
|
|
21
|
+
|
|
22
|
+
static styles = css`
|
|
23
|
+
:host {
|
|
24
|
+
display: inline-flex;
|
|
25
|
+
font-family: var(--rel-fontFamilies-primary);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.avatar {
|
|
29
|
+
display: inline-flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
border-radius: 50%;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
box-sizing: border-box;
|
|
35
|
+
border: var(--rel-borders-width-stroke-100, 1px) solid transparent;
|
|
36
|
+
font-weight: var(--rel-fontWeights-semibold);
|
|
37
|
+
user-select: none;
|
|
38
|
+
text-transform: uppercase;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* ── Variants ─────────────────────────────────────────────── */
|
|
42
|
+
|
|
43
|
+
:host([variant="fill"]) .avatar {
|
|
44
|
+
background-color: var(--rel-avatar-bg-fill, #0b0b0b);
|
|
45
|
+
color: var(--rel-avatar-color-fill, #ffffff);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host([variant="subtle"]) .avatar {
|
|
49
|
+
background-color: var(--rel-avatar-bg-subtle, #f5f5f5);
|
|
50
|
+
color: var(--rel-avatar-color-subtle, #0b0b0b);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:host([variant="outline"]) .avatar {
|
|
54
|
+
background-color: transparent;
|
|
55
|
+
border-color: var(--rel-avatar-border-outline, var(--rel-color-border-default));
|
|
56
|
+
color: var(--rel-avatar-color-outline, #0b0b0b);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ── Sizes ────────────────────────────────────────────────── */
|
|
60
|
+
|
|
61
|
+
.avatar-lg {
|
|
62
|
+
width: 40px;
|
|
63
|
+
height: 40px;
|
|
64
|
+
font-size: var(--rel-fontSizes-lg); /* 20px */
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.avatar-md {
|
|
68
|
+
width: 32px;
|
|
69
|
+
height: 32px;
|
|
70
|
+
font-size: 16px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.avatar-sm {
|
|
74
|
+
width: 24px;
|
|
75
|
+
height: 24px;
|
|
76
|
+
font-size: var(--rel-fontSizes-sm); /* 12px */
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.avatar-xs {
|
|
80
|
+
width: 20px;
|
|
81
|
+
height: 20px;
|
|
82
|
+
font-size: var(--rel-fontSizes-xs); /* 10px */
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ── Image ────────────────────────────────────────────────── */
|
|
86
|
+
|
|
87
|
+
img {
|
|
88
|
+
width: 100%;
|
|
89
|
+
height: 100%;
|
|
90
|
+
object-fit: cover;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* ── Icon slot ────────────────────────────────────────────── */
|
|
94
|
+
|
|
95
|
+
.icon-slot {
|
|
96
|
+
width: 100%;
|
|
97
|
+
height: 100%;
|
|
98
|
+
display: inline-flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
justify-content: center;
|
|
101
|
+
color: inherit;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.icon-slot ::slotted(svg) {
|
|
105
|
+
width: 50%;
|
|
106
|
+
height: 50%;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ── Dark mode ────────────────────────────────────────────────
|
|
110
|
+
:host() can never be preceded by a combinator inside a shadow-tree
|
|
111
|
+
stylesheet, so ":host-context(dark) :host([variant=...]) .avatar"
|
|
112
|
+
(the previous approach) is invalid and silently matches nothing.
|
|
113
|
+
Instead, redefine the same custom properties the variant rules
|
|
114
|
+
above already read via var(--token, fallback) — a plain
|
|
115
|
+
:host-context() selector with no compounding, guaranteed valid. ── */
|
|
116
|
+
|
|
117
|
+
:host-context([data-theme="dark"]) {
|
|
118
|
+
--rel-avatar-bg-fill: #ffffff;
|
|
119
|
+
--rel-avatar-color-fill: #0b0b0b;
|
|
120
|
+
--rel-avatar-bg-subtle: #2b2b2b;
|
|
121
|
+
--rel-avatar-color-subtle: #f5f5f5;
|
|
122
|
+
--rel-avatar-border-outline: #525252;
|
|
123
|
+
--rel-avatar-color-outline: #f5f5f5;
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
render() {
|
|
128
|
+
return html`
|
|
129
|
+
<div class="avatar avatar-${this.size}" style=${[this.bg ? `background-color:${this.bg}` : "", this.color ? `color:${this.color}` : ""].filter(Boolean).join(";")}>
|
|
130
|
+
${this.type === "image" && this.src
|
|
131
|
+
? html`<img src=${this.src} alt=${this.alt} />`
|
|
132
|
+
: this.type === "text"
|
|
133
|
+
? html`<span>${this.text}</span>`
|
|
134
|
+
: html`<span class="icon-slot"><slot></slot></span>`}
|
|
135
|
+
</div>
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -25,6 +25,11 @@ A simple notification badge component displaying numeric counts or dot indicator
|
|
|
25
25
|
<rel-badge number="1" size="sm"></rel-badge>
|
|
26
26
|
<rel-badge number="2" size="md"></rel-badge>
|
|
27
27
|
<rel-badge number="3" size="lg"></rel-badge>
|
|
28
|
+
|
|
29
|
+
<!-- Custom colors -->
|
|
30
|
+
<rel-badge number="3" color="#7d7d7d"></rel-badge>
|
|
31
|
+
<rel-badge number="3" color="teal" text-color="#1a1a1a"></rel-badge>
|
|
32
|
+
<rel-badge variant="dot" color="lavender"></rel-badge>
|
|
28
33
|
```
|
|
29
34
|
|
|
30
35
|
## API
|
|
@@ -35,6 +40,8 @@ A simple notification badge component displaying numeric counts or dot indicator
|
|
|
35
40
|
| `number` | `string` | `""` | Text to display in number variant (can be numeric or text like "99+") |
|
|
36
41
|
| `size` | `"sm" \| "md" \| "lg"` (reflected) | `"md"` | Size variant |
|
|
37
42
|
| `variant` | `"dot" \| "number"` (reflected) | `"number"` | Display mode (number shows text, dot shows indicator only) |
|
|
43
|
+
| `color` | `string` (reflected) | `""` | Direct CSS color override for the badge background. Accepts any valid CSS color (hex, rgb, hsl, named, `var(...)`). Falls back to the default token when empty |
|
|
44
|
+
| `text-color` | `string` (reflected) | `""` | Direct CSS color override for the badge text/icon color. Accepts any valid CSS color. Falls back to white when empty |
|
|
38
45
|
|
|
39
46
|
## Events
|
|
40
47
|
None.
|
|
@@ -16,6 +16,24 @@ export class RelBadge extends LitElement {
|
|
|
16
16
|
@property({ type: String, reflect: true })
|
|
17
17
|
variant: "dot" | "number" = "number";
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Direct CSS color override for the badge background. Accepts any valid
|
|
21
|
+
* CSS color value: hex, rgb(...), hsl(...), named color, or var(--token).
|
|
22
|
+
*
|
|
23
|
+
* Clear it (set to `''`) to fall back to the default token.
|
|
24
|
+
*/
|
|
25
|
+
@property({ type: String, reflect: true })
|
|
26
|
+
color = "";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Direct CSS color override for the badge text/icon color. Accepts any
|
|
30
|
+
* valid CSS color value: hex, rgb(...), hsl(...), named color, or var(--token).
|
|
31
|
+
*
|
|
32
|
+
* Clear it (set to `''`) to fall back to the default (white).
|
|
33
|
+
*/
|
|
34
|
+
@property({ type: String, reflect: true, attribute: "text-color" })
|
|
35
|
+
textColor = "";
|
|
36
|
+
|
|
19
37
|
static styles = css`
|
|
20
38
|
:host {
|
|
21
39
|
display: inline-flex;
|
|
@@ -25,46 +43,63 @@ export class RelBadge extends LitElement {
|
|
|
25
43
|
display: inline-flex;
|
|
26
44
|
align-items: center;
|
|
27
45
|
justify-content: center;
|
|
46
|
+
box-sizing: border-box;
|
|
28
47
|
font-family: var(--rel-fontFamilies-primary, sans-serif);
|
|
29
48
|
font-weight: var(--rel-fontWeights-semibold, 600);
|
|
30
|
-
background-color: var(--rel-error-surface-default);
|
|
31
|
-
color: #ffffff;
|
|
32
|
-
|
|
49
|
+
background-color: var(--rel-badge-bg, var(--rel-error-surface-default));
|
|
50
|
+
color: var(--rel-badge-color, #ffffff);
|
|
51
|
+
/* Large fixed radius (not 50%) — stays a perfect circle for 1-2 digits,
|
|
52
|
+
but becomes a pill instead of clipping when content like "999+"
|
|
53
|
+
is wider than the minimum circle. */
|
|
54
|
+
border-radius: 999px;
|
|
55
|
+
white-space: nowrap;
|
|
33
56
|
}
|
|
34
57
|
|
|
35
|
-
/* NUMBER BADGES
|
|
58
|
+
/* NUMBER BADGES — min-width (not width) lets multi-character content
|
|
59
|
+
like "999+" grow the badge into a pill instead of overflowing a fixed circle. */
|
|
36
60
|
.badge-sm {
|
|
37
|
-
width: 20px;
|
|
61
|
+
min-width: 20px;
|
|
38
62
|
height: 20px;
|
|
63
|
+
padding: 0 4px;
|
|
39
64
|
font-size: var(--rel-fontSizes-xs, 12px);
|
|
40
65
|
}
|
|
41
66
|
|
|
42
67
|
.badge-md {
|
|
43
|
-
width: 28px;
|
|
68
|
+
min-width: 28px;
|
|
44
69
|
height: 28px;
|
|
70
|
+
padding: 0 6px;
|
|
45
71
|
font-size: var(--rel-fontSizes-sm, 14px);
|
|
46
72
|
}
|
|
47
73
|
|
|
48
74
|
.badge-lg {
|
|
49
|
-
width: 40px;
|
|
75
|
+
min-width: 40px;
|
|
50
76
|
height: 40px;
|
|
77
|
+
padding: 0 8px;
|
|
51
78
|
font-size: var(--rel-fontSizes-lg, 20px);
|
|
52
79
|
}
|
|
53
80
|
|
|
54
|
-
/* DOT BADGES
|
|
81
|
+
/* DOT BADGES — explicitly reset min-width/padding inherited from the
|
|
82
|
+
number-badge size rules above; otherwise min-width wins over this
|
|
83
|
+
smaller width and the dot gets stretched into a squashed pill. */
|
|
55
84
|
.badge-dot.badge-sm {
|
|
56
85
|
width: 8px;
|
|
57
86
|
height: 8px;
|
|
87
|
+
min-width: 0;
|
|
88
|
+
padding: 0;
|
|
58
89
|
}
|
|
59
90
|
|
|
60
91
|
.badge-dot.badge-md {
|
|
61
92
|
width: 10px;
|
|
62
93
|
height: 10px;
|
|
94
|
+
min-width: 0;
|
|
95
|
+
padding: 0;
|
|
63
96
|
}
|
|
64
97
|
|
|
65
98
|
.badge-dot.badge-lg {
|
|
66
99
|
width: 12px;
|
|
67
100
|
height: 12px;
|
|
101
|
+
min-width: 0;
|
|
102
|
+
padding: 0;
|
|
68
103
|
}
|
|
69
104
|
`;
|
|
70
105
|
|
|
@@ -72,6 +107,24 @@ export class RelBadge extends LitElement {
|
|
|
72
107
|
return ["badge", `badge-${this.size}`, `badge-${this.variant}`].join(" ");
|
|
73
108
|
}
|
|
74
109
|
|
|
110
|
+
override updated(changedProperties: Map<PropertyKey, unknown>): void {
|
|
111
|
+
if (changedProperties.has("color")) {
|
|
112
|
+
if (this.color) {
|
|
113
|
+
this.style.setProperty("--rel-badge-bg", this.color);
|
|
114
|
+
} else {
|
|
115
|
+
this.style.removeProperty("--rel-badge-bg");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (changedProperties.has("textColor")) {
|
|
120
|
+
if (this.textColor) {
|
|
121
|
+
this.style.setProperty("--rel-badge-color", this.textColor);
|
|
122
|
+
} else {
|
|
123
|
+
this.style.removeProperty("--rel-badge-color");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
75
128
|
render() {
|
|
76
129
|
return html`
|
|
77
130
|
<span class="${this.classes}" aria-label=${this.ariaLabel || `${this.number} ${this.suffix}`}>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "../../styles/vars-v2.css";
|
|
2
|
+
import "../rel-badge/rel-badge";
|
|
2
3
|
import { LitElement, html, css } from "lit";
|
|
3
4
|
import { customElement, property } from "lit/decorators.js";
|
|
4
5
|
import { ifDefined } from "lit/directives/if-defined.js";
|
|
@@ -23,9 +24,33 @@ export class RelButton extends LitElement {
|
|
|
23
24
|
|
|
24
25
|
@property({ type: String, attribute: "aria-label" }) ariaLabel: string | null = null;
|
|
25
26
|
|
|
27
|
+
/** Numeric/overflow text shown in a corner badge (e.g. "3", "999+"). Ignored when badgeDot is set. */
|
|
28
|
+
@property({ type: String }) badge = "";
|
|
29
|
+
|
|
30
|
+
/** Shows a small corner dot instead of a numbered badge — takes precedence over `badge`. */
|
|
31
|
+
@property({ type: Boolean, attribute: "badge-dot" }) badgeDot = false;
|
|
32
|
+
|
|
26
33
|
static styles = css`
|
|
27
34
|
:host {
|
|
28
35
|
display: inline-flex;
|
|
36
|
+
position: relative;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.btn-badge {
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: -6px;
|
|
42
|
+
right: -6px;
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Icon buttons are a 40px circle (radius 20). An 8px dot's center needs to
|
|
47
|
+
land ON that circle's edge at the 45° corner point — which works out to
|
|
48
|
+
roughly 2px inward from each edge (R - R/√2 - dot-radius ≈ 1.9px), not
|
|
49
|
+
outside it like the numbered badge. Negative offsets here would float
|
|
50
|
+
the dot in the empty bounding-box corner outside the visible circle. */
|
|
51
|
+
.btn-badge[variant="dot"] {
|
|
52
|
+
top: 2px;
|
|
53
|
+
right: 2px;
|
|
29
54
|
}
|
|
30
55
|
|
|
31
56
|
button {
|
|
@@ -76,6 +101,10 @@ export class RelButton extends LitElement {
|
|
|
76
101
|
/* Disabled */
|
|
77
102
|
:host([disabled]) {
|
|
78
103
|
cursor: not-allowed;
|
|
104
|
+
/* Without this, clicks on a disabled button hit-test fall through the
|
|
105
|
+
inner button's pointer-events:none straight onto the host, which still
|
|
106
|
+
dispatches a normal click to any externally-attached listener. */
|
|
107
|
+
pointer-events: none;
|
|
79
108
|
}
|
|
80
109
|
|
|
81
110
|
:host([disabled]) button {
|
|
@@ -245,6 +274,27 @@ export class RelButton extends LitElement {
|
|
|
245
274
|
/* btn-link: blue in both modes — no dark override */
|
|
246
275
|
`;
|
|
247
276
|
|
|
277
|
+
connectedCallback() {
|
|
278
|
+
super.connectedCallback();
|
|
279
|
+
// Capture-phase, on the host itself: blocks programmatic el.click() calls
|
|
280
|
+
// and any other path that bypasses the inner button's pointer-events:none
|
|
281
|
+
// (e.g. CSS pointer-events doesn't stop .click(), which targets the host
|
|
282
|
+
// directly regardless of hit-testing).
|
|
283
|
+
this.addEventListener("click", this.handleHostClick, { capture: true });
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
disconnectedCallback() {
|
|
287
|
+
this.removeEventListener("click", this.handleHostClick, { capture: true });
|
|
288
|
+
super.disconnectedCallback();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private handleHostClick = (e: MouseEvent) => {
|
|
292
|
+
if (this.disabled) {
|
|
293
|
+
e.preventDefault();
|
|
294
|
+
e.stopImmediatePropagation();
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
|
|
248
298
|
private get classes() {
|
|
249
299
|
return [
|
|
250
300
|
`btn-${this.variant}`,
|
|
@@ -261,16 +311,15 @@ export class RelButton extends LitElement {
|
|
|
261
311
|
return;
|
|
262
312
|
}
|
|
263
313
|
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
composed: true,
|
|
269
|
-
})
|
|
270
|
-
);
|
|
314
|
+
// Native click events are already composed: true, so this bubbles
|
|
315
|
+
// through the shadow boundary to the host on its own — no re-dispatch
|
|
316
|
+
// needed. (A manual re-dispatch here previously caused every @click
|
|
317
|
+
// listener on <rel-button> to fire twice per real click.)
|
|
271
318
|
}
|
|
272
319
|
|
|
273
320
|
render() {
|
|
321
|
+
const showBadge = this.badgeDot || !!this.badge;
|
|
322
|
+
|
|
274
323
|
return html`
|
|
275
324
|
<button
|
|
276
325
|
class="${this.classes}"
|
|
@@ -281,6 +330,14 @@ export class RelButton extends LitElement {
|
|
|
281
330
|
>
|
|
282
331
|
<slot></slot>
|
|
283
332
|
</button>
|
|
333
|
+
${showBadge
|
|
334
|
+
? html`<rel-badge
|
|
335
|
+
class="btn-badge"
|
|
336
|
+
variant=${this.badgeDot ? "dot" : "number"}
|
|
337
|
+
number=${this.badge}
|
|
338
|
+
size="sm"
|
|
339
|
+
></rel-badge>`
|
|
340
|
+
: null}
|
|
284
341
|
`;
|
|
285
342
|
}
|
|
286
343
|
}
|
|
@@ -17,6 +17,9 @@ A compact chip component for displaying tags, labels, or selected options. Suppo
|
|
|
17
17
|
<!-- Outline variant -->
|
|
18
18
|
<rel-chip label="Outline Style" tone="blue" outline></rel-chip>
|
|
19
19
|
|
|
20
|
+
<!-- Small size variant -->
|
|
21
|
+
<rel-chip label="Small" size="sm" tone="blue"></rel-chip>
|
|
22
|
+
|
|
20
23
|
<!-- With avatar -->
|
|
21
24
|
<rel-chip id="avatarChip" label="John Doe" avatar="./user.jpg"></rel-chip>
|
|
22
25
|
|
|
@@ -43,6 +46,7 @@ A compact chip component for displaying tags, labels, or selected options. Suppo
|
|
|
43
46
|
| Name | Type | Default | Description |
|
|
44
47
|
|------|------|---------|-------------|
|
|
45
48
|
| `label` | `string` | `"Label"` | Text displayed on the chip |
|
|
49
|
+
| `size` (reflected) | `"sm" \| "md"` | `"md"` | Chip size variant |
|
|
46
50
|
| `tone` | `"default" \| "blue" \| "yellow" \| "red" \| "green"` | `"default"` | Color tone variant |
|
|
47
51
|
| `leadingIcon` | `string` | - | SVG or HTML string for leading icon |
|
|
48
52
|
| `trailingIcon` | `string` | - | SVG or HTML string for trailing icon |
|
|
@@ -103,6 +107,9 @@ None exposed.
|
|
|
103
107
|
- Remove button focus: 2px white outline with 1px offset
|
|
104
108
|
|
|
105
109
|
## Notes / Edge Cases
|
|
110
|
+
- **Size variants**:
|
|
111
|
+
- **md** (default): `--rel-fontSizes-md` text, `--rel-spacing-space-2xs`/`--rel-spacing-space-xs` padding, 20px × 20px avatar, 16px × 16px icons
|
|
112
|
+
- **sm**: `--rel-fontSizes-sm` text, `--rel-spacing-space-3xs`/`--rel-spacing-space-2xs` padding, 16px × 16px avatar, 12px × 12px icons
|
|
106
113
|
- Icons (`leadingIcon`, `trailingIcon`) must be passed as raw HTML/SVG strings via JavaScript (see examples)
|
|
107
114
|
- Icons are injected using `renderIcon()` which creates a template element and clones the content
|
|
108
115
|
- Avatar images are 20px × 20px circular (`border-radius: 50%`, `object-fit: cover`)
|