@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
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
40
40
|
import Button from "../Button/Button.svelte";
|
|
41
41
|
//
|
|
42
|
-
import "./index.css";
|
|
43
42
|
import { tooltip, type TooltipConfig } from "../../actions/index.js";
|
|
44
43
|
|
|
45
44
|
let {
|
|
@@ -88,42 +87,11 @@
|
|
|
88
87
|
});
|
|
89
88
|
});
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const CLS = `
|
|
94
|
-
stuic-button-group
|
|
95
|
-
${rounded}
|
|
96
|
-
w-full
|
|
97
|
-
py-1.5 px-1.5 inline-block space-x-1
|
|
98
|
-
bg-button-group-bg text-button-group-text
|
|
99
|
-
dark:bg-button-group-bg-dark dark:text-button-group-text-dark
|
|
100
|
-
border-1
|
|
101
|
-
border-button-group-border dark:border-button-group-border-dark
|
|
102
|
-
flex justify-between
|
|
103
|
-
|
|
104
|
-
focus-within:border-button-group-accent focus-within:dark:border-button-group-accent-dark
|
|
105
|
-
focus-within:ring-button-group-accent/20 focus-within:dark:ring-button-group-accent-dark/20
|
|
106
|
-
focus-within:ring-4
|
|
107
|
-
`;
|
|
108
|
-
|
|
109
|
-
const CLS_BUTTON = `
|
|
110
|
-
${rounded}
|
|
111
|
-
w-full inline-block
|
|
112
|
-
bg-transparent text-button-group-text dark:text-button-group-text-dark
|
|
113
|
-
hover:bg-transparent hover:text-button-group-text hover:dark:text-button-group-text-dark
|
|
114
|
-
outline-none focus:outline-none
|
|
115
|
-
`;
|
|
90
|
+
// Base class - structural styling handled by CSS
|
|
91
|
+
const CLS = `stuic-button-group`;
|
|
116
92
|
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
const CLS_BUTTON_ACTIVE = `
|
|
120
|
-
shadow-none
|
|
121
|
-
bg-button-group-bg-active dark:bg-button-group-bg-active-dark
|
|
122
|
-
text-button-group-text-active dark:text-button-group-text-active-dark
|
|
123
|
-
hover:bg-button-group-bg-active hover:dark:bg-button-group-bg-active
|
|
124
|
-
hover:text-button-group-text-active hover:dark:text-button-group-text-active-dark
|
|
125
|
-
`;
|
|
126
|
-
// shadow-[0px_0px_1px_1px_rgba(0_0_0_/_.6)]
|
|
93
|
+
// Button class - styling handled by CSS via aria-checked attribute
|
|
94
|
+
const CLS_BUTTON = `stuic-button-group-button`;
|
|
127
95
|
|
|
128
96
|
let els = $state<Record<number, HTMLButtonElement>>({});
|
|
129
97
|
|
|
@@ -138,6 +106,7 @@
|
|
|
138
106
|
{#if coll.size}
|
|
139
107
|
<div
|
|
140
108
|
class={twMerge(CLS, classProp)}
|
|
109
|
+
data-size={size}
|
|
141
110
|
{style}
|
|
142
111
|
role="radiogroup"
|
|
143
112
|
aria-labelledby={$coll?.active?.id || ""}
|
|
@@ -145,15 +114,14 @@
|
|
|
145
114
|
>
|
|
146
115
|
{#each coll.items as item, i}
|
|
147
116
|
<Button
|
|
117
|
+
unstyled
|
|
148
118
|
tabindex={$coll.activeIndex === i ? tabindex : -1}
|
|
149
119
|
class={twMerge(
|
|
150
|
-
"border-none shadow-none",
|
|
151
120
|
CLS_BUTTON,
|
|
152
121
|
classButton,
|
|
153
|
-
$coll.activeIndex === i &&
|
|
122
|
+
$coll.activeIndex === i && classButtonActive
|
|
154
123
|
)}
|
|
155
124
|
{disabled}
|
|
156
|
-
{size}
|
|
157
125
|
type="button"
|
|
158
126
|
role="radio"
|
|
159
127
|
aria-checked={$coll.activeIndex === i}
|
|
@@ -22,7 +22,6 @@ export interface Props {
|
|
|
22
22
|
buttonProps?: (index: number, coll: ItemColl) => undefined | Record<string, any>;
|
|
23
23
|
tooltip?: TooltipConfig;
|
|
24
24
|
}
|
|
25
|
-
import "./index.css";
|
|
26
25
|
import { type TooltipConfig } from "../../actions/index.js";
|
|
27
26
|
declare const ButtonGroupRadio: import("svelte").Component<Props, {}, "value" | "activeIndex">;
|
|
28
27
|
type ButtonGroupRadio = ReturnType<typeof ButtonGroupRadio>;
|
|
@@ -12,12 +12,13 @@ A radio button group styled as a segmented button toggle. Supports keyboard navi
|
|
|
12
12
|
| `size` | `"sm" \| "md" \| "lg" \| string` | `"md"` | Button size |
|
|
13
13
|
| `disabled` | `boolean` | `false` | Disable all buttons |
|
|
14
14
|
| `tabindex` | `number` | `0` | Tab index for active button |
|
|
15
|
-
| `class` | `string` | - | CSS for container |
|
|
16
|
-
| `classButton` | `string` | - | CSS for all buttons |
|
|
17
|
-
| `classButtonActive` | `string` | - | CSS for active button |
|
|
15
|
+
| `class` | `string` | - | CSS classes for container |
|
|
16
|
+
| `classButton` | `string` | - | CSS classes for all buttons |
|
|
17
|
+
| `classButtonActive` | `string` | - | CSS classes for active button |
|
|
18
18
|
| `style` | `string` | - | Inline styles for container |
|
|
19
19
|
| `onButtonClick` | `(index, coll) => Promise<boolean> \| boolean` | - | Async validation hook (return `false` to prevent) |
|
|
20
20
|
| `buttonProps` | `(index, coll) => Record<string, any>` | - | Dynamic props per button |
|
|
21
|
+
| `tooltip` | `TooltipConfig` | - | Tooltip configuration |
|
|
21
22
|
|
|
22
23
|
## Option Format
|
|
23
24
|
|
|
@@ -38,7 +39,7 @@ A radio button group styled as a segmented button toggle. Supports keyboard navi
|
|
|
38
39
|
|
|
39
40
|
```svelte
|
|
40
41
|
<script lang="ts">
|
|
41
|
-
import { ButtonGroupRadio } from 'stuic';
|
|
42
|
+
import { ButtonGroupRadio } from '@marianmeres/stuic';
|
|
42
43
|
|
|
43
44
|
let selected = $state('monthly');
|
|
44
45
|
</script>
|
|
@@ -88,7 +89,84 @@ A radio button group styled as a segmented button toggle. Supports keyboard navi
|
|
|
88
89
|
/>
|
|
89
90
|
```
|
|
90
91
|
|
|
92
|
+
### Custom Styling
|
|
93
|
+
|
|
94
|
+
```svelte
|
|
95
|
+
<!-- Override component tokens inline -->
|
|
96
|
+
<ButtonGroupRadio
|
|
97
|
+
options={['One', 'Two', 'Three']}
|
|
98
|
+
style="--stuic-button-group-radius: 9999px;"
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
<!-- Override via Tailwind classes -->
|
|
102
|
+
<ButtonGroupRadio
|
|
103
|
+
options={['One', 'Two', 'Three']}
|
|
104
|
+
class="bg-slate-100 border-slate-300"
|
|
105
|
+
classButton="font-semibold"
|
|
106
|
+
classButtonActive="bg-indigo-600 text-white"
|
|
107
|
+
/>
|
|
108
|
+
```
|
|
109
|
+
|
|
91
110
|
## Keyboard Navigation
|
|
92
111
|
|
|
93
112
|
- **Arrow Left/Up**: Select previous option
|
|
94
113
|
- **Arrow Right/Down**: Select next option
|
|
114
|
+
|
|
115
|
+
## CSS Variables
|
|
116
|
+
|
|
117
|
+
### Component Tokens
|
|
118
|
+
|
|
119
|
+
| Variable | Default | Description |
|
|
120
|
+
|----------|---------|-------------|
|
|
121
|
+
| `--stuic-button-group-radius` | `var(--radius-md)` | Border radius for container and buttons |
|
|
122
|
+
| `--stuic-button-group-padding` | `0.375rem` | Container padding |
|
|
123
|
+
| `--stuic-button-group-gap` | `0.25rem` | Gap between buttons |
|
|
124
|
+
| `--stuic-button-group-border-width` | `1px` | Container border width |
|
|
125
|
+
| `--stuic-button-group-transition` | `150ms` | Transition duration |
|
|
126
|
+
| `--stuic-button-group-ring-width` | `3px` | Focus ring width |
|
|
127
|
+
| `--stuic-button-group-ring-color` | `var(--stuic-color-ring)` | Focus ring color |
|
|
128
|
+
| `--stuic-button-group-button-padding-x` | `0.75rem` | Button horizontal padding |
|
|
129
|
+
| `--stuic-button-group-button-padding-y` | `0.5rem` | Button vertical padding |
|
|
130
|
+
| `--stuic-button-group-button-min-height` | `2.75rem` | Button min height (44px touch target) |
|
|
131
|
+
|
|
132
|
+
### Color Tokens
|
|
133
|
+
|
|
134
|
+
| Variable | Default | Description |
|
|
135
|
+
|----------|---------|-------------|
|
|
136
|
+
| `--stuic-button-group-bg` | `var(--stuic-color-surface)` | Container background |
|
|
137
|
+
| `--stuic-button-group-text` | `var(--stuic-color-foreground)` | Container text color |
|
|
138
|
+
| `--stuic-button-group-border` | `var(--stuic-color-border)` | Container border color |
|
|
139
|
+
| `--stuic-button-group-button-bg` | `transparent` | Inactive button background |
|
|
140
|
+
| `--stuic-button-group-button-text` | `var(--stuic-color-foreground)` | Inactive button text |
|
|
141
|
+
| `--stuic-button-group-button-bg-hover` | `var(--stuic-color-muted)` | Inactive button hover background |
|
|
142
|
+
| `--stuic-button-group-button-bg-active` | `var(--stuic-color-primary)` | Active button background |
|
|
143
|
+
| `--stuic-button-group-button-text-active` | `var(--stuic-color-primary-foreground)` | Active button text |
|
|
144
|
+
| `--stuic-button-group-button-bg-active-hover` | `var(--stuic-color-primary-hover)` | Active button hover background |
|
|
145
|
+
|
|
146
|
+
### Customization Examples
|
|
147
|
+
|
|
148
|
+
```css
|
|
149
|
+
/* Global override */
|
|
150
|
+
:root {
|
|
151
|
+
--stuic-button-group-radius: 0;
|
|
152
|
+
--stuic-button-group-button-bg-active: var(--stuic-color-accent);
|
|
153
|
+
--stuic-button-group-button-text-active: var(--stuic-color-accent-foreground);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```svelte
|
|
158
|
+
<!-- Local override via style prop -->
|
|
159
|
+
<ButtonGroupRadio
|
|
160
|
+
options={['A', 'B', 'C']}
|
|
161
|
+
style="--stuic-button-group-radius: 9999px; --stuic-button-group-button-bg-active: #10b981;"
|
|
162
|
+
/>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Data Attributes
|
|
166
|
+
|
|
167
|
+
The container uses:
|
|
168
|
+
- `data-size` - The size value (`sm`, `md`, `lg`)
|
|
169
|
+
|
|
170
|
+
The inner buttons use:
|
|
171
|
+
- `aria-checked` - `true` when selected (used for active state styling)
|
|
172
|
+
- `role="radio"` - Accessibility role
|
|
@@ -1,20 +1,164 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
BUTTON GROUP RADIO COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-button-group-radius: 0; }
|
|
4
|
+
Override locally: <ButtonGroupRadio style="--stuic-button-group-radius: 9999px;">
|
|
5
|
+
============================================================================ */
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
:root {
|
|
8
|
+
/* Structure - reference Tailwind vars where applicable */
|
|
9
|
+
--stuic-button-group-radius: var(--radius-md);
|
|
10
|
+
--stuic-button-group-padding: 0.375rem;
|
|
11
|
+
--stuic-button-group-gap: 0.25rem;
|
|
12
|
+
--stuic-button-group-border-width: 1px;
|
|
13
|
+
--stuic-button-group-transition: 150ms;
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
--
|
|
15
|
+
/* Button sizing - 44px is Apple HIG minimum touch target */
|
|
16
|
+
--stuic-button-group-button-padding-x: 0.75rem;
|
|
17
|
+
--stuic-button-group-button-padding-y: 0.5rem;
|
|
18
|
+
--stuic-button-group-button-min-height: 2.75rem; /* 44px */
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
--
|
|
20
|
+
/* Focus ring */
|
|
21
|
+
--stuic-button-group-ring-width: 3px;
|
|
22
|
+
--stuic-button-group-ring-color: var(--stuic-color-ring);
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
--
|
|
24
|
+
/* Container colors - theme vars */
|
|
25
|
+
--stuic-button-group-bg: var(--stuic-color-surface);
|
|
26
|
+
--stuic-button-group-text: var(--stuic-color-foreground);
|
|
27
|
+
--stuic-button-group-border: var(--stuic-color-border);
|
|
17
28
|
|
|
18
|
-
|
|
19
|
-
|
|
29
|
+
/* Button colors (inactive) */
|
|
30
|
+
--stuic-button-group-button-bg: transparent;
|
|
31
|
+
--stuic-button-group-button-text: var(--stuic-color-foreground);
|
|
32
|
+
--stuic-button-group-button-bg-hover: var(--stuic-color-muted);
|
|
33
|
+
--stuic-button-group-button-text-hover: var(--stuic-color-foreground);
|
|
34
|
+
|
|
35
|
+
/* Button colors (active) */
|
|
36
|
+
--stuic-button-group-button-bg-active: var(--stuic-color-primary);
|
|
37
|
+
--stuic-button-group-button-text-active: var(--stuic-color-primary-foreground);
|
|
38
|
+
--stuic-button-group-button-bg-active-hover: var(--stuic-color-primary-hover);
|
|
39
|
+
--stuic-button-group-button-text-active-hover: var(
|
|
40
|
+
--stuic-color-primary-foreground-hover
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@layer components {
|
|
45
|
+
/* ============================================================================
|
|
46
|
+
BASE STYLES
|
|
47
|
+
============================================================================ */
|
|
48
|
+
|
|
49
|
+
.stuic-button-group {
|
|
50
|
+
/* Layout */
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: space-between;
|
|
54
|
+
gap: var(--stuic-button-group-gap);
|
|
55
|
+
width: 100%;
|
|
56
|
+
|
|
57
|
+
/* Box model */
|
|
58
|
+
padding: var(--stuic-button-group-padding);
|
|
59
|
+
border-width: var(--stuic-button-group-border-width);
|
|
60
|
+
border-style: solid;
|
|
61
|
+
border-radius: var(--stuic-button-group-radius);
|
|
62
|
+
|
|
63
|
+
/* Colors */
|
|
64
|
+
background: var(--stuic-button-group-bg);
|
|
65
|
+
color: var(--stuic-button-group-text);
|
|
66
|
+
border-color: var(--stuic-button-group-border);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Focus-within state */
|
|
70
|
+
.stuic-button-group:focus-within {
|
|
71
|
+
outline: var(--stuic-button-group-ring-width) solid
|
|
72
|
+
var(--stuic-button-group-ring-color);
|
|
73
|
+
outline-offset: 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ============================================================================
|
|
77
|
+
SIZE VARIANTS
|
|
78
|
+
============================================================================ */
|
|
79
|
+
|
|
80
|
+
.stuic-button-group[data-size="sm"] {
|
|
81
|
+
--stuic-button-group-padding: 0.25rem;
|
|
82
|
+
--stuic-button-group-gap: 0.125rem;
|
|
83
|
+
--stuic-button-group-button-padding-x: 0.5rem;
|
|
84
|
+
--stuic-button-group-button-padding-y: 0.375rem;
|
|
85
|
+
--stuic-button-group-button-min-height: 2.25rem; /* 36px - still touch-friendly */
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.stuic-button-group[data-size="lg"] {
|
|
89
|
+
--stuic-button-group-padding: 0.5rem;
|
|
90
|
+
--stuic-button-group-gap: 0.375rem;
|
|
91
|
+
--stuic-button-group-button-padding-x: 1rem;
|
|
92
|
+
--stuic-button-group-button-padding-y: 0.625rem;
|
|
93
|
+
--stuic-button-group-button-min-height: 3rem; /* 48px */
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* ============================================================================
|
|
97
|
+
BUTTON STYLES
|
|
98
|
+
============================================================================ */
|
|
99
|
+
|
|
100
|
+
.stuic-button-group-button {
|
|
101
|
+
/* Layout */
|
|
102
|
+
display: inline-flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
flex: 1;
|
|
106
|
+
|
|
107
|
+
/* Box model - mobile-friendly touch targets */
|
|
108
|
+
padding: var(--stuic-button-group-button-padding-y)
|
|
109
|
+
var(--stuic-button-group-button-padding-x);
|
|
110
|
+
min-height: var(--stuic-button-group-button-min-height);
|
|
111
|
+
border: none;
|
|
112
|
+
border-radius: var(--stuic-button-group-radius);
|
|
113
|
+
|
|
114
|
+
/* Typography */
|
|
115
|
+
white-space: nowrap;
|
|
116
|
+
line-height: 1;
|
|
117
|
+
text-align: center;
|
|
118
|
+
|
|
119
|
+
/* Colors */
|
|
120
|
+
background: var(--stuic-button-group-button-bg);
|
|
121
|
+
color: var(--stuic-button-group-button-text);
|
|
122
|
+
|
|
123
|
+
/* Interaction - mobile-friendly */
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
user-select: none;
|
|
126
|
+
-webkit-tap-highlight-color: transparent;
|
|
127
|
+
touch-action: manipulation;
|
|
128
|
+
|
|
129
|
+
/* Transition */
|
|
130
|
+
transition:
|
|
131
|
+
background var(--stuic-button-group-transition),
|
|
132
|
+
color var(--stuic-button-group-transition);
|
|
133
|
+
|
|
134
|
+
/* Focus */
|
|
135
|
+
outline: none;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.stuic-button-group-button:hover:not(:disabled):not([aria-checked="true"]) {
|
|
139
|
+
background: var(--stuic-button-group-button-bg-hover);
|
|
140
|
+
color: var(--stuic-button-group-button-text-hover);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.stuic-button-group-button:focus-visible {
|
|
144
|
+
outline: none; /* Focus handled by container */
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Active/selected button */
|
|
148
|
+
.stuic-button-group-button[aria-checked="true"] {
|
|
149
|
+
background: var(--stuic-button-group-button-bg-active);
|
|
150
|
+
color: var(--stuic-button-group-button-text-active);
|
|
151
|
+
box-shadow: none;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.stuic-button-group-button[aria-checked="true"]:hover:not(:disabled) {
|
|
155
|
+
background: var(--stuic-button-group-button-bg-active-hover);
|
|
156
|
+
color: var(--stuic-button-group-button-text-active-hover);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* Disabled state */
|
|
160
|
+
.stuic-button-group-button:disabled {
|
|
161
|
+
opacity: 0.5;
|
|
162
|
+
cursor: not-allowed;
|
|
163
|
+
}
|
|
20
164
|
}
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
classContent?: string;
|
|
24
24
|
/** Toggle button class */
|
|
25
25
|
classToggle?: string;
|
|
26
|
-
/**
|
|
27
|
-
|
|
26
|
+
/** Inline styles (for CSS variable overrides) */
|
|
27
|
+
style?: string;
|
|
28
28
|
/** Bind reference to container element */
|
|
29
29
|
el?: HTMLDivElement;
|
|
30
30
|
/** Optional translate function */
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
i18nSpanWrap: boolean = true
|
|
40
40
|
) {
|
|
41
41
|
const m: Record<string, string> = {
|
|
42
|
-
more: "
|
|
43
|
-
less: "
|
|
42
|
+
more: "More...",
|
|
43
|
+
less: "Less...",
|
|
44
44
|
};
|
|
45
45
|
let out = m[k] ?? fallback ?? k;
|
|
46
46
|
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
class: classProp,
|
|
59
59
|
classContent,
|
|
60
60
|
classToggle,
|
|
61
|
-
|
|
61
|
+
style,
|
|
62
62
|
el = $bindable(),
|
|
63
63
|
t = t_default,
|
|
64
64
|
}: Props = $props();
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
bind:this={el}
|
|
87
87
|
bind:clientWidth={containerWidth}
|
|
88
88
|
class={twMerge("stuic-collapsible", classProp)}
|
|
89
|
+
{style}
|
|
89
90
|
>
|
|
90
91
|
<div class="flex items-end">
|
|
91
92
|
<div
|
|
@@ -98,8 +99,7 @@
|
|
|
98
99
|
<button
|
|
99
100
|
type="button"
|
|
100
101
|
class={twMerge(
|
|
101
|
-
|
|
102
|
-
"hover:opacity-100 cursor-pointer px-2 py-1 -my-1 -mr-2",
|
|
102
|
+
"stuic-collapsible-toggle cursor-pointer -my-1 -mr-2",
|
|
103
103
|
classToggle
|
|
104
104
|
)}
|
|
105
105
|
onclick={() => (expanded = !expanded)}
|
|
@@ -17,8 +17,8 @@ export interface Props {
|
|
|
17
17
|
classContent?: string;
|
|
18
18
|
/** Toggle button class */
|
|
19
19
|
classToggle?: string;
|
|
20
|
-
/**
|
|
21
|
-
|
|
20
|
+
/** Inline styles (for CSS variable overrides) */
|
|
21
|
+
style?: string;
|
|
22
22
|
/** Bind reference to container element */
|
|
23
23
|
el?: HTMLDivElement;
|
|
24
24
|
/** Optional translate function */
|
|
@@ -14,8 +14,9 @@ A component that truncates content to a specified number of lines with an expand
|
|
|
14
14
|
| `class` | `string` | - | Container element class |
|
|
15
15
|
| `classContent` | `string` | - | Content wrapper class |
|
|
16
16
|
| `classToggle` | `string` | - | Toggle button class |
|
|
17
|
-
| `
|
|
17
|
+
| `style` | `string` | - | Inline styles (for CSS variable overrides) |
|
|
18
18
|
| `el` | `HTMLDivElement`| - | Bind reference to container element |
|
|
19
|
+
| `t` | `TranslateFn` | - | Optional translate function |
|
|
19
20
|
|
|
20
21
|
## Usage
|
|
21
22
|
|
|
@@ -74,8 +75,39 @@ A component that truncates content to a specified number of lines with an expand
|
|
|
74
75
|
class="bg-gray-100 p-4 rounded"
|
|
75
76
|
classContent="text-sm text-gray-600"
|
|
76
77
|
classToggle="text-blue-500 font-bold"
|
|
77
|
-
toggleOpacity="opacity-100"
|
|
78
78
|
>
|
|
79
79
|
Styled collapsible content.
|
|
80
80
|
</Collapsible>
|
|
81
81
|
```
|
|
82
|
+
|
|
83
|
+
### CSS Variable Overrides
|
|
84
|
+
|
|
85
|
+
```svelte
|
|
86
|
+
<!-- Local override via inline style -->
|
|
87
|
+
<Collapsible style="--stuic-collapsible-toggle-opacity: 1;">
|
|
88
|
+
Always fully visible toggle button.
|
|
89
|
+
</Collapsible>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## CSS Variables
|
|
93
|
+
|
|
94
|
+
Override to customize appearance:
|
|
95
|
+
|
|
96
|
+
| Variable | Default | Description |
|
|
97
|
+
|----------|---------|-------------|
|
|
98
|
+
| `--stuic-collapsible-toggle-opacity` | `0.7` | Toggle button opacity |
|
|
99
|
+
| `--stuic-collapsible-toggle-opacity-hover` | `1` | Hover opacity |
|
|
100
|
+
| `--stuic-collapsible-toggle-padding-x` | `calc(var(--spacing) * 2)` | Horizontal padding |
|
|
101
|
+
| `--stuic-collapsible-toggle-padding-y` | `0.25rem` | Vertical padding |
|
|
102
|
+
| `--stuic-collapsible-transition` | `150ms` | Transition duration |
|
|
103
|
+
| `--stuic-collapsible-ring-width` | `2px` | Focus ring width |
|
|
104
|
+
| `--stuic-collapsible-ring-color` | `--stuic-color-ring` | Focus ring color |
|
|
105
|
+
|
|
106
|
+
### Global Override
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
:root {
|
|
110
|
+
--stuic-collapsible-toggle-opacity: 0.5;
|
|
111
|
+
--stuic-collapsible-toggle-opacity-hover: 0.8;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
COLLAPSIBLE COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-collapsible-toggle-opacity: 0.5; }
|
|
4
|
+
Override locally: <Collapsible style="--stuic-collapsible-toggle-opacity: 1;">
|
|
5
|
+
============================================================================ */
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* Toggle button styling */
|
|
9
|
+
--stuic-collapsible-toggle-opacity: 0.7;
|
|
10
|
+
--stuic-collapsible-toggle-opacity-hover: 1;
|
|
11
|
+
--stuic-collapsible-toggle-padding-x: calc(var(--spacing) * 2);
|
|
12
|
+
--stuic-collapsible-toggle-padding-y: calc(var(--spacing) * 1);
|
|
13
|
+
--stuic-collapsible-transition: 150ms;
|
|
14
|
+
|
|
15
|
+
/* Focus ring (uses theme token) */
|
|
16
|
+
--stuic-collapsible-ring-width: 2px;
|
|
17
|
+
--stuic-collapsible-ring-color: var(--stuic-color-ring);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@layer components {
|
|
21
|
+
/* ============================================================================
|
|
22
|
+
TOGGLE BUTTON STYLES
|
|
23
|
+
============================================================================ */
|
|
24
|
+
|
|
25
|
+
.stuic-collapsible-toggle {
|
|
26
|
+
opacity: var(--stuic-collapsible-toggle-opacity);
|
|
27
|
+
padding: var(--stuic-collapsible-toggle-padding-y)
|
|
28
|
+
var(--stuic-collapsible-toggle-padding-x);
|
|
29
|
+
transition: opacity var(--stuic-collapsible-transition);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.stuic-collapsible-toggle:hover {
|
|
33
|
+
opacity: var(--stuic-collapsible-toggle-opacity-hover);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.stuic-collapsible-toggle:focus-visible {
|
|
37
|
+
outline: var(--stuic-collapsible-ring-width) solid var(--stuic-collapsible-ring-color);
|
|
38
|
+
outline-offset: 2px;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
</script>
|
|
63
63
|
|
|
64
64
|
<script lang="ts">
|
|
65
|
-
import "
|
|
65
|
+
import Button from "../Button/Button.svelte";
|
|
66
66
|
|
|
67
67
|
const clog = createClog("CommandMenu");
|
|
68
68
|
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
<ModalDialog
|
|
224
224
|
bind:this={modalDialog}
|
|
225
225
|
classDialog="items-start"
|
|
226
|
-
class="w-full max-w-3xl bg-transparent pointer-events-none"
|
|
226
|
+
class="w-full max-w-3xl bg-transparent! shadow-none! pointer-events-none"
|
|
227
227
|
{noScrollLock}
|
|
228
228
|
>
|
|
229
229
|
<div class="pt-0 md:pt-[20vh] w-full">
|
|
@@ -251,8 +251,8 @@
|
|
|
251
251
|
placeholder={searchPlaceholder ?? t("search_placeholder")}
|
|
252
252
|
classInputBoxWrap={twMerge(
|
|
253
253
|
// always look like focused
|
|
254
|
-
`border-primary border-
|
|
255
|
-
`ring-
|
|
254
|
+
`border-primary border-(--stuic-input-accent)`,
|
|
255
|
+
`ring-(--stuic-input-accent)/20 ring-4`
|
|
256
256
|
)}
|
|
257
257
|
onkeydown={(e) => {
|
|
258
258
|
if (e.key === "Enter") {
|
|
@@ -262,25 +262,26 @@
|
|
|
262
262
|
}}
|
|
263
263
|
>
|
|
264
264
|
{#snippet inputBefore()}
|
|
265
|
-
<div
|
|
265
|
+
<div
|
|
266
|
+
class="flex flex-col items-center justify-center pl-3 stuic-command-menu-muted"
|
|
267
|
+
>
|
|
266
268
|
{@html iconSearch({ size: 19, strokeWidth: 3 })}
|
|
267
269
|
</div>
|
|
268
270
|
{/snippet}
|
|
269
271
|
{#snippet inputAfter()}
|
|
270
|
-
<div
|
|
272
|
+
<div
|
|
273
|
+
class="flex pl-2 items-center justify-center stuic-command-menu-placeholder"
|
|
274
|
+
>
|
|
271
275
|
{#if isFetching}
|
|
272
276
|
<Spinner class="w-4" />
|
|
273
277
|
{/if}
|
|
274
278
|
</div>
|
|
275
279
|
<div class="flex items-center justify-center">
|
|
276
|
-
<
|
|
280
|
+
<Button
|
|
281
|
+
x
|
|
282
|
+
variant="ghost"
|
|
283
|
+
roundedFull
|
|
277
284
|
type="button"
|
|
278
|
-
class={twMerge(
|
|
279
|
-
"rounded m-1 opacity-75",
|
|
280
|
-
"hover:opacity-100 hover:bg-neutral-200 dark:hover:bg-neutral-800",
|
|
281
|
-
"focus-visible:opacity-100 focus-visible:outline-0",
|
|
282
|
-
"focus-visible:bg-neutral-200 dark:focus-visible:bg-neutral-800"
|
|
283
|
-
)}
|
|
284
285
|
onclick={(e) => {
|
|
285
286
|
e.preventDefault();
|
|
286
287
|
if (!`${q || ""}`.trim()) {
|
|
@@ -289,9 +290,7 @@
|
|
|
289
290
|
q = "";
|
|
290
291
|
input?.focus();
|
|
291
292
|
}}
|
|
292
|
-
|
|
293
|
-
<X class="m-2 size-6" />
|
|
294
|
-
</button>
|
|
293
|
+
/>
|
|
295
294
|
</div>
|
|
296
295
|
{/snippet}
|
|
297
296
|
{#snippet inputBelow()}
|
|
@@ -304,10 +303,9 @@
|
|
|
304
303
|
<div
|
|
305
304
|
class={twMerge(
|
|
306
305
|
"stuic-command-menu-options",
|
|
307
|
-
"
|
|
306
|
+
"block space-y-1 p-1",
|
|
308
307
|
"overflow-y-auto overflow-x-hidden mb-1",
|
|
309
|
-
"border-t
|
|
310
|
-
"max-h-60"
|
|
308
|
+
"border-t"
|
|
311
309
|
)}
|
|
312
310
|
bind:this={optionsBox}
|
|
313
311
|
tabindex="-1"
|
|
@@ -320,10 +318,7 @@
|
|
|
320
318
|
<div class="p-1">
|
|
321
319
|
{#if _optgroup}
|
|
322
320
|
<div
|
|
323
|
-
class=
|
|
324
|
-
"mb-1 p-1 text-xs font-semibold uppercase tracking-wide",
|
|
325
|
-
"text-neutral-500 dark:text-neutral-400",
|
|
326
|
-
]}
|
|
321
|
+
class="stuic-command-menu-group-header mb-1 p-1 font-semibold uppercase tracking-wide"
|
|
327
322
|
>
|
|
328
323
|
{_optgroup}
|
|
329
324
|
</div>
|
|
@@ -369,9 +364,6 @@
|
|
|
369
364
|
</ModalDialog>
|
|
370
365
|
|
|
371
366
|
<style>
|
|
372
|
-
.options {
|
|
373
|
-
scrollbar-width: thin;
|
|
374
|
-
}
|
|
375
367
|
.sr-only {
|
|
376
368
|
position: absolute;
|
|
377
369
|
width: 1px;
|
|
@@ -17,7 +17,6 @@ export interface Props {
|
|
|
17
17
|
classOptionActive?: string;
|
|
18
18
|
showAllOnEmptyQ?: boolean;
|
|
19
19
|
}
|
|
20
|
-
import "./index.css";
|
|
21
20
|
declare const CommandMenu: import("svelte").Component<Props, {
|
|
22
21
|
close: () => void;
|
|
23
22
|
open: (openerOrEvent?: null | HTMLElement | MouseEvent) => void;
|