@noahbaumgartner/svelte-ui 0.0.5 → 0.0.6
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/LICENSE +21 -0
- package/README.md +20 -5
- package/dist/components/accordion/Accordion.svelte +16 -6
- package/dist/components/accordion/Accordion.svelte.d.ts +3 -1
- package/dist/components/accordion/AccordionItem.svelte +106 -67
- package/dist/components/accordion/AccordionItem.svelte.d.ts +5 -1
- package/dist/components/alert-dialog/AlertDialog.svelte +108 -76
- package/dist/components/alert-dialog/AlertDialog.svelte.d.ts +5 -2
- package/dist/components/avatar/Avatar.svelte +71 -49
- package/dist/components/avatar/Avatar.svelte.d.ts +5 -2
- package/dist/components/avatar-group/AvatarGroup.svelte +72 -45
- package/dist/components/avatar-group/AvatarGroup.svelte.d.ts +5 -1
- package/dist/components/badge/Badge.svelte +50 -28
- package/dist/components/badge/Badge.svelte.d.ts +6 -4
- package/dist/components/breadcrumb/Breadcrumb.svelte +21 -17
- package/dist/components/breadcrumb/Breadcrumb.svelte.d.ts +3 -1
- package/dist/components/breadcrumb/BreadcrumbEllipsis.svelte +17 -6
- package/dist/components/breadcrumb/BreadcrumbEllipsis.svelte.d.ts +5 -2
- package/dist/components/breadcrumb/BreadcrumbItem.svelte +75 -36
- package/dist/components/breadcrumb/BreadcrumbItem.svelte.d.ts +8 -5
- package/dist/components/breadcrumb/BreadcrumbSeparator.svelte +32 -9
- package/dist/components/breadcrumb/BreadcrumbSeparator.svelte.d.ts +10 -17
- package/dist/components/button/Button.svelte +206 -168
- package/dist/components/button/Button.svelte.d.ts +9 -5
- package/dist/components/button-group/ButtonGroup.svelte +52 -55
- package/dist/components/button-group/ButtonGroup.svelte.d.ts +3 -1
- package/dist/components/calendar/Calendar.svelte +232 -144
- package/dist/components/calendar/Calendar.svelte.d.ts +19 -2
- package/dist/components/calendar/dates.d.ts +4 -1
- package/dist/components/calendar/dates.js +8 -2
- package/dist/components/card/Card.svelte +48 -32
- package/dist/components/card/Card.svelte.d.ts +3 -1
- package/dist/components/card/CardAction.svelte +11 -7
- package/dist/components/card/CardAction.svelte.d.ts +3 -1
- package/dist/components/card/CardContent.svelte +8 -4
- package/dist/components/card/CardContent.svelte.d.ts +3 -1
- package/dist/components/card/CardDescription.svelte +11 -7
- package/dist/components/card/CardDescription.svelte.d.ts +3 -1
- package/dist/components/card/CardFooter.svelte +15 -11
- package/dist/components/card/CardFooter.svelte.d.ts +3 -1
- package/dist/components/card/CardHeader.svelte +15 -11
- package/dist/components/card/CardHeader.svelte.d.ts +3 -1
- package/dist/components/card/CardTitle.svelte +11 -7
- package/dist/components/card/CardTitle.svelte.d.ts +3 -1
- package/dist/components/checkbox/Checkbox.svelte +152 -61
- package/dist/components/checkbox/Checkbox.svelte.d.ts +5 -2
- package/dist/components/color-picker/ColorPicker.svelte +131 -78
- package/dist/components/color-picker/ColorPicker.svelte.d.ts +10 -1
- package/dist/components/context-menu/ContextMenu.svelte +78 -61
- package/dist/components/context-menu/ContextMenu.svelte.d.ts +5 -2
- package/dist/components/context-menu/ContextMenuInfo.svelte +91 -0
- package/dist/components/context-menu/ContextMenuInfo.svelte.d.ts +19 -0
- package/dist/components/context-menu/ContextMenuItem.svelte +102 -57
- package/dist/components/context-menu/ContextMenuItem.svelte.d.ts +10 -5
- package/dist/components/context-menu/ContextMenuLabel.svelte +28 -0
- package/dist/components/context-menu/ContextMenuLabel.svelte.d.ts +10 -0
- package/dist/components/context-menu/ContextMenuSeparator.svelte +29 -0
- package/dist/components/context-menu/ContextMenuSeparator.svelte.d.ts +8 -0
- package/dist/components/dialog/Dialog.svelte +149 -108
- package/dist/components/dialog/Dialog.svelte.d.ts +7 -2
- package/dist/components/drawer/Drawer.svelte +240 -189
- package/dist/components/drawer/Drawer.svelte.d.ts +7 -2
- package/dist/components/empty-state/EmptyState.svelte +67 -47
- package/dist/components/empty-state/EmptyState.svelte.d.ts +7 -4
- package/dist/components/entry/Entry.svelte +53 -42
- package/dist/components/entry/Entry.svelte.d.ts +2 -1
- package/dist/components/field/Field.svelte +66 -45
- package/dist/components/field/Field.svelte.d.ts +2 -1
- package/dist/components/field/FieldContent.svelte +11 -8
- package/dist/components/field/FieldContent.svelte.d.ts +2 -1
- package/dist/components/field/FieldDescription.svelte +18 -15
- package/dist/components/field/FieldDescription.svelte.d.ts +2 -1
- package/dist/components/field/FieldError.svelte +22 -13
- package/dist/components/field/FieldError.svelte.d.ts +2 -1
- package/dist/components/field/FieldGroup.svelte +15 -12
- package/dist/components/field/FieldGroup.svelte.d.ts +2 -1
- package/dist/components/field/FieldLegend.svelte +23 -14
- package/dist/components/field/FieldLegend.svelte.d.ts +2 -1
- package/dist/components/field/FieldSeparator.svelte +12 -9
- package/dist/components/field/FieldSeparator.svelte.d.ts +2 -1
- package/dist/components/field/FieldSet.svelte +18 -15
- package/dist/components/field/FieldSet.svelte.d.ts +2 -1
- package/dist/components/footer/Footer.svelte +63 -47
- package/dist/components/footer/Footer.svelte.d.ts +2 -1
- package/dist/components/footer/FooterColumn.svelte +17 -14
- package/dist/components/footer/FooterColumn.svelte.d.ts +2 -1
- package/dist/components/image/Image.svelte +61 -0
- package/dist/components/image/Image.svelte.d.ts +18 -0
- package/dist/components/input/Input.svelte +307 -208
- package/dist/components/input/Input.svelte.d.ts +12 -1
- package/dist/components/input-group/InputGroup.svelte +101 -61
- package/dist/components/input-group/InputGroup.svelte.d.ts +2 -1
- package/dist/components/input-group/InputGroupAddon.svelte +58 -49
- package/dist/components/kbd/Kbd.svelte +39 -30
- package/dist/components/kbd/Kbd.svelte.d.ts +2 -1
- package/dist/components/kbd/KbdGroup.svelte +15 -12
- package/dist/components/kbd/KbdGroup.svelte.d.ts +2 -1
- package/dist/components/label/Label.svelte +47 -28
- package/dist/components/label/Label.svelte.d.ts +2 -1
- package/dist/components/link/Link.svelte +71 -17
- package/dist/components/link/Link.svelte.d.ts +2 -1
- package/dist/components/mesh-gradient/MeshGradient.svelte +33 -22
- package/dist/components/mesh-gradient/MeshGradient.svelte.d.ts +2 -3
- package/dist/components/navbar/Navbar.svelte +137 -99
- package/dist/components/navbar/Navbar.svelte.d.ts +4 -2
- package/dist/components/navigation-menu/NavigationMenu.svelte +37 -20
- package/dist/components/navigation-menu/NavigationMenu.svelte.d.ts +4 -2
- package/dist/components/navigation-menu/NavigationMenuItem.svelte +131 -89
- package/dist/components/navigation-menu/NavigationMenuItem.svelte.d.ts +4 -2
- package/dist/components/navigation-menu/NavigationMenuLink.svelte +90 -51
- package/dist/components/navigation-menu/NavigationMenuLink.svelte.d.ts +7 -5
- package/dist/components/number-stepper/NumberStepper.svelte +39 -20
- package/dist/components/number-stepper/NumberStepper.svelte.d.ts +6 -1
- package/dist/components/popover/Popover.svelte +85 -65
- package/dist/components/popover/Popover.svelte.d.ts +5 -2
- package/dist/components/preview-card/PreviewCard.svelte +116 -98
- package/dist/components/preview-card/PreviewCard.svelte.d.ts +9 -6
- package/dist/components/progress/Progress.svelte +61 -38
- package/dist/components/progress/Progress.svelte.d.ts +2 -1
- package/dist/components/radio-group/RadioGroup.svelte +24 -19
- package/dist/components/radio-group/RadioGroup.svelte.d.ts +2 -1
- package/dist/components/radio-group/RadioGroupItem.svelte +101 -54
- package/dist/components/radio-group/RadioGroupItem.svelte.d.ts +2 -1
- package/dist/components/section/Section.svelte +114 -0
- package/dist/components/section/Section.svelte.d.ts +22 -0
- package/dist/components/select/Select.svelte +216 -133
- package/dist/components/select/Select.svelte.d.ts +11 -2
- package/dist/components/separator/Separator.svelte +21 -10
- package/dist/components/separator/Separator.svelte.d.ts +2 -1
- package/dist/components/sidebar/Sidebar.svelte +142 -108
- package/dist/components/sidebar/Sidebar.svelte.d.ts +6 -1
- package/dist/components/sidebar/SidebarContent.svelte +15 -12
- package/dist/components/sidebar/SidebarContent.svelte.d.ts +2 -1
- package/dist/components/sidebar/SidebarFooter.svelte +10 -7
- package/dist/components/sidebar/SidebarFooter.svelte.d.ts +2 -1
- package/dist/components/sidebar/SidebarGroup.svelte +35 -25
- package/dist/components/sidebar/SidebarGroup.svelte.d.ts +2 -1
- package/dist/components/sidebar/SidebarHeader.svelte +21 -16
- package/dist/components/sidebar/SidebarHeader.svelte.d.ts +6 -1
- package/dist/components/sidebar/SidebarInset.svelte +11 -8
- package/dist/components/sidebar/SidebarInset.svelte.d.ts +2 -1
- package/dist/components/sidebar/SidebarMenu.svelte +13 -10
- package/dist/components/sidebar/SidebarMenu.svelte.d.ts +2 -1
- package/dist/components/sidebar/SidebarMenuItem.svelte +195 -114
- package/dist/components/sidebar/SidebarMenuItem.svelte.d.ts +11 -5
- package/dist/components/sidebar/SidebarProvider.svelte +18 -9
- package/dist/components/sidebar/SidebarProvider.svelte.d.ts +2 -1
- package/dist/components/sidebar/SidebarSeparator.svelte +6 -1
- package/dist/components/sidebar/SidebarSeparator.svelte.d.ts +6 -17
- package/dist/components/sidebar/SidebarTrigger.svelte +17 -5
- package/dist/components/sidebar/SidebarTrigger.svelte.d.ts +4 -2
- package/dist/components/skeleton/Skeleton.svelte +26 -16
- package/dist/components/skeleton/Skeleton.svelte.d.ts +4 -2
- package/dist/components/spinner/Spinner.svelte +71 -46
- package/dist/components/spinner/Spinner.svelte.d.ts +2 -1
- package/dist/components/switch/Switch.svelte +126 -65
- package/dist/components/switch/Switch.svelte.d.ts +4 -2
- package/dist/components/table/Table.svelte +135 -76
- package/dist/components/table/Table.svelte.d.ts +12 -2
- package/dist/components/tabs/Tabs.svelte +173 -116
- package/dist/components/tabs/Tabs.svelte.d.ts +10 -8
- package/dist/components/textarea/Textarea.svelte +76 -42
- package/dist/components/textarea/Textarea.svelte.d.ts +4 -1
- package/dist/components/time-picker/TimePicker.svelte +214 -85
- package/dist/components/time-picker/TimePicker.svelte.d.ts +18 -1
- package/dist/components/toaster/Toaster.svelte +132 -70
- package/dist/components/toaster/Toaster.svelte.d.ts +18 -2
- package/dist/components/toaster/toast.svelte.d.ts +3 -3
- package/dist/components/toggle/Toggle.svelte +25 -4
- package/dist/components/toggle/Toggle.svelte.d.ts +1 -1
- package/dist/components/tooltip/Tooltip.svelte +87 -58
- package/dist/components/tooltip/Tooltip.svelte.d.ts +4 -2
- package/dist/icon.d.ts +12 -0
- package/dist/icon.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/internal/icons/ArrowDown.svelte +14 -0
- package/dist/internal/icons/ArrowDown.svelte.d.ts +4 -0
- package/dist/internal/icons/ArrowUp.svelte +14 -0
- package/dist/internal/icons/ArrowUp.svelte.d.ts +4 -0
- package/dist/internal/icons/Calendar.svelte +16 -0
- package/dist/internal/icons/Calendar.svelte.d.ts +4 -0
- package/dist/internal/icons/Check.svelte +8 -0
- package/dist/internal/icons/Check.svelte.d.ts +4 -0
- package/dist/internal/icons/ChevronDown.svelte +8 -0
- package/dist/internal/icons/ChevronDown.svelte.d.ts +4 -0
- package/dist/internal/icons/ChevronLeft.svelte +8 -0
- package/dist/internal/icons/ChevronLeft.svelte.d.ts +4 -0
- package/dist/internal/icons/ChevronRight.svelte +8 -0
- package/dist/internal/icons/ChevronRight.svelte.d.ts +4 -0
- package/dist/internal/icons/ChevronUp.svelte +8 -0
- package/dist/internal/icons/ChevronUp.svelte.d.ts +4 -0
- package/dist/internal/icons/ChevronsUpDown.svelte +14 -0
- package/dist/internal/icons/ChevronsUpDown.svelte.d.ts +4 -0
- package/dist/internal/icons/Clock.svelte +14 -0
- package/dist/internal/icons/Clock.svelte.d.ts +4 -0
- package/dist/internal/icons/Ellipsis.svelte +15 -0
- package/dist/internal/icons/Ellipsis.svelte.d.ts +4 -0
- package/dist/internal/icons/Icon.svelte +33 -0
- package/dist/internal/icons/Icon.svelte.d.ts +8 -0
- package/dist/internal/icons/Minus.svelte +8 -0
- package/dist/internal/icons/Minus.svelte.d.ts +4 -0
- package/dist/internal/icons/PanelLeft.svelte +14 -0
- package/dist/internal/icons/PanelLeft.svelte.d.ts +4 -0
- package/dist/internal/icons/Plus.svelte +14 -0
- package/dist/internal/icons/Plus.svelte.d.ts +4 -0
- package/dist/internal/icons/User.svelte +14 -0
- package/dist/internal/icons/User.svelte.d.ts +4 -0
- package/dist/internal/icons/X.svelte +14 -0
- package/dist/internal/icons/X.svelte.d.ts +4 -0
- package/dist/styles/tokens.css +39 -41
- package/package.json +5 -10
- package/dist/icons.d.ts +0 -2
- package/dist/icons.js +0 -4
|
@@ -7,9 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
<script lang="ts">
|
|
9
9
|
import type { Snippet } from 'svelte';
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import type { HTMLDialogAttributes } from 'svelte/elements';
|
|
11
|
+
import X from '../../internal/icons/X.svelte';
|
|
12
|
+
|
|
13
|
+
type Props = Omit<
|
|
14
|
+
HTMLDialogAttributes,
|
|
15
|
+
'open' | 'title' | 'children' | 'aria-labelledby' | 'aria-describedby'
|
|
16
|
+
> & {
|
|
17
|
+
/** The dialog element. Bindable. */
|
|
18
|
+
ref?: HTMLDialogElement | null;
|
|
13
19
|
/**
|
|
14
20
|
* Whether the drawer is open. Bindable. A sheet from the bottom on phones, a panel on the right from 768px up.
|
|
15
21
|
* Escape, the handle or close button, dragging it away and a click on the backdrop close it.
|
|
@@ -23,12 +29,25 @@
|
|
|
23
29
|
children?: Snippet;
|
|
24
30
|
/** Optional Buttons in the footer, stacked at full width with the primary one last; it ends up on top. Call `close` to close the drawer. */
|
|
25
31
|
actions?: Snippet<[close: () => void]>;
|
|
32
|
+
/** Accessible name of the handle and close button. */
|
|
33
|
+
closeLabel?: string;
|
|
26
34
|
};
|
|
27
35
|
|
|
28
|
-
let {
|
|
36
|
+
let {
|
|
37
|
+
ref = $bindable(null),
|
|
38
|
+
open = $bindable(false),
|
|
39
|
+
title,
|
|
40
|
+
description,
|
|
41
|
+
trigger,
|
|
42
|
+
children,
|
|
43
|
+
actions,
|
|
44
|
+
closeLabel = 'Close',
|
|
45
|
+
class: className,
|
|
46
|
+
style,
|
|
47
|
+
...rest
|
|
48
|
+
}: Props = $props();
|
|
29
49
|
|
|
30
50
|
const id = $props.id();
|
|
31
|
-
let dialogEl: HTMLDialogElement;
|
|
32
51
|
|
|
33
52
|
const triggerProps: DrawerTriggerProps = {
|
|
34
53
|
onclick: () => (open = true),
|
|
@@ -40,10 +59,11 @@
|
|
|
40
59
|
}
|
|
41
60
|
|
|
42
61
|
$effect(() => {
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
62
|
+
if (!ref) return;
|
|
63
|
+
if (open && !ref.open) {
|
|
64
|
+
ref.showModal();
|
|
65
|
+
} else if (!open && ref.open) {
|
|
66
|
+
ref.close();
|
|
47
67
|
}
|
|
48
68
|
});
|
|
49
69
|
|
|
@@ -77,7 +97,8 @@
|
|
|
77
97
|
const velocity = offset / Math.max(1, e.timeStamp - startTime);
|
|
78
98
|
const dismiss =
|
|
79
99
|
e.type === 'pointerup' &&
|
|
80
|
-
(offset > (sideways ?
|
|
100
|
+
(offset > (sideways ? (ref?.offsetWidth ?? 0) : (ref?.offsetHeight ?? 0)) / 3 ||
|
|
101
|
+
velocity > 0.5);
|
|
81
102
|
dragging = false;
|
|
82
103
|
offset = 0;
|
|
83
104
|
if (dismiss) close();
|
|
@@ -94,10 +115,12 @@
|
|
|
94
115
|
{@render trigger?.(triggerProps)}
|
|
95
116
|
|
|
96
117
|
<dialog
|
|
97
|
-
|
|
118
|
+
{...rest}
|
|
119
|
+
bind:this={ref}
|
|
98
120
|
aria-labelledby="{id}-title"
|
|
99
121
|
aria-describedby={description ? `${id}-description` : undefined}
|
|
100
|
-
class={['drawer', { 'drawer--dragging': dragging }]}
|
|
122
|
+
class={['drawer', { 'drawer--dragging': dragging }, className]}
|
|
123
|
+
{style}
|
|
101
124
|
style:translate={dragging ? (sideways ? `${offset}px 0` : `0 ${offset}px`) : undefined}
|
|
102
125
|
onkeydown={(event) => {
|
|
103
126
|
if (event.key !== 'Escape') return;
|
|
@@ -111,8 +134,8 @@
|
|
|
111
134
|
onclose={() => (open = false)}
|
|
112
135
|
onclick={(event) => {
|
|
113
136
|
// Clicks on the ::backdrop target the <dialog> itself, outside its box
|
|
114
|
-
if (event.target !==
|
|
115
|
-
const rect =
|
|
137
|
+
if (event.target !== ref || !ref) return;
|
|
138
|
+
const rect = ref.getBoundingClientRect();
|
|
116
139
|
const inside =
|
|
117
140
|
event.clientX >= rect.left &&
|
|
118
141
|
event.clientX <= rect.right &&
|
|
@@ -138,7 +161,7 @@
|
|
|
138
161
|
<button
|
|
139
162
|
type="button"
|
|
140
163
|
class="drawer-handle"
|
|
141
|
-
aria-label=
|
|
164
|
+
aria-label={closeLabel}
|
|
142
165
|
onpointerdown={startDrag}
|
|
143
166
|
onclick={() => {
|
|
144
167
|
if (!dragged) close();
|
|
@@ -150,219 +173,247 @@
|
|
|
150
173
|
</dialog>
|
|
151
174
|
|
|
152
175
|
<style>
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
.drawer {
|
|
160
|
-
box-sizing: border-box;
|
|
161
|
-
width: 100%;
|
|
162
|
-
max-width: 560px;
|
|
163
|
-
max-height: calc(100dvh - 48px);
|
|
164
|
-
flex-direction: column;
|
|
165
|
-
/* Pinned to the bottom edge */
|
|
166
|
-
margin: auto auto 0;
|
|
167
|
-
padding: 0 0 env(safe-area-inset-bottom);
|
|
168
|
-
overflow: hidden;
|
|
169
|
-
background-color: var(--color-bg);
|
|
170
|
-
color: var(--color-text);
|
|
171
|
-
border: 1px solid var(--color-border);
|
|
172
|
-
border-bottom: 0;
|
|
173
|
-
border-radius: 16px 16px 0 0;
|
|
174
|
-
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.12);
|
|
175
|
-
outline: none;
|
|
176
|
-
translate: 0 100%;
|
|
177
|
-
transition:
|
|
178
|
-
translate 260ms cubic-bezier(0.32, 0.72, 0, 1),
|
|
179
|
-
display 260ms allow-discrete,
|
|
180
|
-
overlay 260ms allow-discrete;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.drawer[open] {
|
|
184
|
-
display: flex;
|
|
185
|
-
translate: 0 0;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/* Follows the finger directly */
|
|
189
|
-
.drawer--dragging {
|
|
190
|
-
transition: none;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.drawer::backdrop {
|
|
194
|
-
background-color: rgba(0, 0, 0, 0);
|
|
195
|
-
transition:
|
|
196
|
-
background-color 260ms ease,
|
|
197
|
-
display 260ms allow-discrete,
|
|
198
|
-
overlay 260ms allow-discrete;
|
|
199
|
-
}
|
|
176
|
+
@layer svelte-ui {
|
|
177
|
+
/* Locks page scrolling while open; the gutter keeps the layout from shifting */
|
|
178
|
+
:global(html:has(.drawer[open])) {
|
|
179
|
+
overflow: hidden;
|
|
180
|
+
scrollbar-gutter: stable;
|
|
181
|
+
}
|
|
200
182
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
183
|
+
.drawer {
|
|
184
|
+
box-sizing: border-box;
|
|
185
|
+
width: 100%;
|
|
186
|
+
max-width: 560px;
|
|
187
|
+
max-height: calc(100dvh - 48px);
|
|
188
|
+
flex-direction: column;
|
|
189
|
+
/* Pinned to the bottom edge */
|
|
190
|
+
margin: auto auto 0;
|
|
191
|
+
padding: 0 0 env(safe-area-inset-bottom);
|
|
192
|
+
overflow: hidden;
|
|
193
|
+
background-color: var(--color-bg);
|
|
194
|
+
color: var(--color-text);
|
|
195
|
+
border: 1px solid var(--color-border);
|
|
196
|
+
border-bottom: 0;
|
|
197
|
+
border-radius: 16px 16px 0 0;
|
|
198
|
+
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.12);
|
|
199
|
+
outline: none;
|
|
200
|
+
translate: 0 100%;
|
|
201
|
+
transition:
|
|
202
|
+
translate 260ms cubic-bezier(0.32, 0.72, 0, 1),
|
|
203
|
+
display 260ms allow-discrete,
|
|
204
|
+
overlay 260ms allow-discrete;
|
|
205
|
+
}
|
|
204
206
|
|
|
205
|
-
@starting-style {
|
|
206
207
|
.drawer[open] {
|
|
207
|
-
|
|
208
|
+
display: flex;
|
|
209
|
+
translate: 0 0;
|
|
208
210
|
}
|
|
209
211
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
+
/* Follows the finger directly */
|
|
213
|
+
.drawer--dragging {
|
|
214
|
+
transition: none;
|
|
212
215
|
}
|
|
213
|
-
}
|
|
214
216
|
|
|
215
|
-
@media (prefers-reduced-motion: reduce) {
|
|
216
|
-
.drawer,
|
|
217
217
|
.drawer::backdrop {
|
|
218
|
-
|
|
218
|
+
background-color: rgba(0, 0, 0, 0);
|
|
219
|
+
transition:
|
|
220
|
+
background-color 260ms ease,
|
|
221
|
+
display 260ms allow-discrete,
|
|
222
|
+
overlay 260ms allow-discrete;
|
|
219
223
|
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.drawer-header {
|
|
223
|
-
flex-shrink: 0;
|
|
224
|
-
/* Room for the handle */
|
|
225
|
-
padding: 28px 20px 12px;
|
|
226
|
-
cursor: grab;
|
|
227
|
-
user-select: none;
|
|
228
|
-
/* Dragging must not scroll the page or get cancelled by the browser */
|
|
229
|
-
touch-action: none;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
.drawer--dragging .drawer-header,
|
|
233
|
-
.drawer--dragging .drawer-handle {
|
|
234
|
-
cursor: grabbing;
|
|
235
|
-
}
|
|
236
224
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
font-weight: 600;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.drawer-description {
|
|
244
|
-
margin: 6px 0 0;
|
|
245
|
-
font-size: 13px;
|
|
246
|
-
line-height: 1.5;
|
|
247
|
-
color: var(--color-text-muted);
|
|
248
|
-
}
|
|
225
|
+
.drawer[open]::backdrop {
|
|
226
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
227
|
+
}
|
|
249
228
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
overscroll-behavior: contain;
|
|
255
|
-
font-size: 13px;
|
|
256
|
-
}
|
|
229
|
+
@starting-style {
|
|
230
|
+
.drawer[open] {
|
|
231
|
+
translate: 0 100%;
|
|
232
|
+
}
|
|
257
233
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
flex-direction: column-reverse;
|
|
263
|
-
gap: 8px;
|
|
264
|
-
padding: 4px 20px 20px;
|
|
265
|
-
}
|
|
234
|
+
.drawer[open]::backdrop {
|
|
235
|
+
background-color: rgba(0, 0, 0, 0);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
266
238
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
239
|
+
@media (prefers-reduced-motion: reduce) {
|
|
240
|
+
.drawer,
|
|
241
|
+
.drawer::backdrop,
|
|
242
|
+
.drawer-handle-bar {
|
|
243
|
+
transition: none;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
270
246
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
padding: 10px 24px;
|
|
276
|
-
background: none;
|
|
277
|
-
border: 0;
|
|
278
|
-
border-radius: 8px;
|
|
279
|
-
cursor: grab;
|
|
280
|
-
translate: -50% 0;
|
|
281
|
-
touch-action: none;
|
|
282
|
-
-webkit-tap-highlight-color: transparent;
|
|
283
|
-
}
|
|
247
|
+
@media (forced-colors: active) {
|
|
248
|
+
.drawer {
|
|
249
|
+
border: 1px solid CanvasText;
|
|
250
|
+
}
|
|
284
251
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
252
|
+
.drawer-handle-bar {
|
|
253
|
+
background-color: ButtonText;
|
|
254
|
+
}
|
|
289
255
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
background-color: var(--color-border-strong);
|
|
295
|
-
border-radius: 2px;
|
|
296
|
-
transition: background-color 120ms ease;
|
|
297
|
-
}
|
|
256
|
+
.drawer-handle:focus-visible {
|
|
257
|
+
outline-color: Highlight;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
298
260
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
261
|
+
@media (pointer: coarse) {
|
|
262
|
+
.drawer-handle {
|
|
263
|
+
display: flex;
|
|
264
|
+
align-items: center;
|
|
265
|
+
justify-content: center;
|
|
266
|
+
box-sizing: border-box;
|
|
267
|
+
min-width: 44px;
|
|
268
|
+
min-height: 44px;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
302
271
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
272
|
+
.drawer-header {
|
|
273
|
+
flex-shrink: 0;
|
|
274
|
+
/* Room for the handle */
|
|
275
|
+
padding: 28px 20px 12px;
|
|
276
|
+
cursor: grab;
|
|
277
|
+
user-select: none;
|
|
278
|
+
/* Dragging must not scroll the page or get cancelled by the browser */
|
|
279
|
+
touch-action: none;
|
|
280
|
+
}
|
|
308
281
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
width: 400px;
|
|
313
|
-
max-width: calc(100% - 48px);
|
|
314
|
-
height: calc(100dvh - 2 * var(--drawer-inset));
|
|
315
|
-
max-height: none;
|
|
316
|
-
/* Floats with a gap to the screen edges */
|
|
317
|
-
--drawer-inset: 8px;
|
|
318
|
-
margin: var(--drawer-inset) var(--drawer-inset) var(--drawer-inset) auto;
|
|
319
|
-
padding: 0;
|
|
320
|
-
border: 1px solid var(--color-border);
|
|
321
|
-
border-radius: 20px;
|
|
322
|
-
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16);
|
|
323
|
-
translate: calc(100% + var(--drawer-inset)) 0;
|
|
282
|
+
.drawer--dragging .drawer-header,
|
|
283
|
+
.drawer--dragging .drawer-handle {
|
|
284
|
+
cursor: grabbing;
|
|
324
285
|
}
|
|
325
286
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
287
|
+
.drawer-title {
|
|
288
|
+
margin: 0;
|
|
289
|
+
font-size: 15px;
|
|
290
|
+
font-weight: 600;
|
|
330
291
|
}
|
|
331
292
|
|
|
332
|
-
.drawer-
|
|
333
|
-
|
|
293
|
+
.drawer-description {
|
|
294
|
+
margin: 6px 0 0;
|
|
295
|
+
font-size: 13px;
|
|
296
|
+
line-height: 1.5;
|
|
297
|
+
color: var(--color-text-muted);
|
|
334
298
|
}
|
|
335
299
|
|
|
336
|
-
/* Pushes the actions to the bottom */
|
|
337
300
|
.drawer-body {
|
|
338
|
-
|
|
301
|
+
min-height: 0;
|
|
302
|
+
padding: 4px 20px 20px;
|
|
303
|
+
overflow-y: auto;
|
|
304
|
+
overscroll-behavior: contain;
|
|
305
|
+
font-size: 13px;
|
|
339
306
|
}
|
|
340
307
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
translate: none;
|
|
308
|
+
/* Stacked, the primary action (last in the markup) on top */
|
|
309
|
+
.drawer-actions {
|
|
310
|
+
display: flex;
|
|
311
|
+
flex-shrink: 0;
|
|
312
|
+
flex-direction: column-reverse;
|
|
313
|
+
gap: 8px;
|
|
314
|
+
padding: 4px 20px 20px;
|
|
349
315
|
}
|
|
350
316
|
|
|
351
|
-
.drawer-
|
|
352
|
-
|
|
353
|
-
|
|
317
|
+
.drawer-actions :global(.button) {
|
|
318
|
+
width: 100%;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.drawer-handle {
|
|
322
|
+
position: absolute;
|
|
323
|
+
top: 0;
|
|
324
|
+
left: 50%;
|
|
325
|
+
padding: 10px 24px;
|
|
326
|
+
background: none;
|
|
327
|
+
border: 0;
|
|
328
|
+
border-radius: 8px;
|
|
329
|
+
cursor: grab;
|
|
330
|
+
translate: -50% 0;
|
|
331
|
+
touch-action: none;
|
|
332
|
+
-webkit-tap-highlight-color: transparent;
|
|
354
333
|
}
|
|
355
334
|
|
|
356
335
|
.drawer-handle:focus-visible {
|
|
357
|
-
outline
|
|
336
|
+
outline: 2px solid var(--color-accent);
|
|
337
|
+
outline-offset: -4px;
|
|
358
338
|
}
|
|
359
339
|
|
|
360
340
|
.drawer-handle-bar {
|
|
361
|
-
display:
|
|
341
|
+
display: block;
|
|
342
|
+
width: 36px;
|
|
343
|
+
height: 4px;
|
|
344
|
+
background-color: var(--color-border-strong);
|
|
345
|
+
border-radius: 2px;
|
|
346
|
+
transition: background-color 120ms ease;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.drawer-handle:hover .drawer-handle-bar {
|
|
350
|
+
background-color: var(--color-text-faint);
|
|
362
351
|
}
|
|
363
352
|
|
|
364
353
|
.drawer-handle :global(.drawer-handle-icon) {
|
|
365
|
-
display:
|
|
354
|
+
display: none;
|
|
355
|
+
width: 16px;
|
|
356
|
+
height: 16px;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* Larger screens: a floating panel on the right, with a close button instead of the handle */
|
|
360
|
+
@media (min-width: 768px) {
|
|
361
|
+
.drawer {
|
|
362
|
+
width: 400px;
|
|
363
|
+
max-width: calc(100% - 48px);
|
|
364
|
+
height: calc(100dvh - 2 * var(--drawer-inset));
|
|
365
|
+
max-height: none;
|
|
366
|
+
/* Floats with a gap to the screen edges */
|
|
367
|
+
--drawer-inset: 8px;
|
|
368
|
+
margin: var(--drawer-inset) var(--drawer-inset) var(--drawer-inset) auto;
|
|
369
|
+
padding: 0;
|
|
370
|
+
border: 1px solid var(--color-border);
|
|
371
|
+
border-radius: 20px;
|
|
372
|
+
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16);
|
|
373
|
+
translate: calc(100% + var(--drawer-inset)) 0;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
@starting-style {
|
|
377
|
+
.drawer[open] {
|
|
378
|
+
translate: calc(100% + var(--drawer-inset)) 0;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.drawer-header {
|
|
383
|
+
padding: 20px 56px 12px 20px;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/* Pushes the actions to the bottom */
|
|
387
|
+
.drawer-body {
|
|
388
|
+
flex: 1;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.drawer-handle {
|
|
392
|
+
top: 14px;
|
|
393
|
+
right: 14px;
|
|
394
|
+
left: auto;
|
|
395
|
+
padding: 6px;
|
|
396
|
+
color: var(--color-text-muted);
|
|
397
|
+
cursor: pointer;
|
|
398
|
+
translate: none;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.drawer-handle:hover {
|
|
402
|
+
color: var(--color-text);
|
|
403
|
+
background-color: var(--color-surface);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.drawer-handle:focus-visible {
|
|
407
|
+
outline-offset: 2px;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.drawer-handle-bar {
|
|
411
|
+
display: none;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.drawer-handle :global(.drawer-handle-icon) {
|
|
415
|
+
display: block;
|
|
416
|
+
}
|
|
366
417
|
}
|
|
367
418
|
}
|
|
368
419
|
</style>
|
|
@@ -3,7 +3,10 @@ export type DrawerTriggerProps = {
|
|
|
3
3
|
'aria-haspopup': 'dialog';
|
|
4
4
|
};
|
|
5
5
|
import type { Snippet } from 'svelte';
|
|
6
|
-
type
|
|
6
|
+
import type { HTMLDialogAttributes } from 'svelte/elements';
|
|
7
|
+
type Props = Omit<HTMLDialogAttributes, 'open' | 'title' | 'children' | 'aria-labelledby' | 'aria-describedby'> & {
|
|
8
|
+
/** The dialog element. Bindable. */
|
|
9
|
+
ref?: HTMLDialogElement | null;
|
|
7
10
|
/**
|
|
8
11
|
* Whether the drawer is open. Bindable. A sheet from the bottom on phones, a panel on the right from 768px up.
|
|
9
12
|
* Escape, the handle or close button, dragging it away and a click on the backdrop close it.
|
|
@@ -17,7 +20,9 @@ type Props = {
|
|
|
17
20
|
children?: Snippet;
|
|
18
21
|
/** Optional Buttons in the footer, stacked at full width with the primary one last; it ends up on top. Call `close` to close the drawer. */
|
|
19
22
|
actions?: Snippet<[close: () => void]>;
|
|
23
|
+
/** Accessible name of the handle and close button. */
|
|
24
|
+
closeLabel?: string;
|
|
20
25
|
};
|
|
21
|
-
declare const Drawer: import("svelte").Component<Props, {}, "open">;
|
|
26
|
+
declare const Drawer: import("svelte").Component<Props, {}, "ref" | "open">;
|
|
22
27
|
type Drawer = ReturnType<typeof Drawer>;
|
|
23
28
|
export default Drawer;
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import type {
|
|
4
|
+
import type { IconComponent } from '../../icon.js';
|
|
5
5
|
|
|
6
6
|
type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'title'> & {
|
|
7
|
-
/** Any
|
|
8
|
-
icon?:
|
|
7
|
+
/** Any icon component, e.g. from `@lucide/svelte`. */
|
|
8
|
+
icon?: IconComponent;
|
|
9
9
|
title: string;
|
|
10
10
|
description?: string;
|
|
11
11
|
/** `outline` has a dashed border, for empty areas that can be filled. */
|
|
12
12
|
variant?: 'secondary' | 'outline';
|
|
13
13
|
/** Optional actions below the text, e.g. a Button that creates the first entry. */
|
|
14
14
|
children?: Snippet;
|
|
15
|
+
/** Custom media instead of `icon`. */
|
|
16
|
+
media?: Snippet;
|
|
17
|
+
ref?: HTMLDivElement | null;
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
let {
|
|
@@ -21,66 +24,83 @@
|
|
|
21
24
|
variant = 'secondary',
|
|
22
25
|
class: className,
|
|
23
26
|
children,
|
|
27
|
+
media,
|
|
28
|
+
ref = $bindable(null),
|
|
24
29
|
...rest
|
|
25
30
|
}: Props = $props();
|
|
26
31
|
</script>
|
|
27
32
|
|
|
28
|
-
<div {...rest} class={['empty-state', `empty-state--${variant}`, className]}>
|
|
29
|
-
{#if
|
|
33
|
+
<div {...rest} bind:this={ref} class={['empty-state', `empty-state--${variant}`, className]}>
|
|
34
|
+
{#if media}{@render media()}{:else if Icon}<Icon
|
|
35
|
+
class="empty-state-icon"
|
|
36
|
+
aria-hidden="true"
|
|
37
|
+
/>{/if}
|
|
30
38
|
<p class="empty-state-title">{title}</p>
|
|
31
39
|
{#if description}<p class="empty-state-description">{description}</p>{/if}
|
|
32
40
|
{#if children}<div class="empty-state-actions">{@render children()}</div>{/if}
|
|
33
41
|
</div>
|
|
34
42
|
|
|
35
43
|
<style>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
@layer svelte-ui {
|
|
45
|
+
.empty-state {
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
align-items: center;
|
|
49
|
+
gap: 6px;
|
|
50
|
+
box-sizing: border-box;
|
|
51
|
+
padding: 32px 16px;
|
|
52
|
+
font-size: 13px;
|
|
53
|
+
line-height: 1.5;
|
|
54
|
+
color: var(--color-text);
|
|
55
|
+
text-align: center;
|
|
56
|
+
border-radius: 14px;
|
|
57
|
+
}
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
.empty-state--secondary {
|
|
60
|
+
background-color: var(--color-surface);
|
|
61
|
+
border: 1px solid transparent;
|
|
62
|
+
}
|
|
54
63
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
.empty-state--outline {
|
|
65
|
+
border: 1px dashed var(--color-border-strong);
|
|
66
|
+
}
|
|
58
67
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
.empty-state :global(.empty-state-icon) {
|
|
69
|
+
width: 20px;
|
|
70
|
+
height: 20px;
|
|
71
|
+
margin-bottom: 4px;
|
|
72
|
+
color: var(--color-text-muted);
|
|
73
|
+
}
|
|
65
74
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
p {
|
|
76
|
+
max-width: 44ch;
|
|
77
|
+
margin: 0;
|
|
78
|
+
}
|
|
70
79
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
.empty-state-title {
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
}
|
|
74
83
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
.empty-state-description {
|
|
85
|
+
color: var(--color-text-muted);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.empty-state-actions {
|
|
89
|
+
display: flex;
|
|
90
|
+
flex-wrap: wrap;
|
|
91
|
+
justify-content: center;
|
|
92
|
+
gap: 8px;
|
|
93
|
+
margin-top: 8px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@media (forced-colors: active) {
|
|
97
|
+
.empty-state--secondary {
|
|
98
|
+
border-color: GrayText;
|
|
99
|
+
}
|
|
78
100
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
gap: 8px;
|
|
84
|
-
margin-top: 8px;
|
|
101
|
+
.empty-state--outline {
|
|
102
|
+
border-color: CanvasText;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
85
105
|
}
|
|
86
106
|
</style>
|