@marianmeres/stuic 2.66.0 → 3.0.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/README.md +292 -4
- package/dist/README.md +41 -18
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- 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/actions/typeahead.svelte.d.ts +53 -0
- package/dist/actions/typeahead.svelte.js +328 -0
- package/dist/base.css +17 -0
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +10 -10
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +4 -3
- package/dist/components/AlertConfirmPrompt/Current.svelte +15 -18
- package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +4 -3
- package/dist/components/AlertConfirmPrompt/acp-icons.js +5 -4
- package/dist/components/AlertConfirmPrompt/index.css +66 -0
- package/dist/components/AssetsPreview/AssetsPreview.svelte +91 -73
- package/dist/components/AssetsPreview/index.css +61 -0
- package/dist/components/Avatar/Avatar.svelte +31 -18
- package/dist/components/Avatar/README.md +166 -0
- package/dist/components/Avatar/index.css +130 -0
- package/dist/components/Backdrop/Backdrop.svelte +7 -2
- package/dist/components/Backdrop/README.md +71 -6
- package/dist/components/Backdrop/index.css +31 -0
- package/dist/components/Button/Button.svelte +116 -124
- package/dist/components/Button/Button.svelte.d.ts +35 -24
- package/dist/components/Button/README.md +87 -21
- package/dist/components/Button/index.css +475 -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 -39
- package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte.d.ts +0 -1
- package/dist/components/ButtonGroupRadio/README.md +82 -4
- package/dist/components/ButtonGroupRadio/index.css +158 -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 +40 -0
- package/dist/components/CommandMenu/CommandMenu.svelte +18 -26
- package/dist/components/CommandMenu/CommandMenu.svelte.d.ts +0 -1
- package/dist/components/CommandMenu/README.md +39 -0
- package/dist/components/CommandMenu/index.css +47 -2
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte +53 -51
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +6 -6
- package/dist/components/DismissibleMessage/README.md +93 -11
- package/dist/components/DismissibleMessage/index.css +128 -8
- package/dist/components/DismissibleMessage/index.d.ts +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -51
- package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +6 -7
- package/dist/components/DropdownMenu/README.md +132 -0
- package/dist/components/DropdownMenu/index.css +258 -52
- 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 +9 -1
- package/dist/components/Input/FieldInput.svelte.d.ts +2 -0
- package/dist/components/Input/FieldOptions.svelte +42 -39
- 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 +524 -116
- package/dist/components/KbdShortcut/KbdShortcut.svelte +4 -12
- package/dist/components/KbdShortcut/README.md +34 -0
- package/dist/components/KbdShortcut/index.css +55 -0
- package/dist/components/ListItemButton/ListItemButton.svelte +37 -74
- package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +1 -10
- package/dist/components/ListItemButton/README.md +100 -45
- package/dist/components/ListItemButton/index.css +173 -52
- package/dist/components/ListItemButton/index.d.ts +1 -1
- package/dist/components/ListItemButton/index.js +1 -1
- package/dist/components/Modal/Modal.svelte +1 -8
- package/dist/components/Modal/README.md +29 -0
- package/dist/components/Modal/index.css +38 -0
- package/dist/components/ModalDialog/ModalDialog.svelte +2 -21
- package/dist/components/ModalDialog/README.md +35 -0
- package/dist/components/ModalDialog/index.css +59 -0
- package/dist/components/Nav/Nav.svelte +732 -0
- package/dist/components/Nav/Nav.svelte.d.ts +110 -0
- package/dist/components/Nav/README.md +334 -0
- package/dist/components/Nav/index.css +318 -0
- package/dist/components/Nav/index.d.ts +1 -0
- package/dist/components/Nav/index.js +1 -0
- package/dist/components/Notifications/Notifications.svelte +44 -129
- package/dist/components/Notifications/Notifications.svelte.d.ts +9 -18
- package/dist/components/Notifications/README.md +186 -70
- package/dist/components/Notifications/index.css +212 -15
- package/dist/components/Notifications/notifications-stack.svelte.d.ts +4 -0
- package/dist/components/Notifications/notifications-stack.svelte.js +8 -0
- package/dist/components/Progress/Progress.svelte +4 -2
- package/dist/components/Progress/Progress.svelte.d.ts +1 -0
- package/dist/components/Progress/README.md +97 -11
- package/dist/components/Progress/_internal/Bar.svelte +4 -15
- package/dist/components/Progress/_internal/Bar.svelte.d.ts +1 -1
- package/dist/components/Progress/_internal/Circle.svelte +30 -2
- package/dist/components/Progress/_internal/Circle.svelte.d.ts +1 -0
- package/dist/components/Progress/index.css +50 -4
- package/dist/components/Skeleton/README.md +152 -0
- package/dist/components/Skeleton/Skeleton.svelte +9 -9
- package/dist/components/Skeleton/Skeleton.svelte.d.ts +0 -1
- package/dist/components/Skeleton/index.css +72 -45
- package/dist/components/Spinner/README.md +149 -37
- package/dist/components/Spinner/Spinner.svelte +14 -38
- package/dist/components/Spinner/Spinner.svelte.d.ts +2 -1
- package/dist/components/Spinner/SpinnerCircle.svelte +6 -34
- package/dist/components/Spinner/SpinnerCircle.svelte.d.ts +1 -0
- package/dist/components/Spinner/SpinnerCircleOscillate.svelte +10 -5
- package/dist/components/Spinner/SpinnerUnicode.svelte +3 -1
- package/dist/components/Spinner/SpinnerUnicode.svelte.d.ts +1 -0
- package/dist/components/Spinner/index.css +104 -0
- package/dist/components/Switch/README.md +45 -14
- package/dist/components/Switch/Switch.svelte +23 -48
- package/dist/components/Switch/Switch.svelte.d.ts +4 -2
- package/dist/components/Switch/index.css +121 -4
- package/dist/components/Switch/index.d.ts +1 -2
- package/dist/components/Switch/index.js +1 -2
- package/dist/components/TabbedMenu/README.md +37 -21
- package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -46
- package/dist/components/TabbedMenu/TabbedMenu.svelte.d.ts +0 -1
- package/dist/components/TabbedMenu/index.css +84 -17
- package/dist/components/ThemePreview/README.md +289 -0
- package/dist/components/ThemePreview/ThemePreview.svelte +394 -0
- package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +35 -0
- package/dist/components/ThemePreview/index.css +509 -0
- package/dist/components/ThemePreview/index.d.ts +1 -0
- package/dist/components/ThemePreview/index.js +1 -0
- package/dist/components/TwCheck/README.md +32 -13
- package/dist/components/TwCheck/TwCheck.svelte +11 -9
- package/dist/components/TwCheck/TwCheck.svelte.d.ts +0 -1
- package/dist/components/TwCheck/index.css +17 -2
- package/dist/components/TypeaheadInput/TypeaheadInput.svelte +20 -188
- package/dist/components/TypeaheadInput/TypeaheadInput.svelte.d.ts +4 -2
- 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 +46 -26
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/themes/blue-orange.css +217 -0
- package/dist/themes/blue-orange.d.ts +6 -0
- package/dist/themes/blue-orange.js +175 -0
- package/dist/themes/cyan-red.css +217 -0
- package/dist/themes/cyan-red.d.ts +6 -0
- package/dist/themes/cyan-red.js +175 -0
- package/dist/themes/cyan-slate.css +217 -0
- package/dist/themes/cyan-slate.d.ts +6 -0
- package/dist/themes/cyan-slate.js +175 -0
- package/dist/themes/emerald-pink.css +217 -0
- package/dist/themes/emerald-pink.d.ts +6 -0
- package/dist/themes/emerald-pink.js +175 -0
- package/dist/themes/fuchsia-emerald.css +217 -0
- package/dist/themes/fuchsia-emerald.d.ts +6 -0
- package/dist/themes/fuchsia-emerald.js +175 -0
- package/dist/themes/gray.css +217 -0
- package/dist/themes/gray.d.ts +6 -0
- package/dist/themes/gray.js +175 -0
- package/dist/themes/indigo-amber.css +217 -0
- package/dist/themes/indigo-amber.d.ts +6 -0
- package/dist/themes/indigo-amber.js +175 -0
- package/dist/themes/neutral.css +217 -0
- package/dist/themes/neutral.d.ts +6 -0
- package/dist/themes/neutral.js +175 -0
- package/dist/themes/pink-emerald.css +217 -0
- package/dist/themes/pink-emerald.d.ts +6 -0
- package/dist/themes/pink-emerald.js +175 -0
- package/dist/themes/purple-yellow.css +217 -0
- package/dist/themes/purple-yellow.d.ts +6 -0
- package/dist/themes/purple-yellow.js +175 -0
- package/dist/themes/rainbow.css +217 -0
- package/dist/themes/rainbow.d.ts +6 -0
- package/dist/themes/rainbow.js +180 -0
- package/dist/themes/red-blue.css +217 -0
- package/dist/themes/red-blue.d.ts +6 -0
- package/dist/themes/red-blue.js +175 -0
- package/dist/themes/red-cyan.css +217 -0
- package/dist/themes/red-cyan.d.ts +6 -0
- package/dist/themes/red-cyan.js +175 -0
- package/dist/themes/rose-teal.css +217 -0
- package/dist/themes/rose-teal.d.ts +6 -0
- package/dist/themes/rose-teal.js +175 -0
- package/dist/themes/sky-amber.css +217 -0
- package/dist/themes/sky-amber.d.ts +6 -0
- package/dist/themes/sky-amber.js +175 -0
- package/dist/themes/slate-cyan.css +217 -0
- package/dist/themes/slate-cyan.d.ts +6 -0
- package/dist/themes/slate-cyan.js +175 -0
- package/dist/themes/tailwind-color-pairs.md +31 -0
- package/dist/themes/teal-rose.css +217 -0
- package/dist/themes/teal-rose.d.ts +6 -0
- package/dist/themes/teal-rose.js +175 -0
- package/dist/themes/violet-lime.css +217 -0
- package/dist/themes/violet-lime.d.ts +6 -0
- package/dist/themes/violet-lime.js +175 -0
- package/dist/utils/design-tokens.d.ts +43 -0
- package/dist/utils/design-tokens.js +127 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/storage-abstraction.js +1 -1
- package/package.json +14 -11
- package/dist/components/Switch/SwitchButton.svelte +0 -135
- package/dist/components/Switch/SwitchButton.svelte.d.ts +0 -21
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import type { FocusTrapOptions } from "../../actions/focus-trap.js";
|
|
4
|
-
import { BodyScroll, focusTrap as focusTrapAction
|
|
4
|
+
import { BodyScroll, focusTrap as focusTrapAction } from "../../index.js";
|
|
5
5
|
import { createClog } from "@marianmeres/clog";
|
|
6
6
|
import { watch } from "runed";
|
|
7
7
|
import { onDestroy } from "svelte";
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
</script>
|
|
27
27
|
|
|
28
28
|
<script lang="ts">
|
|
29
|
+
import { twMerge } from "../../utils/tw-merge.js";
|
|
30
|
+
|
|
29
31
|
const clog = createClog("Backdrop", { color: "auto" });
|
|
30
32
|
|
|
31
33
|
let {
|
|
@@ -142,6 +144,9 @@
|
|
|
142
144
|
}
|
|
143
145
|
return opts;
|
|
144
146
|
});
|
|
147
|
+
|
|
148
|
+
// Build class string - add base class for CSS targeting, allow user overrides
|
|
149
|
+
let _class = $derived(twMerge("stuic-backdrop", classProp));
|
|
145
150
|
</script>
|
|
146
151
|
|
|
147
152
|
{#if visible}
|
|
@@ -149,7 +154,7 @@
|
|
|
149
154
|
bind:this={el}
|
|
150
155
|
role="presentation"
|
|
151
156
|
tabindex="-1"
|
|
152
|
-
class={
|
|
157
|
+
class={_class}
|
|
153
158
|
in:fade={{ duration: fadeInDuration }}
|
|
154
159
|
out:fade={{ duration: fadeOutDuration }}
|
|
155
160
|
use:focusTrapAction={focusTrapOptions}
|
|
@@ -12,9 +12,10 @@ A semi-transparent overlay with focus trap and body scroll locking. Commonly use
|
|
|
12
12
|
| `fadeOutDuration` | `number` | `150` | Fade out transition duration (ms) |
|
|
13
13
|
| `transitionEnabled` | `boolean` | `true` | Enable/disable transitions |
|
|
14
14
|
| `onEscape` | `() => void` | - | Callback when Escape key is pressed |
|
|
15
|
+
| `onBackdropClick` | `() => void` | - | Callback when backdrop area is clicked |
|
|
15
16
|
| `noScrollLock` | `boolean` | `false` | Disable body scroll locking |
|
|
16
17
|
| `el` | `HTMLDivElement` | - | Element reference (bindable) |
|
|
17
|
-
| `class` | `string` | - | CSS classes
|
|
18
|
+
| `class` | `string` | - | Additional CSS classes |
|
|
18
19
|
|
|
19
20
|
## Methods
|
|
20
21
|
|
|
@@ -25,13 +26,52 @@ A semi-transparent overlay with focus trap and body scroll locking. Commonly use
|
|
|
25
26
|
| `setOpener(el)` | Set element to refocus when closed |
|
|
26
27
|
| `visibility()` | Returns object with `visible` getter |
|
|
27
28
|
|
|
29
|
+
## CSS Variables
|
|
30
|
+
|
|
31
|
+
Override these tokens to customize appearance:
|
|
32
|
+
|
|
33
|
+
| Variable | Default | Description |
|
|
34
|
+
|----------|---------|-------------|
|
|
35
|
+
| `--stuic-backdrop-bg` | `rgb(0 0 0 / 0.5)` | Background color |
|
|
36
|
+
| `--stuic-backdrop-z-index` | `10` | Stacking order |
|
|
37
|
+
|
|
38
|
+
### Global Override
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
:root {
|
|
42
|
+
--stuic-backdrop-bg: rgb(0 0 0 / 0.7);
|
|
43
|
+
--stuic-backdrop-z-index: 50;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Local Override
|
|
48
|
+
|
|
49
|
+
```svelte
|
|
50
|
+
<Backdrop
|
|
51
|
+
bind:visible
|
|
52
|
+
style="--stuic-backdrop-bg: rgb(0 0 0 / 0.8);"
|
|
53
|
+
>
|
|
54
|
+
...
|
|
55
|
+
</Backdrop>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Tailwind Class Override
|
|
59
|
+
|
|
60
|
+
You can still override styles using Tailwind classes via the `class` prop:
|
|
61
|
+
|
|
62
|
+
```svelte
|
|
63
|
+
<Backdrop bind:visible class="bg-black/25">
|
|
64
|
+
...
|
|
65
|
+
</Backdrop>
|
|
66
|
+
```
|
|
67
|
+
|
|
28
68
|
## Usage
|
|
29
69
|
|
|
30
70
|
### Basic Backdrop
|
|
31
71
|
|
|
32
72
|
```svelte
|
|
33
73
|
<script lang="ts">
|
|
34
|
-
import { Backdrop } from 'stuic';
|
|
74
|
+
import { Backdrop } from '@marianmeres/stuic';
|
|
35
75
|
|
|
36
76
|
let visible = $state(false);
|
|
37
77
|
</script>
|
|
@@ -41,7 +81,7 @@ A semi-transparent overlay with focus trap and body scroll locking. Commonly use
|
|
|
41
81
|
<Backdrop
|
|
42
82
|
bind:visible
|
|
43
83
|
onEscape={() => visible = false}
|
|
44
|
-
|
|
84
|
+
onBackdropClick={() => visible = false}
|
|
45
85
|
>
|
|
46
86
|
<div class="m-auto p-8 bg-white rounded">
|
|
47
87
|
Modal content
|
|
@@ -54,7 +94,7 @@ A semi-transparent overlay with focus trap and body scroll locking. Commonly use
|
|
|
54
94
|
|
|
55
95
|
```svelte
|
|
56
96
|
<script lang="ts">
|
|
57
|
-
import { Backdrop } from 'stuic';
|
|
97
|
+
import { Backdrop } from '@marianmeres/stuic';
|
|
58
98
|
|
|
59
99
|
let backdrop: Backdrop;
|
|
60
100
|
</script>
|
|
@@ -64,7 +104,6 @@ A semi-transparent overlay with focus trap and body scroll locking. Commonly use
|
|
|
64
104
|
<Backdrop
|
|
65
105
|
bind:this={backdrop}
|
|
66
106
|
onEscape={() => backdrop.close()}
|
|
67
|
-
class="bg-black/50"
|
|
68
107
|
>
|
|
69
108
|
<div class="m-auto p-8 bg-white rounded">
|
|
70
109
|
Content here
|
|
@@ -72,10 +111,36 @@ A semi-transparent overlay with focus trap and body scroll locking. Commonly use
|
|
|
72
111
|
</Backdrop>
|
|
73
112
|
```
|
|
74
113
|
|
|
114
|
+
### Custom Styling
|
|
115
|
+
|
|
116
|
+
```svelte
|
|
117
|
+
<!-- Lighter overlay -->
|
|
118
|
+
<Backdrop bind:visible class="bg-black/25">
|
|
119
|
+
<div>Overlay content</div>
|
|
120
|
+
</Backdrop>
|
|
121
|
+
|
|
122
|
+
<!-- Blur effect with CSS variable override -->
|
|
123
|
+
<Backdrop
|
|
124
|
+
bind:visible
|
|
125
|
+
class="backdrop-blur-sm"
|
|
126
|
+
style="--stuic-backdrop-bg: rgb(0 0 0 / 0.3);"
|
|
127
|
+
>
|
|
128
|
+
<div>Blurred backdrop content</div>
|
|
129
|
+
</Backdrop>
|
|
130
|
+
|
|
131
|
+
<!-- Higher z-index for stacking -->
|
|
132
|
+
<Backdrop
|
|
133
|
+
bind:visible
|
|
134
|
+
style="--stuic-backdrop-z-index: 100;"
|
|
135
|
+
>
|
|
136
|
+
<div>High priority overlay</div>
|
|
137
|
+
</Backdrop>
|
|
138
|
+
```
|
|
139
|
+
|
|
75
140
|
### Without Scroll Lock
|
|
76
141
|
|
|
77
142
|
```svelte
|
|
78
|
-
<Backdrop bind:visible noScrollLock
|
|
143
|
+
<Backdrop bind:visible noScrollLock>
|
|
79
144
|
<div>Overlay content - page still scrollable</div>
|
|
80
145
|
</Backdrop>
|
|
81
146
|
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
BACKDROP COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-backdrop-bg: rgb(0 0 0 / 0.3); }
|
|
4
|
+
Override locally: <Backdrop style="--stuic-backdrop-bg: rgb(0 0 0 / 0.8);">
|
|
5
|
+
============================================================================ */
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* Component-level customization tokens */
|
|
9
|
+
--stuic-backdrop-bg: rgb(0 0 0 / 0.5);
|
|
10
|
+
--stuic-backdrop-z-index: 10;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@layer components {
|
|
14
|
+
/* ============================================================================
|
|
15
|
+
BASE STYLES
|
|
16
|
+
============================================================================ */
|
|
17
|
+
|
|
18
|
+
.stuic-backdrop {
|
|
19
|
+
/* Layout */
|
|
20
|
+
position: fixed;
|
|
21
|
+
inset: 0;
|
|
22
|
+
display: flex;
|
|
23
|
+
height: 100dvh;
|
|
24
|
+
|
|
25
|
+
/* Stacking */
|
|
26
|
+
z-index: var(--stuic-backdrop-z-index);
|
|
27
|
+
|
|
28
|
+
/* Colors */
|
|
29
|
+
background: var(--stuic-backdrop-bg);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,121 +1,79 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
+
import type { HTMLButtonAttributes, HTMLAnchorAttributes } from "svelte/elements";
|
|
2
3
|
import type { Snippet } from "svelte";
|
|
3
|
-
import type {
|
|
4
|
+
import type { IntentColorKey } from "../../utils/design-tokens.js";
|
|
5
|
+
|
|
6
|
+
export type ButtonVariant = "solid" | "outline" | "ghost" | "soft" | "link";
|
|
7
|
+
export type ButtonSize = "sm" | "md" | "lg" | "xl";
|
|
4
8
|
|
|
5
9
|
export interface Props extends Omit<HTMLButtonAttributes, "children"> {
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
/** Color intent (semantic meaning) */
|
|
11
|
+
intent?: IntentColorKey;
|
|
12
|
+
/** Visual variant (how colors are applied) */
|
|
13
|
+
variant?: ButtonVariant | string;
|
|
14
|
+
/** Size preset */
|
|
15
|
+
size?: ButtonSize | string;
|
|
16
|
+
/** Reduce emphasis */
|
|
10
17
|
muted?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
/** 3D push effect */
|
|
19
|
+
raised?: boolean;
|
|
13
20
|
/** Skip all default styling, use only custom classes */
|
|
14
21
|
unstyled?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
|
|
22
|
+
/** Render as rounded-full */
|
|
23
|
+
roundedFull?: boolean;
|
|
24
|
+
/** Render as aspect ratio 1 */
|
|
25
|
+
aspect1?: boolean;
|
|
26
|
+
/** Additional CSS classes */
|
|
17
27
|
class?: string;
|
|
18
28
|
/** Render as anchor tag instead of button */
|
|
19
29
|
href?: string;
|
|
30
|
+
/** Content snippet */
|
|
20
31
|
children?: Snippet<[{ checked?: boolean }]>;
|
|
21
|
-
/**
|
|
22
|
-
roleSwitch?: boolean;
|
|
32
|
+
/** Toggle state for switch behavior */
|
|
23
33
|
checked?: boolean;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
/** Enable switch/toggle behavior */
|
|
35
|
+
roleSwitch?: boolean;
|
|
36
|
+
/** Bindable element reference */
|
|
37
|
+
el?: HTMLElement;
|
|
38
|
+
/** Optional tooltip configuration or direct content */
|
|
39
|
+
tooltip?: string | TooltipConfig;
|
|
40
|
+
/** Is this button a "X" button (this is a pragmatic convenience) */
|
|
41
|
+
x?: boolean | XProps;
|
|
42
|
+
/** Optional out-of-the-box spinner support */
|
|
43
|
+
spinner?: boolean | THC;
|
|
44
|
+
/** Show only spinner when spinner? */
|
|
45
|
+
spinnerOnly?: boolean;
|
|
35
46
|
}
|
|
36
|
-
|
|
37
|
-
export const BUTTON_STUIC_BASE_CLASSES = `
|
|
38
|
-
bg-button-bg text-button-text
|
|
39
|
-
dark:bg-button-bg-dark dark:text-button-text-dark
|
|
40
|
-
text-base text-center
|
|
41
|
-
leading-none
|
|
42
|
-
border-1
|
|
43
|
-
border-button-border dark:border-button-border-dark
|
|
44
|
-
rounded-lg
|
|
45
|
-
inline-flex items-center justify-center gap-x-2
|
|
46
|
-
px-4 py-3
|
|
47
|
-
select-none
|
|
48
|
-
min-h-[44px] min-w-[44px]
|
|
49
|
-
|
|
50
|
-
hover:brightness-105
|
|
51
|
-
active:brightness-95
|
|
52
|
-
disabled:hover:brightness-100 disabled:opacity-50
|
|
53
|
-
|
|
54
|
-
focus:brightness-105
|
|
55
|
-
focus:border-button-border-focus focus:dark:border-button-border-focus-dark
|
|
56
|
-
|
|
57
|
-
focus:outline-4 focus:outline-black/10 focus:dark:outline-white/20
|
|
58
|
-
focus-visible:outline-4 focus-visible:outline-black/10 focus-visible:dark:outline-white/20
|
|
59
|
-
`;
|
|
60
|
-
|
|
61
|
-
export const BUTTON_STUIC_PRESET_CLASSES: ButtonPresetClasses = {
|
|
62
|
-
size: {
|
|
63
|
-
sm: `text-sm rounded-md px-3 py-2 min-h-none min-w-none`,
|
|
64
|
-
lg: `text-lg rounded-xl`,
|
|
65
|
-
},
|
|
66
|
-
variant: {
|
|
67
|
-
primary: `font-medium`,
|
|
68
|
-
secondary: `
|
|
69
|
-
bg-neutral-100 dark:bg-neutral-600
|
|
70
|
-
text-black/60 dark:text-white/80
|
|
71
|
-
shadow-[1px_1px_0_0_rgba(0_0_0_/_.2)]
|
|
72
|
-
active:shadow-none active:translate-[1px]
|
|
73
|
-
focus:shadow-black/30
|
|
74
|
-
`,
|
|
75
|
-
},
|
|
76
|
-
muted: `text-black/70 dark:text-white/70`,
|
|
77
|
-
shadow: `
|
|
78
|
-
shadow-[1px_1px_0_0_rgba(0_0_0_/_.4)]
|
|
79
|
-
active:shadow-none active:translate-[1px]
|
|
80
|
-
disabled:shadow-none disabled:active:shadow-none disabled:active:translate-none
|
|
81
|
-
`,
|
|
82
|
-
inverse: `
|
|
83
|
-
bg-transparent dark:bg-transparent
|
|
84
|
-
hover:bg-button-bg hover:dark:bg-button-bg-dark
|
|
85
|
-
hover:brightness-100
|
|
86
|
-
`,
|
|
87
|
-
};
|
|
88
47
|
</script>
|
|
89
48
|
|
|
90
49
|
<script lang="ts">
|
|
91
50
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
92
|
-
|
|
93
|
-
import "
|
|
94
|
-
import {
|
|
95
|
-
|
|
51
|
+
import { tooltip, type TooltipConfig } from "../../actions/tooltip/tooltip.svelte.js";
|
|
52
|
+
import { X, type XProps } from "../X/index.js";
|
|
53
|
+
import Thc, { type THC } from "../Thc/Thc.svelte";
|
|
54
|
+
import Spinner from "../Spinner/Spinner.svelte";
|
|
96
55
|
let {
|
|
97
|
-
variant,
|
|
98
|
-
size,
|
|
99
56
|
class: classProp,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
inverse,
|
|
104
|
-
unstyled,
|
|
57
|
+
intent,
|
|
58
|
+
size = "md",
|
|
59
|
+
variant = "solid",
|
|
105
60
|
href,
|
|
106
61
|
children,
|
|
107
|
-
//
|
|
108
|
-
roleSwitch = false,
|
|
109
62
|
checked = $bindable(false),
|
|
63
|
+
roleSwitch = false,
|
|
110
64
|
el = $bindable(),
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
65
|
+
muted = false,
|
|
66
|
+
raised = false,
|
|
67
|
+
unstyled = false,
|
|
68
|
+
roundedFull = false,
|
|
69
|
+
aspect1 = false,
|
|
70
|
+
tooltip: _tooltip,
|
|
71
|
+
x,
|
|
72
|
+
spinner,
|
|
73
|
+
spinnerOnly,
|
|
114
74
|
...rest
|
|
115
75
|
}: Props = $props();
|
|
116
76
|
|
|
117
|
-
// let button: HTMLButtonElement | undefined = $state();
|
|
118
|
-
|
|
119
77
|
$effect(() => {
|
|
120
78
|
const toggle = () => (checked = !checked);
|
|
121
79
|
if (!href && roleSwitch && el) {
|
|
@@ -124,51 +82,85 @@
|
|
|
124
82
|
return () => el?.removeEventListener("click", toggle);
|
|
125
83
|
});
|
|
126
84
|
|
|
127
|
-
|
|
128
|
-
|
|
85
|
+
// Build class string - add base class for CSS targeting unless unstyled
|
|
86
|
+
let _class = $derived(unstyled ? classProp : twMerge("stuic-button", classProp));
|
|
87
|
+
|
|
88
|
+
let _tooltipConfig: TooltipConfig = $derived.by(() => {
|
|
89
|
+
if (typeof _tooltip === "string") {
|
|
90
|
+
return () => ({ enabled: true, content: _tooltip });
|
|
91
|
+
}
|
|
92
|
+
return _tooltip ? _tooltip : () => ({ enabled: false });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
let _xProps: undefined | XProps = $derived.by(() => {
|
|
96
|
+
if (x) {
|
|
97
|
+
return typeof x === "boolean" ? {} : x;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
129
100
|
|
|
130
|
-
//
|
|
131
|
-
let
|
|
132
|
-
[
|
|
133
|
-
// "namespace" (so we can target it in css files when customizing)
|
|
134
|
-
"stuic-button",
|
|
135
|
-
// pass all styling props as classnames as well
|
|
136
|
-
variant,
|
|
137
|
-
size,
|
|
138
|
-
muted && "muted",
|
|
139
|
-
noshadow && "no-shadow",
|
|
140
|
-
noborder && "border-none",
|
|
141
|
-
inverse && "inverse",
|
|
142
|
-
// now, attach the default tw classes (unless not explicitly forbidden)
|
|
143
|
-
!unstyled && _base,
|
|
144
|
-
!unstyled && size && _preset.size[size],
|
|
145
|
-
!unstyled && variant && _preset.variant[variant],
|
|
146
|
-
!unstyled && muted && _preset.muted,
|
|
147
|
-
!unstyled && !noshadow && _preset.shadow,
|
|
148
|
-
!unstyled && inverse && _preset.inverse,
|
|
149
|
-
]
|
|
150
|
-
.filter(Boolean)
|
|
151
|
-
.join(" ")
|
|
152
|
-
);
|
|
101
|
+
// "x" implicitly set aspect1
|
|
102
|
+
let _isAspect1 = $derived(aspect1 || _xProps);
|
|
153
103
|
</script>
|
|
154
104
|
|
|
155
105
|
{#if href}
|
|
156
106
|
<a
|
|
157
107
|
{href}
|
|
158
108
|
bind:this={el}
|
|
159
|
-
class={
|
|
160
|
-
|
|
161
|
-
{
|
|
109
|
+
class={_class}
|
|
110
|
+
data-intent={!unstyled ? intent : undefined}
|
|
111
|
+
data-variant={!unstyled ? variant : undefined}
|
|
112
|
+
data-size={!unstyled ? size : undefined}
|
|
113
|
+
data-muted={!unstyled && muted ? "true" : undefined}
|
|
114
|
+
data-raised={!unstyled && raised ? "true" : undefined}
|
|
115
|
+
data-checked={roleSwitch && checked ? "true" : undefined}
|
|
116
|
+
data-rounded-full={!unstyled && roundedFull ? "true" : undefined}
|
|
117
|
+
data-aspect1={!unstyled && _isAspect1 ? "true" : undefined}
|
|
118
|
+
use:tooltip={_tooltipConfig}
|
|
119
|
+
{...rest as HTMLAnchorAttributes}
|
|
162
120
|
>
|
|
163
|
-
{
|
|
121
|
+
{#if _xProps}
|
|
122
|
+
<X {..._xProps} />
|
|
123
|
+
{:else}
|
|
124
|
+
{#if spinner}
|
|
125
|
+
{#if typeof spinner === "boolean"}
|
|
126
|
+
<Spinner />
|
|
127
|
+
{:else}
|
|
128
|
+
<Thc thc={spinner} />
|
|
129
|
+
{/if}
|
|
130
|
+
{/if}
|
|
131
|
+
{#if !spinner || (spinner && !spinnerOnly)}
|
|
132
|
+
{@render children?.({ checked })}
|
|
133
|
+
{/if}
|
|
134
|
+
{/if}
|
|
164
135
|
</a>
|
|
165
136
|
{:else}
|
|
166
137
|
<button
|
|
167
138
|
bind:this={el}
|
|
168
|
-
class={
|
|
169
|
-
|
|
139
|
+
class={_class}
|
|
140
|
+
data-intent={!unstyled ? intent : undefined}
|
|
141
|
+
data-variant={!unstyled ? variant : undefined}
|
|
142
|
+
data-size={!unstyled ? size : undefined}
|
|
143
|
+
data-muted={!unstyled && muted ? "true" : undefined}
|
|
144
|
+
data-raised={!unstyled && raised ? "true" : undefined}
|
|
145
|
+
data-checked={roleSwitch && checked ? "true" : undefined}
|
|
146
|
+
data-rounded-full={!unstyled && roundedFull ? "true" : undefined}
|
|
147
|
+
data-aspect1={!unstyled && _isAspect1 ? "true" : undefined}
|
|
148
|
+
use:tooltip={_tooltipConfig}
|
|
170
149
|
{...rest}
|
|
171
150
|
>
|
|
172
|
-
{
|
|
151
|
+
{#if _xProps}
|
|
152
|
+
<X {..._xProps} />
|
|
153
|
+
{:else}
|
|
154
|
+
{#if spinner}
|
|
155
|
+
{#if typeof spinner === "boolean"}
|
|
156
|
+
<Spinner />
|
|
157
|
+
{:else}
|
|
158
|
+
<Thc thc={spinner} />
|
|
159
|
+
{/if}
|
|
160
|
+
{/if}
|
|
161
|
+
{#if !spinner || (spinner && !spinnerOnly)}
|
|
162
|
+
{@render children?.({ checked })}
|
|
163
|
+
{/if}
|
|
164
|
+
{/if}
|
|
173
165
|
</button>
|
|
174
166
|
{/if}
|
|
@@ -1,40 +1,51 @@
|
|
|
1
|
-
import type { Snippet } from "svelte";
|
|
2
1
|
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { IntentColorKey } from "../../utils/design-tokens.js";
|
|
4
|
+
export type ButtonVariant = "solid" | "outline" | "ghost" | "soft" | "link";
|
|
5
|
+
export type ButtonSize = "sm" | "md" | "lg" | "xl";
|
|
3
6
|
export interface Props extends Omit<HTMLButtonAttributes, "children"> {
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
/** Color intent (semantic meaning) */
|
|
8
|
+
intent?: IntentColorKey;
|
|
9
|
+
/** Visual variant (how colors are applied) */
|
|
10
|
+
variant?: ButtonVariant | string;
|
|
11
|
+
/** Size preset */
|
|
12
|
+
size?: ButtonSize | string;
|
|
13
|
+
/** Reduce emphasis */
|
|
8
14
|
muted?: boolean;
|
|
9
|
-
|
|
10
|
-
|
|
15
|
+
/** 3D push effect */
|
|
16
|
+
raised?: boolean;
|
|
11
17
|
/** Skip all default styling, use only custom classes */
|
|
12
18
|
unstyled?: boolean;
|
|
13
|
-
/**
|
|
14
|
-
|
|
19
|
+
/** Render as rounded-full */
|
|
20
|
+
roundedFull?: boolean;
|
|
21
|
+
/** Render as aspect ratio 1 */
|
|
22
|
+
aspect1?: boolean;
|
|
23
|
+
/** Additional CSS classes */
|
|
15
24
|
class?: string;
|
|
16
25
|
/** Render as anchor tag instead of button */
|
|
17
26
|
href?: string;
|
|
27
|
+
/** Content snippet */
|
|
18
28
|
children?: Snippet<[{
|
|
19
29
|
checked?: boolean;
|
|
20
30
|
}]>;
|
|
21
|
-
/**
|
|
22
|
-
roleSwitch?: boolean;
|
|
31
|
+
/** Toggle state for switch behavior */
|
|
23
32
|
checked?: boolean;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
/** Enable switch/toggle behavior */
|
|
34
|
+
roleSwitch?: boolean;
|
|
35
|
+
/** Bindable element reference */
|
|
36
|
+
el?: HTMLElement;
|
|
37
|
+
/** Optional tooltip configuration or direct content */
|
|
38
|
+
tooltip?: string | TooltipConfig;
|
|
39
|
+
/** Is this button a "X" button (this is a pragmatic convenience) */
|
|
40
|
+
x?: boolean | XProps;
|
|
41
|
+
/** Optional out-of-the-box spinner support */
|
|
42
|
+
spinner?: boolean | THC;
|
|
43
|
+
/** Show only spinner when spinner? */
|
|
44
|
+
spinnerOnly?: boolean;
|
|
33
45
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
import "
|
|
37
|
-
import { type TooltipConfig } from "../../actions/index.js";
|
|
46
|
+
import { type TooltipConfig } from "../../actions/tooltip/tooltip.svelte.js";
|
|
47
|
+
import { type XProps } from "../X/index.js";
|
|
48
|
+
import { type THC } from "../Thc/Thc.svelte";
|
|
38
49
|
declare const Button: import("svelte").Component<Props, {}, "checked" | "el">;
|
|
39
50
|
type Button = ReturnType<typeof Button>;
|
|
40
51
|
export default Button;
|