@leodamours/ds-components 0.3.0 → 0.4.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/README.md +492 -49
- package/dist/components/DsSwitch.vue.d.ts +57 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1592 -1688
- package/dist/palette-DkSoRw54.js +250 -0
- package/dist/style.css +1 -0
- package/dist/styles/ds-preset.d.ts +22 -0
- package/dist/uno.d.ts +2 -0
- package/dist/uno.js +183 -0
- package/package.json +12 -2
- package/dist/index.css +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @leodamours/ds-components
|
|
2
2
|
|
|
3
|
-
Vue 3 component library with built-in design tokens
|
|
3
|
+
Vue 3 component library with built-in design tokens, theming via CSS custom properties, and algorithmic palette generation.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,7 +8,9 @@ Vue 3 component library with built-in design tokens and theming support via CSS
|
|
|
8
8
|
npm install @leodamours/ds-components
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
**Peer
|
|
11
|
+
**Peer dependencies:** `vue ^3.5.0`
|
|
12
|
+
|
|
13
|
+
**Optional:** [`@leodamours/ds-icons`](https://www.npmjs.com/package/@leodamours/ds-icons) — 1,920 Lucide-based icon components that pair with this library.
|
|
12
14
|
|
|
13
15
|
## Setup
|
|
14
16
|
|
|
@@ -17,7 +19,7 @@ npm install @leodamours/ds-components
|
|
|
17
19
|
import '@leodamours/ds-components/style.css'
|
|
18
20
|
```
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
The stylesheet bundles the default light theme, dark theme (`[data-theme="dark"]`), and all component styles. No additional CSS imports needed.
|
|
21
23
|
|
|
22
24
|
## Usage
|
|
23
25
|
|
|
@@ -36,27 +38,308 @@ import { DsButton, DsInput } from '@leodamours/ds-components'
|
|
|
36
38
|
|
|
37
39
|
| Component | Description |
|
|
38
40
|
|---|---|
|
|
39
|
-
| `DsAvatar` | User avatar with initials fallback |
|
|
41
|
+
| `DsAvatar` | User avatar with image or initials fallback |
|
|
40
42
|
| `DsBadge` | Status badge / label |
|
|
41
43
|
| `DsButton` | Button with variants: primary, secondary, outline, ghost, danger, success |
|
|
44
|
+
| `DsCard` | Container card with variants: default, outlined, elevated |
|
|
42
45
|
| `DsCheckbox` | Checkbox input |
|
|
43
46
|
| `DsDropdownSelect` | Dropdown select with floating UI positioning |
|
|
47
|
+
| `DsExpandableCard` | Collapsible card with title, supports `v-model` for expand state |
|
|
44
48
|
| `DsInput` | Text input with label, help text, error state |
|
|
45
49
|
| `DsLoadingSpinner` | Animated loading spinner |
|
|
46
50
|
| `DsModal` | Modal dialog with backdrop |
|
|
47
51
|
| `DsRadio` | Radio input |
|
|
48
52
|
| `DsSelect` | Native select wrapper |
|
|
53
|
+
| `DsSlider` | Range slider with optional value display |
|
|
54
|
+
| `DsSwitch` | Toggle switch for boolean settings |
|
|
49
55
|
| `DsTable` | Data table with sorting and pagination |
|
|
50
56
|
| `DsTabs` | Tab navigation |
|
|
51
57
|
| `DsTextarea` | Multiline text input |
|
|
52
|
-
| `DsToast` / `DsToastContainer` | Toast notifications |
|
|
58
|
+
| `DsToast` / `DsToastContainer` | Toast notifications (see [Toast system](#toast-system) below) |
|
|
53
59
|
| `DsTooltip` | Tooltip on hover |
|
|
60
|
+
| `DsUnderConstruction` | Placeholder for pages not yet built |
|
|
61
|
+
|
|
62
|
+
All components export their prop types (e.g., `DsButtonProps`, `DsCardProps`).
|
|
63
|
+
|
|
64
|
+
### Component props
|
|
65
|
+
|
|
66
|
+
#### DsAvatar
|
|
67
|
+
|
|
68
|
+
| Prop | Type | Default | Description |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| `src` | `string` | — | Image URL |
|
|
71
|
+
| `alt` | `string` | — | Alt text for image |
|
|
72
|
+
| `name` | `string` | — | Full name (used for initials fallback) |
|
|
73
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Avatar size |
|
|
74
|
+
| `variant` | `'brand' \| 'neutral'` | `'brand'` | Color variant for initials background |
|
|
75
|
+
|
|
76
|
+
#### DsBadge
|
|
77
|
+
|
|
78
|
+
| Prop | Type | Default | Description |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| `label` | `string` | — | Badge text (can also use default slot) |
|
|
81
|
+
| `variant` | `'brand' \| 'neutral' \| 'error' \| 'success' \| 'warning' \| 'info' \| 'processing'` | `'neutral'` | Color variant |
|
|
82
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Badge size |
|
|
83
|
+
|
|
84
|
+
#### DsButton
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
|---|---|---|---|
|
|
88
|
+
| `label` | `string` | — | Button text (can also use default slot) |
|
|
89
|
+
| `variant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost' \| 'danger' \| 'success' \| 'warning'` | `'primary'` | Visual style |
|
|
90
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Button size |
|
|
91
|
+
| `htmlType` | `'button' \| 'submit' \| 'reset'` | `'button'` | Native button type |
|
|
92
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
93
|
+
| `loading` | `boolean` | `false` | Show loading spinner |
|
|
94
|
+
| `fullWidth` | `boolean` | `false` | Expand to fill container |
|
|
95
|
+
| `iconLeft` | `Component` | — | Vue component icon on the left |
|
|
96
|
+
| `iconRight` | `Component` | — | Vue component icon on the right |
|
|
97
|
+
| `ariaLabel` | `string` | — | Accessible label override |
|
|
98
|
+
|
|
99
|
+
#### DsCard
|
|
100
|
+
|
|
101
|
+
| Prop | Type | Default | Description |
|
|
102
|
+
|---|---|---|---|
|
|
103
|
+
| `variant` | `'default' \| 'outlined' \| 'elevated'` | `'default'` | Card style |
|
|
104
|
+
| `noPadding` | `boolean` | `false` | Remove inner padding |
|
|
105
|
+
|
|
106
|
+
Default slot for card content.
|
|
107
|
+
|
|
108
|
+
#### DsCheckbox
|
|
109
|
+
|
|
110
|
+
| Prop | Type | Default | Description |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| `modelValue` | `boolean` | `false` | Checked state (`v-model`) |
|
|
113
|
+
| `label` | `string` | — | Checkbox label |
|
|
114
|
+
| `id` | `string` | auto | HTML id attribute |
|
|
115
|
+
| `value` | `string \| number \| boolean` | — | Form value |
|
|
116
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
117
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Checkbox size |
|
|
118
|
+
|
|
119
|
+
#### DsDropdownSelect
|
|
120
|
+
|
|
121
|
+
| Prop | Type | Default | Description |
|
|
122
|
+
|---|---|---|---|
|
|
123
|
+
| `modelValue` | `string \| number` | — | Selected value (`v-model`) |
|
|
124
|
+
| `options` | `(string \| number \| { label, value, disabled? })[]` | `[]` | List of options |
|
|
125
|
+
| `placeholder` | `string` | `'Select an option'` | Placeholder text |
|
|
126
|
+
| `variant` | `'primary' \| 'secondary' \| 'ghost'` | `'primary'` | Trigger button style |
|
|
127
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Trigger button size |
|
|
128
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
129
|
+
| `loading` | `boolean` | `false` | Show loading state |
|
|
130
|
+
| `iconLeft` | `Component` | — | Icon in the trigger button |
|
|
131
|
+
| `fullWidth` | `boolean` | `false` | Expand to fill container |
|
|
132
|
+
| `emptyText` | `string` | `'No options available'` | Text shown when options list is empty |
|
|
133
|
+
|
|
134
|
+
#### DsExpandableCard
|
|
135
|
+
|
|
136
|
+
| Prop | Type | Default | Description |
|
|
137
|
+
|---|---|---|---|
|
|
138
|
+
| `title` | `string` | **required** | Card header text |
|
|
139
|
+
| `modelValue` | `boolean` | — | Controlled expand state (`v-model`) |
|
|
140
|
+
| `defaultExpanded` | `boolean` | `false` | Initial expand state (uncontrolled) |
|
|
141
|
+
| `variant` | `'default' \| 'outlined' \| 'elevated'` | `'default'` | Card style |
|
|
142
|
+
|
|
143
|
+
Default slot for expandable content.
|
|
144
|
+
|
|
145
|
+
#### DsInput
|
|
146
|
+
|
|
147
|
+
| Prop | Type | Default | Description |
|
|
148
|
+
|---|---|---|---|
|
|
149
|
+
| `modelValue` | `string \| number` | — | Input value (`v-model`) |
|
|
150
|
+
| `label` | `string` | — | Label text |
|
|
151
|
+
| `type` | `'text' \| 'email' \| 'password' \| 'number' \| 'tel' \| 'url' \| 'search'` | `'text'` | Input type |
|
|
152
|
+
| `placeholder` | `string` | — | Placeholder text |
|
|
153
|
+
| `helpText` | `string` | — | Help text below the input |
|
|
154
|
+
| `error` | `string` | — | Error message (replaces help text) |
|
|
155
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Input size |
|
|
156
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
157
|
+
| `readonly` | `boolean` | `false` | Read-only state |
|
|
158
|
+
| `required` | `boolean` | `false` | Mark as required |
|
|
159
|
+
| `clearable` | `boolean` | `false` | Show clear button when filled |
|
|
160
|
+
| `iconLeft` | `Component` | — | Icon on the left |
|
|
161
|
+
| `iconRight` | `Component` | — | Icon on the right |
|
|
162
|
+
| `autocomplete` | `string` | — | HTML autocomplete attribute |
|
|
163
|
+
| `maxLength` | `number` | — | Character limit |
|
|
164
|
+
| `min` | `number \| string` | — | Minimum value (number input) |
|
|
165
|
+
| `max` | `number \| string` | — | Maximum value (number input) |
|
|
166
|
+
| `step` | `number \| string` | — | Step increment (number input) |
|
|
167
|
+
|
|
168
|
+
#### DsLoadingSpinner
|
|
169
|
+
|
|
170
|
+
| Prop | Type | Default | Description |
|
|
171
|
+
|---|---|---|---|
|
|
172
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Spinner size |
|
|
173
|
+
| `variant` | `'primary' \| 'secondary' \| 'white' \| 'current'` | `'primary'` | Color variant |
|
|
174
|
+
|
|
175
|
+
#### DsModal
|
|
176
|
+
|
|
177
|
+
| Prop | Type | Default | Description |
|
|
178
|
+
|---|---|---|---|
|
|
179
|
+
| `modelValue` | `boolean` | **required** | Open state (`v-model`) |
|
|
180
|
+
| `title` | `string` | — | Modal title |
|
|
181
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Modal width |
|
|
182
|
+
| `closable` | `boolean` | `true` | Show close button |
|
|
183
|
+
| `persistent` | `boolean` | `false` | Prevent closing on backdrop click |
|
|
184
|
+
|
|
185
|
+
Slots: `default` (body), `header`, `footer`.
|
|
186
|
+
|
|
187
|
+
#### DsRadio
|
|
188
|
+
|
|
189
|
+
| Prop | Type | Default | Description |
|
|
190
|
+
|---|---|---|---|
|
|
191
|
+
| `modelValue` | `string \| number \| boolean` | — | Selected value (`v-model`) |
|
|
192
|
+
| `label` | `string` | — | Radio label |
|
|
193
|
+
| `id` | `string` | auto | HTML id attribute |
|
|
194
|
+
| `name` | `string` | — | Radio group name |
|
|
195
|
+
| `value` | `string \| number \| boolean` | — | This radio's value |
|
|
196
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
197
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Radio size |
|
|
198
|
+
|
|
199
|
+
#### DsSelect
|
|
200
|
+
|
|
201
|
+
| Prop | Type | Default | Description |
|
|
202
|
+
|---|---|---|---|
|
|
203
|
+
| `modelValue` | `string \| number` | — | Selected value (`v-model`) |
|
|
204
|
+
| `label` | `string` | — | Label text |
|
|
205
|
+
| `placeholder` | `string` | — | Placeholder text |
|
|
206
|
+
| `helpText` | `string` | — | Help text below the select |
|
|
207
|
+
| `error` | `string` | — | Error message |
|
|
208
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Select size |
|
|
209
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
210
|
+
| `required` | `boolean` | `false` | Mark as required |
|
|
211
|
+
| `options` | `DsSelectOption[]` | **required** | `{ label: string, value: string \| number, disabled?: boolean }` |
|
|
212
|
+
|
|
213
|
+
#### DsSlider
|
|
214
|
+
|
|
215
|
+
| Prop | Type | Default | Description |
|
|
216
|
+
|---|---|---|---|
|
|
217
|
+
| `modelValue` | `number` | `0` | Slider value (`v-model`) |
|
|
218
|
+
| `min` | `number` | `0` | Minimum value |
|
|
219
|
+
| `max` | `number` | `100` | Maximum value |
|
|
220
|
+
| `step` | `number` | `1` | Step increment |
|
|
221
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
222
|
+
| `label` | `string` | — | Label text |
|
|
223
|
+
| `showValue` | `boolean` | `false` | Display current value |
|
|
224
|
+
|
|
225
|
+
#### DsSwitch
|
|
226
|
+
|
|
227
|
+
| Prop | Type | Default | Description |
|
|
228
|
+
|---|---|---|---|
|
|
229
|
+
| `modelValue` | `boolean` | `false` | Checked state (`v-model`) |
|
|
230
|
+
| `label` | `string` | — | Label text |
|
|
231
|
+
| `id` | `string` | auto | HTML id attribute |
|
|
232
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
233
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Switch size |
|
|
234
|
+
| `labelPosition` | `'left' \| 'right'` | `'right'` | Label placement |
|
|
235
|
+
|
|
236
|
+
#### DsTable
|
|
237
|
+
|
|
238
|
+
| Prop | Type | Default | Description |
|
|
239
|
+
|---|---|---|---|
|
|
240
|
+
| `columns` | `DsTableColumn[]` | **required** | Column definitions (see below) |
|
|
241
|
+
| `rows` | `Record<string, any>[]` | **required** | Row data |
|
|
242
|
+
| `sortBy` | `string` | — | Active sort column key |
|
|
243
|
+
| `sortOrder` | `'asc' \| 'desc'` | — | Sort direction |
|
|
244
|
+
| `loading` | `boolean` | `false` | Show loading state |
|
|
245
|
+
| `emptyText` | `string` | `'No data available'` | Text when no rows |
|
|
246
|
+
| `striped` | `boolean` | `false` | Alternate row shading |
|
|
247
|
+
| `stickyHeader` | `boolean` | `false` | Sticky column headers |
|
|
248
|
+
| `pagination` | `DsTablePagination` | — | Enable pagination (see below) |
|
|
249
|
+
| `nextPageLabel` | `string` | `'Next'` | Pagination next label |
|
|
250
|
+
| `previousPageLabel` | `string` | `'Previous'` | Pagination previous label |
|
|
251
|
+
| `ofLabel` | `string` | — | Pagination "of" label |
|
|
252
|
+
|
|
253
|
+
**`DsTableColumn`**: `{ key: string, label: string, sortable?: boolean, width?: string, align?: 'left' | 'center' | 'right' }`
|
|
254
|
+
|
|
255
|
+
**`DsTablePagination`**: `{ page: number, perPage: number, total: number }`
|
|
256
|
+
|
|
257
|
+
Column cells can be customized via named slots: `#cell-{key}="{ row, column }"`.
|
|
258
|
+
|
|
259
|
+
#### DsTabs
|
|
260
|
+
|
|
261
|
+
| Prop | Type | Default | Description |
|
|
262
|
+
|---|---|---|---|
|
|
263
|
+
| `modelValue` | `string` | **required** | Active tab key (`v-model`) |
|
|
264
|
+
| `tabs` | `DsTab[]` | **required** | Tab definitions |
|
|
265
|
+
| `variant` | `'line' \| 'pill'` | `'line'` | Tab style |
|
|
266
|
+
| `ariaLabel` | `string` | `'Tabs'` | Accessible label |
|
|
267
|
+
|
|
268
|
+
**`DsTab`**: `{ key: string, label: string, disabled?: boolean }`
|
|
269
|
+
|
|
270
|
+
Tab content is rendered via named slots: `#tab-{key}`.
|
|
271
|
+
|
|
272
|
+
#### DsTextarea
|
|
273
|
+
|
|
274
|
+
| Prop | Type | Default | Description |
|
|
275
|
+
|---|---|---|---|
|
|
276
|
+
| `modelValue` | `string` | — | Textarea value (`v-model`) |
|
|
277
|
+
| `label` | `string` | — | Label text |
|
|
278
|
+
| `placeholder` | `string` | — | Placeholder text |
|
|
279
|
+
| `helpText` | `string` | — | Help text below the textarea |
|
|
280
|
+
| `error` | `string` | — | Error message |
|
|
281
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Textarea size |
|
|
282
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
283
|
+
| `readonly` | `boolean` | `false` | Read-only state |
|
|
284
|
+
| `required` | `boolean` | `false` | Mark as required |
|
|
285
|
+
| `rows` | `number` | `3` | Visible rows |
|
|
286
|
+
| `maxLength` | `number` | — | Character limit (shows counter) |
|
|
287
|
+
|
|
288
|
+
#### DsTooltip
|
|
289
|
+
|
|
290
|
+
| Prop | Type | Default | Description |
|
|
291
|
+
|---|---|---|---|
|
|
292
|
+
| `content` | `string` | **required** | Tooltip text |
|
|
293
|
+
| `placement` | `Placement` | `'top'` | Position (`'top'`, `'bottom'`, `'left'`, `'right'`, etc.) |
|
|
294
|
+
| `disabled` | `boolean` | `false` | Disable tooltip |
|
|
295
|
+
|
|
296
|
+
Wrap any element in `<DsTooltip>` — the default slot is the trigger.
|
|
297
|
+
|
|
298
|
+
#### DsUnderConstruction
|
|
299
|
+
|
|
300
|
+
| Prop | Type | Default | Description |
|
|
301
|
+
|---|---|---|---|
|
|
302
|
+
| `title` | `string` | `'Under Construction'` | Heading text |
|
|
303
|
+
| `description` | `string` | `'This page is under construction...'` | Body text |
|
|
304
|
+
|
|
305
|
+
## Toast system
|
|
306
|
+
|
|
307
|
+
Place `<DsToastContainer />` once at the root of your app, then trigger toasts from anywhere via the `useToast` composable:
|
|
308
|
+
|
|
309
|
+
```vue
|
|
310
|
+
<!-- App.vue -->
|
|
311
|
+
<script setup>
|
|
312
|
+
import { DsToastContainer } from '@leodamours/ds-components'
|
|
313
|
+
</script>
|
|
314
|
+
|
|
315
|
+
<template>
|
|
316
|
+
<router-view />
|
|
317
|
+
<DsToastContainer />
|
|
318
|
+
</template>
|
|
319
|
+
```
|
|
54
320
|
|
|
55
|
-
|
|
321
|
+
```ts
|
|
322
|
+
// Any component or composable
|
|
323
|
+
import { useToast } from '@leodamours/ds-components'
|
|
324
|
+
|
|
325
|
+
const toast = useToast()
|
|
326
|
+
|
|
327
|
+
toast.success('Saved successfully')
|
|
328
|
+
toast.error('Something went wrong', { title: 'Error' })
|
|
329
|
+
toast.warning('Session expiring soon', { duration: 8000 })
|
|
330
|
+
toast.info('New version available')
|
|
331
|
+
toast.brand('Welcome back!')
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Each method accepts `(message, options?)` where options are `{ title?: string, duration?: number }`. Default duration is 5000ms.
|
|
56
335
|
|
|
57
336
|
## Theming
|
|
58
337
|
|
|
59
|
-
Every color in the library flows through CSS custom properties prefixed with `--ds-`. The default theme is included in `style.css`.
|
|
338
|
+
Every color in the library flows through CSS custom properties prefixed with `--ds-`. The default theme is included in `style.css`.
|
|
339
|
+
|
|
340
|
+
### Option 1: CSS overrides
|
|
341
|
+
|
|
342
|
+
Override only the variables you need:
|
|
60
343
|
|
|
61
344
|
```css
|
|
62
345
|
/* my-theme.css */
|
|
@@ -66,77 +349,237 @@ Every color in the library flows through CSS custom properties prefixed with `--
|
|
|
66
349
|
--ds-brand-active: #6D28D9;
|
|
67
350
|
--ds-brand-on-solid: #FFFFFF;
|
|
68
351
|
--ds-bg: #FAFAFA;
|
|
69
|
-
--ds-error: #DC2626;
|
|
70
352
|
/* Only override what differs — everything else inherits defaults */
|
|
71
353
|
}
|
|
72
354
|
```
|
|
73
355
|
|
|
74
356
|
```ts
|
|
75
357
|
import '@leodamours/ds-components/style.css' // defaults
|
|
76
|
-
import './my-theme.css' // overrides
|
|
358
|
+
import './my-theme.css' // your overrides
|
|
77
359
|
```
|
|
78
360
|
|
|
79
|
-
###
|
|
80
|
-
|
|
81
|
-
Tokens follow a **role + tone** pattern: `{role}[-{tone}][-{state}]`
|
|
361
|
+
### Option 2: Generate a full theme from 7 base colors
|
|
82
362
|
|
|
83
|
-
|
|
84
|
-
|---|---|---|
|
|
85
|
-
| Core | Page-level UI | `bg`, `fg`, `border`, `icon`, `surface-hover` |
|
|
86
|
-
| `brand` | Primary actions | `brand`, `brand-hover`, `brand-soft`, `brand-on-solid` |
|
|
87
|
-
| `neutral` | Secondary actions | `neutral-soft`, `neutral-on-soft`, `neutral-border` |
|
|
88
|
-
| `error` | Error / destructive | `error`, `error-soft`, `error-on-solid`, `error-border` |
|
|
89
|
-
| `success` | Success feedback | `success`, `success-soft`, `success-on-solid` |
|
|
90
|
-
| `warning` | Warning feedback | `warning`, `warning-soft`, `warning-on-soft` |
|
|
91
|
-
| `info` | Informational | `info`, `info-soft`, `info-on-soft` |
|
|
92
|
-
|
|
93
|
-
**Tones:**
|
|
94
|
-
- `{role}` — the solid color (e.g., `--ds-error` = `#EF4444`)
|
|
95
|
-
- `{role}-soft` — light background variant (e.g., `--ds-error-soft` = `#FEF2F2`)
|
|
96
|
-
- `{role}-on-solid` — text/icon color on the solid bg (e.g., `--ds-error-on-solid` = `#FFFFFF`)
|
|
97
|
-
- `{role}-on-soft` — text/icon color on the soft bg (e.g., `--ds-error-on-soft` = `#EF4444`)
|
|
98
|
-
- `{role}-border` — border color for that role
|
|
363
|
+
The `generateFullTheme` function derives all hover, soft, border, contrast, and disabled variants automatically from just one hex per semantic role:
|
|
99
364
|
|
|
100
|
-
|
|
365
|
+
```ts
|
|
366
|
+
import { generateFullTheme } from '@leodamours/ds-components'
|
|
367
|
+
|
|
368
|
+
const css = generateFullTheme(
|
|
369
|
+
{
|
|
370
|
+
brand: '#8B5CF6',
|
|
371
|
+
error: '#E11D48',
|
|
372
|
+
success: '#059669',
|
|
373
|
+
warning: '#EA580C',
|
|
374
|
+
info: '#6366F1',
|
|
375
|
+
processing: '#D946EF',
|
|
376
|
+
neutral: '#6B5F7D',
|
|
377
|
+
},
|
|
378
|
+
'[data-theme="purple"]', // CSS selector (defaults to ':root')
|
|
379
|
+
)
|
|
101
380
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
--ds-border: #334155;
|
|
107
|
-
--ds-brand: #38BDF8;
|
|
108
|
-
}
|
|
381
|
+
// Inject into a <style> tag
|
|
382
|
+
const style = document.createElement('style')
|
|
383
|
+
style.textContent = css
|
|
384
|
+
document.head.appendChild(style)
|
|
109
385
|
```
|
|
110
386
|
|
|
387
|
+
For finer control, `generatePalette(hex)` returns the full variant set for a single color:
|
|
388
|
+
|
|
111
389
|
```ts
|
|
112
|
-
|
|
390
|
+
import { generatePalette } from '@leodamours/ds-components'
|
|
391
|
+
|
|
392
|
+
const brandPalette = generatePalette('#8B5CF6')
|
|
393
|
+
// => { base, hover, active, disabled, soft, soft-hover, soft-active,
|
|
394
|
+
// on-solid, on-soft, border, border-hover, border-strong }
|
|
113
395
|
```
|
|
114
396
|
|
|
115
|
-
###
|
|
397
|
+
### Option 3: Override individual tokens at runtime
|
|
116
398
|
|
|
117
399
|
```ts
|
|
118
400
|
import { generateThemeCss } from '@leodamours/ds-components'
|
|
119
401
|
|
|
120
402
|
const css = generateThemeCss(
|
|
121
403
|
{ brand: '#8B5CF6', 'brand-hover': '#7C3AED' },
|
|
122
|
-
'[data-theme="purple"]'
|
|
404
|
+
'[data-theme="purple"]',
|
|
123
405
|
)
|
|
124
|
-
// Returns a CSS string you can inject into a <style> tag
|
|
125
406
|
```
|
|
126
407
|
|
|
127
|
-
|
|
408
|
+
### Runtime theme switching
|
|
409
|
+
|
|
410
|
+
A dark theme is bundled and activates via `data-theme`:
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
// Switch to dark
|
|
414
|
+
document.documentElement.dataset.theme = 'dark'
|
|
415
|
+
|
|
416
|
+
// Switch back to light
|
|
417
|
+
delete document.documentElement.dataset.theme
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Token naming convention
|
|
421
|
+
|
|
422
|
+
Tokens follow a **role + tone** pattern: `--ds-{role}[-{tone}][-{state}]`
|
|
423
|
+
|
|
424
|
+
**Core UI tokens:**
|
|
425
|
+
|
|
426
|
+
| Token | Purpose |
|
|
427
|
+
|---|---|
|
|
428
|
+
| `bg`, `bg-secondary`, `bg-tertiary` | Page backgrounds |
|
|
429
|
+
| `bg-inverse`, `bg-inverse-secondary` | Inverted backgrounds |
|
|
430
|
+
| `fg`, `fg-secondary`, `fg-tertiary`, `fg-inverse`, `fg-disabled` | Text colors |
|
|
431
|
+
| `icon`, `icon-hover`, `icon-active`, `icon-inverse`, `icon-disabled` | Icon colors |
|
|
432
|
+
| `border`, `border-light`, `border-strong`, `border-focus` | Border colors |
|
|
433
|
+
| `surface-hover`, `surface-hover-light`, `surface-active`, `surface-disabled` | Interactive surfaces |
|
|
434
|
+
| `overlay`, `focus-ring` | Overlays and focus states |
|
|
435
|
+
|
|
436
|
+
**Semantic role tokens** — each role (`brand`, `error`, `success`, `warning`, `info`, `processing`, `neutral`) has:
|
|
437
|
+
|
|
438
|
+
| Tone | Purpose | Example |
|
|
439
|
+
|---|---|---|
|
|
440
|
+
| `{role}` | Solid color | `--ds-brand` |
|
|
441
|
+
| `{role}-hover` | Hover state | `--ds-brand-hover` |
|
|
442
|
+
| `{role}-active` | Active/pressed state | `--ds-brand-active` |
|
|
443
|
+
| `{role}-soft` | Light background | `--ds-error-soft` |
|
|
444
|
+
| `{role}-soft-hover` | Soft hover state | `--ds-error-soft-hover` |
|
|
445
|
+
| `{role}-soft-active` | Soft active state | `--ds-error-soft-active` |
|
|
446
|
+
| `{role}-on-solid` | Text on solid bg | `--ds-success-on-solid` |
|
|
447
|
+
| `{role}-on-soft` | Text on soft bg | `--ds-success-on-soft` |
|
|
448
|
+
| `{role}-border` | Border color | `--ds-warning-border` |
|
|
449
|
+
| `{role}-border-hover` | Border hover | `--ds-warning-border-hover` |
|
|
450
|
+
| `{role}-border-strong` | Strong border | `--ds-info-border-strong` |
|
|
451
|
+
|
|
452
|
+
## UnoCSS Preset
|
|
453
|
+
|
|
454
|
+
If your app uses UnoCSS, import the design system preset instead of configuring tokens manually. It includes the full theme, rules, shortcuts, variants, and CSS custom properties.
|
|
455
|
+
|
|
456
|
+
### Basic setup
|
|
457
|
+
|
|
458
|
+
```ts
|
|
459
|
+
// uno.config.ts
|
|
460
|
+
import { defineConfig, presetUno } from 'unocss'
|
|
461
|
+
import { dsPreset } from '@leodamours/ds-components/uno'
|
|
462
|
+
|
|
463
|
+
export default defineConfig({
|
|
464
|
+
presets: [presetUno(), dsPreset()],
|
|
465
|
+
})
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Custom palette
|
|
469
|
+
|
|
470
|
+
Pass base colors to override the default palette. All hover, soft, border, and contrast variants are derived automatically:
|
|
471
|
+
|
|
472
|
+
```ts
|
|
473
|
+
dsPreset({
|
|
474
|
+
brand: '#8B5CF6',
|
|
475
|
+
error: '#E11D48',
|
|
476
|
+
success: '#059669',
|
|
477
|
+
warning: '#EA580C',
|
|
478
|
+
info: '#6366F1',
|
|
479
|
+
processing: '#D946EF',
|
|
480
|
+
neutral: '#6B5F7D',
|
|
481
|
+
})
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Only override what differs — unspecified roles keep their defaults. The preset accepts these roles: `brand`, `error`, `success`, `warning`, `info`, `processing`, `neutral`.
|
|
485
|
+
|
|
486
|
+
## Full export reference
|
|
487
|
+
|
|
488
|
+
### Components
|
|
489
|
+
|
|
490
|
+
```ts
|
|
491
|
+
import {
|
|
492
|
+
DsAvatar,
|
|
493
|
+
DsBadge,
|
|
494
|
+
DsButton,
|
|
495
|
+
DsCard,
|
|
496
|
+
DsCheckbox,
|
|
497
|
+
DsDropdownSelect,
|
|
498
|
+
DsExpandableCard,
|
|
499
|
+
DsInput,
|
|
500
|
+
DsLoadingSpinner,
|
|
501
|
+
DsModal,
|
|
502
|
+
DsRadio,
|
|
503
|
+
DsSelect,
|
|
504
|
+
DsSlider,
|
|
505
|
+
DsSwitch,
|
|
506
|
+
DsTable,
|
|
507
|
+
DsTabs,
|
|
508
|
+
DsTextarea,
|
|
509
|
+
DsToast,
|
|
510
|
+
DsToastContainer,
|
|
511
|
+
DsTooltip,
|
|
512
|
+
DsUnderConstruction,
|
|
513
|
+
} from '@leodamours/ds-components'
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Prop types
|
|
517
|
+
|
|
518
|
+
```ts
|
|
519
|
+
import type {
|
|
520
|
+
DsAvatarProps,
|
|
521
|
+
DsBadgeProps,
|
|
522
|
+
DsButtonProps,
|
|
523
|
+
DsCardProps,
|
|
524
|
+
DsCheckboxProps,
|
|
525
|
+
DsDropdownSelectProps,
|
|
526
|
+
DsExpandableCardProps,
|
|
527
|
+
DsInputProps,
|
|
528
|
+
DsLoadingSpinnerProps,
|
|
529
|
+
DsModalProps,
|
|
530
|
+
DsRadioProps,
|
|
531
|
+
DsSelectProps,
|
|
532
|
+
DsSelectOption,
|
|
533
|
+
DsSliderProps,
|
|
534
|
+
DsSwitchProps,
|
|
535
|
+
DsTableProps,
|
|
536
|
+
DsTableColumn,
|
|
537
|
+
DsTablePagination,
|
|
538
|
+
DsTabsProps,
|
|
539
|
+
DsTab,
|
|
540
|
+
DsTextareaProps,
|
|
541
|
+
DsTooltipProps,
|
|
542
|
+
DsUnderConstructionProps,
|
|
543
|
+
Toast,
|
|
544
|
+
ToastVariant,
|
|
545
|
+
} from '@leodamours/ds-components'
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Token utilities
|
|
128
549
|
|
|
129
550
|
```ts
|
|
130
|
-
|
|
131
|
-
|
|
551
|
+
import {
|
|
552
|
+
colorTokens, // All color token values as a JS object
|
|
553
|
+
spacingTokens, // Spacing scale values
|
|
554
|
+
radiusTokens, // Border radius values
|
|
555
|
+
shadowTokens, // Box shadow values
|
|
556
|
+
allTokens, // All tokens combined
|
|
557
|
+
generateThemeCss, // Override specific tokens → CSS string
|
|
558
|
+
tokenToCssVar, // Convert token name to CSS var reference
|
|
559
|
+
} from '@leodamours/ds-components'
|
|
560
|
+
|
|
561
|
+
import type { ColorToken, SpacingToken, RadiusToken, ShadowToken, ThemeOverride } from '@leodamours/ds-components'
|
|
562
|
+
```
|
|
132
563
|
|
|
133
|
-
|
|
134
|
-
import type { DsButtonProps, DsInputProps } from '@leodamours/ds-components'
|
|
564
|
+
### Palette generation
|
|
135
565
|
|
|
136
|
-
|
|
137
|
-
import {
|
|
138
|
-
|
|
566
|
+
```ts
|
|
567
|
+
import {
|
|
568
|
+
generatePalette, // Single hex → full SemanticPalette (12 variants)
|
|
569
|
+
generateFullTheme, // 7 base colors → complete CSS theme string
|
|
570
|
+
expandBases, // 7 base colors → flat token map (no CSS wrapping)
|
|
571
|
+
hexToHSL, // Hex → { h, s, l }
|
|
572
|
+
hslToHex, // (h, s, l) → hex string
|
|
573
|
+
} from '@leodamours/ds-components'
|
|
574
|
+
|
|
575
|
+
import type { SemanticPalette, ThemeBases, SemanticRole } from '@leodamours/ds-components'
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Composables
|
|
139
579
|
|
|
140
|
-
|
|
580
|
+
```ts
|
|
141
581
|
import { useToast, useId } from '@leodamours/ds-components'
|
|
142
582
|
```
|
|
583
|
+
|
|
584
|
+
- **`useToast()`** — returns `{ toasts, removeToast, success, error, warning, info, brand }` (see [Toast system](#toast-system))
|
|
585
|
+
- **`useId()`** — generates unique IDs for accessible form element associations
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export interface DsSwitchProps {
|
|
2
|
+
modelValue?: boolean;
|
|
3
|
+
label?: string;
|
|
4
|
+
id?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
size?: 'small' | 'medium' | 'large';
|
|
7
|
+
labelPosition?: 'left' | 'right';
|
|
8
|
+
}
|
|
9
|
+
declare function __VLS_template(): {
|
|
10
|
+
default?(_: {}): any;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_component: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<DsSwitchProps>, {
|
|
13
|
+
modelValue: boolean;
|
|
14
|
+
disabled: boolean;
|
|
15
|
+
size: string;
|
|
16
|
+
labelPosition: string;
|
|
17
|
+
}>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
18
|
+
"update:modelValue": (value: boolean) => void;
|
|
19
|
+
change: (value: boolean, event: Event) => void;
|
|
20
|
+
}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<DsSwitchProps>, {
|
|
21
|
+
modelValue: boolean;
|
|
22
|
+
disabled: boolean;
|
|
23
|
+
size: string;
|
|
24
|
+
labelPosition: string;
|
|
25
|
+
}>>> & Readonly<{
|
|
26
|
+
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
27
|
+
onChange?: ((value: boolean, event: Event) => any) | undefined;
|
|
28
|
+
}>, {
|
|
29
|
+
size: "small" | "medium" | "large";
|
|
30
|
+
disabled: boolean;
|
|
31
|
+
modelValue: boolean;
|
|
32
|
+
labelPosition: "left" | "right";
|
|
33
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
34
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
|
|
35
|
+
export default _default;
|
|
36
|
+
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
37
|
+
type __VLS_TypePropsToRuntimeProps<T> = {
|
|
38
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
39
|
+
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
|
40
|
+
} : {
|
|
41
|
+
type: import('vue').PropType<T[K]>;
|
|
42
|
+
required: true;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
type __VLS_WithDefaults<P, D> = {
|
|
46
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
|
47
|
+
default: D[K];
|
|
48
|
+
}> : P[K];
|
|
49
|
+
};
|
|
50
|
+
type __VLS_Prettify<T> = {
|
|
51
|
+
[K in keyof T]: T[K];
|
|
52
|
+
} & {};
|
|
53
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
54
|
+
new (): {
|
|
55
|
+
$slots: S;
|
|
56
|
+
};
|
|
57
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { default as DsModal } from './components/DsModal.vue';
|
|
|
12
12
|
export { default as DsRadio } from './components/DsRadio.vue';
|
|
13
13
|
export { default as DsSelect } from './components/DsSelect.vue';
|
|
14
14
|
export { default as DsSlider } from './components/DsSlider.vue';
|
|
15
|
+
export { default as DsSwitch } from './components/DsSwitch.vue';
|
|
15
16
|
export { default as DsTable } from './components/DsTable.vue';
|
|
16
17
|
export { default as DsTabs } from './components/DsTabs.vue';
|
|
17
18
|
export { default as DsTextarea } from './components/DsTextarea.vue';
|
|
@@ -38,6 +39,7 @@ export type { DsModalProps } from './components/DsModal.vue';
|
|
|
38
39
|
export type { DsRadioProps } from './components/DsRadio.vue';
|
|
39
40
|
export type { DsSelectProps, DsSelectOption } from './components/DsSelect.vue';
|
|
40
41
|
export type { DsSliderProps } from './components/DsSlider.vue';
|
|
42
|
+
export type { DsSwitchProps } from './components/DsSwitch.vue';
|
|
41
43
|
export type { DsTableProps, DsTableColumn, DsTablePagination } from './components/DsTable.vue';
|
|
42
44
|
export type { DsTabsProps, DsTab } from './components/DsTabs.vue';
|
|
43
45
|
export type { DsTextareaProps } from './components/DsTextarea.vue';
|