@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
|
@@ -93,6 +93,45 @@ The command menu uses `ModalDialog` internally with top-aligned positioning:
|
|
|
93
93
|
- **Mobile**: Input at top of screen with 1rem margins from edges
|
|
94
94
|
- **Desktop (md+)**: Input positioned at ~20% from top, max-width 768px, centered horizontally
|
|
95
95
|
|
|
96
|
+
## CSS Variables
|
|
97
|
+
|
|
98
|
+
All styling can be customized via CSS variables. Define them on a parent element or in `:root` to override defaults.
|
|
99
|
+
|
|
100
|
+
### Structure Tokens
|
|
101
|
+
|
|
102
|
+
| Variable | Default | Description |
|
|
103
|
+
|----------|---------|-------------|
|
|
104
|
+
| `--stuic-command-menu-transition` | `150ms` | Transition duration for hover/focus states |
|
|
105
|
+
| `--stuic-command-menu-options-max-height` | `15rem` | Maximum height of options container |
|
|
106
|
+
|
|
107
|
+
### Color Tokens
|
|
108
|
+
|
|
109
|
+
| Variable | Default | Description |
|
|
110
|
+
|----------|---------|-------------|
|
|
111
|
+
| `--stuic-command-menu-divider-color` | `var(--stuic-color-border)` | Border color between input and options |
|
|
112
|
+
| `--stuic-command-menu-group-header-color` | `var(--stuic-color-muted-foreground)` | Option group header text color |
|
|
113
|
+
| `--stuic-command-menu-group-header-font-size` | `var(--text-xs)` | Option group header font size |
|
|
114
|
+
|
|
115
|
+
### Custom Theme Example
|
|
116
|
+
|
|
117
|
+
```svelte
|
|
118
|
+
<div style="
|
|
119
|
+
--stuic-command-menu-divider-color: var(--color-blue-200);
|
|
120
|
+
">
|
|
121
|
+
<CommandMenu ... />
|
|
122
|
+
</div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Global Theme Override
|
|
126
|
+
|
|
127
|
+
```css
|
|
128
|
+
/* In your app.css */
|
|
129
|
+
:root {
|
|
130
|
+
--stuic-command-menu-options-max-height: 20rem;
|
|
131
|
+
--stuic-command-menu-group-header-color: var(--color-indigo-500);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
96
135
|
## Keyboard Navigation
|
|
97
136
|
|
|
98
137
|
- **Arrow Up/Down**: Navigate options
|
|
@@ -1,3 +1,48 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
1
|
+
/* =============================================================================
|
|
2
|
+
COMMAND MENU COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-command-menu-divider-color: red; }
|
|
4
|
+
Override locally: <div style="--stuic-command-menu-divider-color: blue;">
|
|
5
|
+
============================================================================= */
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* Structure */
|
|
9
|
+
--stuic-command-menu-transition: 150ms;
|
|
10
|
+
--stuic-command-menu-options-max-height: 15rem;
|
|
11
|
+
|
|
12
|
+
/* Colors */
|
|
13
|
+
--stuic-command-menu-divider-color: var(--stuic-color-border);
|
|
14
|
+
--stuic-command-menu-group-header-color: var(--stuic-color-muted-foreground);
|
|
15
|
+
--stuic-command-menu-group-header-font-size: var(--text-xs);
|
|
16
|
+
|
|
17
|
+
/* Muted/placeholder states (align with FieldOptions) */
|
|
18
|
+
--stuic-command-menu-muted-text: var(--stuic-color-muted-foreground);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@layer components {
|
|
22
|
+
/* =============================================================================
|
|
23
|
+
BASE STYLES
|
|
24
|
+
============================================================================= */
|
|
25
|
+
|
|
26
|
+
/* Options container */
|
|
27
|
+
.stuic-command-menu-options {
|
|
28
|
+
scrollbar-width: thin;
|
|
29
|
+
max-height: var(--stuic-command-menu-options-max-height);
|
|
30
|
+
border-top-color: var(--stuic-command-menu-divider-color);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Option group header */
|
|
34
|
+
.stuic-command-menu-group-header {
|
|
35
|
+
color: var(--stuic-command-menu-group-header-color);
|
|
36
|
+
font-size: var(--stuic-command-menu-group-header-font-size);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Muted elements (search icon) */
|
|
40
|
+
.stuic-command-menu-muted {
|
|
41
|
+
color: var(--stuic-command-menu-muted-text);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Placeholder/loading states (spinner) */
|
|
45
|
+
.stuic-command-menu-placeholder {
|
|
46
|
+
color: var(--stuic-command-menu-muted-text);
|
|
47
|
+
}
|
|
3
48
|
}
|
|
@@ -1,92 +1,94 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
-
import type { TW_COLORS } from "../../types.js";
|
|
3
2
|
import type { THC } from "../Thc/Thc.svelte";
|
|
4
3
|
|
|
4
|
+
export type MessageIntent = "destructive" | "warning" | "success" | "info";
|
|
5
|
+
|
|
5
6
|
export interface Props {
|
|
6
7
|
class?: string;
|
|
7
8
|
classContent?: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
theme?: TW_COLORS;
|
|
9
|
+
classIcon?: string;
|
|
10
|
+
message: THC | Error | undefined | null;
|
|
11
|
+
intent?: MessageIntent;
|
|
12
12
|
forceAsHtml?: boolean;
|
|
13
13
|
duration?: number;
|
|
14
14
|
onDismiss?: (() => void) | null | false;
|
|
15
|
+
withIcon?: boolean;
|
|
16
|
+
iconFn?: (() => string) | false;
|
|
15
17
|
}
|
|
16
18
|
</script>
|
|
17
19
|
|
|
18
20
|
<script lang="ts">
|
|
19
21
|
import { slide } from "svelte/transition";
|
|
20
|
-
import Thc, { isTHCNotEmpty } from "../Thc/Thc.svelte";
|
|
21
|
-
import X from "../X/X.svelte";
|
|
22
22
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
23
|
+
import Thc, { isTHCNotEmpty } from "../Thc/Thc.svelte";
|
|
24
|
+
import Button from "../Button/Button.svelte";
|
|
25
|
+
import {
|
|
26
|
+
iconAlertWarning,
|
|
27
|
+
iconAlertSuccess,
|
|
28
|
+
iconAlertInfo,
|
|
29
|
+
iconAlertError,
|
|
30
|
+
} from "../../icons/index.js";
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
|
|
33
|
+
const INTENT_ICONS: Record<MessageIntent, () => string> = {
|
|
34
|
+
destructive: () => iconAlertError({ size: 29 }),
|
|
35
|
+
warning: () => iconAlertWarning({ size: 29 }),
|
|
36
|
+
success: () => iconAlertSuccess({ size: 29 }),
|
|
37
|
+
info: () => iconAlertInfo({ size: 29 }),
|
|
38
|
+
};
|
|
25
39
|
|
|
26
40
|
let {
|
|
27
41
|
class: classProps,
|
|
28
42
|
classContent,
|
|
29
|
-
|
|
30
|
-
classX,
|
|
43
|
+
classIcon,
|
|
31
44
|
message,
|
|
32
|
-
|
|
45
|
+
intent,
|
|
33
46
|
forceAsHtml = true,
|
|
34
47
|
duration = 150,
|
|
35
48
|
onDismiss = () => (message = ""),
|
|
49
|
+
withIcon,
|
|
50
|
+
iconFn,
|
|
36
51
|
}: Props = $props();
|
|
37
52
|
|
|
38
|
-
let _message = $derived(
|
|
53
|
+
let _message = $derived(message ? String(message) : "");
|
|
39
54
|
let _show = $derived(isTHCNotEmpty(_message));
|
|
55
|
+
|
|
56
|
+
let _iconHtml = $derived.by(() => {
|
|
57
|
+
if (iconFn === false) return "";
|
|
58
|
+
if (typeof iconFn === "function") return iconFn();
|
|
59
|
+
if (withIcon && intent) return INTENT_ICONS[intent]?.();
|
|
60
|
+
return "";
|
|
61
|
+
});
|
|
40
62
|
</script>
|
|
41
63
|
|
|
42
64
|
{#if _show}
|
|
43
65
|
<div
|
|
44
|
-
class={twMerge(
|
|
45
|
-
|
|
46
|
-
`mb-4 rounded flex text-sm
|
|
47
|
-
bg-dismiss-bg dark:bg-dismiss-bg-dark
|
|
48
|
-
border-dismiss-border dark:border-dismiss-border-dark
|
|
49
|
-
text-dismiss-text dark:text-dismiss-text-dark`,
|
|
50
|
-
classProps
|
|
51
|
-
)}
|
|
52
|
-
style={theme
|
|
53
|
-
? `
|
|
54
|
-
--color-dismiss-bg: var(--color-${theme}-100);
|
|
55
|
-
--color-dismiss-bg-dark: var(--color-${theme}-700);
|
|
56
|
-
|
|
57
|
-
--color-dismiss-text: var(--color-${theme}-800);
|
|
58
|
-
--color-dismiss-text-dark: var(--color-${theme}-50);
|
|
59
|
-
|
|
60
|
-
--color-dismiss-border: var(--color-${theme}-500);
|
|
61
|
-
--color-dismiss-border-dark: var(--color-${theme}-500);
|
|
62
|
-
`
|
|
63
|
-
: ``}
|
|
66
|
+
class={twMerge("stuic-dismissible-message", "mb-4", classProps)}
|
|
67
|
+
data-intent={intent}
|
|
64
68
|
transition:slide={{ duration }}
|
|
65
69
|
>
|
|
66
|
-
|
|
70
|
+
{#if _iconHtml}
|
|
71
|
+
<div class={twMerge("icon", classIcon)}>
|
|
72
|
+
{@html _iconHtml}
|
|
73
|
+
</div>
|
|
74
|
+
{/if}
|
|
75
|
+
|
|
76
|
+
<div class={twMerge("content", classContent)}>
|
|
67
77
|
<Thc thc={_message} {forceAsHtml} />
|
|
68
78
|
</div>
|
|
69
79
|
|
|
70
80
|
{#if typeof onDismiss === "function"}
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
group`,
|
|
81
|
-
classDismiss
|
|
82
|
-
)}
|
|
83
|
-
type="button"
|
|
84
|
-
>
|
|
85
|
-
<X
|
|
86
|
-
class={twMerge("x", "opacity-75 group-hover:opacity-100", classX)}
|
|
87
|
-
strokeWidth={1.5}
|
|
81
|
+
<div class="dismiss">
|
|
82
|
+
<Button
|
|
83
|
+
x
|
|
84
|
+
class="text-inherit!"
|
|
85
|
+
variant="ghost"
|
|
86
|
+
roundedFull
|
|
87
|
+
size="sm"
|
|
88
|
+
type="button"
|
|
89
|
+
onclick={() => onDismiss()}
|
|
88
90
|
/>
|
|
89
|
-
</
|
|
91
|
+
</div>
|
|
90
92
|
{/if}
|
|
91
93
|
</div>
|
|
92
94
|
{/if}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type { TW_COLORS } from "../../types.js";
|
|
2
1
|
import type { THC } from "../Thc/Thc.svelte";
|
|
2
|
+
export type MessageIntent = "destructive" | "warning" | "success" | "info";
|
|
3
3
|
export interface Props {
|
|
4
4
|
class?: string;
|
|
5
5
|
classContent?: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
theme?: TW_COLORS;
|
|
6
|
+
classIcon?: string;
|
|
7
|
+
message: THC | Error | undefined | null;
|
|
8
|
+
intent?: MessageIntent;
|
|
10
9
|
forceAsHtml?: boolean;
|
|
11
10
|
duration?: number;
|
|
12
11
|
onDismiss?: (() => void) | null | false;
|
|
12
|
+
withIcon?: boolean;
|
|
13
|
+
iconFn?: (() => string) | false;
|
|
13
14
|
}
|
|
14
|
-
import "./index.css";
|
|
15
15
|
declare const DismissibleMessage: import("svelte").Component<Props, {}, "">;
|
|
16
16
|
type DismissibleMessage = ReturnType<typeof DismissibleMessage>;
|
|
17
17
|
export default DismissibleMessage;
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
# DismissibleMessage
|
|
2
2
|
|
|
3
|
-
A dismissible alert/message component with
|
|
3
|
+
A dismissible alert/message component with semantic intents and slide transition.
|
|
4
4
|
|
|
5
5
|
## Props
|
|
6
6
|
|
|
7
7
|
| Prop | Type | Default | Description |
|
|
8
8
|
|------|------|---------|-------------|
|
|
9
9
|
| `message` | `THC \| Error` | - | Message content (string, HTML, or Error object) |
|
|
10
|
-
| `
|
|
10
|
+
| `intent` | `"destructive" \| "warning" \| "success" \| "info"` | - | Semantic color intent |
|
|
11
11
|
| `forceAsHtml` | `boolean` | `true` | Render message as HTML |
|
|
12
12
|
| `duration` | `number` | `150` | Slide transition duration (ms) |
|
|
13
13
|
| `onDismiss` | `(() => void) \| null \| false` | - | Dismiss callback (set to `false` to hide X button) |
|
|
14
14
|
| `class` | `string` | - | CSS for container |
|
|
15
15
|
| `classContent` | `string` | - | CSS for content area |
|
|
16
|
-
| `classDismiss` | `string` | - | CSS for dismiss button |
|
|
17
|
-
| `classX` | `string` | - | CSS for X icon |
|
|
18
16
|
|
|
19
17
|
## Usage
|
|
20
18
|
|
|
@@ -22,7 +20,7 @@ A dismissible alert/message component with color themes and slide transition.
|
|
|
22
20
|
|
|
23
21
|
```svelte
|
|
24
22
|
<script lang="ts">
|
|
25
|
-
import { DismissibleMessage } from 'stuic';
|
|
23
|
+
import { DismissibleMessage } from '@marianmeres/stuic';
|
|
26
24
|
|
|
27
25
|
let message = $state('This is an important notice.');
|
|
28
26
|
</script>
|
|
@@ -33,27 +31,41 @@ A dismissible alert/message component with color themes and slide transition.
|
|
|
33
31
|
/>
|
|
34
32
|
```
|
|
35
33
|
|
|
36
|
-
### With
|
|
34
|
+
### With Semantic Intents
|
|
37
35
|
|
|
38
36
|
```svelte
|
|
39
37
|
<script lang="ts">
|
|
40
|
-
import { DismissibleMessage } from 'stuic';
|
|
38
|
+
import { DismissibleMessage } from '@marianmeres/stuic';
|
|
41
39
|
|
|
42
40
|
let error = $state('Something went wrong!');
|
|
43
41
|
let success = $state('Operation completed successfully.');
|
|
44
42
|
</script>
|
|
45
43
|
|
|
44
|
+
<!-- Error/destructive message -->
|
|
46
45
|
<DismissibleMessage
|
|
47
46
|
message={error}
|
|
48
|
-
|
|
47
|
+
intent="destructive"
|
|
49
48
|
onDismiss={() => error = ''}
|
|
50
49
|
/>
|
|
51
50
|
|
|
51
|
+
<!-- Success message -->
|
|
52
52
|
<DismissibleMessage
|
|
53
53
|
message={success}
|
|
54
|
-
|
|
54
|
+
intent="success"
|
|
55
55
|
onDismiss={() => success = ''}
|
|
56
56
|
/>
|
|
57
|
+
|
|
58
|
+
<!-- Warning message -->
|
|
59
|
+
<DismissibleMessage
|
|
60
|
+
message="Please review your changes"
|
|
61
|
+
intent="warning"
|
|
62
|
+
/>
|
|
63
|
+
|
|
64
|
+
<!-- Info message -->
|
|
65
|
+
<DismissibleMessage
|
|
66
|
+
message="New features are available"
|
|
67
|
+
intent="info"
|
|
68
|
+
/>
|
|
57
69
|
```
|
|
58
70
|
|
|
59
71
|
### Non-Dismissible
|
|
@@ -61,7 +73,7 @@ A dismissible alert/message component with color themes and slide transition.
|
|
|
61
73
|
```svelte
|
|
62
74
|
<DismissibleMessage
|
|
63
75
|
message="This message cannot be dismissed."
|
|
64
|
-
|
|
76
|
+
intent="info"
|
|
65
77
|
onDismiss={false}
|
|
66
78
|
/>
|
|
67
79
|
```
|
|
@@ -84,8 +96,78 @@ A dismissible alert/message component with color themes and slide transition.
|
|
|
84
96
|
{#if error}
|
|
85
97
|
<DismissibleMessage
|
|
86
98
|
message={error}
|
|
87
|
-
|
|
99
|
+
intent="destructive"
|
|
88
100
|
onDismiss={() => error = null}
|
|
89
101
|
/>
|
|
90
102
|
{/if}
|
|
91
103
|
```
|
|
104
|
+
|
|
105
|
+
## CSS Variables
|
|
106
|
+
|
|
107
|
+
### Component Tokens
|
|
108
|
+
|
|
109
|
+
| Variable | Default | Description |
|
|
110
|
+
|----------|---------|-------------|
|
|
111
|
+
| `--stuic-dismissible-message-radius` | `var(--radius-md)` | Border radius |
|
|
112
|
+
| `--stuic-dismissible-message-padding-x` | `calc(var(--spacing) * 4)` | Horizontal padding |
|
|
113
|
+
| `--stuic-dismissible-message-padding-y` | `calc(var(--spacing) * 3)` | Vertical padding |
|
|
114
|
+
| `--stuic-dismissible-message-border-width` | `1px` | Border width |
|
|
115
|
+
| `--stuic-dismissible-message-transition` | `150ms` | Color transition duration |
|
|
116
|
+
|
|
117
|
+
### Customization Examples
|
|
118
|
+
|
|
119
|
+
```css
|
|
120
|
+
/* Global override */
|
|
121
|
+
:root {
|
|
122
|
+
--stuic-dismissible-message-radius: var(--radius-lg);
|
|
123
|
+
--stuic-dismissible-message-padding-x: calc(var(--spacing) * 6);
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```svelte
|
|
128
|
+
<!-- Inline override -->
|
|
129
|
+
<DismissibleMessage
|
|
130
|
+
message="Custom styled message"
|
|
131
|
+
style="--stuic-dismissible-message-radius: 9999px;"
|
|
132
|
+
/>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Intent Colors
|
|
136
|
+
|
|
137
|
+
Intent colors are derived from the global STUIC design tokens:
|
|
138
|
+
|
|
139
|
+
| Intent | Token Used |
|
|
140
|
+
|--------|------------|
|
|
141
|
+
| `destructive` | `--stuic-color-destructive` |
|
|
142
|
+
| `warning` | `--stuic-color-warning` |
|
|
143
|
+
| `success` | `--stuic-color-success` |
|
|
144
|
+
| `info` | `--stuic-color-info` |
|
|
145
|
+
|
|
146
|
+
Customize these in your theme file to change all components at once.
|
|
147
|
+
|
|
148
|
+
## Data Attributes
|
|
149
|
+
|
|
150
|
+
The component uses data attributes for CSS targeting:
|
|
151
|
+
|
|
152
|
+
- `data-intent` - The intent value (when set)
|
|
153
|
+
|
|
154
|
+
```css
|
|
155
|
+
/* Custom styling for specific intent */
|
|
156
|
+
.stuic-dismissible-message[data-intent="destructive"] {
|
|
157
|
+
font-weight: bold;
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Migration from v2
|
|
162
|
+
|
|
163
|
+
The `theme` prop has been replaced with `intent`:
|
|
164
|
+
|
|
165
|
+
| Old (v2) | New (v3) |
|
|
166
|
+
|----------|----------|
|
|
167
|
+
| `theme="red"` | `intent="destructive"` |
|
|
168
|
+
| `theme="orange"` | `intent="warning"` |
|
|
169
|
+
| `theme="green"` | `intent="success"` |
|
|
170
|
+
| `theme="blue"` | `intent="info"` |
|
|
171
|
+
| No theme | No intent (default) |
|
|
172
|
+
|
|
173
|
+
The `classDismiss` and `classX` props have been removed.
|
|
@@ -1,11 +1,131 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/* =============================================================================
|
|
2
|
+
DISMISSIBLE MESSAGE COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-dismissible-message-radius: 0; }
|
|
4
|
+
Override locally: style="--stuic-dismissible-message-radius: 9999px;"
|
|
5
|
+
============================================================================= */
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
--
|
|
7
|
+
:root {
|
|
8
|
+
--stuic-dismissible-message-radius: var(--radius-md);
|
|
9
|
+
--stuic-dismissible-message-padding-x: calc(var(--spacing) * 4);
|
|
10
|
+
--stuic-dismissible-message-padding-y: calc(var(--spacing) * 3);
|
|
11
|
+
--stuic-dismissible-message-border-width: 1px;
|
|
12
|
+
--stuic-dismissible-message-transition: 150ms;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@layer components {
|
|
16
|
+
/* =============================================================================
|
|
17
|
+
BASE STYLES
|
|
18
|
+
============================================================================= */
|
|
19
|
+
|
|
20
|
+
.stuic-dismissible-message {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
border-width: var(--stuic-dismissible-message-border-width);
|
|
24
|
+
border-style: solid;
|
|
25
|
+
border-radius: var(--stuic-dismissible-message-radius);
|
|
26
|
+
transition:
|
|
27
|
+
background var(--stuic-dismissible-message-transition),
|
|
28
|
+
border-color var(--stuic-dismissible-message-transition);
|
|
29
|
+
|
|
30
|
+
/* Colors via internal vars set by intent */
|
|
31
|
+
background: var(--_bg);
|
|
32
|
+
color: var(--_text);
|
|
33
|
+
border-color: var(--_border);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Content area */
|
|
37
|
+
.stuic-dismissible-message > .content {
|
|
38
|
+
flex: 1;
|
|
39
|
+
padding: var(--stuic-dismissible-message-padding-y)
|
|
40
|
+
var(--stuic-dismissible-message-padding-x);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Icon container (left side) */
|
|
44
|
+
.stuic-dismissible-message > .icon {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
flex-shrink: 0;
|
|
49
|
+
padding-left: var(--stuic-dismissible-message-padding-x);
|
|
50
|
+
color: var(--_text);
|
|
51
|
+
opacity: 0.85;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.stuic-dismissible-message > .icon svg {
|
|
55
|
+
width: 1.5rem;
|
|
56
|
+
height: 1.5rem;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Dismiss button container */
|
|
60
|
+
.stuic-dismissible-message > .dismiss {
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
padding: calc(var(--stuic-dismissible-message-padding-y) * 0.75);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Dismiss button inherits message text color */
|
|
68
|
+
.stuic-dismissible-message > .dismiss .stuic-button {
|
|
69
|
+
color: var(--_text);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* =============================================================================
|
|
73
|
+
DEFAULT (NO INTENT): NEUTRAL MUTED APPEARANCE
|
|
74
|
+
============================================================================= */
|
|
75
|
+
|
|
76
|
+
.stuic-dismissible-message:not([data-intent]) {
|
|
77
|
+
--_bg: var(--stuic-color-muted);
|
|
78
|
+
--_text: var(--stuic-color-muted-foreground);
|
|
79
|
+
--_border: var(--stuic-color-border);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* =============================================================================
|
|
83
|
+
INTENT COLOR MAPPING (SOFT STYLE)
|
|
84
|
+
Each intent uses a soft/tinted appearance appropriate for messages.
|
|
85
|
+
============================================================================= */
|
|
86
|
+
|
|
87
|
+
/* Destructive: error messages */
|
|
88
|
+
.stuic-dismissible-message[data-intent="destructive"] {
|
|
89
|
+
--_bg: color-mix(in srgb, var(--stuic-color-destructive) 15%, transparent);
|
|
90
|
+
/* --_text: var(--stuic-color-destructive); */
|
|
91
|
+
--_text: color-mix(in srgb, var(--stuic-color-destructive), black 15%);
|
|
92
|
+
--_border: color-mix(in srgb, var(--stuic-color-destructive) 30%, transparent);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Warning: caution messages */
|
|
96
|
+
.stuic-dismissible-message[data-intent="warning"] {
|
|
97
|
+
--_bg: color-mix(in srgb, var(--stuic-color-warning) 15%, transparent);
|
|
98
|
+
/* --_text: var(--stuic-color-warning); */
|
|
99
|
+
--_text: color-mix(in srgb, var(--stuic-color-warning), black 15%);
|
|
100
|
+
--_border: color-mix(in srgb, var(--stuic-color-warning) 30%, transparent);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Success: confirmation messages */
|
|
104
|
+
.stuic-dismissible-message[data-intent="success"] {
|
|
105
|
+
--_bg: color-mix(in srgb, var(--stuic-color-success) 15%, transparent);
|
|
106
|
+
/* --_text: var(--stuic-color-success); */
|
|
107
|
+
--_text: color-mix(in srgb, var(--stuic-color-success), black 15%);
|
|
108
|
+
--_border: color-mix(in srgb, var(--stuic-color-success) 30%, transparent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Info: informational messages */
|
|
112
|
+
.stuic-dismissible-message[data-intent="info"] {
|
|
113
|
+
--_bg: color-mix(in srgb, var(--stuic-color-info) 15%, transparent);
|
|
114
|
+
/* --_text: var(--stuic-color-info); */
|
|
115
|
+
--_text: color-mix(in srgb, var(--stuic-color-info), black 15%);
|
|
116
|
+
--_border: color-mix(in srgb, var(--stuic-color-info) 30%, transparent);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* =============================================================================
|
|
120
|
+
DARK MODE ADJUSTMENTS
|
|
121
|
+
Increase color intensity for better visibility in dark mode.
|
|
122
|
+
============================================================================= */
|
|
8
123
|
|
|
9
|
-
|
|
10
|
-
|
|
124
|
+
.dark .stuic-dismissible-message[data-intent="destructive"],
|
|
125
|
+
.dark .stuic-dismissible-message[data-intent="warning"],
|
|
126
|
+
.dark .stuic-dismissible-message[data-intent="success"],
|
|
127
|
+
.dark .stuic-dismissible-message[data-intent="info"] {
|
|
128
|
+
--_bg: color-mix(in srgb, var(--_text) 20%, transparent);
|
|
129
|
+
--_border: color-mix(in srgb, var(--_text) 40%, transparent);
|
|
130
|
+
}
|
|
11
131
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as DismissibleMessage, type Props as DismissibleMessageProps, } from "./DismissibleMessage.svelte";
|
|
1
|
+
export { default as DismissibleMessage, type Props as DismissibleMessageProps, type MessageIntent as DismissibleMessageIntent, } from "./DismissibleMessage.svelte";
|
|
@@ -205,49 +205,17 @@
|
|
|
205
205
|
);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
export const DROPDOWN_MENU_BASE_CLASSES = `stuic-dropdown-menu
|
|
209
|
-
|
|
210
|
-
export const DROPDOWN_MENU_TRIGGER_CLASSES = `
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
`;
|
|
220
|
-
// focus-visible:outline-2 focus-visible:outline-offset-2
|
|
221
|
-
|
|
222
|
-
export const DROPDOWN_MENU_DROPDOWN_CLASSES = `
|
|
223
|
-
stuic-dropdown-menu-dropdown
|
|
224
|
-
bg-white dark:bg-neutral-800
|
|
225
|
-
text-neutral-900 dark:text-neutral-100
|
|
226
|
-
border border-neutral-200 dark:border-neutral-700
|
|
227
|
-
rounded-md shadow-sm
|
|
228
|
-
p-1
|
|
229
|
-
overflow-y-auto
|
|
230
|
-
z-50
|
|
231
|
-
min-w-48
|
|
232
|
-
`;
|
|
233
|
-
|
|
234
|
-
export const DROPDOWN_MENU_DIVIDER_CLASSES = `
|
|
235
|
-
h-px my-1
|
|
236
|
-
bg-neutral-200 dark:bg-neutral-700
|
|
237
|
-
`;
|
|
238
|
-
|
|
239
|
-
export const DROPDOWN_MENU_HEADER_CLASSES = `
|
|
240
|
-
px-2 py-1.5
|
|
241
|
-
text-xs font-semibold uppercase tracking-wide
|
|
242
|
-
text-neutral-500 dark:text-neutral-400
|
|
243
|
-
select-none
|
|
244
|
-
`;
|
|
245
|
-
|
|
246
|
-
export const DROPDOWN_MENU_BACKDROP_CLASSES = `
|
|
247
|
-
stuic-dropdown-menu-backdrop
|
|
248
|
-
fixed inset-0 bg-black/25
|
|
249
|
-
z-40
|
|
250
|
-
`;
|
|
208
|
+
export const DROPDOWN_MENU_BASE_CLASSES = `stuic-dropdown-menu`;
|
|
209
|
+
|
|
210
|
+
export const DROPDOWN_MENU_TRIGGER_CLASSES = `stuic-dropdown-menu-trigger`;
|
|
211
|
+
|
|
212
|
+
export const DROPDOWN_MENU_DROPDOWN_CLASSES = `stuic-dropdown-menu-dropdown`;
|
|
213
|
+
|
|
214
|
+
export const DROPDOWN_MENU_DIVIDER_CLASSES = `stuic-dropdown-menu-divider`;
|
|
215
|
+
|
|
216
|
+
export const DROPDOWN_MENU_HEADER_CLASSES = `stuic-dropdown-menu-header`;
|
|
217
|
+
|
|
218
|
+
export const DROPDOWN_MENU_BACKDROP_CLASSES = `stuic-dropdown-menu-backdrop`;
|
|
251
219
|
</script>
|
|
252
220
|
|
|
253
221
|
<script lang="ts">
|
|
@@ -261,7 +229,6 @@
|
|
|
261
229
|
import { untrack } from "svelte";
|
|
262
230
|
import Thc from "../Thc/Thc.svelte";
|
|
263
231
|
import ListItemButton from "../ListItemButton/ListItemButton.svelte";
|
|
264
|
-
import "./index.css";
|
|
265
232
|
import { BodyScroll } from "../../utils/body-scroll-locker.js";
|
|
266
233
|
import { waitForTwoRepaints } from "../../utils/paint.js";
|
|
267
234
|
|
|
@@ -659,15 +626,11 @@
|
|
|
659
626
|
>
|
|
660
627
|
<!-- Close button (fallback mode only) -->
|
|
661
628
|
{#if !isSupported}
|
|
662
|
-
<div class="sticky top-0 right-0 z-10 flex
|
|
629
|
+
<div class="sticky top-0 right-0 z-10 flex pointer-events-none">
|
|
663
630
|
<button
|
|
664
631
|
type="button"
|
|
665
632
|
aria-label="Close"
|
|
666
|
-
class=
|
|
667
|
-
"bg-black text-white rounded-md cursor-pointer opacity-60",
|
|
668
|
-
"absolute right-0 top-0 p-2",
|
|
669
|
-
"leading-none hover:opacity-100 pointer-events-auto",
|
|
670
|
-
]}
|
|
633
|
+
class="stuic-dropdown-menu-close absolute right-0 top-0 pointer-events-auto"
|
|
671
634
|
onclick={() => {
|
|
672
635
|
isOpen = false;
|
|
673
636
|
triggerEl?.focus();
|
|
@@ -760,7 +723,7 @@
|
|
|
760
723
|
{#if isExpanded}
|
|
761
724
|
<div
|
|
762
725
|
class={twMerge(
|
|
763
|
-
"stuic-dropdown-menu-expandable-content
|
|
726
|
+
"stuic-dropdown-menu-expandable-content",
|
|
764
727
|
classExpandableContent
|
|
765
728
|
)}
|
|
766
729
|
transition:slide={{ duration: transitionDuration }}
|