seblify 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +329 -2
- package/dist/components/AppShell.svelte +136 -136
- package/dist/components/Banner.svelte +56 -56
- package/dist/components/Button.svelte +64 -64
- package/dist/components/Icon.svelte +67 -67
- package/dist/components/Sidebar.svelte +106 -106
- package/dist/components/Snackbar.svelte +26 -26
- package/dist/components/Toast.svelte +27 -27
- package/dist/components/component-doc.d.ts +1 -1
- package/dist/components/display/annotation/badge/badge.thumbnail.png +0 -0
- package/package.json +22 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sebastian Andresen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
+
[](https://seblify.com)
|
|
2
|
+
[](https://www.npmjs.com/package/seblify)
|
|
3
|
+
[](https://www.npmjs.com/package/seblify)
|
|
4
|
+
|
|
1
5
|
# Seblify
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
[comment]: <> (==== ========================= ====)
|
|
8
|
+
[comment]: <> (=== AUTOGENERATED - DO NOT EDIT ===)
|
|
9
|
+
[comment]: <> (==== ========================= ====)
|
|
10
|
+
[comment]: <> (= edit scripts/readme/template.md =)
|
|
11
|
+
[comment]: <> (==== ========================= ====)
|
|
12
|
+
|
|
13
|
+
Svelte UI component library for building themed interfaces.
|
|
14
|
+
|
|
15
|
+
### Feedback
|
|
16
|
+
|
|
17
|
+
Seblify is a work in progress, and I am very open to feedback. If you find a bug, hit a rough edge, or have an idea for a component, API, example, or design-system improvement, please let me know.
|
|
4
18
|
|
|
5
|
-
|
|
19
|
+
Ideas and bug reports are genuinely welcome: [support.seblify@gmail.com](mailto:support.seblify@gmail.com)
|
|
6
20
|
|
|
7
21
|
## Installation
|
|
8
22
|
|
|
@@ -16,3 +30,316 @@ npm install seblify
|
|
|
16
30
|
import { Button, Badge } from 'seblify';
|
|
17
31
|
import 'seblify/theme.css';
|
|
18
32
|
```
|
|
33
|
+
|
|
34
|
+
## Components
|
|
35
|
+
|
|
36
|
+
Explore the supported components in this library. Components are grouped by purpose and linked to their full documentation, including usage examples, props, accessibility notes, and design-system guidance.
|
|
37
|
+
|
|
38
|
+
[](https://seblify.com/components)
|
|
39
|
+
[](https://seblify.com/components)
|
|
40
|
+
[](https://seblify.com/components)
|
|
41
|
+
|
|
42
|
+
### Quick links
|
|
43
|
+
|
|
44
|
+
- [Input Components](https://seblify.com/sections/action)
|
|
45
|
+
- [Display Components](https://seblify.com/sections/display)
|
|
46
|
+
- [Framework Components](https://seblify.com/sections/framework)
|
|
47
|
+
- [Design System](https://seblify.com/design-system)
|
|
48
|
+
|
|
49
|
+
<br />
|
|
50
|
+
|
|
51
|
+
### Input Components
|
|
52
|
+
|
|
53
|
+
_6 items_
|
|
54
|
+
|
|
55
|
+
Components that let users make choices, submit data, and trigger behavior.
|
|
56
|
+
|
|
57
|
+
<details>
|
|
58
|
+
<summary><strong>Input Fields · 1</strong></summary>
|
|
59
|
+
|
|
60
|
+
Text-like controls for entering structured user input.
|
|
61
|
+
|
|
62
|
+
| Component | Summary | Status |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| [Pin Input](https://seblify.com/components/pin-input) | A segmented numeric input for short verification codes. | Draft |
|
|
65
|
+
|
|
66
|
+
</details>
|
|
67
|
+
<br />
|
|
68
|
+
|
|
69
|
+
<details>
|
|
70
|
+
<summary><strong>Selectable · 5</strong></summary>
|
|
71
|
+
|
|
72
|
+
Controls for selecting boolean, range, or option-based values.
|
|
73
|
+
|
|
74
|
+
| Component | Summary | Status |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| [Checkbox](https://seblify.com/components/checkbox) | A boolean selection control for one option in a form or settings flow. | Draft |
|
|
77
|
+
| [SegmentControl](https://seblify.com/components/segment-control) | A compact single-selection control for switching between a small set of options. | Draft |
|
|
78
|
+
| [Slider](https://seblify.com/components/slider) | A range input for choosing an approximate numeric value. | Draft |
|
|
79
|
+
| [Switch](https://seblify.com/components/switch) | A two-state control for immediately turning a setting on or off. | Draft |
|
|
80
|
+
| [ThemeSwitch](https://seblify.com/components/theme-switch) | A segmented control for selecting system, light, or dark color mode. | Draft |
|
|
81
|
+
|
|
82
|
+
</details>
|
|
83
|
+
<br />
|
|
84
|
+
|
|
85
|
+
### Display Components
|
|
86
|
+
|
|
87
|
+
_8 items_
|
|
88
|
+
|
|
89
|
+
Components for showing content, feedback, media, and motion.
|
|
90
|
+
|
|
91
|
+
<details>
|
|
92
|
+
<summary><strong>Annotation · 3</strong></summary>
|
|
93
|
+
|
|
94
|
+
Small attached indicators, labels, and supporting markers.
|
|
95
|
+
|
|
96
|
+
| Component | Summary | Status |
|
|
97
|
+
| --- | --- | --- |
|
|
98
|
+
| [Badge](https://seblify.com/components/badge) | A small attached indicator for counts, labels, and presence states around another item. | Draft |
|
|
99
|
+
| [Tag](https://seblify.com/components/tag) | A compact text marker for statuses, categories, and item labels. | Draft |
|
|
100
|
+
| [TagGroup](https://seblify.com/components/tag-group) | A wrapping inline group for tags with the standard tag spacing. | Draft |
|
|
101
|
+
|
|
102
|
+
</details>
|
|
103
|
+
<br />
|
|
104
|
+
|
|
105
|
+
<details>
|
|
106
|
+
<summary><strong>Loading · 2</strong></summary>
|
|
107
|
+
|
|
108
|
+
Progress indicators and waiting states.
|
|
109
|
+
|
|
110
|
+
| Component | Summary | Status |
|
|
111
|
+
| --- | --- | --- |
|
|
112
|
+
| [Loading Dots](https://seblify.com/components/loading-dots) | A compact animated loading indicator for inline waiting states. | Draft |
|
|
113
|
+
| [Spinner](https://seblify.com/components/spinner) | A circular loading indicator for indeterminate progress. | Draft |
|
|
114
|
+
|
|
115
|
+
</details>
|
|
116
|
+
<br />
|
|
117
|
+
|
|
118
|
+
<details>
|
|
119
|
+
<summary><strong>Typography · 2</strong></summary>
|
|
120
|
+
|
|
121
|
+
Text primitives and typographic treatments for readable interfaces.
|
|
122
|
+
|
|
123
|
+
| Component | Summary | Status |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| [Eyebrow](https://seblify.com/components/eyebrow) | A short contextual label that sits above a heading or dense content block. | Draft |
|
|
126
|
+
| [Highlight](https://seblify.com/components/highlight) | Highlights case-insensitive text matches inside a plain text string. | Draft |
|
|
127
|
+
|
|
128
|
+
</details>
|
|
129
|
+
<br />
|
|
130
|
+
|
|
131
|
+
<details>
|
|
132
|
+
<summary><strong>Media · 1</strong></summary>
|
|
133
|
+
|
|
134
|
+
Icons, images, video, and other visual media components.
|
|
135
|
+
|
|
136
|
+
| Component | Summary | Status |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| [Icon](https://seblify.com/components/icon) | A convenient registry-based icon component for Seblify SVG icons. | Draft |
|
|
139
|
+
|
|
140
|
+
</details>
|
|
141
|
+
<br />
|
|
142
|
+
|
|
143
|
+
### Framework Components
|
|
144
|
+
|
|
145
|
+
_10 items_
|
|
146
|
+
|
|
147
|
+
Layout, navigation, overlays, and surface primitives.
|
|
148
|
+
|
|
149
|
+
<details>
|
|
150
|
+
<summary><strong>Align · 4</strong></summary>
|
|
151
|
+
|
|
152
|
+
Small layout primitives for spacing and aligning content.
|
|
153
|
+
|
|
154
|
+
| Component | Summary | Status |
|
|
155
|
+
| --- | --- | --- |
|
|
156
|
+
| [Cluster](https://seblify.com/components/cluster) | A wrapping horizontal layout primitive that spaces items with a configurable gap. | Draft |
|
|
157
|
+
| [Grid](https://seblify.com/components/grid) | A responsive grid layout primitive with automatic columns or an explicit column count. | Draft |
|
|
158
|
+
| [Row](https://seblify.com/components/row) | A horizontal layout primitive that spaces items with a configurable gap. | Draft |
|
|
159
|
+
| [Stack](https://seblify.com/components/stack) | A vertical layout primitive that spaces items with a configurable gap. | Draft |
|
|
160
|
+
|
|
161
|
+
</details>
|
|
162
|
+
<br />
|
|
163
|
+
|
|
164
|
+
<details>
|
|
165
|
+
<summary><strong>Container · 3</strong></summary>
|
|
166
|
+
|
|
167
|
+
Page and region containers that define app structure.
|
|
168
|
+
|
|
169
|
+
| Component | Summary | Status |
|
|
170
|
+
| --- | --- | --- |
|
|
171
|
+
| [AppShell](https://seblify.com/components/app-shell) | A full-page application frame with sidebar, header, and content regions. | Draft |
|
|
172
|
+
| [PageHeader](https://seblify.com/components/page-header) | A page-level heading block with optional breadcrumb, eyebrow, summary, and actions. | Draft |
|
|
173
|
+
| [Sidebar](https://seblify.com/components/sidebar) | A responsive side container for persistent or overlay navigation. | Draft |
|
|
174
|
+
|
|
175
|
+
</details>
|
|
176
|
+
<br />
|
|
177
|
+
|
|
178
|
+
<details>
|
|
179
|
+
<summary><strong>Navigation · 2</strong></summary>
|
|
180
|
+
|
|
181
|
+
Components that help users understand location and move around.
|
|
182
|
+
|
|
183
|
+
| Component | Summary | Status |
|
|
184
|
+
| --- | --- | --- |
|
|
185
|
+
| [Breadcrumb](https://seblify.com/components/breadcrumb) | A contextual navigation trail for showing page hierarchy. | Draft |
|
|
186
|
+
| [Sidenav](https://seblify.com/components/sidenav) | A hierarchical side navigation for sections, links, and nested pages. | Draft |
|
|
187
|
+
|
|
188
|
+
</details>
|
|
189
|
+
<br />
|
|
190
|
+
|
|
191
|
+
<details>
|
|
192
|
+
<summary><strong>Surface · 1</strong></summary>
|
|
193
|
+
|
|
194
|
+
Framing primitives for cards, papers, tiles, and other contained regions.
|
|
195
|
+
|
|
196
|
+
| Component | Summary | Status |
|
|
197
|
+
| --- | --- | --- |
|
|
198
|
+
| [Paper](https://seblify.com/components/paper) | A themed container for grouping content with configurable variant, tone, padding, border, and elevation. | Draft |
|
|
199
|
+
|
|
200
|
+
</details>
|
|
201
|
+
<br />
|
|
202
|
+
|
|
203
|
+
## Design System
|
|
204
|
+
|
|
205
|
+
Theme, tokens, and styling guidance for Seblify.
|
|
206
|
+
|
|
207
|
+
| Guide | Summary |
|
|
208
|
+
| --- | --- |
|
|
209
|
+
| [Component API](https://seblify.com/design-system/component-api) | Shared prop naming rules for variants, tones, size, slots, radius, placement, and contextual inheritance. |
|
|
210
|
+
| [Icons](https://seblify.com/design-system/icons) | Browse all generated Seblify icons, grouped automatically from the SVG source folders. |
|
|
211
|
+
| [Theme](https://seblify.com/design-system/theme) | Seblify themes use CSS variables for light, dark, system, and custom color modes. |
|
|
212
|
+
|
|
213
|
+
<br />
|
|
214
|
+
|
|
215
|
+
## Release Notes <small>· 0.2.0</small>
|
|
216
|
+
|
|
217
|
+
_May 14 2026_ · _28 items updated_
|
|
218
|
+
|
|
219
|
+
Recent changes are summarized below. For the full release history, see the [changelog](https://seblify.com/release-notes).
|
|
220
|
+
|
|
221
|
+
### [AppShell](https://seblify.com/components/app-shell)
|
|
222
|
+
|
|
223
|
+
- Added AppShell component
|
|
224
|
+
|
|
225
|
+
### [Badge](https://seblify.com/components/badge)
|
|
226
|
+
|
|
227
|
+
- Added badge component. It takes a number or a short text
|
|
228
|
+
- Added inheritable dir support. Added right-to-left example
|
|
229
|
+
- Badge can now be placed on the center edge of its content
|
|
230
|
+
- Badge can be colored with the tone property
|
|
231
|
+
- Added appear animation when badge is populated. Added interactive example for badge with no content
|
|
232
|
+
- Fixed badge placement on round objects
|
|
233
|
+
|
|
234
|
+
### [Breadcrumb](https://seblify.com/components/breadcrumb)
|
|
235
|
+
|
|
236
|
+
- Added breadcrumb component with examples
|
|
237
|
+
|
|
238
|
+
### [Checkbox](https://seblify.com/components/checkbox)
|
|
239
|
+
|
|
240
|
+
- Added checkbox component. Added example with optional disable state. Added example with checkboxes in a table
|
|
241
|
+
|
|
242
|
+
### [Cluster](https://seblify.com/components/cluster)
|
|
243
|
+
|
|
244
|
+
- Added cluster component for wrapping lines
|
|
245
|
+
|
|
246
|
+
### [component-api](https://seblify.com/components/component-api)
|
|
247
|
+
|
|
248
|
+
- Reserved prop value options to streamline semantics across components
|
|
249
|
+
|
|
250
|
+
### [Eyebrow](https://seblify.com/components/eyebrow)
|
|
251
|
+
|
|
252
|
+
- Added eyebrow component
|
|
253
|
+
|
|
254
|
+
### [general](https://seblify.com/components/general)
|
|
255
|
+
|
|
256
|
+
- Setup release note collection flow
|
|
257
|
+
|
|
258
|
+
### [Grid](https://seblify.com/components/grid)
|
|
259
|
+
|
|
260
|
+
- Added grid component. Set column amount or item size
|
|
261
|
+
|
|
262
|
+
### [Highlight](https://seblify.com/components/highlight)
|
|
263
|
+
|
|
264
|
+
- Added highlight component to highlight query matches in a text
|
|
265
|
+
- Customize highlight style with tone and variant prop
|
|
266
|
+
- Made a better example with a longer text
|
|
267
|
+
|
|
268
|
+
### [Icon](https://seblify.com/components/icon)
|
|
269
|
+
|
|
270
|
+
- Added icon component. Takes the name of an icon to display
|
|
271
|
+
- Generates icon components. Specific icons can be imported instead of entire svg collection. Better tree-shaking support
|
|
272
|
+
|
|
273
|
+
### [icons](https://seblify.com/components/icons)
|
|
274
|
+
|
|
275
|
+
- Added initial icons as poc
|
|
276
|
+
|
|
277
|
+
### [Loading Dots](https://seblify.com/components/loading-dots)
|
|
278
|
+
|
|
279
|
+
- Added loading dots component. Takes size prop
|
|
280
|
+
- Different colors via tones prop
|
|
281
|
+
|
|
282
|
+
### [PageHeader](https://seblify.com/components/page-header)
|
|
283
|
+
|
|
284
|
+
- Added page-header component. Uses eyebrow and breadcrumb
|
|
285
|
+
|
|
286
|
+
### [Paper](https://seblify.com/components/paper)
|
|
287
|
+
|
|
288
|
+
- Added Paper basic surface component
|
|
289
|
+
|
|
290
|
+
### [Pin Input](https://seblify.com/components/pin-input)
|
|
291
|
+
|
|
292
|
+
- Added pin-input component. It has optional length and can be disabled
|
|
293
|
+
|
|
294
|
+
### [Row](https://seblify.com/components/row)
|
|
295
|
+
|
|
296
|
+
- Added row component as non-wrapping horizontal container
|
|
297
|
+
|
|
298
|
+
### [SegmentControl](https://seblify.com/components/segment-control)
|
|
299
|
+
|
|
300
|
+
- Added segment-control component
|
|
301
|
+
|
|
302
|
+
### [Sidebar](https://seblify.com/components/sidebar)
|
|
303
|
+
|
|
304
|
+
- Added sidebar component - a left-side container. Uses sidenav component
|
|
305
|
+
|
|
306
|
+
### [Sidenav](https://seblify.com/components/sidenav)
|
|
307
|
+
|
|
308
|
+
- Added sidenav component. Takes tree data to build collapsible nav items
|
|
309
|
+
|
|
310
|
+
### [Slider](https://seblify.com/components/slider)
|
|
311
|
+
|
|
312
|
+
- Added slider component. It can take stepsize
|
|
313
|
+
- Added example with optional disabled slider
|
|
314
|
+
|
|
315
|
+
### [Spinner](https://seblify.com/components/spinner)
|
|
316
|
+
|
|
317
|
+
- Added spinner component with customizable size
|
|
318
|
+
- Accepts tone prop
|
|
319
|
+
|
|
320
|
+
### [Stack](https://seblify.com/components/stack)
|
|
321
|
+
|
|
322
|
+
- Added stack component as vertical container with gap prop
|
|
323
|
+
|
|
324
|
+
### [Switch](https://seblify.com/components/switch)
|
|
325
|
+
|
|
326
|
+
- Added switch component
|
|
327
|
+
|
|
328
|
+
### [Tag](https://seblify.com/components/tag)
|
|
329
|
+
|
|
330
|
+
- Added tag component with custom radius
|
|
331
|
+
- Tag takes variant, tone, and border props
|
|
332
|
+
- Nested icons, spinner, or loading dots inherit size and tone
|
|
333
|
+
|
|
334
|
+
### [TagGroup](https://seblify.com/components/tag-group)
|
|
335
|
+
|
|
336
|
+
- Added tag-group component. Used in all tag examples
|
|
337
|
+
|
|
338
|
+
### [theme](https://seblify.com/components/theme)
|
|
339
|
+
|
|
340
|
+
- Setup initial theme structure
|
|
341
|
+
- Added doc example for scoped theme customization
|
|
342
|
+
|
|
343
|
+
### [ThemeSwitch](https://seblify.com/components/theme-switch)
|
|
344
|
+
|
|
345
|
+
- Added theme-switch component. It uses the segment-control
|
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
banners?: Snippet;
|
|
6
|
-
children?: Snippet;
|
|
7
|
-
drawer?: Snippet;
|
|
8
|
-
snackbars?: Snippet;
|
|
9
|
-
sidebar?: Snippet;
|
|
10
|
-
toasts?: Snippet;
|
|
11
|
-
sidebarWidth?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let {
|
|
15
|
-
banners,
|
|
16
|
-
children,
|
|
17
|
-
drawer,
|
|
18
|
-
snackbars,
|
|
19
|
-
sidebar,
|
|
20
|
-
toasts,
|
|
21
|
-
sidebarWidth = '280px',
|
|
22
|
-
}: Props = $props();
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<div class="app-shell" style:--sidebar-width={sidebarWidth}>
|
|
26
|
-
{#if banners}
|
|
27
|
-
<div class="banner-stack" aria-label="Page alerts">
|
|
28
|
-
{@render banners()}
|
|
29
|
-
</div>
|
|
30
|
-
{/if}
|
|
31
|
-
|
|
32
|
-
<div class="app-body">
|
|
33
|
-
{#if sidebar}
|
|
34
|
-
<aside class="sidebar">
|
|
35
|
-
{@render sidebar()}
|
|
36
|
-
</aside>
|
|
37
|
-
{/if}
|
|
38
|
-
|
|
39
|
-
<main class="main-content" tabindex="-1">
|
|
40
|
-
{@render children?.()}
|
|
41
|
-
</main>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
{#if toasts}
|
|
45
|
-
<div class="toast-region" aria-live="polite" aria-label="Confirmations">
|
|
46
|
-
{@render toasts()}
|
|
47
|
-
</div>
|
|
48
|
-
{/if}
|
|
49
|
-
|
|
50
|
-
{#if snackbars}
|
|
51
|
-
<div class="snackbar-region" aria-live="polite" aria-label="Notifications">
|
|
52
|
-
{@render snackbars()}
|
|
53
|
-
</div>
|
|
54
|
-
{/if}
|
|
55
|
-
|
|
56
|
-
{#if drawer}
|
|
57
|
-
<div class="drawer-layer">
|
|
58
|
-
{@render drawer()}
|
|
59
|
-
</div>
|
|
60
|
-
{/if}
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
<style>
|
|
64
|
-
.app-shell {
|
|
65
|
-
display: flex;
|
|
66
|
-
flex-direction: column;
|
|
67
|
-
min-height: 100vh;
|
|
68
|
-
background: var(--app-shell-background, var(--seblify-color-page, #f4f6f8));
|
|
69
|
-
color: var(--app-shell-color, var(--seblify-color-text, #172033));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.banner-stack {
|
|
73
|
-
position: relative;
|
|
74
|
-
z-index: 100;
|
|
75
|
-
display: grid;
|
|
76
|
-
width: 100%;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.app-body {
|
|
80
|
-
flex: 1;
|
|
81
|
-
display: grid;
|
|
82
|
-
grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
|
|
83
|
-
min-height: 0;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.sidebar {
|
|
87
|
-
min-width: 0;
|
|
88
|
-
background: transparent;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.main-content {
|
|
92
|
-
min-width: 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.toast-region {
|
|
96
|
-
position: fixed;
|
|
97
|
-
top: 16px;
|
|
98
|
-
left: 50%;
|
|
99
|
-
z-index: 650;
|
|
100
|
-
display: grid;
|
|
101
|
-
gap: 8px;
|
|
102
|
-
width: min(420px, calc(100vw - 32px));
|
|
103
|
-
transform: translateX(-50%);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.snackbar-region {
|
|
107
|
-
position: fixed;
|
|
108
|
-
right: 16px;
|
|
109
|
-
bottom: 16px;
|
|
110
|
-
z-index: 700;
|
|
111
|
-
display: grid;
|
|
112
|
-
gap: 8px;
|
|
113
|
-
width: min(360px, calc(100vw - 32px));
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.drawer-layer {
|
|
117
|
-
position: fixed;
|
|
118
|
-
inset: 0;
|
|
119
|
-
z-index: 1000;
|
|
120
|
-
pointer-events: none;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.drawer-layer :global(*) {
|
|
124
|
-
pointer-events: auto;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
@media (max-width: 760px) {
|
|
128
|
-
.app-body {
|
|
129
|
-
grid-template-columns: 1fr;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.sidebar {
|
|
133
|
-
border-bottom: 0;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
banners?: Snippet;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
drawer?: Snippet;
|
|
8
|
+
snackbars?: Snippet;
|
|
9
|
+
sidebar?: Snippet;
|
|
10
|
+
toasts?: Snippet;
|
|
11
|
+
sidebarWidth?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
banners,
|
|
16
|
+
children,
|
|
17
|
+
drawer,
|
|
18
|
+
snackbars,
|
|
19
|
+
sidebar,
|
|
20
|
+
toasts,
|
|
21
|
+
sidebarWidth = '280px',
|
|
22
|
+
}: Props = $props();
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<div class="app-shell" style:--sidebar-width={sidebarWidth}>
|
|
26
|
+
{#if banners}
|
|
27
|
+
<div class="banner-stack" aria-label="Page alerts">
|
|
28
|
+
{@render banners()}
|
|
29
|
+
</div>
|
|
30
|
+
{/if}
|
|
31
|
+
|
|
32
|
+
<div class="app-body">
|
|
33
|
+
{#if sidebar}
|
|
34
|
+
<aside class="sidebar">
|
|
35
|
+
{@render sidebar()}
|
|
36
|
+
</aside>
|
|
37
|
+
{/if}
|
|
38
|
+
|
|
39
|
+
<main class="main-content" tabindex="-1">
|
|
40
|
+
{@render children?.()}
|
|
41
|
+
</main>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
{#if toasts}
|
|
45
|
+
<div class="toast-region" aria-live="polite" aria-label="Confirmations">
|
|
46
|
+
{@render toasts()}
|
|
47
|
+
</div>
|
|
48
|
+
{/if}
|
|
49
|
+
|
|
50
|
+
{#if snackbars}
|
|
51
|
+
<div class="snackbar-region" aria-live="polite" aria-label="Notifications">
|
|
52
|
+
{@render snackbars()}
|
|
53
|
+
</div>
|
|
54
|
+
{/if}
|
|
55
|
+
|
|
56
|
+
{#if drawer}
|
|
57
|
+
<div class="drawer-layer">
|
|
58
|
+
{@render drawer()}
|
|
59
|
+
</div>
|
|
60
|
+
{/if}
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<style>
|
|
64
|
+
.app-shell {
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-direction: column;
|
|
67
|
+
min-height: 100vh;
|
|
68
|
+
background: var(--app-shell-background, var(--seblify-color-page, #f4f6f8));
|
|
69
|
+
color: var(--app-shell-color, var(--seblify-color-text, #172033));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.banner-stack {
|
|
73
|
+
position: relative;
|
|
74
|
+
z-index: 100;
|
|
75
|
+
display: grid;
|
|
76
|
+
width: 100%;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.app-body {
|
|
80
|
+
flex: 1;
|
|
81
|
+
display: grid;
|
|
82
|
+
grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
|
|
83
|
+
min-height: 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.sidebar {
|
|
87
|
+
min-width: 0;
|
|
88
|
+
background: transparent;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.main-content {
|
|
92
|
+
min-width: 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.toast-region {
|
|
96
|
+
position: fixed;
|
|
97
|
+
top: 16px;
|
|
98
|
+
left: 50%;
|
|
99
|
+
z-index: 650;
|
|
100
|
+
display: grid;
|
|
101
|
+
gap: 8px;
|
|
102
|
+
width: min(420px, calc(100vw - 32px));
|
|
103
|
+
transform: translateX(-50%);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.snackbar-region {
|
|
107
|
+
position: fixed;
|
|
108
|
+
right: 16px;
|
|
109
|
+
bottom: 16px;
|
|
110
|
+
z-index: 700;
|
|
111
|
+
display: grid;
|
|
112
|
+
gap: 8px;
|
|
113
|
+
width: min(360px, calc(100vw - 32px));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.drawer-layer {
|
|
117
|
+
position: fixed;
|
|
118
|
+
inset: 0;
|
|
119
|
+
z-index: 1000;
|
|
120
|
+
pointer-events: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.drawer-layer :global(*) {
|
|
124
|
+
pointer-events: auto;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@media (max-width: 760px) {
|
|
128
|
+
.app-body {
|
|
129
|
+
grid-template-columns: 1fr;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.sidebar {
|
|
133
|
+
border-bottom: 0;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
</style>
|