@arclux/arc-ui 1.3.0 → 1.5.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.
- package/package.json +2 -1
- package/src/button-styles.js +50 -0
- package/src/card-styles.js +42 -0
- package/src/content/accordion.js +3 -0
- package/src/content/avatar.js +35 -4
- package/src/content/badge.js +6 -0
- package/src/content/callout.js +48 -27
- package/src/content/card.js +20 -27
- package/src/content/divider.js +40 -2
- package/src/content/feature-card.js +3 -28
- package/src/content/skeleton.js +20 -9
- package/src/content/stat.js +35 -2
- package/src/content/tag.js +6 -0
- package/src/feedback/alert.js +18 -53
- package/src/feedback/modal.js +19 -4
- package/src/feedback/progress.js +23 -1
- package/src/feedback/toast.js +48 -33
- package/src/input/button.js +33 -37
- package/src/input/checkbox.js +10 -0
- package/src/input/chip.js +10 -48
- package/src/input/icon-button.js +15 -31
- package/src/input/input.js +29 -1
- package/src/input/radio-group.js +10 -0
- package/src/input/select.js +31 -1
- package/src/input/textarea.js +28 -6
- package/src/input/toggle.js +11 -0
- package/src/layout/container.js +16 -4
- package/src/navigation/breadcrumb.js +4 -2
- package/src/navigation/footer.js +9 -1
- package/src/navigation/link.js +15 -4
- package/src/navigation/navigation-menu.js +29 -4
- package/src/navigation/pagination.js +35 -24
- package/src/navigation/sidebar.js +19 -1
- package/src/navigation/tabs.js +30 -1
- package/src/navigation/top-bar.js +28 -14
- package/src/shared-styles.js +8 -0
- package/src/status-styles.js +33 -0
- package/src/status-utils.js +12 -0
- package/src/tokens.css +322 -0
package/src/content/stat.js
CHANGED
|
@@ -3,8 +3,10 @@ import { tokenStyles } from '../shared-styles.js';
|
|
|
3
3
|
|
|
4
4
|
export class ArcStat extends LitElement {
|
|
5
5
|
static properties = {
|
|
6
|
-
value:
|
|
7
|
-
label:
|
|
6
|
+
value: { type: String },
|
|
7
|
+
label: { type: String },
|
|
8
|
+
trend: { type: String, reflect: true },
|
|
9
|
+
change: { type: String },
|
|
8
10
|
};
|
|
9
11
|
|
|
10
12
|
static styles = [
|
|
@@ -49,6 +51,25 @@ export class ArcStat extends LitElement {
|
|
|
49
51
|
text-transform: uppercase;
|
|
50
52
|
color: var(--text-muted);
|
|
51
53
|
}
|
|
54
|
+
|
|
55
|
+
.stat__trend {
|
|
56
|
+
display: inline-flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: 4px;
|
|
59
|
+
font-family: var(--font-mono);
|
|
60
|
+
font-size: var(--text-sm);
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
margin-top: var(--space-xs);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
:host([trend="up"]) .stat__trend { color: var(--color-success); }
|
|
66
|
+
:host([trend="down"]) .stat__trend { color: var(--color-error); }
|
|
67
|
+
:host([trend="neutral"]) .stat__trend { color: var(--text-muted); }
|
|
68
|
+
|
|
69
|
+
.stat__trend-arrow {
|
|
70
|
+
width: 12px;
|
|
71
|
+
height: 12px;
|
|
72
|
+
}
|
|
52
73
|
`,
|
|
53
74
|
];
|
|
54
75
|
|
|
@@ -56,14 +77,26 @@ export class ArcStat extends LitElement {
|
|
|
56
77
|
super();
|
|
57
78
|
this.value = '';
|
|
58
79
|
this.label = '';
|
|
80
|
+
this.trend = '';
|
|
81
|
+
this.change = '';
|
|
59
82
|
}
|
|
60
83
|
|
|
61
84
|
render() {
|
|
85
|
+
const arrowUp = html`<svg class="stat__trend-arrow" viewBox="0 0 16 16" fill="currentColor"><path d="M8 3.5l4.5 5H3.5z"/></svg>`;
|
|
86
|
+
const arrowDown = html`<svg class="stat__trend-arrow" viewBox="0 0 16 16" fill="currentColor"><path d="M8 12.5l4.5-5H3.5z"/></svg>`;
|
|
87
|
+
const dash = html`<svg class="stat__trend-arrow" viewBox="0 0 16 16" fill="currentColor"><rect x="3" y="7" width="10" height="2" rx="1"/></svg>`;
|
|
88
|
+
|
|
62
89
|
return html`
|
|
63
90
|
<div class="stat" part="stat">
|
|
64
91
|
<span class="stat__value" part="value">${this.value}</span>
|
|
65
92
|
<span class="stat__rule"></span>
|
|
66
93
|
<span class="stat__label" part="label">${this.label}</span>
|
|
94
|
+
${this.trend ? html`
|
|
95
|
+
<span class="stat__trend" part="trend">
|
|
96
|
+
${this.trend === 'up' ? arrowUp : this.trend === 'down' ? arrowDown : dash}
|
|
97
|
+
${this.change || ''}
|
|
98
|
+
</span>
|
|
99
|
+
` : ''}
|
|
67
100
|
</div>
|
|
68
101
|
`;
|
|
69
102
|
}
|
package/src/content/tag.js
CHANGED
|
@@ -4,6 +4,7 @@ import { tokenStyles } from '../shared-styles.js';
|
|
|
4
4
|
export class ArcTag extends LitElement {
|
|
5
5
|
static properties = {
|
|
6
6
|
variant: { type: String, reflect: true },
|
|
7
|
+
size: { type: String, reflect: true },
|
|
7
8
|
removable: { type: Boolean, reflect: true },
|
|
8
9
|
disabled: { type: Boolean, reflect: true },
|
|
9
10
|
color: { type: String },
|
|
@@ -70,6 +71,10 @@ export class ArcTag extends LitElement {
|
|
|
70
71
|
:host([variant="warning"]) .tag:hover { box-shadow: 0 0 12px rgba(var(--color-warning-rgb), 0.15); }
|
|
71
72
|
:host([variant="danger"]) .tag:hover { box-shadow: 0 0 12px rgba(var(--color-error-rgb), 0.15); }
|
|
72
73
|
|
|
74
|
+
/* Sizes */
|
|
75
|
+
:host([size="sm"]) .tag { font-size: calc(var(--text-xs) - 1px); padding: 2px var(--space-sm); letter-spacing: 1.5px; }
|
|
76
|
+
:host([size="lg"]) .tag { font-size: var(--text-sm); padding: var(--space-sm) var(--space-lg); }
|
|
77
|
+
|
|
73
78
|
.tag__label {
|
|
74
79
|
display: inline-flex;
|
|
75
80
|
align-items: center;
|
|
@@ -118,6 +123,7 @@ export class ArcTag extends LitElement {
|
|
|
118
123
|
constructor() {
|
|
119
124
|
super();
|
|
120
125
|
this.variant = 'default';
|
|
126
|
+
this.size = 'md';
|
|
121
127
|
this.removable = false;
|
|
122
128
|
this.disabled = false;
|
|
123
129
|
this.color = '';
|
package/src/feedback/alert.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import { tokenStyles } from '../shared-styles.js';
|
|
3
|
+
import { statusVars } from '../status-styles.js';
|
|
4
|
+
import { getStatusIcon } from '../status-utils.js';
|
|
3
5
|
|
|
4
6
|
export class ArcAlert extends LitElement {
|
|
5
7
|
static properties = {
|
|
6
8
|
variant: { type: String, reflect: true },
|
|
9
|
+
compact: { type: Boolean, reflect: true },
|
|
7
10
|
dismissible: { type: Boolean },
|
|
8
11
|
heading: { type: String },
|
|
9
12
|
};
|
|
10
13
|
|
|
11
14
|
static styles = [
|
|
12
15
|
tokenStyles,
|
|
16
|
+
statusVars,
|
|
13
17
|
css`
|
|
14
18
|
:host { display: block; }
|
|
15
19
|
|
|
@@ -32,24 +36,8 @@ export class ArcAlert extends LitElement {
|
|
|
32
36
|
left: 0;
|
|
33
37
|
right: 0;
|
|
34
38
|
height: 2px;
|
|
35
|
-
background: var(--
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
:host([variant="info"]) .alert::before {
|
|
39
|
-
background: linear-gradient(90deg, transparent, var(--accent-primary), transparent);
|
|
40
|
-
box-shadow: 0 0 12px rgba(var(--accent-primary-rgb), 0.15);
|
|
41
|
-
}
|
|
42
|
-
:host([variant="success"]) .alert::before {
|
|
43
|
-
background: linear-gradient(90deg, transparent, var(--color-success), transparent);
|
|
44
|
-
box-shadow: 0 0 12px rgba(var(--color-success-rgb), 0.15);
|
|
45
|
-
}
|
|
46
|
-
:host([variant="warning"]) .alert::before {
|
|
47
|
-
background: linear-gradient(90deg, transparent, var(--color-warning), transparent);
|
|
48
|
-
box-shadow: 0 0 12px rgba(var(--color-warning-rgb), 0.15);
|
|
49
|
-
}
|
|
50
|
-
:host([variant="error"]) .alert::before {
|
|
51
|
-
background: linear-gradient(90deg, transparent, var(--color-error), transparent);
|
|
52
|
-
box-shadow: 0 0 12px rgba(var(--color-error-rgb), 0.15);
|
|
39
|
+
background: linear-gradient(90deg, transparent, var(--_status-color), transparent);
|
|
40
|
+
box-shadow: 0 0 12px rgba(var(--_status-rgb), 0.15);
|
|
53
41
|
}
|
|
54
42
|
|
|
55
43
|
.alert__icon-wrap {
|
|
@@ -62,31 +50,10 @@ export class ArcAlert extends LitElement {
|
|
|
62
50
|
border-radius: var(--radius-md);
|
|
63
51
|
font-size: var(--text-md);
|
|
64
52
|
transition: box-shadow var(--transition-base);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
border: 1px solid rgba(var(--accent-primary-rgb), 0.15);
|
|
70
|
-
color: var(--accent-primary);
|
|
71
|
-
box-shadow: 0 0 16px rgba(var(--accent-primary-rgb), 0.1);
|
|
72
|
-
}
|
|
73
|
-
:host([variant="success"]) .alert__icon-wrap {
|
|
74
|
-
background: rgba(var(--color-success-rgb), 0.08);
|
|
75
|
-
border: 1px solid rgba(var(--color-success-rgb), 0.15);
|
|
76
|
-
color: var(--color-success);
|
|
77
|
-
box-shadow: 0 0 16px rgba(var(--color-success-rgb), 0.1);
|
|
78
|
-
}
|
|
79
|
-
:host([variant="warning"]) .alert__icon-wrap {
|
|
80
|
-
background: rgba(var(--color-warning-rgb), 0.08);
|
|
81
|
-
border: 1px solid rgba(var(--color-warning-rgb), 0.15);
|
|
82
|
-
color: var(--color-warning);
|
|
83
|
-
box-shadow: 0 0 16px rgba(var(--color-warning-rgb), 0.1);
|
|
84
|
-
}
|
|
85
|
-
:host([variant="error"]) .alert__icon-wrap {
|
|
86
|
-
background: rgba(var(--color-error-rgb), 0.08);
|
|
87
|
-
border: 1px solid rgba(var(--color-error-rgb), 0.15);
|
|
88
|
-
color: var(--color-error);
|
|
89
|
-
box-shadow: 0 0 16px rgba(var(--color-error-rgb), 0.1);
|
|
53
|
+
background: rgba(var(--_status-rgb), 0.08);
|
|
54
|
+
border: 1px solid rgba(var(--_status-rgb), 0.15);
|
|
55
|
+
color: var(--_status-color);
|
|
56
|
+
box-shadow: 0 0 16px rgba(var(--_status-rgb), 0.1);
|
|
90
57
|
}
|
|
91
58
|
|
|
92
59
|
.alert__body { flex: 1; min-width: 0; }
|
|
@@ -106,6 +73,12 @@ export class ArcAlert extends LitElement {
|
|
|
106
73
|
color: var(--text-secondary);
|
|
107
74
|
}
|
|
108
75
|
|
|
76
|
+
/* Compact variant */
|
|
77
|
+
:host([compact]) .alert { padding: var(--space-sm) var(--space-md); gap: var(--space-sm); }
|
|
78
|
+
:host([compact]) .alert__icon-wrap { width: 24px; height: 24px; font-size: var(--text-sm); }
|
|
79
|
+
:host([compact]) .alert__heading { font-size: var(--text-sm); margin-bottom: 2px; }
|
|
80
|
+
:host([compact]) .alert__content { font-size: var(--text-xs); }
|
|
81
|
+
|
|
109
82
|
.alert__dismiss {
|
|
110
83
|
position: absolute;
|
|
111
84
|
top: var(--space-sm);
|
|
@@ -150,19 +123,11 @@ export class ArcAlert extends LitElement {
|
|
|
150
123
|
constructor() {
|
|
151
124
|
super();
|
|
152
125
|
this.variant = 'info';
|
|
126
|
+
this.compact = false;
|
|
153
127
|
this.dismissible = false;
|
|
154
128
|
this.heading = '';
|
|
155
129
|
}
|
|
156
130
|
|
|
157
|
-
_getIcon() {
|
|
158
|
-
switch (this.variant) {
|
|
159
|
-
case 'success': return '\u2713';
|
|
160
|
-
case 'warning': return '\u26A0';
|
|
161
|
-
case 'error': return '\u2717';
|
|
162
|
-
default: return '\u2139';
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
131
|
_dismiss() {
|
|
167
132
|
this.dispatchEvent(new CustomEvent('arc-dismiss', { bubbles: true, composed: true }));
|
|
168
133
|
this.style.display = 'none';
|
|
@@ -171,7 +136,7 @@ export class ArcAlert extends LitElement {
|
|
|
171
136
|
render() {
|
|
172
137
|
return html`
|
|
173
138
|
<div class="alert" role="alert" part="alert">
|
|
174
|
-
<div class="alert__icon-wrap" part="icon">${this.
|
|
139
|
+
<div class="alert__icon-wrap" part="icon">${getStatusIcon(this.variant)}</div>
|
|
175
140
|
<div class="alert__body">
|
|
176
141
|
${this.heading ? html`<p class="alert__heading" part="heading">${this.heading}</p>` : ''}
|
|
177
142
|
<div class="alert__content" part="content"><slot></slot></div>
|
package/src/feedback/modal.js
CHANGED
|
@@ -3,10 +3,11 @@ import { tokenStyles } from '../shared-styles.js';
|
|
|
3
3
|
|
|
4
4
|
export class ArcModal extends LitElement {
|
|
5
5
|
static properties = {
|
|
6
|
-
open:
|
|
7
|
-
heading:
|
|
8
|
-
size:
|
|
9
|
-
|
|
6
|
+
open: { type: Boolean, reflect: true },
|
|
7
|
+
heading: { type: String },
|
|
8
|
+
size: { type: String, reflect: true },
|
|
9
|
+
fullscreen: { type: Boolean, reflect: true },
|
|
10
|
+
closable: { type: Boolean },
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
static styles = [
|
|
@@ -58,6 +59,19 @@ export class ArcModal extends LitElement {
|
|
|
58
59
|
:host([size="md"]) .modal__dialog { max-width: 560px; }
|
|
59
60
|
:host([size="lg"]) .modal__dialog { max-width: 720px; }
|
|
60
61
|
|
|
62
|
+
:host([fullscreen]) .modal__dialog {
|
|
63
|
+
max-width: none;
|
|
64
|
+
max-height: none;
|
|
65
|
+
width: 100%;
|
|
66
|
+
height: 100%;
|
|
67
|
+
border-radius: 0;
|
|
68
|
+
border: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
:host([fullscreen]) .modal__backdrop {
|
|
72
|
+
padding: 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
61
75
|
.modal__header {
|
|
62
76
|
display: flex;
|
|
63
77
|
align-items: center;
|
|
@@ -127,6 +141,7 @@ export class ArcModal extends LitElement {
|
|
|
127
141
|
this.open = false;
|
|
128
142
|
this.heading = '';
|
|
129
143
|
this.size = 'md';
|
|
144
|
+
this.fullscreen = false;
|
|
130
145
|
this.closable = true;
|
|
131
146
|
this._handleKeydown = this._handleKeydown.bind(this);
|
|
132
147
|
}
|
package/src/feedback/progress.js
CHANGED
|
@@ -7,6 +7,7 @@ export class ArcProgress extends LitElement {
|
|
|
7
7
|
variant: { type: String, reflect: true },
|
|
8
8
|
size: { type: String, reflect: true },
|
|
9
9
|
indeterminate: { type: Boolean, reflect: true },
|
|
10
|
+
showValue: { type: Boolean, attribute: 'show-value', reflect: true },
|
|
10
11
|
label: { type: String },
|
|
11
12
|
};
|
|
12
13
|
|
|
@@ -84,6 +85,19 @@ export class ArcProgress extends LitElement {
|
|
|
84
85
|
animation: spinner-dash 1.4s ease-in-out infinite;
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
.progress__header {
|
|
89
|
+
display: flex;
|
|
90
|
+
justify-content: space-between;
|
|
91
|
+
align-items: baseline;
|
|
92
|
+
margin-bottom: var(--space-xs);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.progress__value {
|
|
96
|
+
font-family: var(--font-mono);
|
|
97
|
+
font-size: var(--text-xs);
|
|
98
|
+
color: var(--text-muted);
|
|
99
|
+
}
|
|
100
|
+
|
|
87
101
|
@keyframes progress-indeterminate {
|
|
88
102
|
0% { transform: translateX(-100%); }
|
|
89
103
|
100% { transform: translateX(400%); }
|
|
@@ -115,6 +129,7 @@ export class ArcProgress extends LitElement {
|
|
|
115
129
|
this.variant = 'bar';
|
|
116
130
|
this.size = 'md';
|
|
117
131
|
this.indeterminate = false;
|
|
132
|
+
this.showValue = false;
|
|
118
133
|
this.label = '';
|
|
119
134
|
}
|
|
120
135
|
|
|
@@ -143,9 +158,16 @@ export class ArcProgress extends LitElement {
|
|
|
143
158
|
`;
|
|
144
159
|
}
|
|
145
160
|
|
|
161
|
+
const hasHeader = this.label || (this.showValue && !this.indeterminate);
|
|
162
|
+
|
|
146
163
|
return html`
|
|
147
164
|
<div part="progress">
|
|
148
|
-
${
|
|
165
|
+
${hasHeader ? html`
|
|
166
|
+
<div class="progress__header">
|
|
167
|
+
${this.label ? html`<span class="progress__label" style="margin-bottom:0" part="label">${this.label}</span>` : html`<span></span>`}
|
|
168
|
+
${this.showValue && !this.indeterminate ? html`<span class="progress__value" part="value">${clampedValue}%</span>` : ''}
|
|
169
|
+
</div>
|
|
170
|
+
` : ''}
|
|
149
171
|
<div
|
|
150
172
|
class="progress__track"
|
|
151
173
|
role="progressbar"
|
package/src/feedback/toast.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import { tokenStyles } from '../shared-styles.js';
|
|
3
|
+
import { getStatusIcon } from '../status-utils.js';
|
|
4
|
+
|
|
5
|
+
/** Returns inline style string setting --_status-color/rgb for a given variant */
|
|
6
|
+
function statusStyle(variant) {
|
|
7
|
+
const map = {
|
|
8
|
+
info: { color: 'var(--accent-primary)', rgb: 'var(--accent-primary-rgb)' },
|
|
9
|
+
success: { color: 'var(--color-success)', rgb: 'var(--color-success-rgb)' },
|
|
10
|
+
warning: { color: 'var(--color-warning)', rgb: 'var(--color-warning-rgb)' },
|
|
11
|
+
error: { color: 'var(--color-error)', rgb: 'var(--color-error-rgb)' },
|
|
12
|
+
};
|
|
13
|
+
const v = map[variant] || map.info;
|
|
14
|
+
return `--_status-color:${v.color};--_status-rgb:${v.rgb}`;
|
|
15
|
+
}
|
|
3
16
|
|
|
4
17
|
export class ArcToast extends LitElement {
|
|
5
18
|
static properties = {
|
|
@@ -71,33 +84,16 @@ export class ArcToast extends LitElement {
|
|
|
71
84
|
left: 0;
|
|
72
85
|
right: 0;
|
|
73
86
|
height: 2px;
|
|
74
|
-
background: var(--
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.toast--info::after {
|
|
78
|
-
background: linear-gradient(90deg, transparent, var(--accent-primary), transparent);
|
|
79
|
-
}
|
|
80
|
-
.toast--success::after {
|
|
81
|
-
background: linear-gradient(90deg, transparent, var(--color-success), transparent);
|
|
82
|
-
}
|
|
83
|
-
.toast--warning::after {
|
|
84
|
-
background: linear-gradient(90deg, transparent, var(--color-warning), transparent);
|
|
85
|
-
}
|
|
86
|
-
.toast--error::after {
|
|
87
|
-
background: linear-gradient(90deg, transparent, var(--color-error), transparent);
|
|
87
|
+
background: linear-gradient(90deg, transparent, var(--_status-color), transparent);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
.toast__icon {
|
|
91
91
|
font-size: var(--text-sm);
|
|
92
92
|
flex-shrink: 0;
|
|
93
93
|
line-height: 1;
|
|
94
|
+
color: var(--_status-color);
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
.toast--info .toast__icon { color: var(--accent-primary); }
|
|
97
|
-
.toast--success .toast__icon { color: var(--color-success); }
|
|
98
|
-
.toast--warning .toast__icon { color: var(--color-warning); }
|
|
99
|
-
.toast--error .toast__icon { color: var(--color-error); }
|
|
100
|
-
|
|
101
97
|
.toast__message { flex: 1; }
|
|
102
98
|
|
|
103
99
|
.toast__dismiss {
|
|
@@ -114,6 +110,26 @@ export class ArcToast extends LitElement {
|
|
|
114
110
|
|
|
115
111
|
.toast__dismiss:hover { color: var(--text-primary); }
|
|
116
112
|
|
|
113
|
+
.toast__action {
|
|
114
|
+
background: none;
|
|
115
|
+
border: none;
|
|
116
|
+
color: var(--_status-color);
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
font-family: var(--font-accent);
|
|
119
|
+
font-size: var(--text-xs);
|
|
120
|
+
font-weight: 600;
|
|
121
|
+
letter-spacing: 1px;
|
|
122
|
+
text-transform: uppercase;
|
|
123
|
+
padding: var(--space-xs) var(--space-sm);
|
|
124
|
+
border-radius: var(--radius-sm);
|
|
125
|
+
transition: background var(--transition-fast);
|
|
126
|
+
white-space: nowrap;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.toast__action:hover {
|
|
130
|
+
background: rgba(var(--_status-rgb), 0.1);
|
|
131
|
+
}
|
|
132
|
+
|
|
117
133
|
.toast.is-exiting {
|
|
118
134
|
animation: toast-out 200ms ease-in forwards;
|
|
119
135
|
}
|
|
@@ -149,25 +165,21 @@ export class ArcToast extends LitElement {
|
|
|
149
165
|
this._counter = 0;
|
|
150
166
|
}
|
|
151
167
|
|
|
152
|
-
|
|
153
|
-
switch (variant) {
|
|
154
|
-
case 'success': return '\u2713';
|
|
155
|
-
case 'warning': return '\u26A0';
|
|
156
|
-
case 'error': return '\u2717';
|
|
157
|
-
default: return '\u2139';
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
show({ message, variant = 'info', duration }) {
|
|
168
|
+
show({ message, variant = 'info', duration, action, actionLabel, persistent = false }) {
|
|
162
169
|
const id = ++this._counter;
|
|
163
170
|
const dur = duration ?? this.duration;
|
|
164
|
-
this._toasts = [...this._toasts, { id, message, variant }];
|
|
171
|
+
this._toasts = [...this._toasts, { id, message, variant, action, actionLabel }];
|
|
165
172
|
|
|
166
|
-
if (dur > 0) {
|
|
173
|
+
if (!persistent && dur > 0) {
|
|
167
174
|
setTimeout(() => this._dismiss(id), dur);
|
|
168
175
|
}
|
|
169
176
|
}
|
|
170
177
|
|
|
178
|
+
_handleAction(toast) {
|
|
179
|
+
if (toast.action) toast.action();
|
|
180
|
+
this._dismiss(toast.id);
|
|
181
|
+
}
|
|
182
|
+
|
|
171
183
|
_dismiss(id) {
|
|
172
184
|
if (!this._toasts.some(t => t.id === id)) return;
|
|
173
185
|
const el = this.shadowRoot.querySelector(`[data-toast-id="${id}"]`);
|
|
@@ -193,9 +205,12 @@ export class ArcToast extends LitElement {
|
|
|
193
205
|
return html`
|
|
194
206
|
<div class="toast-container" role="status" aria-live="polite" aria-atomic="false" part="container">
|
|
195
207
|
${this._toasts.map(t => html`
|
|
196
|
-
<div class="toast
|
|
197
|
-
<span class="toast__icon" aria-hidden="true">${
|
|
208
|
+
<div class="toast" style=${statusStyle(t.variant)} data-toast-id=${t.id} part="toast">
|
|
209
|
+
<span class="toast__icon" aria-hidden="true">${getStatusIcon(t.variant)}</span>
|
|
198
210
|
<span class="toast__message">${t.message}</span>
|
|
211
|
+
${t.actionLabel ? html`
|
|
212
|
+
<button class="toast__action" @click=${() => this._handleAction(t)} part="action">${t.actionLabel}</button>
|
|
213
|
+
` : ''}
|
|
199
214
|
<button class="toast__dismiss" @click=${() => this._dismiss(t.id)} aria-label="Dismiss">×</button>
|
|
200
215
|
</div>
|
|
201
216
|
`)}
|
package/src/input/button.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import { tokenStyles } from '../shared-styles.js';
|
|
3
|
+
import { buttonVariantStyles } from '../button-styles.js';
|
|
3
4
|
|
|
4
5
|
export class ArcButton extends LitElement {
|
|
5
6
|
static properties = {
|
|
@@ -7,6 +8,7 @@ export class ArcButton extends LitElement {
|
|
|
7
8
|
size: { type: String, reflect: true },
|
|
8
9
|
href: { type: String },
|
|
9
10
|
disabled: { type: Boolean, reflect: true },
|
|
11
|
+
loading: { type: Boolean, reflect: true },
|
|
10
12
|
type: { type: String },
|
|
11
13
|
_hasPrefix: { state: true },
|
|
12
14
|
_hasSuffix: { state: true },
|
|
@@ -14,9 +16,30 @@ export class ArcButton extends LitElement {
|
|
|
14
16
|
|
|
15
17
|
static styles = [
|
|
16
18
|
tokenStyles,
|
|
19
|
+
buttonVariantStyles,
|
|
17
20
|
css`
|
|
18
21
|
:host { display: inline-flex; }
|
|
19
|
-
:host([disabled])
|
|
22
|
+
:host([disabled]),
|
|
23
|
+
:host([loading]) { pointer-events: none; }
|
|
24
|
+
|
|
25
|
+
:host([loading]) .btn { opacity: 0.7; }
|
|
26
|
+
|
|
27
|
+
.btn__spinner {
|
|
28
|
+
display: none;
|
|
29
|
+
width: 14px;
|
|
30
|
+
height: 14px;
|
|
31
|
+
border: 2px solid currentColor;
|
|
32
|
+
border-top-color: transparent;
|
|
33
|
+
border-radius: var(--radius-full);
|
|
34
|
+
animation: arc-btn-spin 600ms linear infinite;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:host([loading]) .btn__spinner { display: inline-block; }
|
|
38
|
+
:host([loading]) .btn__label { opacity: 0.6; }
|
|
39
|
+
|
|
40
|
+
@keyframes arc-btn-spin {
|
|
41
|
+
to { transform: rotate(360deg); }
|
|
42
|
+
}
|
|
20
43
|
|
|
21
44
|
.btn {
|
|
22
45
|
display: inline-flex;
|
|
@@ -48,55 +71,26 @@ export class ArcButton extends LitElement {
|
|
|
48
71
|
:host([size="md"]) .btn { font-size: var(--text-xs); padding: var(--space-sm) var(--space-lg); }
|
|
49
72
|
:host([size="lg"]) .btn { font-size: var(--text-xs); padding: var(--space-md) var(--space-xl); letter-spacing: 3px; }
|
|
50
73
|
|
|
51
|
-
/*
|
|
52
|
-
:host(:not([variant])) .btn
|
|
53
|
-
:host([variant="primary"]) .btn {
|
|
74
|
+
/* Default → primary */
|
|
75
|
+
:host(:not([variant])) .btn {
|
|
54
76
|
background: var(--accent-primary);
|
|
55
77
|
color: var(--bg-deep);
|
|
56
78
|
border-color: var(--accent-primary);
|
|
57
79
|
}
|
|
58
|
-
:host(:not([variant])) .btn:hover
|
|
59
|
-
|
|
80
|
+
:host(:not([variant])) .btn:hover { box-shadow: var(--glow-primary); }
|
|
81
|
+
|
|
82
|
+
/* :active scale */
|
|
60
83
|
:host(:not([variant])) .btn:active,
|
|
61
84
|
:host([variant="primary"]) .btn:active { transform: scale(0.97); box-shadow: 0 0 8px rgba(var(--accent-primary-rgb),0.5); }
|
|
62
|
-
|
|
63
|
-
/* Secondary */
|
|
64
|
-
:host([variant="secondary"]) .btn {
|
|
65
|
-
background: transparent;
|
|
66
|
-
color: var(--text-primary);
|
|
67
|
-
border-color: var(--border-default);
|
|
68
|
-
}
|
|
69
|
-
:host([variant="secondary"]) .btn:hover {
|
|
70
|
-
border-color: var(--accent-primary);
|
|
71
|
-
color: var(--accent-primary);
|
|
72
|
-
box-shadow: 0 0 20px var(--accent-primary-ring);
|
|
73
|
-
}
|
|
74
85
|
:host([variant="secondary"]) .btn:active {
|
|
75
86
|
transform: scale(0.97);
|
|
76
87
|
background: rgba(var(--accent-primary-rgb),0.05);
|
|
77
88
|
}
|
|
78
|
-
|
|
79
|
-
/* Ghost */
|
|
80
|
-
:host([variant="ghost"]) .btn {
|
|
81
|
-
background: transparent;
|
|
82
|
-
color: var(--text-muted);
|
|
83
|
-
border-color: transparent;
|
|
84
|
-
}
|
|
85
|
-
:host([variant="ghost"]) .btn:hover {
|
|
86
|
-
color: var(--text-primary);
|
|
87
|
-
background: var(--bg-hover);
|
|
88
|
-
}
|
|
89
89
|
:host([variant="ghost"]) .btn:active {
|
|
90
90
|
transform: scale(0.97);
|
|
91
91
|
background: var(--bg-elevated);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
/* Focus */
|
|
95
|
-
.btn:focus-visible { outline: none; box-shadow: var(--focus-glow); }
|
|
96
|
-
|
|
97
|
-
/* Disabled */
|
|
98
|
-
:host([disabled]) .btn { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
|
|
99
|
-
|
|
100
94
|
/* Prefix / Suffix */
|
|
101
95
|
.btn__prefix,
|
|
102
96
|
.btn__suffix {
|
|
@@ -130,6 +124,7 @@ export class ArcButton extends LitElement {
|
|
|
130
124
|
this.size = 'md';
|
|
131
125
|
this.href = '';
|
|
132
126
|
this.disabled = false;
|
|
127
|
+
this.loading = false;
|
|
133
128
|
this.type = 'button';
|
|
134
129
|
this._hasPrefix = false;
|
|
135
130
|
this._hasSuffix = false;
|
|
@@ -145,10 +140,11 @@ export class ArcButton extends LitElement {
|
|
|
145
140
|
|
|
146
141
|
_renderContent() {
|
|
147
142
|
return html`
|
|
143
|
+
${this.loading ? html`<span class="btn__spinner" aria-hidden="true"></span>` : ''}
|
|
148
144
|
<span class="btn__prefix ${this._hasPrefix ? '' : 'btn__prefix--empty'}">
|
|
149
145
|
<slot name="prefix" @slotchange=${this._onPrefixSlotChange}></slot>
|
|
150
146
|
</span>
|
|
151
|
-
<slot></slot>
|
|
147
|
+
<span class="btn__label"><slot></slot></span>
|
|
152
148
|
<span class="btn__suffix ${this._hasSuffix ? '' : 'btn__suffix--empty'}">
|
|
153
149
|
<slot name="suffix" @slotchange=${this._onSuffixSlotChange}></slot>
|
|
154
150
|
</span>
|
|
@@ -159,7 +155,7 @@ export class ArcButton extends LitElement {
|
|
|
159
155
|
if (this.href) {
|
|
160
156
|
return html`<a class="btn" href=${this.href} part="button">${this._renderContent()}</a>`;
|
|
161
157
|
}
|
|
162
|
-
return html`<button class="btn" type=${this.type} ?disabled=${this.disabled} part="button">${this._renderContent()}</button>`;
|
|
158
|
+
return html`<button class="btn" type=${this.type} ?disabled=${this.disabled || this.loading} aria-busy=${this.loading ? 'true' : 'false'} part="button">${this._renderContent()}</button>`;
|
|
163
159
|
}
|
|
164
160
|
}
|
|
165
161
|
|
package/src/input/checkbox.js
CHANGED
|
@@ -8,6 +8,7 @@ export class ArcCheckbox extends LitElement {
|
|
|
8
8
|
checked: { type: Boolean, reflect: true },
|
|
9
9
|
indeterminate: { type: Boolean, reflect: true },
|
|
10
10
|
disabled: { type: Boolean, reflect: true },
|
|
11
|
+
size: { type: String, reflect: true },
|
|
11
12
|
label: { type: String },
|
|
12
13
|
name: { type: String },
|
|
13
14
|
value: { type: String },
|
|
@@ -77,6 +78,14 @@ export class ArcCheckbox extends LitElement {
|
|
|
77
78
|
user-select: none;
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
/* Sizes */
|
|
82
|
+
:host([size="sm"]) .checkbox__box { width: 14px; height: 14px; }
|
|
83
|
+
:host([size="sm"]) .checkbox__icon { width: 10px; height: 10px; }
|
|
84
|
+
:host([size="sm"]) .checkbox__label { font-size: var(--text-sm); }
|
|
85
|
+
:host([size="lg"]) .checkbox__box { width: 22px; height: 22px; }
|
|
86
|
+
:host([size="lg"]) .checkbox__icon { width: 14px; height: 14px; }
|
|
87
|
+
:host([size="lg"]) .checkbox__label { font-size: var(--text-md); }
|
|
88
|
+
|
|
80
89
|
.checkbox__box:focus-visible {
|
|
81
90
|
outline: none;
|
|
82
91
|
box-shadow: var(--focus-glow);
|
|
@@ -100,6 +109,7 @@ export class ArcCheckbox extends LitElement {
|
|
|
100
109
|
this.checked = false;
|
|
101
110
|
this.indeterminate = false;
|
|
102
111
|
this.disabled = false;
|
|
112
|
+
this.size = 'md';
|
|
103
113
|
this.label = '';
|
|
104
114
|
this.name = '';
|
|
105
115
|
this.value = '';
|