@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
|
@@ -107,6 +107,21 @@ A toggle switch component with size variants, keyboard support, and optional asy
|
|
|
107
107
|
<Switch checked={false} disabled />
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
## CSS Variables
|
|
111
|
+
|
|
112
|
+
| Variable | Default | Description |
|
|
113
|
+
|----------|---------|-------------|
|
|
114
|
+
| `--stuic-switch-accent` | `--stuic-accent` | Active (checked) color |
|
|
115
|
+
|
|
116
|
+
### Example Override
|
|
117
|
+
|
|
118
|
+
```css
|
|
119
|
+
:root {
|
|
120
|
+
/* Green switches globally */
|
|
121
|
+
--stuic-switch-accent: var(--color-green-500);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
110
125
|
## Keyboard Support
|
|
111
126
|
|
|
112
127
|
- **Space**: Toggle switch
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
export interface Props extends Omit<HTMLLabelAttributes, "children" | "onchange"> {
|
|
10
10
|
button?: HTMLButtonElement;
|
|
11
11
|
checked?: boolean;
|
|
12
|
-
size?: "
|
|
12
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
13
13
|
/** Form field name for the hidden checkbox */
|
|
14
14
|
name?: string;
|
|
15
15
|
class?: string;
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
|
|
43
43
|
let {
|
|
44
44
|
button = $bindable(),
|
|
45
|
-
size = "
|
|
45
|
+
size = "lg",
|
|
46
46
|
name,
|
|
47
47
|
class: classProp,
|
|
48
48
|
dotClass,
|
|
@@ -62,7 +62,6 @@
|
|
|
62
62
|
|
|
63
63
|
const _preset: any = {
|
|
64
64
|
size: {
|
|
65
|
-
xs: `h-4 w-7`,
|
|
66
65
|
sm: `h-5 w-9`,
|
|
67
66
|
md: `h-6 w-11`,
|
|
68
67
|
lg: `h-7 w-13`,
|
|
@@ -70,7 +69,6 @@
|
|
|
70
69
|
},
|
|
71
70
|
dot: {
|
|
72
71
|
size: {
|
|
73
|
-
xs: `size-2 data-[checked=true]:translate-x-4`,
|
|
74
72
|
sm: `size-3 data-[checked=true]:translate-x-5`,
|
|
75
73
|
md: `size-4 data-[checked=true]:translate-x-6`,
|
|
76
74
|
lg: `size-5 data-[checked=true]:translate-x-7`,
|
|
@@ -107,11 +105,10 @@
|
|
|
107
105
|
|
|
108
106
|
bg-neutral-400 dark:bg-neutral-400
|
|
109
107
|
|
|
110
|
-
data-[checked=true]:bg-switch-accent
|
|
111
|
-
dark:data-[checked=true]:bg-switch-accent-dark
|
|
108
|
+
data-[checked=true]:bg-(--stuic-switch-accent)
|
|
112
109
|
|
|
113
110
|
focus:outline-0
|
|
114
|
-
focus:ring-
|
|
111
|
+
focus:ring-(--stuic-switch-accent)/20
|
|
115
112
|
focus:ring-4`,
|
|
116
113
|
size,
|
|
117
114
|
_preset.size[size],
|
|
@@ -4,7 +4,7 @@ import type { ValidateOptions, ValidationResult } from "../../actions/validate.s
|
|
|
4
4
|
export interface Props extends Omit<HTMLLabelAttributes, "children" | "onchange"> {
|
|
5
5
|
button?: HTMLButtonElement;
|
|
6
6
|
checked?: boolean;
|
|
7
|
-
size?: "
|
|
7
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
8
8
|
/** Form field name for the hidden checkbox */
|
|
9
9
|
name?: string;
|
|
10
10
|
class?: string;
|
|
@@ -76,12 +76,11 @@
|
|
|
76
76
|
disabled:!cursor-not-allowed disabled:!opacity-50 disabled:hover:brightness-100
|
|
77
77
|
|
|
78
78
|
bg-neutral-400 dark:bg-neutral-400
|
|
79
|
-
|
|
80
|
-
aria-[checked=true]:bg-switch-accent
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
|
|
80
|
+
aria-[checked=true]:bg-(--stuic-switch-accent)
|
|
81
|
+
|
|
83
82
|
focus:outline-0
|
|
84
|
-
focus:ring-
|
|
83
|
+
focus:ring-(--stuic-switch-accent)/20
|
|
85
84
|
focus:ring-4`,
|
|
86
85
|
size,
|
|
87
86
|
_preset.size[size],
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
--
|
|
4
|
-
--color-switch-accent-dark: var(--color-switch-accent-dark, var(--color-red-400));
|
|
1
|
+
/* Switch component tokens */
|
|
2
|
+
:root {
|
|
3
|
+
--stuic-switch-accent: var(--stuic-color-primary);
|
|
5
4
|
}
|
|
@@ -51,30 +51,35 @@ interface TabbedMenuItem {
|
|
|
51
51
|
|
|
52
52
|
## CSS Variables
|
|
53
53
|
|
|
54
|
+
Customize the component's appearance using CSS custom properties:
|
|
55
|
+
|
|
56
|
+
| Variable | Default | Description |
|
|
57
|
+
|----------|---------|-------------|
|
|
58
|
+
| `--stuic-tabbed-menu-tab-bg` | `--stuic-surface-sunken` | Tab background |
|
|
59
|
+
| `--stuic-tabbed-menu-tab-text` | `--stuic-text-muted` | Tab text color |
|
|
60
|
+
| `--stuic-tabbed-menu-tab-bg-active` | `--stuic-surface` | Active tab background |
|
|
61
|
+
| `--stuic-tabbed-menu-tab-text-active` | `--stuic-text` | Active tab text color |
|
|
62
|
+
| `--stuic-tabbed-menu-border` | `--stuic-border` | Border color |
|
|
63
|
+
|
|
64
|
+
### Example Override
|
|
65
|
+
|
|
54
66
|
```css
|
|
55
|
-
|
|
56
|
-
--
|
|
57
|
-
--
|
|
58
|
-
|
|
59
|
-
--color-tabbed-menu-tab-text-dark
|
|
60
|
-
|
|
61
|
-
/* Active tab */
|
|
62
|
-
--color-tabbed-menu-tab-active-bg
|
|
63
|
-
--color-tabbed-menu-tab-active-bg-dark
|
|
64
|
-
--color-tabbed-menu-tab-active-text
|
|
65
|
-
--color-tabbed-menu-tab-active-text-dark
|
|
66
|
-
|
|
67
|
-
/* Border */
|
|
68
|
-
--color-tabbed-menu-border
|
|
69
|
-
--color-tabbed-menu-border-dark
|
|
70
|
-
|
|
71
|
-
/* Sizing */
|
|
72
|
-
--tabbed-menu-border-radius: 0.5rem
|
|
73
|
-
--tabbed-menu-padding-x: 1rem
|
|
74
|
-
--tabbed-menu-padding-y: 0.5rem
|
|
75
|
-
--tabbed-menu-gap: 0.25rem
|
|
67
|
+
:root {
|
|
68
|
+
--stuic-tabbed-menu-tab-bg-active: var(--color-indigo-100);
|
|
69
|
+
--stuic-tabbed-menu-tab-text-active: var(--color-indigo-900);
|
|
70
|
+
}
|
|
76
71
|
```
|
|
77
72
|
|
|
73
|
+
### Legacy Variables (Backwards Compatibility)
|
|
74
|
+
|
|
75
|
+
The following legacy variable names still work as aliases:
|
|
76
|
+
|
|
77
|
+
| Legacy Name | New Name |
|
|
78
|
+
|-------------|----------|
|
|
79
|
+
| `--color-tabbed-menu-tab-bg` | `--stuic-tabbed-menu-tab-bg` |
|
|
80
|
+
| `--color-tabbed-menu-tab-active-bg` | `--stuic-tabbed-menu-tab-bg-active` |
|
|
81
|
+
| `--color-tabbed-menu-border` | `--stuic-tabbed-menu-border` |
|
|
82
|
+
|
|
78
83
|
## Keyboard Navigation
|
|
79
84
|
|
|
80
85
|
- `ArrowRight` / `ArrowDown` - Move to next tab
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
px-4 py-2
|
|
70
70
|
rounded-t-md
|
|
71
71
|
border border-b-0
|
|
72
|
-
border-
|
|
73
|
-
bg-
|
|
74
|
-
text-
|
|
72
|
+
border-(--stuic-tabbed-menu-border)
|
|
73
|
+
bg-(--stuic-tabbed-menu-tab-bg)
|
|
74
|
+
text-(--stuic-tabbed-menu-tab-text)
|
|
75
75
|
cursor-pointer
|
|
76
76
|
transition-colors duration-150
|
|
77
77
|
hover:brightness-105
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
// focus-visible:outline-2 focus-visible:outline-offset-2
|
|
83
83
|
|
|
84
84
|
const CLS_BUTTON_ACTIVE = `
|
|
85
|
-
bg-tabbed-menu-tab-
|
|
86
|
-
text-tabbed-menu-tab-
|
|
85
|
+
bg-(--stuic-tabbed-menu-tab-bg-active)
|
|
86
|
+
text-(--stuic-tabbed-menu-tab-text-active)
|
|
87
87
|
font-medium
|
|
88
88
|
`;
|
|
89
89
|
|
|
@@ -1,23 +1,8 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
--color-tabbed-menu-tab-text: var(--color-tabbed-menu-tab-text, var(--color-neutral-600));
|
|
9
|
-
--color-tabbed-menu-tab-text-dark: var(--color-tabbed-menu-tab-text-dark, var(--color-neutral-300));
|
|
10
|
-
|
|
11
|
-
/* Active tab background */
|
|
12
|
-
--color-tabbed-menu-tab-active-bg: var(--color-tabbed-menu-tab-active-bg, var(--color-white));
|
|
13
|
-
--color-tabbed-menu-tab-active-bg-dark: var(--color-tabbed-menu-tab-active-bg-dark, var(--color-neutral-800));
|
|
14
|
-
|
|
15
|
-
/* Active tab text */
|
|
16
|
-
--color-tabbed-menu-tab-active-text: var(--color-tabbed-menu-tab-active-text, var(--color-neutral-900));
|
|
17
|
-
--color-tabbed-menu-tab-active-text-dark: var(--color-tabbed-menu-tab-active-text-dark, var(--color-white));
|
|
18
|
-
|
|
19
|
-
/* Border */
|
|
20
|
-
--color-tabbed-menu-border: var(--color-tabbed-menu-border, var(--color-neutral-300));
|
|
21
|
-
--color-tabbed-menu-border-dark: var(--color-tabbed-menu-border-dark, var(--color-neutral-600));
|
|
22
|
-
|
|
1
|
+
/* TabbedMenu component tokens */
|
|
2
|
+
:root {
|
|
3
|
+
--stuic-tabbed-menu-tab-bg: var(--stuic-color-muted);
|
|
4
|
+
--stuic-tabbed-menu-tab-text: var(--stuic-color-muted-foreground);
|
|
5
|
+
--stuic-tabbed-menu-tab-bg-active: var(--stuic-color-surface);
|
|
6
|
+
--stuic-tabbed-menu-tab-text-active: var(--stuic-color-foreground);
|
|
7
|
+
--stuic-tabbed-menu-border: var(--stuic-color-border);
|
|
23
8
|
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# ThemePreview
|
|
2
|
+
|
|
3
|
+
A comprehensive theme preview component that serves two purposes:
|
|
4
|
+
|
|
5
|
+
1. **Visual Preview** - Shows all design tokens in action as a mini webpage layout
|
|
6
|
+
2. **Reference Implementation** - Demonstrates theming best practices for creating components
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```svelte
|
|
11
|
+
<script lang="ts">
|
|
12
|
+
import { ThemePreview } from '@marianmeres/stuic';
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<ThemePreview />
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Compact Mode
|
|
19
|
+
|
|
20
|
+
```svelte
|
|
21
|
+
<ThemePreview compact showLabels={false} />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Custom Sections
|
|
25
|
+
|
|
26
|
+
```svelte
|
|
27
|
+
<ThemePreview>
|
|
28
|
+
{#snippet header()}
|
|
29
|
+
<h1>My Custom Theme</h1>
|
|
30
|
+
{/snippet}
|
|
31
|
+
|
|
32
|
+
{#snippet sidebar()}
|
|
33
|
+
<nav>Custom navigation...</nav>
|
|
34
|
+
{/snippet}
|
|
35
|
+
</ThemePreview>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Props
|
|
39
|
+
|
|
40
|
+
| Prop | Type | Default | Description |
|
|
41
|
+
|------|------|---------|-------------|
|
|
42
|
+
| `showLabels` | `boolean` | `true` | Show section labels |
|
|
43
|
+
| `compact` | `boolean` | `false` | Reduced spacing |
|
|
44
|
+
| `showAllVariants` | `boolean` | `true` | Show all button variants |
|
|
45
|
+
| `showInputs` | `boolean` | `true` | Show input examples |
|
|
46
|
+
| `class` | `string` | - | Additional CSS classes |
|
|
47
|
+
| `el` | `HTMLDivElement` | - | Bindable element reference |
|
|
48
|
+
| `header` | `Snippet` | - | Custom header content |
|
|
49
|
+
| `sidebar` | `Snippet` | - | Custom sidebar content |
|
|
50
|
+
| `footer` | `Snippet` | - | Custom footer content |
|
|
51
|
+
|
|
52
|
+
## Component Tokens
|
|
53
|
+
|
|
54
|
+
Override to customize appearance:
|
|
55
|
+
|
|
56
|
+
```css
|
|
57
|
+
:root {
|
|
58
|
+
--stuic-theme-preview-radius: var(--radius-lg);
|
|
59
|
+
--stuic-theme-preview-gap: 2rem;
|
|
60
|
+
--stuic-theme-preview-transition: 200ms;
|
|
61
|
+
--stuic-theme-preview-sidebar-width: 250px;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
# Theming Best Practices
|
|
68
|
+
|
|
69
|
+
This component demonstrates the patterns used throughout stuic. Follow these when creating new components.
|
|
70
|
+
|
|
71
|
+
## 1. Theme Token Reference
|
|
72
|
+
|
|
73
|
+
### Intent Colors
|
|
74
|
+
|
|
75
|
+
Communicate **purpose** and **meaning**:
|
|
76
|
+
|
|
77
|
+
| Token | Purpose |
|
|
78
|
+
|-------|---------|
|
|
79
|
+
| `--stuic-color-primary` | Main actions ("do this") |
|
|
80
|
+
| `--stuic-color-accent` | Highlights ("notice this") |
|
|
81
|
+
| `--stuic-color-destructive` | Dangerous/irreversible actions |
|
|
82
|
+
| `--stuic-color-warning` | Caution states |
|
|
83
|
+
| `--stuic-color-success` | Positive outcomes |
|
|
84
|
+
| `--stuic-color-info` | Neutral information |
|
|
85
|
+
|
|
86
|
+
Each intent has states and foregrounds:
|
|
87
|
+
- `--stuic-color-{intent}` - base color
|
|
88
|
+
- `--stuic-color-{intent}-hover` - hover state
|
|
89
|
+
- `--stuic-color-{intent}-active` - active/pressed state
|
|
90
|
+
- `--stuic-color-{intent}-foreground` - text on base
|
|
91
|
+
- `--stuic-color-{intent}-foreground-hover`
|
|
92
|
+
- `--stuic-color-{intent}-foreground-active`
|
|
93
|
+
|
|
94
|
+
### Role Colors
|
|
95
|
+
|
|
96
|
+
Define **position** in the visual hierarchy:
|
|
97
|
+
|
|
98
|
+
| Token | Purpose |
|
|
99
|
+
|-------|---------|
|
|
100
|
+
| `--stuic-color-background` | Page background |
|
|
101
|
+
| `--stuic-color-foreground` | Primary text |
|
|
102
|
+
| `--stuic-color-surface` | Card/panel backgrounds |
|
|
103
|
+
| `--stuic-color-surface-foreground` | Text on surfaces |
|
|
104
|
+
| `--stuic-color-muted` | Subtle backgrounds |
|
|
105
|
+
| `--stuic-color-muted-foreground` | Secondary text |
|
|
106
|
+
| `--stuic-color-border` | Border color |
|
|
107
|
+
| `--stuic-color-input` | Input field backgrounds |
|
|
108
|
+
| `--stuic-color-ring` | Focus ring color |
|
|
109
|
+
|
|
110
|
+
## 2. Internal Variable Pattern
|
|
111
|
+
|
|
112
|
+
The core theming technique in stuic separates **what colors to use** (intent) from **how to apply them** (variant).
|
|
113
|
+
|
|
114
|
+
### Step 1: Intent Sets the Palette
|
|
115
|
+
|
|
116
|
+
```css
|
|
117
|
+
.my-component[data-intent="primary"] {
|
|
118
|
+
--_color: var(--stuic-color-primary);
|
|
119
|
+
--_color-hover: var(--stuic-color-primary-hover);
|
|
120
|
+
--_color-active: var(--stuic-color-primary-active);
|
|
121
|
+
--_fg: var(--stuic-color-primary-foreground);
|
|
122
|
+
--_fg-hover: var(--stuic-color-primary-foreground-hover);
|
|
123
|
+
--_fg-active: var(--stuic-color-primary-foreground-active);
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Step 2: Variant Determines Application
|
|
128
|
+
|
|
129
|
+
```css
|
|
130
|
+
/* Solid: filled background */
|
|
131
|
+
.my-component[data-variant="solid"] {
|
|
132
|
+
--_bg: var(--_color);
|
|
133
|
+
--_text: var(--_fg);
|
|
134
|
+
--_border: var(--_color);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Outline: transparent, colored border */
|
|
138
|
+
.my-component[data-variant="outline"] {
|
|
139
|
+
--_bg: transparent;
|
|
140
|
+
--_bg-hover: color-mix(in srgb, var(--_color) 10%, transparent);
|
|
141
|
+
--_text: var(--_color);
|
|
142
|
+
--_border: var(--_color);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Step 3: Base Styles Consume Variables
|
|
147
|
+
|
|
148
|
+
```css
|
|
149
|
+
.my-component {
|
|
150
|
+
background: var(--_bg);
|
|
151
|
+
color: var(--_text);
|
|
152
|
+
border-color: var(--_border);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.my-component:hover {
|
|
156
|
+
background: var(--_bg-hover);
|
|
157
|
+
color: var(--_text-hover);
|
|
158
|
+
border-color: var(--_border-hover);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
This pattern allows any intent + variant combination to work automatically.
|
|
163
|
+
|
|
164
|
+
## 3. Foreground Pairing Convention
|
|
165
|
+
|
|
166
|
+
When using a background color, always use its paired foreground for text:
|
|
167
|
+
|
|
168
|
+
```css
|
|
169
|
+
.card {
|
|
170
|
+
background: var(--stuic-color-surface);
|
|
171
|
+
color: var(--stuic-color-surface-foreground);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.muted-section {
|
|
175
|
+
background: var(--stuic-color-muted);
|
|
176
|
+
color: var(--stuic-color-muted-foreground);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## 4. Component Tokens
|
|
181
|
+
|
|
182
|
+
Define component-level tokens in `:root` for easy customization:
|
|
183
|
+
|
|
184
|
+
```css
|
|
185
|
+
:root {
|
|
186
|
+
--stuic-my-component-radius: var(--radius-md);
|
|
187
|
+
--stuic-my-component-padding: 1rem;
|
|
188
|
+
--stuic-my-component-transition: 150ms;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.my-component {
|
|
192
|
+
border-radius: var(--stuic-my-component-radius);
|
|
193
|
+
padding: var(--stuic-my-component-padding);
|
|
194
|
+
transition: all var(--stuic-my-component-transition);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Users can override globally or locally:
|
|
199
|
+
```css
|
|
200
|
+
/* Global override */
|
|
201
|
+
:root {
|
|
202
|
+
--stuic-my-component-radius: 0;
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```svelte
|
|
207
|
+
<!-- Local override -->
|
|
208
|
+
<MyComponent style="--stuic-my-component-radius: 999px;" />
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## 5. State Handling
|
|
212
|
+
|
|
213
|
+
Always define hover and active states using theme tokens:
|
|
214
|
+
|
|
215
|
+
```css
|
|
216
|
+
.element {
|
|
217
|
+
background: var(--stuic-color-surface);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.element:hover {
|
|
221
|
+
background: var(--stuic-color-surface-hover);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.element:active {
|
|
225
|
+
background: var(--stuic-color-surface-active);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.element:focus-visible {
|
|
229
|
+
outline: 3px solid var(--stuic-color-ring);
|
|
230
|
+
outline-offset: 2px;
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## 6. Dark Mode
|
|
235
|
+
|
|
236
|
+
Themes handle dark mode via `:root.dark` selector. When using theme tokens properly, components don't need explicit dark mode styles - the theme handles everything.
|
|
237
|
+
|
|
238
|
+
```css
|
|
239
|
+
/* Theme defines both modes */
|
|
240
|
+
:root {
|
|
241
|
+
--stuic-color-background: var(--color-white);
|
|
242
|
+
--stuic-color-foreground: var(--color-neutral-900);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
:root.dark {
|
|
246
|
+
--stuic-color-background: var(--color-neutral-950);
|
|
247
|
+
--stuic-color-foreground: var(--color-neutral-100);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* Component just uses tokens - works in both modes */
|
|
251
|
+
.my-component {
|
|
252
|
+
background: var(--stuic-color-background);
|
|
253
|
+
color: var(--stuic-color-foreground);
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## 7. Accessibility
|
|
258
|
+
|
|
259
|
+
- Use `--stuic-color-ring` for focus indicators
|
|
260
|
+
- Ensure sufficient contrast between background and foreground pairs
|
|
261
|
+
- Respect reduced motion preferences:
|
|
262
|
+
|
|
263
|
+
```css
|
|
264
|
+
@media (prefers-reduced-motion: reduce) {
|
|
265
|
+
.my-component {
|
|
266
|
+
transition: none;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## 8. Data Attributes
|
|
272
|
+
|
|
273
|
+
Use data attributes for styling variants instead of classes:
|
|
274
|
+
|
|
275
|
+
```svelte
|
|
276
|
+
<button
|
|
277
|
+
data-intent={intent}
|
|
278
|
+
data-variant={variant}
|
|
279
|
+
data-size={size}
|
|
280
|
+
>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```css
|
|
284
|
+
.button[data-intent="primary"] { ... }
|
|
285
|
+
.button[data-variant="outline"] { ... }
|
|
286
|
+
.button[data-size="lg"] { ... }
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
This keeps the class attribute clean for user customization via `class` prop.
|