sv5ui 0.0.1 → 1.1.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 -21
- package/README.md +167 -62
- package/dist/Accordion/Accordion.svelte +196 -0
- package/dist/Accordion/Accordion.svelte.d.ts +6 -0
- package/dist/Accordion/accordion.types.d.ts +225 -0
- package/dist/Accordion/accordion.types.js +1 -0
- package/dist/Accordion/accordion.variants.d.ts +88 -0
- package/dist/Accordion/accordion.variants.js +28 -0
- package/dist/Accordion/index.d.ts +2 -0
- package/dist/Accordion/index.js +1 -0
- package/dist/Alert/Alert.svelte +120 -120
- package/dist/Avatar/Avatar.svelte +88 -70
- package/dist/AvatarGroup/AvatarGroup.svelte +64 -66
- package/dist/Badge/Badge.svelte +7 -3
- package/dist/Badge/badge.variants.js +21 -7
- package/dist/Breadcrumb/Breadcrumb.svelte +88 -0
- package/dist/Breadcrumb/Breadcrumb.svelte.d.ts +5 -0
- package/dist/Breadcrumb/breadcrumb.types.d.ts +62 -0
- package/dist/Breadcrumb/breadcrumb.types.js +1 -0
- package/dist/Breadcrumb/breadcrumb.variants.d.ts +128 -0
- package/dist/Breadcrumb/breadcrumb.variants.js +49 -0
- package/dist/Breadcrumb/index.d.ts +2 -0
- package/dist/Breadcrumb/index.js +1 -0
- package/dist/Button/Button.svelte +121 -103
- package/dist/Button/button.types.d.ts +0 -5
- package/dist/Calendar/Calendar.svelte +292 -0
- package/dist/Calendar/Calendar.svelte.d.ts +6 -0
- package/dist/Calendar/calendar.types.d.ts +99 -0
- package/dist/Calendar/calendar.types.js +1 -0
- package/dist/Calendar/calendar.variants.d.ts +553 -0
- package/dist/Calendar/calendar.variants.js +367 -0
- package/dist/Calendar/index.d.ts +2 -0
- package/dist/Calendar/index.js +1 -0
- package/dist/Card/Card.svelte +53 -53
- package/dist/Checkbox/Checkbox.svelte +138 -0
- package/dist/Checkbox/Checkbox.svelte.d.ts +6 -0
- package/dist/Checkbox/checkbox.types.d.ts +86 -0
- package/dist/Checkbox/checkbox.types.js +1 -0
- package/dist/Checkbox/checkbox.variants.d.ts +358 -0
- package/dist/Checkbox/checkbox.variants.js +140 -0
- package/dist/Checkbox/index.d.ts +2 -0
- package/dist/Checkbox/index.js +1 -0
- package/dist/Chip/chip.variants.js +20 -4
- package/dist/Container/Container.svelte +1 -7
- package/dist/ContextMenu/ContextMenu.svelte +334 -0
- package/dist/ContextMenu/ContextMenu.svelte.d.ts +6 -0
- package/dist/ContextMenu/context-menu.types.d.ts +260 -0
- package/dist/ContextMenu/context-menu.types.js +1 -0
- package/dist/ContextMenu/context-menu.variants.d.ts +393 -0
- package/dist/ContextMenu/context-menu.variants.js +176 -0
- package/dist/ContextMenu/index.d.ts +2 -0
- package/dist/ContextMenu/index.js +1 -0
- package/dist/Drawer/Drawer.svelte +200 -0
- package/dist/Drawer/Drawer.svelte.d.ts +6 -0
- package/dist/Drawer/drawer.types.d.ts +75 -0
- package/dist/Drawer/drawer.types.js +1 -0
- package/dist/Drawer/drawer.variants.d.ts +193 -0
- package/dist/Drawer/drawer.variants.js +139 -0
- package/dist/Drawer/index.d.ts +2 -0
- package/dist/Drawer/index.js +1 -0
- package/dist/DropdownMenu/DropdownMenu.svelte +371 -0
- package/dist/DropdownMenu/DropdownMenu.svelte.d.ts +6 -0
- package/dist/DropdownMenu/dropdown-menu.types.d.ts +266 -0
- package/dist/DropdownMenu/dropdown-menu.types.js +1 -0
- package/dist/DropdownMenu/dropdown-menu.variants.d.ts +463 -0
- package/dist/DropdownMenu/dropdown-menu.variants.js +192 -0
- package/dist/DropdownMenu/index.d.ts +2 -0
- package/dist/DropdownMenu/index.js +1 -0
- package/dist/Empty/Empty.svelte +83 -83
- package/dist/FieldGroup/FieldGroup.svelte +48 -0
- package/dist/FieldGroup/FieldGroup.svelte.d.ts +5 -0
- package/dist/FieldGroup/field-group.types.d.ts +33 -0
- package/dist/FieldGroup/field-group.types.js +1 -0
- package/dist/FieldGroup/field-group.variants.d.ts +116 -0
- package/dist/FieldGroup/field-group.variants.js +49 -0
- package/dist/FieldGroup/index.d.ts +2 -0
- package/dist/FieldGroup/index.js +1 -0
- package/dist/FormField/FormField.svelte +128 -0
- package/dist/FormField/FormField.svelte.d.ts +5 -0
- package/dist/FormField/form-field.types.d.ts +90 -0
- package/dist/FormField/form-field.types.js +1 -0
- package/dist/FormField/form-field.variants.d.ts +313 -0
- package/dist/FormField/form-field.variants.js +74 -0
- package/dist/FormField/index.d.ts +2 -0
- package/dist/FormField/index.js +1 -0
- package/dist/Input/Input.svelte +174 -0
- package/dist/Input/Input.svelte.d.ts +5 -0
- package/dist/Input/index.d.ts +2 -0
- package/dist/Input/index.js +1 -0
- package/dist/Input/input.types.d.ts +92 -0
- package/dist/Input/input.types.js +1 -0
- package/dist/Input/input.variants.d.ts +413 -0
- package/dist/Input/input.variants.js +406 -0
- package/dist/Kbd/Kbd.svelte +35 -35
- package/dist/Kbd/kbd.variants.js +65 -13
- package/dist/Kbd/useKbd.svelte.js +13 -3
- package/dist/Link/Link.svelte +122 -117
- package/dist/Modal/Modal.svelte +197 -0
- package/dist/Modal/Modal.svelte.d.ts +5 -0
- package/dist/Modal/index.d.ts +2 -0
- package/dist/Modal/index.js +1 -0
- package/dist/Modal/modal.types.d.ts +129 -0
- package/dist/Modal/modal.types.js +1 -0
- package/dist/Modal/modal.variants.d.ts +208 -0
- package/dist/Modal/modal.variants.js +71 -0
- package/dist/Pagination/Pagination.svelte +198 -0
- package/dist/Pagination/Pagination.svelte.d.ts +6 -0
- package/dist/Pagination/index.d.ts +2 -0
- package/dist/Pagination/index.js +1 -0
- package/dist/Pagination/pagination.types.d.ts +169 -0
- package/dist/Pagination/pagination.types.js +1 -0
- package/dist/Pagination/pagination.variants.d.ts +598 -0
- package/dist/Pagination/pagination.variants.js +145 -0
- package/dist/Popover/Popover.svelte +125 -0
- package/dist/Popover/Popover.svelte.d.ts +6 -0
- package/dist/Popover/index.d.ts +2 -0
- package/dist/Popover/index.js +1 -0
- package/dist/Popover/popover.types.d.ts +52 -0
- package/dist/Popover/popover.types.js +1 -0
- package/dist/Popover/popover.variants.d.ts +123 -0
- package/dist/Popover/popover.variants.js +41 -0
- package/dist/Progress/Progress.svelte +99 -89
- package/dist/Progress/progress.variants.js +16 -8
- package/dist/RadioGroup/RadioGroup.svelte +175 -0
- package/dist/RadioGroup/RadioGroup.svelte.d.ts +6 -0
- package/dist/RadioGroup/index.d.ts +2 -0
- package/dist/RadioGroup/index.js +1 -0
- package/dist/RadioGroup/radio-group.types.d.ts +96 -0
- package/dist/RadioGroup/radio-group.types.js +1 -0
- package/dist/RadioGroup/radio-group.variants.d.ts +453 -0
- package/dist/RadioGroup/radio-group.variants.js +163 -0
- package/dist/Select/Select.svelte +383 -0
- package/dist/Select/Select.svelte.d.ts +6 -0
- package/dist/Select/index.d.ts +2 -0
- package/dist/Select/index.js +1 -0
- package/dist/Select/select.types.d.ts +221 -0
- package/dist/Select/select.types.js +1 -0
- package/dist/Select/select.variants.d.ts +713 -0
- package/dist/Select/select.variants.js +482 -0
- package/dist/Separator/Separator.svelte +5 -1
- package/dist/Skeleton/Skeleton.svelte +25 -31
- package/dist/Slideover/Slideover.svelte +191 -0
- package/dist/Slideover/Slideover.svelte.d.ts +5 -0
- package/dist/Slideover/index.d.ts +2 -0
- package/dist/Slideover/index.js +1 -0
- package/dist/Slideover/slideover.types.d.ts +128 -0
- package/dist/Slideover/slideover.types.js +1 -0
- package/dist/Slideover/slideover.variants.d.ts +203 -0
- package/dist/Slideover/slideover.variants.js +140 -0
- package/dist/Switch/Switch.svelte +157 -0
- package/dist/Switch/Switch.svelte.d.ts +6 -0
- package/dist/Switch/index.d.ts +2 -0
- package/dist/Switch/index.js +1 -0
- package/dist/Switch/switch.types.d.ts +75 -0
- package/dist/Switch/switch.types.js +1 -0
- package/dist/Switch/switch.variants.d.ts +433 -0
- package/dist/Switch/switch.variants.js +171 -0
- package/dist/Tabs/Tabs.svelte +189 -0
- package/dist/Tabs/Tabs.svelte.d.ts +6 -0
- package/dist/Tabs/index.d.ts +2 -0
- package/dist/Tabs/index.js +1 -0
- package/dist/Tabs/tabs.types.d.ts +205 -0
- package/dist/Tabs/tabs.types.js +1 -0
- package/dist/Tabs/tabs.variants.d.ts +298 -0
- package/dist/Tabs/tabs.variants.js +249 -0
- package/dist/Textarea/Textarea.svelte +196 -0
- package/dist/Textarea/Textarea.svelte.d.ts +5 -0
- package/dist/Textarea/index.d.ts +2 -0
- package/dist/Textarea/index.js +1 -0
- package/dist/Textarea/textarea.types.d.ts +103 -0
- package/dist/Textarea/textarea.types.js +1 -0
- package/dist/Textarea/textarea.variants.d.ts +403 -0
- package/dist/Textarea/textarea.variants.js +404 -0
- package/dist/ThemeModeButton/ThemeModeButton.svelte +73 -0
- package/dist/ThemeModeButton/ThemeModeButton.svelte.d.ts +5 -0
- package/dist/ThemeModeButton/index.d.ts +2 -0
- package/dist/ThemeModeButton/index.js +1 -0
- package/dist/ThemeModeButton/theme-mode-button.types.d.ts +64 -0
- package/dist/ThemeModeButton/theme-mode-button.types.js +1 -0
- package/dist/ThemeModeButton/theme-mode-button.variants.d.ts +21 -0
- package/dist/ThemeModeButton/theme-mode-button.variants.js +17 -0
- package/dist/Timeline/Timeline.svelte +4 -2
- package/dist/Timeline/timeline.variants.js +96 -16
- package/dist/Tooltip/Tooltip.svelte +147 -0
- package/dist/Tooltip/Tooltip.svelte.d.ts +6 -0
- package/dist/Tooltip/TooltipTestWrapper.svelte +11 -0
- package/dist/Tooltip/TooltipTestWrapper.svelte.d.ts +4 -0
- package/dist/Tooltip/index.d.ts +2 -0
- package/dist/Tooltip/index.js +1 -0
- package/dist/Tooltip/tooltip.types.d.ts +56 -0
- package/dist/Tooltip/tooltip.types.js +1 -0
- package/dist/Tooltip/tooltip.variants.d.ts +133 -0
- package/dist/Tooltip/tooltip.variants.js +44 -0
- package/dist/User/User.svelte +94 -94
- package/dist/config.d.ts +2 -0
- package/dist/config.js +3 -1
- package/dist/index.d.ts +21 -0
- package/dist/index.js +21 -0
- package/dist/theme.css +599 -410
- package/package.json +106 -104
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 ndlabdev
|
|
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.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ndlabdev
|
|
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,124 +1,229 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://img.shields.io/badge/sv5ui-Svelte_5_UI-ff3e00?style=for-the-badge&logo=svelte&logoColor=white" alt="SV5UI" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">SV5UI</h1>
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
A modern, fully-typed UI component library for Svelte 5.<br/>
|
|
9
|
+
Built with Tailwind CSS 4, OKLCH color tokens, and accessible headless primitives.
|
|
10
|
+
</p>
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/sv5ui"><img src="https://img.shields.io/npm/v/sv5ui.svg?style=flat-square&colorA=18181b&colorB=ff3e00" alt="npm version" /></a>
|
|
14
|
+
<a href="https://github.com/ndlabdev/sv5ui/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/sv5ui.svg?style=flat-square&colorA=18181b&colorB=ff3e00" alt="license" /></a>
|
|
15
|
+
<a href="https://www.npmjs.com/package/sv5ui"><img src="https://img.shields.io/npm/dm/sv5ui.svg?style=flat-square&colorA=18181b&colorB=ff3e00" alt="downloads" /></a>
|
|
16
|
+
</p>
|
|
9
17
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Highlights
|
|
21
|
+
|
|
22
|
+
- **Svelte 5** — Built with runes, snippets, and the latest reactivity model
|
|
23
|
+
- **Tailwind CSS 4** — Utility-first styling with [Tailwind Variants](https://www.tailwind-variants.org/) for type-safe, composable variants
|
|
24
|
+
- **Fully Typed** — Strict TypeScript with exported prop types for every component
|
|
25
|
+
- **Accessible** — Built on [Bits UI](https://bits-ui.com) and [Vaul Svelte](https://vaul-svelte.com) headless primitives
|
|
26
|
+
- **200,000+ Icons** — First-class [Iconify](https://iconify.design) integration
|
|
27
|
+
- **Customizable** — Global config system + per-instance slot overrides
|
|
16
28
|
|
|
17
29
|
## Installation
|
|
18
30
|
|
|
19
31
|
```bash
|
|
20
32
|
npm install sv5ui
|
|
33
|
+
# or
|
|
34
|
+
pnpm add sv5ui
|
|
21
35
|
```
|
|
22
36
|
|
|
23
|
-
Peer dependencies
|
|
37
|
+
**Peer dependencies:** `svelte >= 5.0.0`, `tailwindcss >= 4.0.0`
|
|
24
38
|
|
|
25
39
|
## Quick Start
|
|
26
40
|
|
|
41
|
+
**1. Import the theme**
|
|
42
|
+
|
|
27
43
|
```css
|
|
28
44
|
/* layout.css */
|
|
29
45
|
@import 'sv5ui/theme.css';
|
|
30
|
-
@source "../../node_modules/sv5ui/dist";
|
|
31
46
|
```
|
|
32
47
|
|
|
48
|
+
**2. Use components**
|
|
49
|
+
|
|
33
50
|
```svelte
|
|
34
51
|
<script>
|
|
35
|
-
|
|
52
|
+
import { Button, Avatar, Badge, Tooltip } from 'sv5ui'
|
|
36
53
|
</script>
|
|
37
54
|
|
|
38
|
-
<
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
<Tooltip text="Edit profile">
|
|
56
|
+
<Button variant="soft" color="primary" leadingIcon="lucide:edit">Edit</Button>
|
|
57
|
+
</Tooltip>
|
|
58
|
+
|
|
59
|
+
<Avatar src="/photo.jpg" alt="Jane Doe" size="lg" />
|
|
60
|
+
<Badge label="Online" color="success" variant="soft" />
|
|
42
61
|
```
|
|
43
62
|
|
|
44
63
|
## Components
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
| **
|
|
51
|
-
| **
|
|
52
|
-
| **
|
|
53
|
-
| **
|
|
54
|
-
| **
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
| **
|
|
61
|
-
| **
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
### General
|
|
66
|
+
|
|
67
|
+
| Component | Description |
|
|
68
|
+
| :--------------------------------------------- | :--------------------------------------------------------------------------------- |
|
|
69
|
+
| [**Button**](src/lib/Button) | Versatile button with 6 variants, loading state, icons, and avatar support |
|
|
70
|
+
| [**Link**](src/lib/Link) | Smart anchor with automatic active-state detection based on current route |
|
|
71
|
+
| [**Icon**](src/lib/Icon) | Iconify wrapper — render any of 200,000+ icons by name |
|
|
72
|
+
| [**Kbd**](src/lib/Kbd) | Keyboard shortcut display with OS-aware symbol mapping |
|
|
73
|
+
| [**ThemeModeButton**](src/lib/ThemeModeButton) | Light/dark mode toggle button with customizable icons and mode-watcher integration |
|
|
74
|
+
|
|
75
|
+
### Layout
|
|
76
|
+
|
|
77
|
+
| Component | Description |
|
|
78
|
+
| :--------------------------------- | :--------------------------------------------------------------- |
|
|
79
|
+
| [**Card**](src/lib/Card) | Content container with header, body, and footer slots |
|
|
80
|
+
| [**Container**](src/lib/Container) | Responsive max-width wrapper for page content |
|
|
81
|
+
| [**Separator**](src/lib/Separator) | Horizontal/vertical divider with optional label, icon, or avatar |
|
|
82
|
+
|
|
83
|
+
### Data Display
|
|
84
|
+
|
|
85
|
+
| Component | Description |
|
|
86
|
+
| :------------------------------------- | :--------------------------------------------------------------------- |
|
|
87
|
+
| [**Avatar**](src/lib/Avatar) | Profile image with auto-generated initials fallback |
|
|
88
|
+
| [**AvatarGroup**](src/lib/AvatarGroup) | Stacked avatars with overflow count |
|
|
89
|
+
| [**Badge**](src/lib/Badge) | Status indicators and tags in 4 variants and 8 colors |
|
|
90
|
+
| [**Chip**](src/lib/Chip) | Notification dot indicator with configurable positioning |
|
|
91
|
+
| [**User**](src/lib/User) | User profile display combining avatar, name, and description |
|
|
92
|
+
| [**Timeline**](src/lib/Timeline) | Step/sequence visualization with completed, active, and pending states |
|
|
93
|
+
| [**Skeleton**](src/lib/Skeleton) | Animated loading placeholder |
|
|
94
|
+
| [**Empty**](src/lib/Empty) | Empty state with icon, description, and action slots |
|
|
95
|
+
|
|
96
|
+
### Feedback
|
|
97
|
+
|
|
98
|
+
| Component | Description |
|
|
99
|
+
| :------------------------------- | :------------------------------------------------------------------- |
|
|
100
|
+
| [**Alert**](src/lib/Alert) | Notification banner with icon, actions, and dismissible support |
|
|
101
|
+
| [**Progress**](src/lib/Progress) | Determinate/indeterminate progress bar with step mode and animations |
|
|
102
|
+
|
|
103
|
+
### Navigation
|
|
104
|
+
|
|
105
|
+
| Component | Description |
|
|
106
|
+
| :----------------------------------- | :----------------------------------------------------------------------------- |
|
|
107
|
+
| [**Breadcrumb**](src/lib/Breadcrumb) | Hierarchical navigation trail with icons, custom separators, and snippet slots |
|
|
108
|
+
| [**Tabs**](src/lib/Tabs) | Tabbed interface with content panels and configurable orientation |
|
|
109
|
+
| [**Pagination**](src/lib/Pagination) | Page navigation with first/prev/next/last controls and ellipsis |
|
|
110
|
+
|
|
111
|
+
### Overlay
|
|
112
|
+
|
|
113
|
+
| Component | Description |
|
|
114
|
+
| :--------------------------------------- | :------------------------------------------------------------------------ |
|
|
115
|
+
| [**Modal**](src/lib/Modal) | Accessible dialog with overlay, focus trap, and scroll lock |
|
|
116
|
+
| [**Slideover**](src/lib/Slideover) | Side panel sliding from any edge with inset mode |
|
|
117
|
+
| [**Drawer**](src/lib/Drawer) | Draggable bottom/side sheet with snap points |
|
|
118
|
+
| [**Tooltip**](src/lib/Tooltip) | Hover tooltip with arrow, keyboard shortcut display, and portal rendering |
|
|
119
|
+
| [**Popover**](src/lib/Popover) | Floating interactive content panel with focus management |
|
|
120
|
+
| [**Accordion**](src/lib/Accordion) | Expandable sections with single or multiple open modes |
|
|
121
|
+
| [**DropdownMenu**](src/lib/DropdownMenu) | Triggered floating menu with items, groups, separators, and sub-menus |
|
|
122
|
+
| [**ContextMenu**](src/lib/ContextMenu) | Right-click context menu with items, colors, and keyboard navigation |
|
|
123
|
+
|
|
124
|
+
### Form
|
|
125
|
+
|
|
126
|
+
| Component | Description |
|
|
127
|
+
| :----------------------------------- | :------------------------------------------------------------------------------------------------------ |
|
|
128
|
+
| [**Input**](src/lib/Input) | Text input with 5 variants, icons, avatar, loading state, and FormField integration |
|
|
129
|
+
| [**Textarea**](src/lib/Textarea) | Multi-line text input with 5 variants, icons, autoresize with maxrows, and FormField integration |
|
|
130
|
+
| [**Select**](src/lib/Select) | Dropdown select with 5 variants, icons, avatars, groups, descriptions, and FormField support |
|
|
131
|
+
| [**Switch**](src/lib/Switch) | Toggle switch with 8 colors, 5 sizes, checked/unchecked icons, loading state, and FormField integration |
|
|
132
|
+
| [**Checkbox**](src/lib/Checkbox) | Checkbox with 8 colors, 5 sizes, indeterminate state, custom icons, and FormField integration |
|
|
133
|
+
| [**RadioGroup**](src/lib/RadioGroup) | Radio group for single-selection with items API, legend, orientation, and FormField integration |
|
|
134
|
+
| [**FormField**](src/lib/FormField) | Form control wrapper providing label, description, hint, help, and error handling |
|
|
135
|
+
| [**FieldGroup**](src/lib/FieldGroup) | Groups buttons and inputs with seamless borders and shared size/orientation context |
|
|
136
|
+
| [**Calendar**](src/lib/Calendar) | Date picker calendar with single, multiple, and range selection modes |
|
|
64
137
|
|
|
65
138
|
## Theming
|
|
66
139
|
|
|
67
|
-
SV5UI uses OKLCH color space with semantic tokens. Light and dark modes work
|
|
140
|
+
SV5UI uses **OKLCH color space** with semantic tokens. Light and dark modes work out of the box.
|
|
141
|
+
|
|
142
|
+
### Color Tokens
|
|
68
143
|
|
|
69
|
-
|
|
144
|
+
Each color provides a set of related tokens for surfaces, text, and containers:
|
|
70
145
|
|
|
71
|
-
|
|
146
|
+
```
|
|
147
|
+
--color-{name} Main color
|
|
148
|
+
--color-on-{name} Contrast text on main color
|
|
149
|
+
--color-{name}-container Lighter background variant
|
|
150
|
+
--color-on-{name}-container Text on container background
|
|
151
|
+
```
|
|
72
152
|
|
|
73
|
-
**
|
|
153
|
+
**Available colors:** `primary` · `secondary` · `tertiary` · `success` · `warning` · `error` · `info` · `surface`
|
|
154
|
+
|
|
155
|
+
### Dark Mode
|
|
156
|
+
|
|
157
|
+
Supported via `.dark` class on `<html>` or `prefers-color-scheme` media query, managed with [mode-watcher](https://github.com/svecosystem/mode-watcher).
|
|
158
|
+
|
|
159
|
+
### Custom Colors
|
|
160
|
+
|
|
161
|
+
Override any token with CSS variables:
|
|
74
162
|
|
|
75
163
|
```css
|
|
76
164
|
:root {
|
|
77
|
-
|
|
78
|
-
|
|
165
|
+
--color-primary: oklch(0.55 0.25 270);
|
|
166
|
+
--color-secondary: oklch(0.45 0.15 240);
|
|
79
167
|
}
|
|
80
168
|
```
|
|
81
169
|
|
|
82
170
|
## Customization
|
|
83
171
|
|
|
84
|
-
### Per-instance
|
|
172
|
+
### Per-instance — `ui` prop
|
|
85
173
|
|
|
86
|
-
Override slot
|
|
174
|
+
Override slot classes directly on any component:
|
|
87
175
|
|
|
88
176
|
```svelte
|
|
89
|
-
<Button ui={{ base: 'rounded-full', label: 'font-bold uppercase' }}>
|
|
90
|
-
Custom
|
|
91
|
-
</Button>
|
|
177
|
+
<Button ui={{ base: 'rounded-full shadow-lg', label: 'font-bold uppercase' }}>Custom</Button>
|
|
92
178
|
```
|
|
93
179
|
|
|
94
|
-
### Global
|
|
180
|
+
### Global — `defineConfig`
|
|
95
181
|
|
|
96
|
-
|
|
182
|
+
Set library-wide defaults for variants, slots, and icons:
|
|
97
183
|
|
|
98
184
|
```typescript
|
|
99
185
|
import { defineConfig } from 'sv5ui'
|
|
100
186
|
|
|
101
187
|
defineConfig({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
188
|
+
button: {
|
|
189
|
+
defaultVariants: { variant: 'outline', size: 'lg' },
|
|
190
|
+
slots: { base: 'shadow-md' }
|
|
191
|
+
},
|
|
192
|
+
avatar: {
|
|
193
|
+
defaultVariants: { size: 'lg' },
|
|
194
|
+
slots: { root: 'ring-2 ring-primary' }
|
|
195
|
+
},
|
|
196
|
+
icons: {
|
|
197
|
+
loading: 'lucide:loader',
|
|
198
|
+
close: 'lucide:x'
|
|
199
|
+
}
|
|
107
200
|
})
|
|
108
201
|
```
|
|
109
202
|
|
|
110
203
|
## Development
|
|
111
204
|
|
|
112
205
|
```bash
|
|
113
|
-
pnpm install
|
|
114
|
-
pnpm dev
|
|
115
|
-
pnpm test
|
|
116
|
-
pnpm check
|
|
117
|
-
pnpm prepack
|
|
118
|
-
pnpm lint
|
|
119
|
-
pnpm format
|
|
206
|
+
pnpm install # Install dependencies
|
|
207
|
+
pnpm dev # Dev server at localhost:5173
|
|
208
|
+
pnpm test # Run unit tests
|
|
209
|
+
pnpm check # TypeScript check
|
|
210
|
+
pnpm prepack # Build library package
|
|
211
|
+
pnpm lint # Lint
|
|
212
|
+
pnpm format # Format code
|
|
120
213
|
```
|
|
121
214
|
|
|
215
|
+
> Run `pnpm dev` and open [localhost:5173](http://localhost:5173) to browse the interactive component demos.
|
|
216
|
+
|
|
217
|
+
## Tech Stack
|
|
218
|
+
|
|
219
|
+
| Layer | Technology |
|
|
220
|
+
| :--------- | :-------------------------------------------------------------------------------------------------- |
|
|
221
|
+
| Framework | [Svelte 5](https://svelte.dev) + [SvelteKit](https://svelte.dev/docs/kit) |
|
|
222
|
+
| Styling | [Tailwind CSS 4](https://tailwindcss.com) + [Tailwind Variants](https://www.tailwind-variants.org/) |
|
|
223
|
+
| Primitives | [Bits UI](https://bits-ui.com) · [Vaul Svelte](https://vaul-svelte.com) |
|
|
224
|
+
| Icons | [Iconify](https://iconify.design) (200,000+ icons) |
|
|
225
|
+
| Testing | [Vitest](https://vitest.dev) + [Playwright](https://playwright.dev) |
|
|
226
|
+
|
|
122
227
|
## License
|
|
123
228
|
|
|
124
|
-
[MIT](LICENSE)
|
|
229
|
+
[MIT](LICENSE) © [ndlabdev](https://github.com/ndlabdev)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { AccordionProps, AccordionItem } from './accordion.types.js'
|
|
3
|
+
|
|
4
|
+
export type Props = AccordionProps
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { Accordion } from 'bits-ui'
|
|
9
|
+
import { slide } from 'svelte/transition'
|
|
10
|
+
import { accordionVariants, accordionDefaults } from './accordion.variants.js'
|
|
11
|
+
import { getComponentConfig } from '../config.js'
|
|
12
|
+
import Icon from '../Icon/Icon.svelte'
|
|
13
|
+
|
|
14
|
+
const config = getComponentConfig('accordion', accordionDefaults)
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
items = [],
|
|
18
|
+
type = 'single',
|
|
19
|
+
value = $bindable(),
|
|
20
|
+
onValueChange,
|
|
21
|
+
disabled = false,
|
|
22
|
+
loop = false,
|
|
23
|
+
orientation = 'vertical',
|
|
24
|
+
forceMount = false,
|
|
25
|
+
trailingIcon = 'lucide:chevron-down',
|
|
26
|
+
ui,
|
|
27
|
+
class: className,
|
|
28
|
+
leading,
|
|
29
|
+
label: labelSlot,
|
|
30
|
+
trailing,
|
|
31
|
+
content: contentSlot,
|
|
32
|
+
body: bodySlot
|
|
33
|
+
}: Props = $props()
|
|
34
|
+
|
|
35
|
+
const variantSlots = $derived(accordionVariants({ disabled }))
|
|
36
|
+
const rootClass = $derived(
|
|
37
|
+
variantSlots.root({ class: [config.slots.root, ui?.root, className] })
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const singleValue = $derived(typeof value === 'string' ? value : undefined)
|
|
41
|
+
const multipleValue = $derived(Array.isArray(value) ? value : undefined)
|
|
42
|
+
|
|
43
|
+
const slotNames = [
|
|
44
|
+
'item',
|
|
45
|
+
'header',
|
|
46
|
+
'trigger',
|
|
47
|
+
'content',
|
|
48
|
+
'body',
|
|
49
|
+
'leadingIcon',
|
|
50
|
+
'trailingIcon',
|
|
51
|
+
'label'
|
|
52
|
+
] as const
|
|
53
|
+
|
|
54
|
+
type SlotName = (typeof slotNames)[number]
|
|
55
|
+
|
|
56
|
+
function getItemClasses(item: AccordionItem) {
|
|
57
|
+
const result = {} as Record<SlotName, string>
|
|
58
|
+
for (const slot of slotNames) {
|
|
59
|
+
const baseClass = [
|
|
60
|
+
config.slots[slot],
|
|
61
|
+
ui?.[slot],
|
|
62
|
+
item.ui?.[slot],
|
|
63
|
+
slot === 'item' ? item.class : undefined
|
|
64
|
+
]
|
|
65
|
+
const opts =
|
|
66
|
+
slot === 'trigger'
|
|
67
|
+
? { class: baseClass, disabled: item.disabled }
|
|
68
|
+
: { class: baseClass }
|
|
69
|
+
result[slot] = variantSlots[slot](opts)
|
|
70
|
+
}
|
|
71
|
+
return result
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isOpen(itemValue: string): boolean {
|
|
75
|
+
if (!value) return false
|
|
76
|
+
if (Array.isArray(value)) return value.includes(itemValue)
|
|
77
|
+
return value === itemValue
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function handleSingleValueChange(newValue: string) {
|
|
81
|
+
value = newValue
|
|
82
|
+
onValueChange?.(newValue)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function handleMultipleValueChange(newValue: string[]) {
|
|
86
|
+
value = newValue
|
|
87
|
+
onValueChange?.(newValue)
|
|
88
|
+
}
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
{#snippet accordionItem(item: AccordionItem, index: number)}
|
|
92
|
+
{@const itemValue = item.value ?? String(index)}
|
|
93
|
+
{@const cls = getItemClasses(item)}
|
|
94
|
+
{@const open = isOpen(itemValue)}
|
|
95
|
+
<Accordion.Item value={itemValue} disabled={item.disabled} class={cls.item}>
|
|
96
|
+
<Accordion.Header class={cls.header}>
|
|
97
|
+
<Accordion.Trigger class={cls.trigger}>
|
|
98
|
+
{#if leading}
|
|
99
|
+
{@render leading({ item, index, open })}
|
|
100
|
+
{:else if item.icon}
|
|
101
|
+
<Icon name={item.icon} class={cls.leadingIcon} />
|
|
102
|
+
{/if}
|
|
103
|
+
|
|
104
|
+
{#if item.label || labelSlot}
|
|
105
|
+
<span class={cls.label}>
|
|
106
|
+
{#if labelSlot}
|
|
107
|
+
{@render labelSlot({ item, index, open })}
|
|
108
|
+
{:else}
|
|
109
|
+
{item.label}
|
|
110
|
+
{/if}
|
|
111
|
+
</span>
|
|
112
|
+
{/if}
|
|
113
|
+
|
|
114
|
+
{#if trailing}
|
|
115
|
+
{@render trailing({ item, index, open })}
|
|
116
|
+
{:else}
|
|
117
|
+
<Icon name={item.trailingIcon ?? trailingIcon} class={cls.trailingIcon} />
|
|
118
|
+
{/if}
|
|
119
|
+
</Accordion.Trigger>
|
|
120
|
+
</Accordion.Header>
|
|
121
|
+
|
|
122
|
+
{#if item.content || contentSlot || bodySlot}
|
|
123
|
+
{#if forceMount}
|
|
124
|
+
<Accordion.Content forceMount>
|
|
125
|
+
{#snippet child({ props, open: isContentOpen })}
|
|
126
|
+
{#if isContentOpen}
|
|
127
|
+
<div {...props} transition:slide={{ duration: 200 }}>
|
|
128
|
+
<div class={cls.content}>
|
|
129
|
+
{#if contentSlot}
|
|
130
|
+
{@render contentSlot({ item, index, open: isContentOpen })}
|
|
131
|
+
{:else}
|
|
132
|
+
<div class={cls.body}>
|
|
133
|
+
{#if bodySlot}
|
|
134
|
+
{@render bodySlot({
|
|
135
|
+
item,
|
|
136
|
+
index,
|
|
137
|
+
open: isContentOpen
|
|
138
|
+
})}
|
|
139
|
+
{:else}
|
|
140
|
+
{item.content}
|
|
141
|
+
{/if}
|
|
142
|
+
</div>
|
|
143
|
+
{/if}
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
{/if}
|
|
147
|
+
{/snippet}
|
|
148
|
+
</Accordion.Content>
|
|
149
|
+
{:else}
|
|
150
|
+
<Accordion.Content class={cls.content}>
|
|
151
|
+
{#if contentSlot}
|
|
152
|
+
{@render contentSlot({ item, index, open })}
|
|
153
|
+
{:else}
|
|
154
|
+
<div class={cls.body}>
|
|
155
|
+
{#if bodySlot}
|
|
156
|
+
{@render bodySlot({ item, index, open })}
|
|
157
|
+
{:else}
|
|
158
|
+
{item.content}
|
|
159
|
+
{/if}
|
|
160
|
+
</div>
|
|
161
|
+
{/if}
|
|
162
|
+
</Accordion.Content>
|
|
163
|
+
{/if}
|
|
164
|
+
{/if}
|
|
165
|
+
</Accordion.Item>
|
|
166
|
+
{/snippet}
|
|
167
|
+
|
|
168
|
+
{#if type === 'single'}
|
|
169
|
+
<Accordion.Root
|
|
170
|
+
type="single"
|
|
171
|
+
value={singleValue}
|
|
172
|
+
onValueChange={handleSingleValueChange}
|
|
173
|
+
{disabled}
|
|
174
|
+
{loop}
|
|
175
|
+
{orientation}
|
|
176
|
+
class={rootClass}
|
|
177
|
+
>
|
|
178
|
+
{#each items as item, index (item.value ?? index)}
|
|
179
|
+
{@render accordionItem(item, index)}
|
|
180
|
+
{/each}
|
|
181
|
+
</Accordion.Root>
|
|
182
|
+
{:else}
|
|
183
|
+
<Accordion.Root
|
|
184
|
+
type="multiple"
|
|
185
|
+
value={multipleValue}
|
|
186
|
+
onValueChange={handleMultipleValueChange}
|
|
187
|
+
{disabled}
|
|
188
|
+
{loop}
|
|
189
|
+
{orientation}
|
|
190
|
+
class={rootClass}
|
|
191
|
+
>
|
|
192
|
+
{#each items as item, index (item.value ?? index)}
|
|
193
|
+
{@render accordionItem(item, index)}
|
|
194
|
+
{/each}
|
|
195
|
+
</Accordion.Root>
|
|
196
|
+
{/if}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AccordionProps } from './accordion.types.js';
|
|
2
|
+
export type Props = AccordionProps;
|
|
3
|
+
import { Accordion } from 'bits-ui';
|
|
4
|
+
declare const Accordion: import("svelte").Component<AccordionProps, {}, "value">;
|
|
5
|
+
type Accordion = ReturnType<typeof Accordion>;
|
|
6
|
+
export default Accordion;
|