@marianmeres/stuic 2.66.0 → 3.0.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/README.md +292 -4
- package/dist/README.md +41 -18
- package/dist/actions/popover/README.md +19 -0
- package/dist/actions/popover/index.css +6 -9
- package/dist/actions/popover/popover.svelte.js +2 -2
- package/dist/actions/tooltip/README.md +18 -0
- package/dist/actions/tooltip/index.css +5 -8
- package/dist/actions/tooltip/tooltip.svelte.js +1 -1
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +9 -10
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +3 -3
- package/dist/components/AlertConfirmPrompt/Current.svelte +15 -17
- package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +5 -3
- package/dist/components/AlertConfirmPrompt/acp-icons.js +5 -4
- package/dist/components/AlertConfirmPrompt/index.css +62 -0
- package/dist/components/AssetsPreview/AssetsPreview.svelte +92 -73
- package/dist/components/AssetsPreview/AssetsPreview.svelte.d.ts +1 -0
- package/dist/components/AssetsPreview/index.css +59 -0
- package/dist/components/Avatar/Avatar.svelte +32 -18
- package/dist/components/Avatar/Avatar.svelte.d.ts +1 -0
- package/dist/components/Avatar/README.md +166 -0
- package/dist/components/Avatar/index.css +128 -0
- package/dist/components/Backdrop/Backdrop.svelte +8 -2
- package/dist/components/Backdrop/Backdrop.svelte.d.ts +1 -0
- package/dist/components/Backdrop/README.md +71 -6
- package/dist/components/Backdrop/index.css +29 -0
- package/dist/components/Button/Button.svelte +117 -124
- package/dist/components/Button/Button.svelte.d.ts +35 -23
- package/dist/components/Button/README.md +87 -21
- package/dist/components/Button/index.css +473 -9
- package/dist/components/Button/index.d.ts +1 -1
- package/dist/components/Button/index.js +1 -1
- package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +7 -38
- package/dist/components/ButtonGroupRadio/README.md +82 -4
- package/dist/components/ButtonGroupRadio/index.css +152 -14
- package/dist/components/Collapsible/Collapsible.svelte +7 -7
- package/dist/components/Collapsible/Collapsible.svelte.d.ts +2 -2
- package/dist/components/Collapsible/README.md +34 -2
- package/dist/components/Collapsible/index.css +38 -0
- package/dist/components/CommandMenu/CommandMenu.svelte +13 -24
- package/dist/components/CommandMenu/README.md +39 -0
- package/dist/components/CommandMenu/index.css +45 -2
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte +53 -50
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +6 -5
- package/dist/components/DismissibleMessage/README.md +93 -11
- package/dist/components/DismissibleMessage/index.css +122 -8
- package/dist/components/DismissibleMessage/index.d.ts +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -50
- package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +6 -6
- package/dist/components/DropdownMenu/README.md +132 -0
- package/dist/components/DropdownMenu/index.css +231 -27
- package/dist/components/Input/FieldAssets.svelte +8 -5
- package/dist/components/Input/FieldCheckbox.svelte +7 -44
- package/dist/components/Input/FieldFile.svelte +1 -6
- package/dist/components/Input/FieldInput.svelte +1 -1
- package/dist/components/Input/FieldOptions.svelte +41 -38
- package/dist/components/Input/FieldRadios.svelte +7 -16
- package/dist/components/Input/FieldSelect.svelte +1 -1
- package/dist/components/Input/FieldSwitch.svelte +1 -5
- package/dist/components/Input/FieldTextarea.svelte +1 -1
- package/dist/components/Input/README.md +194 -0
- package/dist/components/Input/_internal/FieldRadioInternal.svelte +2 -40
- package/dist/components/Input/_internal/InputWrap.svelte +8 -48
- package/dist/components/Input/index.css +522 -127
- package/dist/components/ListItemButton/ListItemButton.svelte +37 -73
- package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +1 -9
- package/dist/components/ListItemButton/README.md +100 -45
- package/dist/components/ListItemButton/index.css +175 -56
- package/dist/components/ListItemButton/index.d.ts +1 -1
- package/dist/components/ListItemButton/index.js +1 -1
- package/dist/components/Modal/Modal.svelte +2 -8
- package/dist/components/Modal/Modal.svelte.d.ts +1 -0
- package/dist/components/Modal/README.md +29 -0
- package/dist/components/Modal/index.css +36 -0
- package/dist/components/ModalDialog/ModalDialog.svelte +2 -21
- package/dist/components/ModalDialog/README.md +35 -0
- package/dist/components/ModalDialog/index.css +57 -0
- package/dist/components/Notifications/Notifications.svelte +44 -128
- package/dist/components/Notifications/Notifications.svelte.d.ts +9 -17
- package/dist/components/Notifications/README.md +186 -70
- package/dist/components/Notifications/index.css +212 -15
- package/dist/components/Progress/README.md +15 -0
- package/dist/components/Progress/_internal/Bar.svelte +2 -2
- package/dist/components/Progress/index.css +4 -4
- package/dist/components/Skeleton/Skeleton.svelte +3 -2
- package/dist/components/Skeleton/index.css +11 -14
- package/dist/components/Spinner/Spinner.svelte +2 -2
- package/dist/components/Spinner/SpinnerCircle.svelte +1 -1
- package/dist/components/Switch/README.md +15 -0
- package/dist/components/Switch/Switch.svelte +4 -7
- package/dist/components/Switch/Switch.svelte.d.ts +1 -1
- package/dist/components/Switch/SwitchButton.svelte +4 -5
- package/dist/components/Switch/index.css +3 -4
- package/dist/components/TabbedMenu/README.md +26 -21
- package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -5
- package/dist/components/TabbedMenu/index.css +7 -22
- package/dist/components/ThemePreview/README.md +289 -0
- package/dist/components/ThemePreview/ThemePreview.svelte +341 -0
- package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +33 -0
- package/dist/components/ThemePreview/index.css +493 -0
- package/dist/components/ThemePreview/index.d.ts +1 -0
- package/dist/components/ThemePreview/index.js +1 -0
- package/dist/components/TwCheck/TwCheck.svelte +4 -4
- package/dist/components/TwCheck/index.css +3 -2
- package/dist/components/TypeaheadInput/TypeaheadInput.svelte +1 -1
- package/dist/components/X/X.svelte +12 -5
- package/dist/components/X/X.svelte.d.ts +1 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.css +31 -16
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/themes/blue-orange.css +163 -0
- package/dist/themes/blue-orange.d.ts +6 -0
- package/dist/themes/blue-orange.js +151 -0
- package/dist/themes/cyan-red.css +163 -0
- package/dist/themes/cyan-red.d.ts +6 -0
- package/dist/themes/cyan-red.js +151 -0
- package/dist/themes/cyan-slate.css +163 -0
- package/dist/themes/cyan-slate.d.ts +6 -0
- package/dist/themes/cyan-slate.js +151 -0
- package/dist/themes/emerald-pink.css +163 -0
- package/dist/themes/emerald-pink.d.ts +6 -0
- package/dist/themes/emerald-pink.js +151 -0
- package/dist/themes/fuchsia-emerald.css +163 -0
- package/dist/themes/fuchsia-emerald.d.ts +6 -0
- package/dist/themes/fuchsia-emerald.js +151 -0
- package/dist/themes/gray.css +163 -0
- package/dist/themes/gray.d.ts +6 -0
- package/dist/themes/gray.js +151 -0
- package/dist/themes/indigo-amber.css +163 -0
- package/dist/themes/indigo-amber.d.ts +6 -0
- package/dist/themes/indigo-amber.js +151 -0
- package/dist/themes/neutral.css +163 -0
- package/dist/themes/neutral.d.ts +6 -0
- package/dist/themes/neutral.js +151 -0
- package/dist/themes/pink-emerald.css +163 -0
- package/dist/themes/pink-emerald.d.ts +6 -0
- package/dist/themes/pink-emerald.js +151 -0
- package/dist/themes/purple-yellow.css +163 -0
- package/dist/themes/purple-yellow.d.ts +6 -0
- package/dist/themes/purple-yellow.js +151 -0
- package/dist/themes/rainbow.css +163 -0
- package/dist/themes/rainbow.d.ts +6 -0
- package/dist/themes/rainbow.js +156 -0
- package/dist/themes/red-blue.css +163 -0
- package/dist/themes/red-blue.d.ts +6 -0
- package/dist/themes/red-blue.js +151 -0
- package/dist/themes/red-cyan.css +163 -0
- package/dist/themes/red-cyan.d.ts +6 -0
- package/dist/themes/red-cyan.js +151 -0
- package/dist/themes/rose-teal.css +163 -0
- package/dist/themes/rose-teal.d.ts +6 -0
- package/dist/themes/rose-teal.js +151 -0
- package/dist/themes/sky-amber.css +163 -0
- package/dist/themes/sky-amber.d.ts +6 -0
- package/dist/themes/sky-amber.js +151 -0
- package/dist/themes/slate-cyan.css +163 -0
- package/dist/themes/slate-cyan.d.ts +6 -0
- package/dist/themes/slate-cyan.js +151 -0
- package/dist/themes/tailwind-color-pairs.md +31 -0
- package/dist/themes/teal-rose.css +163 -0
- package/dist/themes/teal-rose.d.ts +6 -0
- package/dist/themes/teal-rose.js +151 -0
- package/dist/themes/violet-lime.css +163 -0
- package/dist/themes/violet-lime.d.ts +6 -0
- package/dist/themes/violet-lime.js +151 -0
- package/dist/utils/design-tokens.d.ts +43 -0
- package/dist/utils/design-tokens.js +100 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +22 -2
package/README.md
CHANGED
|
@@ -1,8 +1,296 @@
|
|
|
1
1
|
# @marianmeres/stuic
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**S**velte **T**ailwind **UI** **C**omponents
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
An opinionated Svelte 5 component library built with Tailwind CSS v4. Featuring a centralized design token system for consistent theming across all components.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @marianmeres/stuic
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```svelte
|
|
16
|
+
<script>
|
|
17
|
+
import { Button, Modal } from "@marianmeres/stuic";
|
|
18
|
+
|
|
19
|
+
let modal;
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<Button onclick={() => modal.open()}>Open Modal</Button>
|
|
23
|
+
|
|
24
|
+
<Modal bind:this={modal}>
|
|
25
|
+
<p>Hello from Modal!</p>
|
|
26
|
+
</Modal>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Theming System
|
|
30
|
+
|
|
31
|
+
STUIC uses a 3-layer CSS variable token system that enables both global theming and per-component customization.
|
|
32
|
+
|
|
33
|
+
### Architecture
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Layer 1: Global Semantic Tokens (--stuic-accent, --stuic-surface, etc.)
|
|
37
|
+
↓ (used as fallback defaults)
|
|
38
|
+
Layer 2: Component Tokens (--stuic-button-bg, --stuic-input-accent, etc.)
|
|
39
|
+
↓ (Tailwind utility class references)
|
|
40
|
+
Layer 3: Instance Overrides (inline styles, class props)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Global Theming
|
|
44
|
+
|
|
45
|
+
Override global tokens in your app's CSS to change the entire library's appearance:
|
|
46
|
+
|
|
47
|
+
```css
|
|
48
|
+
/* app.css */
|
|
49
|
+
:root {
|
|
50
|
+
/* Change the accent color globally */
|
|
51
|
+
--stuic-accent: #6366f1; /* Indigo brand color */
|
|
52
|
+
--stuic-accent-hover: #4f46e5;
|
|
53
|
+
--stuic-accent-active: #4338ca;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.dark {
|
|
57
|
+
--stuic-accent: #818cf8;
|
|
58
|
+
--stuic-accent-hover: #a5b4fc;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Per-Component Customization
|
|
63
|
+
|
|
64
|
+
Override specific component tokens:
|
|
65
|
+
|
|
66
|
+
```css
|
|
67
|
+
:root {
|
|
68
|
+
/* Only change switches to green */
|
|
69
|
+
--stuic-switch-accent: #10b981;
|
|
70
|
+
|
|
71
|
+
/* Custom button colors */
|
|
72
|
+
--stuic-button-bg: #f3f4f6;
|
|
73
|
+
--stuic-button-bg-hover: #e5e7eb;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Instance Overrides
|
|
78
|
+
|
|
79
|
+
Use class props or inline styles for one-off customizations:
|
|
80
|
+
|
|
81
|
+
```svelte
|
|
82
|
+
<Button class="bg-purple-500 hover:bg-purple-600 text-white">
|
|
83
|
+
Custom Button
|
|
84
|
+
</Button>
|
|
85
|
+
|
|
86
|
+
<div style="--stuic-list-item-button-bg-hover: var(--color-blue-500);">
|
|
87
|
+
<ListItemButton>Blue hover</ListItemButton>
|
|
88
|
+
</div>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Global Design Tokens
|
|
92
|
+
|
|
93
|
+
All tokens are defined in `src/lib/theme.css`. See the full reference below.
|
|
94
|
+
|
|
95
|
+
### Accent Colors
|
|
96
|
+
|
|
97
|
+
| Token | Light Mode | Dark Mode | Description |
|
|
98
|
+
|-------|------------|-----------|-------------|
|
|
99
|
+
| `--stuic-accent` | `sky-600` | `sky-400` | Primary accent for interactive elements |
|
|
100
|
+
| `--stuic-accent-hover` | `sky-700` | `sky-300` | Accent hover state |
|
|
101
|
+
| `--stuic-accent-active` | `sky-800` | `sky-200` | Accent active/pressed state |
|
|
102
|
+
| `--stuic-accent-destructive` | `red-600` | `red-400` | Destructive/error accent |
|
|
103
|
+
| `--stuic-accent-destructive-hover` | `red-700` | `red-300` | Destructive hover state |
|
|
104
|
+
|
|
105
|
+
### Surface Colors
|
|
106
|
+
|
|
107
|
+
| Token | Light Mode | Dark Mode | Description |
|
|
108
|
+
|-------|------------|-----------|-------------|
|
|
109
|
+
| `--stuic-surface` | `white` | `neutral-900` | Base page background |
|
|
110
|
+
| `--stuic-surface-elevated` | `white` | `neutral-800` | Cards, modals, popovers |
|
|
111
|
+
| `--stuic-surface-sunken` | `neutral-100` | `neutral-700` | Input backgrounds, wells |
|
|
112
|
+
| `--stuic-surface-overlay` | `neutral-800` | `neutral-950` | Backdrops, tooltips |
|
|
113
|
+
| `--stuic-surface-interactive` | `neutral-200` | `neutral-600` | Buttons, list items |
|
|
114
|
+
| `--stuic-surface-interactive-hover` | `neutral-500` | `neutral-200` | Interactive hover |
|
|
115
|
+
| `--stuic-surface-interactive-active` | `neutral-600` | `neutral-100` | Interactive active |
|
|
116
|
+
|
|
117
|
+
### Text Colors
|
|
118
|
+
|
|
119
|
+
| Token | Light Mode | Dark Mode | Description |
|
|
120
|
+
|-------|------------|-----------|-------------|
|
|
121
|
+
| `--stuic-text` | `black` | `neutral-100` | Primary text |
|
|
122
|
+
| `--stuic-text-muted` | `neutral-600` | `neutral-400` | Secondary/muted text |
|
|
123
|
+
| `--stuic-text-inverse` | `white` | `neutral-900` | Text on dark backgrounds |
|
|
124
|
+
| `--stuic-text-placeholder` | `neutral-400` | `neutral-500` | Placeholder text |
|
|
125
|
+
| `--stuic-text-on-accent` | `white` | `neutral-950` | Text on accent backgrounds |
|
|
126
|
+
| `--stuic-text-destructive` | `red-600` | `red-400` | Error/destructive text |
|
|
127
|
+
|
|
128
|
+
### Border Colors
|
|
129
|
+
|
|
130
|
+
| Token | Light Mode | Dark Mode | Description |
|
|
131
|
+
|-------|------------|-----------|-------------|
|
|
132
|
+
| `--stuic-border` | `neutral-300` | `neutral-600` | Default border |
|
|
133
|
+
| `--stuic-border-strong` | `neutral-400` | `neutral-500` | Emphasized border |
|
|
134
|
+
| `--stuic-border-subtle` | `neutral-200` | `neutral-700` | Subtle/light border |
|
|
135
|
+
| `--stuic-border-focus` | `sky-500` | `sky-400` | Focus ring border |
|
|
136
|
+
| `--stuic-border-error` | `red-500` | `red-400` | Error state border |
|
|
137
|
+
|
|
138
|
+
### Other Tokens
|
|
139
|
+
|
|
140
|
+
| Token | Default | Description |
|
|
141
|
+
|-------|---------|-------------|
|
|
142
|
+
| `--stuic-ring` | `sky-500` / `sky-400` | Focus ring color |
|
|
143
|
+
| `--stuic-ring-offset` | `2px` | Focus ring offset |
|
|
144
|
+
| `--stuic-ring-width` | `2px` | Focus ring width |
|
|
145
|
+
| `--stuic-radius-sm` | `--radius-sm` | Small border radius |
|
|
146
|
+
| `--stuic-radius` | `--radius-md` | Default border radius |
|
|
147
|
+
| `--stuic-radius-lg` | `--radius-lg` | Large border radius |
|
|
148
|
+
| `--stuic-radius-full` | `9999px` | Fully rounded |
|
|
149
|
+
| `--stuic-transition-fast` | `100ms` | Fast transitions |
|
|
150
|
+
| `--stuic-transition-normal` | `150ms` | Normal transitions |
|
|
151
|
+
| `--stuic-transition-slow` | `300ms` | Slow transitions |
|
|
152
|
+
|
|
153
|
+
## Component Tokens
|
|
154
|
+
|
|
155
|
+
Each component defines its own tokens that reference global tokens as defaults:
|
|
156
|
+
|
|
157
|
+
| Component | Token Prefix | Key Tokens |
|
|
158
|
+
|-----------|--------------|------------|
|
|
159
|
+
| Button | `--stuic-button-*` | `bg`, `text`, `border`, `border-focus` |
|
|
160
|
+
| Switch | `--stuic-switch-*` | `accent` |
|
|
161
|
+
| Input | `--stuic-input-*` | `accent`, `accent-error` |
|
|
162
|
+
| Progress | `--stuic-progress-*` | `bg`, `accent` |
|
|
163
|
+
| ListItemButton | `--stuic-list-item-button-*` | `bg`, `text`, `border`, `bg-hover`, `text-hover`, etc. |
|
|
164
|
+
| ButtonGroupRadio | `--stuic-button-group-*` | `bg`, `text`, `border`, `accent`, `bg-active`, `text-active` |
|
|
165
|
+
| TabbedMenu | `--stuic-tabbed-menu-*` | `tab-bg`, `tab-text`, `tab-bg-active`, `tab-text-active`, `border` |
|
|
166
|
+
| DismissibleMessage | `--stuic-dismissible-message-*` | `bg`, `text`, `border` |
|
|
167
|
+
| Notifications | `--stuic-notification-*` | `bg`, `text`, `border` |
|
|
168
|
+
| Tooltip | `--stuic-tooltip-*` | `bg`, `text` |
|
|
169
|
+
| Popover | `--stuic-popover-*` | `bg`, `text`, `border` |
|
|
170
|
+
| Skeleton | `--stuic-skeleton-*` | `bg`, `bg-highlight`, `duration` |
|
|
171
|
+
|
|
172
|
+
## CSS Variable Naming Convention
|
|
173
|
+
|
|
174
|
+
**STRICT REQUIREMENT**: All CSS variables follow this pattern:
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
--stuic-{component}-{element?}-{property}-{state?}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
- **Full component names** (no abbreviations): `list-item-button` not `lib`
|
|
181
|
+
- **State at end**: `--stuic-button-bg-hover` not `--stuic-button-hover-bg`
|
|
182
|
+
- **No `-dark` suffix**: Dark mode defined in `.dark {}` selector
|
|
183
|
+
- **Properties**: `bg`, `text`, `border`, `ring`, `shadow`, `accent`
|
|
184
|
+
- **States**: `hover`, `active`, `focus`, `disabled`, `error`
|
|
185
|
+
|
|
186
|
+
### Examples
|
|
187
|
+
|
|
188
|
+
```css
|
|
189
|
+
/* Correct */
|
|
190
|
+
--stuic-button-bg
|
|
191
|
+
--stuic-button-bg-hover
|
|
192
|
+
--stuic-list-item-button-text-active
|
|
193
|
+
--stuic-input-accent-error
|
|
194
|
+
|
|
195
|
+
/* Incorrect */
|
|
196
|
+
--stuic-btn-bg /* abbreviated component name */
|
|
197
|
+
--stuic-button-hover-bg /* state not at end */
|
|
198
|
+
--stuic-button-bg-dark /* -dark suffix */
|
|
199
|
+
--color-lib-hover-bg /* old naming convention */
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Customization Approaches
|
|
203
|
+
|
|
204
|
+
### 1. CSS Variables (Recommended)
|
|
205
|
+
|
|
206
|
+
Set variables in your CSS for theming:
|
|
207
|
+
|
|
208
|
+
```css
|
|
209
|
+
:root {
|
|
210
|
+
--stuic-accent: #6366f1;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### 2. Class Props
|
|
215
|
+
|
|
216
|
+
Pass Tailwind classes directly to components:
|
|
217
|
+
|
|
218
|
+
```svelte
|
|
219
|
+
<Button class="bg-linear-to-r from-purple-500 to-pink-500">
|
|
220
|
+
Gradient Button
|
|
221
|
+
</Button>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 3. Unstyled Mode
|
|
225
|
+
|
|
226
|
+
Use `unstyled` prop to remove all default styling:
|
|
227
|
+
|
|
228
|
+
```svelte
|
|
229
|
+
<Button unstyled class="my-custom-button-class">
|
|
230
|
+
Fully Custom
|
|
231
|
+
</Button>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Components
|
|
235
|
+
|
|
236
|
+
See `src/lib/README.md` for the full component list and API documentation.
|
|
237
|
+
|
|
238
|
+
### Layout & Overlays
|
|
239
|
+
- AppShell, Backdrop, Modal, ModalDialog, Drawer
|
|
240
|
+
|
|
241
|
+
### Forms & Inputs
|
|
242
|
+
- FieldInput, FieldTextarea, FieldSelect, FieldCheckbox, FieldRadios, FieldFile, FieldAssets, FieldOptions, FieldKeyValues, FieldSwitch, Fieldset
|
|
243
|
+
|
|
244
|
+
### Buttons & Controls
|
|
245
|
+
- Button, ButtonGroupRadio, Switch, ListItemButton, X
|
|
246
|
+
|
|
247
|
+
### Feedback & Notifications
|
|
248
|
+
- Notifications, AlertConfirmPrompt, DismissibleMessage, Progress, Spinner, Skeleton
|
|
249
|
+
|
|
250
|
+
### Navigation & Menus
|
|
251
|
+
- CommandMenu, DropdownMenu, TabbedMenu, TypeaheadInput, KbdShortcut
|
|
252
|
+
|
|
253
|
+
### Utilities
|
|
254
|
+
- ColorScheme, Thc, SlidingPanels, HoverExpandableWidth, AnimatedElipsis
|
|
255
|
+
|
|
256
|
+
## Actions
|
|
257
|
+
|
|
258
|
+
```svelte
|
|
259
|
+
<input use:autogrow use:validate={{ required: true }} />
|
|
260
|
+
<button use:tooltip aria-label="Tooltip text">Hover me</button>
|
|
261
|
+
<div use:popover={{ content: 'Popover content' }}>Anchor</div>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
- `autogrow` - Auto-expand textarea height
|
|
265
|
+
- `validate` - Form validation with custom validators
|
|
266
|
+
- `focusTrap` - Trap focus within element
|
|
267
|
+
- `tooltip` - Tooltip from aria-label
|
|
268
|
+
- `popover` - Anchored popover
|
|
269
|
+
- `fileDropzone` - Drag-and-drop file upload
|
|
270
|
+
- `highlightDragover` - Visual feedback for drag operations
|
|
271
|
+
|
|
272
|
+
## TypeScript
|
|
273
|
+
|
|
274
|
+
All components export their Props types:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import type { ButtonProps, ModalProps, ListItemButtonProps } from "@marianmeres/stuic";
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Requirements
|
|
281
|
+
|
|
282
|
+
- Svelte 5 (runes mode)
|
|
283
|
+
- Tailwind CSS v4
|
|
284
|
+
- Modern browser with CSS custom properties support
|
|
285
|
+
|
|
286
|
+
## Breaking Changes in v2
|
|
287
|
+
|
|
288
|
+
- All CSS variables renamed from `--color-*` to `--stuic-*` prefix
|
|
289
|
+
- ListItemButton variables renamed from `--color-lib-*` to `--stuic-list-item-button-*`
|
|
290
|
+
- State naming changed from `--*-hover-bg` to `--*-bg-hover` (state at end)
|
|
291
|
+
- Removed `-dark` suffix from variables (use `.dark {}` selector instead)
|
|
292
|
+
- Legacy variable names preserved as aliases for backwards compatibility
|
|
293
|
+
|
|
294
|
+
## License
|
|
295
|
+
|
|
296
|
+
MIT
|
package/dist/README.md
CHANGED
|
@@ -53,6 +53,7 @@ npm install @marianmeres/stuic
|
|
|
53
53
|
- **Button** - Styled button with variants (primary, secondary, ghost)
|
|
54
54
|
- **ButtonGroupRadio** - Radio-style button group
|
|
55
55
|
- **Switch** - Toggle switch component
|
|
56
|
+
- **ListItemButton** - Versatile button for list contexts (dropdowns, menus)
|
|
56
57
|
- **X** - Close/dismiss button icon
|
|
57
58
|
|
|
58
59
|
### Feedback & Notifications
|
|
@@ -62,10 +63,13 @@ npm install @marianmeres/stuic
|
|
|
62
63
|
- **DismissibleMessage** - Closable message banner
|
|
63
64
|
- **Progress** - Progress bar indicator
|
|
64
65
|
- **Spinner** - Loading spinner animation
|
|
66
|
+
- **Skeleton** - Loading placeholder with shimmer animation
|
|
65
67
|
|
|
66
|
-
### Navigation &
|
|
68
|
+
### Navigation & Menus
|
|
67
69
|
|
|
68
70
|
- **CommandMenu** - Keyboard-driven command palette
|
|
71
|
+
- **DropdownMenu** - Anchored dropdown menu with keyboard navigation
|
|
72
|
+
- **TabbedMenu** - Tab-based navigation component
|
|
69
73
|
- **TypeaheadInput** - Autocomplete text input
|
|
70
74
|
- **KbdShortcut** - Keyboard shortcut display
|
|
71
75
|
|
|
@@ -76,17 +80,22 @@ npm install @marianmeres/stuic
|
|
|
76
80
|
- **SlidingPanels** - Animated panel transitions
|
|
77
81
|
- **HoverExpandableWidth** - Expand content on hover
|
|
78
82
|
- **AnimatedElipsis** - Animated loading dots
|
|
83
|
+
- **Collapsible** - Expandable/collapsible content sections
|
|
84
|
+
- **AssetsPreview** - Preview uploaded files/images
|
|
85
|
+
- **Circle** - Circular container/badge component
|
|
79
86
|
|
|
80
87
|
## Actions (use:action)
|
|
81
88
|
|
|
82
89
|
```svelte
|
|
83
90
|
<input use:autogrow use:validate={{ required: true }} />
|
|
91
|
+
<button use:tooltip aria-label="Tooltip text">Hover me</button>
|
|
84
92
|
```
|
|
85
93
|
|
|
86
94
|
- **autogrow** - Auto-expand textarea height
|
|
87
95
|
- **validate** - Form validation with custom validators
|
|
88
96
|
- **focusTrap** - Trap focus within element
|
|
89
|
-
- **tooltip** - Tooltip from aria-label
|
|
97
|
+
- **tooltip** - Tooltip from aria-label (CSS anchor positioning)
|
|
98
|
+
- **popover** - Anchored popover (CSS anchor positioning)
|
|
90
99
|
- **fileDropzone** - Drag-and-drop file upload
|
|
91
100
|
- **highlightDragover** - Visual feedback for drag operations
|
|
92
101
|
|
|
@@ -104,30 +113,44 @@ import { debounce, throttle, twMerge, localStorageState } from "@marianmeres/stu
|
|
|
104
113
|
- **getId** - Generate unique IDs
|
|
105
114
|
- **EventEmitter** - Typed event emitter
|
|
106
115
|
|
|
107
|
-
## Theming
|
|
108
|
-
|
|
109
|
-
Components use CSS custom properties for theming. Override in your CSS:
|
|
110
|
-
|
|
111
|
-
```css
|
|
112
|
-
:root {
|
|
113
|
-
--color-button-bg: theme("colors.blue.500");
|
|
114
|
-
--color-button-text: white;
|
|
115
|
-
--color-input-accent: theme("colors.blue.500");
|
|
116
|
-
/* ... */
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
See `src/lib/theme.css` for all available custom properties.
|
|
121
|
-
|
|
122
116
|
## TypeScript
|
|
123
117
|
|
|
124
118
|
All components export their Props types:
|
|
125
119
|
|
|
126
120
|
```ts
|
|
127
|
-
import type { ButtonProps, ModalProps } from "@marianmeres/stuic";
|
|
121
|
+
import type { ButtonProps, ModalProps, ListItemButtonProps } from "@marianmeres/stuic";
|
|
128
122
|
|
|
129
123
|
const buttonConfig: Partial<ButtonProps> = {
|
|
130
124
|
variant: "primary",
|
|
131
125
|
size: "lg",
|
|
132
126
|
};
|
|
133
127
|
```
|
|
128
|
+
|
|
129
|
+
## Component Token Reference
|
|
130
|
+
|
|
131
|
+
Each component with customizable styling defines CSS custom properties:
|
|
132
|
+
|
|
133
|
+
| Component | Prefix | Key Properties |
|
|
134
|
+
|-----------|--------|----------------|
|
|
135
|
+
| Button | `--stuic-button-*` | `bg`, `text`, `border`, `border-focus` |
|
|
136
|
+
| Switch | `--stuic-switch-*` | `accent` |
|
|
137
|
+
| Input | `--stuic-input-*` | `accent`, `accent-error` |
|
|
138
|
+
| Progress | `--stuic-progress-*` | `bg`, `accent` |
|
|
139
|
+
| Skeleton | `--stuic-skeleton-*` | `bg`, `bg-highlight`, `duration` |
|
|
140
|
+
| ListItemButton | `--stuic-list-item-button-*` | `bg`, `text`, `border`, plus `-hover`, `-active`, `-focus` states |
|
|
141
|
+
| ButtonGroupRadio | `--stuic-button-group-*` | `bg`, `text`, `border`, `accent`, `bg-active`, `text-active` |
|
|
142
|
+
| TabbedMenu | `--stuic-tabbed-menu-*` | `tab-bg`, `tab-text`, `tab-bg-active`, `tab-text-active`, `border` |
|
|
143
|
+
| DismissibleMessage | `--stuic-dismissible-message-*` | `bg`, `text`, `border` |
|
|
144
|
+
| Notifications | `--stuic-notification-*` | `bg`, `text`, `border` |
|
|
145
|
+
| Tooltip | `--stuic-tooltip-*` | `bg`, `text` |
|
|
146
|
+
| Popover | `--stuic-popover-*` | `bg`, `text`, `border` |
|
|
147
|
+
|
|
148
|
+
### CSS Variable Naming Convention
|
|
149
|
+
|
|
150
|
+
**Pattern:** `--stuic-{component}-{element?}-{property}-{state?}`
|
|
151
|
+
|
|
152
|
+
- Full component names (no abbreviations)
|
|
153
|
+
- State at end: `--stuic-button-bg-hover`
|
|
154
|
+
- No `-dark` suffix (use `.dark {}` selector)
|
|
155
|
+
|
|
156
|
+
See `AGENTS.md` for complete development guidelines.
|
|
@@ -137,6 +137,25 @@ if (isPopoverSupported()) {
|
|
|
137
137
|
}
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
+
## CSS Variables
|
|
141
|
+
|
|
142
|
+
| Variable | Default | Description |
|
|
143
|
+
|----------|---------|-------------|
|
|
144
|
+
| `--stuic-popover-bg` | `--stuic-surface-elevated` | Popover background |
|
|
145
|
+
| `--stuic-popover-text` | `--stuic-text` | Popover text color |
|
|
146
|
+
| `--stuic-popover-border` | `--stuic-border-subtle` | Popover border color |
|
|
147
|
+
|
|
148
|
+
### Example Override
|
|
149
|
+
|
|
150
|
+
```css
|
|
151
|
+
:root {
|
|
152
|
+
--stuic-popover-bg: var(--color-slate-50);
|
|
153
|
+
--stuic-popover-border: var(--color-slate-300);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Note:** Popover CSS variables may not work with inline style props because popovers are created outside the anchor's DOM tree. Set them in your global CSS.
|
|
158
|
+
|
|
140
159
|
## Notes
|
|
141
160
|
|
|
142
161
|
- Uses CSS Anchor Positioning API when available
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
--
|
|
7
|
-
--color-popover-text-dark: var(--color-popover-text-dark, var(--color-neutral-100));
|
|
8
|
-
--color-popover-border: var(--color-popover-border, var(--color-neutral-200));
|
|
9
|
-
--color-popover-border-dark: var(--color-popover-border-dark, var(--color-neutral-700));
|
|
1
|
+
/* Popover component tokens */
|
|
2
|
+
/* Note: style props will not work as with regular components, because popovers are created outside of the anchor DOM tree */
|
|
3
|
+
:root {
|
|
4
|
+
--stuic-popover-bg: var(--stuic-color-surface);
|
|
5
|
+
--stuic-popover-text: var(--stuic-color-foreground);
|
|
6
|
+
--stuic-popover-border: var(--stuic-color-border);
|
|
10
7
|
}
|
|
11
8
|
|
|
12
9
|
/* Base popover styles */
|
|
@@ -107,9 +107,9 @@ const POSITION_MAP = {
|
|
|
107
107
|
right: "right",
|
|
108
108
|
};
|
|
109
109
|
const _classPopover = `
|
|
110
|
-
bg-
|
|
110
|
+
bg-(--stuic-popover-bg) text-(--stuic-popover-text)
|
|
111
111
|
shadow-lg rounded-md
|
|
112
|
-
border border-
|
|
112
|
+
border border-(--stuic-popover-border)
|
|
113
113
|
z-50
|
|
114
114
|
`;
|
|
115
115
|
const _classBackdrop = `
|
|
@@ -127,6 +127,24 @@ if (isTooltipSupported()) {
|
|
|
127
127
|
- ARIA attributes are automatically managed (`aria-describedby`, `aria-expanded`)
|
|
128
128
|
- Maximum width is 16rem (256px) by default
|
|
129
129
|
|
|
130
|
+
## CSS Variables
|
|
131
|
+
|
|
132
|
+
| Variable | Default | Description |
|
|
133
|
+
|----------|---------|-------------|
|
|
134
|
+
| `--stuic-tooltip-bg` | `--stuic-surface-overlay` | Tooltip background |
|
|
135
|
+
| `--stuic-tooltip-text` | `--stuic-text-inverse` | Tooltip text color |
|
|
136
|
+
|
|
137
|
+
### Example Override
|
|
138
|
+
|
|
139
|
+
```css
|
|
140
|
+
:root {
|
|
141
|
+
--stuic-tooltip-bg: var(--color-indigo-900);
|
|
142
|
+
--stuic-tooltip-text: var(--color-indigo-100);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Note:** Tooltip CSS variables may not work with inline style props because tooltips are created outside the anchor's DOM tree. Set them in your global CSS.
|
|
147
|
+
|
|
130
148
|
## Browser Support
|
|
131
149
|
|
|
132
150
|
Check [Can I Use - CSS Anchor Positioning](https://caniuse.com/css-anchor-positioning) for current browser support. As of 2025, supported in Chrome 125+ and Edge 125+.
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
--color-tooltip-text: var(--color-tooltip-text, var(--color-white));
|
|
7
|
-
--color-tooltip-text-dark: var(--color-tooltip-text-dark, var(--color-black));
|
|
8
|
-
|
|
1
|
+
/* Tooltip component tokens */
|
|
2
|
+
/* Note: style props will not work as with regular components, because tooltips are created outside of the anchor DOM tree */
|
|
3
|
+
:root {
|
|
4
|
+
--stuic-tooltip-bg: var(--color-black);
|
|
5
|
+
--stuic-tooltip-text: var(--color-white);
|
|
9
6
|
}
|
|
10
7
|
|
|
11
8
|
.stuic-tooltip {
|
|
@@ -28,7 +28,7 @@ export function isTooltipSupported() {
|
|
|
28
28
|
CSS.supports("position-try-fallbacks", "top"));
|
|
29
29
|
}
|
|
30
30
|
const _classTooltip = `
|
|
31
|
-
bg-
|
|
31
|
+
bg-(--stuic-tooltip-bg) text-(--stuic-tooltip-text)
|
|
32
32
|
text-sm tracking-tight rounded my-1
|
|
33
33
|
px-2.5 py-1.5
|
|
34
34
|
max-w-64
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
classButtonCancel?: string;
|
|
22
22
|
classButtonCustom?: string;
|
|
23
23
|
classButtonPrimary?: string;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
intentButtonCancel?: string;
|
|
25
|
+
intentButtonCustom?: string;
|
|
26
|
+
intentButtonPrimary?: string;
|
|
27
27
|
classSpinnerBox?: string;
|
|
28
28
|
defaultIcons?: Partial<
|
|
29
29
|
Record<"info" | "success" | "warn" | "error" | "spinner", () => string | undefined>
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
<script lang="ts">
|
|
35
35
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
36
36
|
import ModalDialog from "../ModalDialog/ModalDialog.svelte";
|
|
37
|
-
import { isTHCNotEmpty } from "../Thc/Thc.svelte";
|
|
38
37
|
import { AlertConfirmPromptType } from "./alert-confirm-prompt-stack.svelte.js";
|
|
39
38
|
import Current from "./Current.svelte";
|
|
40
39
|
|
|
@@ -63,9 +62,9 @@
|
|
|
63
62
|
classButtonCancel,
|
|
64
63
|
classButtonCustom,
|
|
65
64
|
classButtonPrimary,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
intentButtonCancel,
|
|
66
|
+
intentButtonCustom,
|
|
67
|
+
intentButtonPrimary,
|
|
69
68
|
}: Props = $props();
|
|
70
69
|
|
|
71
70
|
let modal = $state<ModalDialog>();
|
|
@@ -124,9 +123,9 @@
|
|
|
124
123
|
{classButtonCancel}
|
|
125
124
|
{classButtonCustom}
|
|
126
125
|
{classButtonPrimary}
|
|
127
|
-
{
|
|
128
|
-
{
|
|
129
|
-
{
|
|
126
|
+
{intentButtonCancel}
|
|
127
|
+
{intentButtonCustom}
|
|
128
|
+
{intentButtonPrimary}
|
|
130
129
|
/>
|
|
131
130
|
</ModalDialog>
|
|
132
131
|
{/if}
|
|
@@ -19,9 +19,9 @@ export interface Props {
|
|
|
19
19
|
classButtonCancel?: string;
|
|
20
20
|
classButtonCustom?: string;
|
|
21
21
|
classButtonPrimary?: string;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
intentButtonCancel?: string;
|
|
23
|
+
intentButtonCustom?: string;
|
|
24
|
+
intentButtonPrimary?: string;
|
|
25
25
|
classSpinnerBox?: string;
|
|
26
26
|
defaultIcons?: Partial<Record<"info" | "success" | "warn" | "error" | "spinner", () => string | undefined>>;
|
|
27
27
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import type { IntentColorKey } from "../../utils/design-tokens.js";
|
|
3
3
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
4
4
|
import Button from "../Button/Button.svelte";
|
|
5
5
|
import FieldInput from "../Input/FieldInput.svelte";
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
AlertConfirmPromptType,
|
|
12
12
|
type AlertConfirmPromptStack,
|
|
13
13
|
} from "./alert-confirm-prompt-stack.svelte.js";
|
|
14
|
+
import "./index.css";
|
|
14
15
|
|
|
15
16
|
const { ALERT, CONFIRM, PROMPT } = AlertConfirmPromptType;
|
|
16
17
|
const isFn = (v: any) => typeof v === "function";
|
|
@@ -37,9 +38,9 @@
|
|
|
37
38
|
classButtonCancel?: string;
|
|
38
39
|
classButtonCustom?: string;
|
|
39
40
|
classButtonPrimary?: string;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
intentButtonCancel?: IntentColorKey;
|
|
42
|
+
intentButtonCustom?: IntentColorKey;
|
|
43
|
+
intentButtonPrimary?: IntentColorKey;
|
|
43
44
|
classSpinnerBox?: string;
|
|
44
45
|
defaultIcons?: Partial<
|
|
45
46
|
Record<"info" | "success" | "warn" | "error" | "spinner", () => string | undefined>
|
|
@@ -66,9 +67,9 @@
|
|
|
66
67
|
classButtonCancel,
|
|
67
68
|
classButtonCustom,
|
|
68
69
|
classButtonPrimary,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
intentButtonCancel,
|
|
71
|
+
intentButtonCustom,
|
|
72
|
+
intentButtonPrimary = "primary",
|
|
72
73
|
classSpinnerBox,
|
|
73
74
|
defaultIcons = acpDefaultIcons,
|
|
74
75
|
}: Props = $props();
|
|
@@ -119,11 +120,8 @@
|
|
|
119
120
|
|
|
120
121
|
const _classIconBox = `size-12 sm:size-10
|
|
121
122
|
mt-1 mb-4 sm:my-0 sm:mr-5
|
|
122
|
-
mx-auto
|
|
123
|
-
flex flex-shrink-0 items-center justify-center
|
|
124
|
-
rounded-full
|
|
125
|
-
bg-neutral-950/10 text-neutral-950/80
|
|
126
|
-
dark:bg-neutral-50/20 dark:text-neutral-50/80`;
|
|
123
|
+
mx-auto
|
|
124
|
+
flex flex-shrink-0 items-center justify-center`;
|
|
127
125
|
|
|
128
126
|
const _classContentBox = `mt-3 sm:mt-0 flex-1 h-full flex flex-col`; // overflow-hidden
|
|
129
127
|
|
|
@@ -137,12 +135,12 @@
|
|
|
137
135
|
|
|
138
136
|
const _classButton = "min-w-24 text-center w-full sm:w-auto";
|
|
139
137
|
|
|
140
|
-
const _classSpinnerBox = `absolute inset-0 flex items-center justify-center
|
|
138
|
+
const _classSpinnerBox = `absolute inset-0 flex items-center justify-center`;
|
|
141
139
|
|
|
142
140
|
let hasCustom = $derived(current.labelCustom && typeof current.onCustom === "function");
|
|
143
141
|
</script>
|
|
144
142
|
|
|
145
|
-
<div class={twMerge("stuic-acp", _class, classProp)}>
|
|
143
|
+
<div class={twMerge("stuic-acp", _class, classProp)} data-variant={current.variant}>
|
|
146
144
|
<div class={twMerge("wrap", _classWrap, classWrap)}>
|
|
147
145
|
{#if iconHtml}
|
|
148
146
|
<div
|
|
@@ -215,7 +213,7 @@
|
|
|
215
213
|
<li class={twMerge(_classMenuLi, classMenuLi, hasCustom && classMenuLiCustom)}>
|
|
216
214
|
<CmpButtonCancel
|
|
217
215
|
class={twMerge("cancel", _classButton, classButton, classButtonCancel)}
|
|
218
|
-
|
|
216
|
+
intent={intentButtonCancel}
|
|
219
217
|
disabled={isPending}
|
|
220
218
|
onclick={createOnClick("cancel", current.onCancel)}
|
|
221
219
|
>
|
|
@@ -227,7 +225,7 @@
|
|
|
227
225
|
<li class={twMerge(_classMenuLi, classMenuLi, classMenuLiCustom)}>
|
|
228
226
|
<CmpButtonCustom
|
|
229
227
|
class={twMerge("custom", _classButton, classButton, classButtonCustom)}
|
|
230
|
-
|
|
228
|
+
intent={intentButtonCustom}
|
|
231
229
|
disabled={isPending}
|
|
232
230
|
onclick={createOnClick("custom", current.onCustom!)}
|
|
233
231
|
>
|
|
@@ -238,7 +236,7 @@
|
|
|
238
236
|
<li class={twMerge(_classMenuLi, classMenuLi, hasCustom && classMenuLiCustom)}>
|
|
239
237
|
<CmpButtonOk
|
|
240
238
|
class={twMerge("ok", _classButton, classButton, classButtonPrimary)}
|
|
241
|
-
|
|
239
|
+
intent={intentButtonPrimary}
|
|
242
240
|
disabled={isPending}
|
|
243
241
|
onclick={createOnClick("ok", current.onOk)}
|
|
244
242
|
bind:el={okButtonEl}
|