@1337exp/taoui 1.2.2 → 1.3.3
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 +213 -204
- package/README.ru.md +492 -0
- package/dist/index.cjs +1214 -297
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +491 -213
- package/dist/index.mjs +1215 -298
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +315 -52
- package/package.json +1 -1
- package/src/styles/date-popup.css +178 -0
package/README.md
CHANGED
|
@@ -1,108 +1,117 @@
|
|
|
1
1
|
# Tao UI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
поменял несколько CSS-переменных — поменялась тема всего набора компонентов.
|
|
3
|
+
**English** · [Русский](README.ru.md)
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
A Vue 3 component library for Nuxt/Vue apps, driven by design tokens:
|
|
6
|
+
change a handful of CSS variables and the whole kit follows.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Components
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
10
|
+
### Basics
|
|
11
|
+
|
|
12
|
+
- **TaoBlock** — container with padding and radius
|
|
13
|
+
- **TaoButton** — `primary` / `secondary` / `ghost` / `danger`, sizes and states
|
|
14
|
+
- **TaoCard** — card with cover / header / footer slots. `#cover` can be a photo or `TaoCarousel`
|
|
15
|
+
- **TaoCopy** — clipboard icon. After a click, a “Copied” tooltip; if the trigger is gone, the tooltip is too
|
|
16
|
+
- **TaoInput** — text field with v-model, validation, and `#prefix` / `#suffix` slots (icon or text inside the frame)
|
|
17
|
+
- **TaoInputGroup** — outer glue: `#before` | field | `#after` (protocol, unit, button)
|
|
18
|
+
- **TaoModal** — modal with animation and slots
|
|
19
|
+
- **TaoDrawer** — side panel (filters, settings). Esc, backdrop click, focus trap — same as the modal
|
|
20
|
+
- **TaoSpoiler** — disclosure. `v-model` and `aria-expanded`. Neighbours do not close each other
|
|
21
|
+
- **TaoSpoilerGroup** — accordion: `v-model` is the open panel key (`null` = all closed); spoilers take `name`
|
|
22
|
+
- **TaoTabs** — tabbed sections
|
|
23
|
+
- **TaoTooltip** — hover hint
|
|
24
|
+
- **TaoPopover** — click panel with any slot content, Esc and outside click. Not a tooltip, not an action menu
|
|
21
25
|
|
|
22
26
|
### Layout
|
|
23
27
|
|
|
24
|
-
- **TaoContainer** —
|
|
25
|
-
- **TaoFlex** —
|
|
26
|
-
- **TaoSpace** —
|
|
27
|
-
- **TaoDivider** —
|
|
28
|
-
- **
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- **
|
|
34
|
-
- **
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
42
|
-
- **
|
|
43
|
-
- **
|
|
44
|
-
- **
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
56
|
-
- **
|
|
57
|
-
- **
|
|
58
|
-
- **
|
|
59
|
-
- **
|
|
60
|
-
- **
|
|
61
|
-
- **
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
- **
|
|
68
|
-
- **
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
- **
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
28
|
+
- **TaoContainer** — max-width (wide / slim / ultra-slim) and centering
|
|
29
|
+
- **TaoFlex** — flexbox wrapper: justify / align / direction / wrap / gap
|
|
30
|
+
- **TaoSpace** — even gap between children
|
|
31
|
+
- **TaoDivider** — `line` (hairline), `text` (line with a label), `gap` (empty space, size: small / medium / large)
|
|
32
|
+
- **TaoFieldset** — grouped frame: `legend` sits on the top border, `align` is start / center / end
|
|
33
|
+
- **TaoAnimatedBorder** — rainbow border wrapper (decorative, not tied to the theme)
|
|
34
|
+
|
|
35
|
+
### Forms
|
|
36
|
+
|
|
37
|
+
- **TaoCheckbox** — checkbox with v-model, pre/post slots, and `indeterminate`
|
|
38
|
+
- **TaoSwitch** — boolean toggle (`role="switch"`)
|
|
39
|
+
- **TaoRadio** / **TaoRadioGroup** — exclusive choice among 2–5 options
|
|
40
|
+
- **TaoSelect** — dropdown with keyboard, same chrome as Input. Clear via “Clear” in the list or Delete
|
|
41
|
+
- **TaoCombobox** — Select with a field: type to filter, `allow-create` writes a custom value into `v-model`, `create` lets the parent append the list
|
|
42
|
+
- **TaoDate** — a single day: `YYYY-MM-DD`, no time, no timezone. Calendar popup like Select
|
|
43
|
+
- **TaoDateRange** — a period: `v-model` is `{ start, end }` or `null`. First click is start, second is end (they swap if end is earlier). An incomplete pick is not written to the model
|
|
44
|
+
- **TaoFormField** — shared label / hint / error for form controls
|
|
45
|
+
- **TaoInputNumber** — number with min/max/step and ± on the right. Empty value is `null`
|
|
46
|
+
- **TaoQuantity** — cart quantity: `− | field | +`, integers, stock; minus at the minimum can remove the row
|
|
47
|
+
- **TaoTextarea** — autosizing multiline. `maxlength` caps input, `count` shows “entered / max”
|
|
48
|
+
- **TaoPinCode** — N cells. By default a click clears the cell and everything to the right (`clear-on="focus"`); `clear-on="input"` replaces the digit only when typing. The last cell blurs and emits `complete`
|
|
49
|
+
- **TaoSlider** — mouse, touch, and arrows. Optional precise input on right-click
|
|
50
|
+
- **TaoFileDrop** — drop zone (drag & drop + click). File names listed under the zone, `v-model` is `File[]`. Clearing the whole batch is the parent’s job (`clear-request`)
|
|
51
|
+
|
|
52
|
+
### Data display
|
|
53
|
+
|
|
54
|
+
- **TaoTable** — simple table: columns, empty, loading, sort via `v-model:sort`. Not a datagrid.
|
|
55
|
+
- **TaoPagination** — pages with ellipsis. Clicking “…” jumps `jump` pages (5 by default)
|
|
56
|
+
- **TaoEmpty** — empty list, no results, no access
|
|
57
|
+
- **TaoStages** — stage list: `wait` / `work` / `ok` / `bad`. Not a linear stepper
|
|
58
|
+
- **TaoSkeleton** — loading placeholder (text / title / circle / rect)
|
|
59
|
+
- **TaoCounter** — flipping digits (not an input)
|
|
60
|
+
- **TaoCarousel** — strip: full slide with `autoplay`, card with `peek`, row with `per-view`. Arrows via `controls` or `#prev` / `#next`, dots via `dots`
|
|
61
|
+
- **TaoAvatar** — photo or initials, sizes `small` / `medium` / `large`. Status `dot` and `count`
|
|
62
|
+
- **TaoTag** — badge with tones (neutral, success, danger, warning, info)
|
|
63
|
+
- **TaoAlert** — inline page/form banner (success / error / warning / info)
|
|
64
|
+
- **TaoProgress** — static bar (`progress` in %). Percent centered on top, or `showPercentage="right"`; `#left` / `#right` slots are captions, then the percent sits in parentheses on the right. `false` hides it. Width is `minWidth` / `maxWidth`, not the value domain
|
|
65
|
+
- **TaoLoader** — four-dot spinner
|
|
66
|
+
- **TaoImage** — `<img>` wrapper: fade-in and placeholder. `lazy` turns on native `loading="lazy"`
|
|
67
|
+
- **TaoIcon** — icon-font wrapper (see Icons below)
|
|
68
|
+
|
|
69
|
+
### Navigation
|
|
70
|
+
|
|
71
|
+
- **TaoLink** — uses `<NuxtLink>` in Nuxt and a plain `<a>` elsewhere, with no extra setup
|
|
72
|
+
- **TaoBreadcrumb** — crumbs: the last item is the current page
|
|
73
|
+
- **TaoDropdownMenu** — dropdown that flips at the viewport edge
|
|
74
|
+
- **TaoScrollTop** — floating “back to top” with a ripple. Appears on reverse scroll after `boundary`
|
|
75
|
+
|
|
76
|
+
### Feedback
|
|
77
|
+
|
|
78
|
+
- **toast()** — fluent toasts: `toast().success().message('Saved')`
|
|
79
|
+
- **confirm()** — overlay question: the same fluent API plus `await`. Not a toast — it waits for an answer and does not dismiss itself.
|
|
80
|
+
- **TaoToastViewport** / **TaoConfirmHost** — hosts; if they are missing from the tree, the first call mounts them on `body`
|
|
81
|
+
|
|
82
|
+
## Conventions
|
|
83
|
+
|
|
84
|
+
Visual tones: `success` | `danger` | `warning` | `info` | `neutral`.
|
|
85
|
+
`error` on Alert, Tag, and `toast()` is an alias of `danger`. Button already uses `danger`.
|
|
86
|
+
Stages describe a process, not a tone: `wait` / `work` / `ok` / `bad` (`danger` is accepted as `bad`).
|
|
87
|
+
|
|
88
|
+
Control sizes: `small` | `medium` | `large`.
|
|
89
|
+
Avatar also accepts short `s` / `m` / `l`. Divider `gap` used to call the large size `big` — that is an alias of `large`.
|
|
90
|
+
Container lives on another axis: `wide` / `slim` / `ultra-slim`.
|
|
91
|
+
|
|
92
|
+
## Icons
|
|
93
|
+
|
|
94
|
+
`TaoIcon` does not ship its own set — it renders `icon-<name>`
|
|
95
|
+
for an external icon font (IcoMoon / Fontello and the like). Connect a font
|
|
96
|
+
with classes such as `.icon-arrow-up { ... }` in the host app.
|
|
97
|
+
|
|
98
|
+
## Install
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm install @1337exp/taoui
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
From a local folder:
|
|
96
105
|
|
|
97
106
|
```bash
|
|
98
107
|
npm install ../path-to-tao-ui
|
|
99
108
|
```
|
|
100
109
|
|
|
101
|
-
##
|
|
110
|
+
## Usage
|
|
102
111
|
|
|
103
|
-
###
|
|
112
|
+
### Nuxt 3
|
|
104
113
|
|
|
105
|
-
|
|
114
|
+
Create `plugins/tao-ui.ts`:
|
|
106
115
|
|
|
107
116
|
```typescript
|
|
108
117
|
import { defineNuxtPlugin } from '#app'
|
|
@@ -113,7 +122,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
113
122
|
})
|
|
114
123
|
```
|
|
115
124
|
|
|
116
|
-
|
|
125
|
+
Import styles in `app.vue` or a layout:
|
|
117
126
|
|
|
118
127
|
```vue
|
|
119
128
|
<script setup>
|
|
@@ -121,7 +130,7 @@ import '@1337exp/taoui/styles.css'
|
|
|
121
130
|
</script>
|
|
122
131
|
```
|
|
123
132
|
|
|
124
|
-
###
|
|
133
|
+
### Vue 3
|
|
125
134
|
|
|
126
135
|
```javascript
|
|
127
136
|
// main.js
|
|
@@ -135,7 +144,7 @@ app.use(TaoUI)
|
|
|
135
144
|
app.mount('#app')
|
|
136
145
|
```
|
|
137
146
|
|
|
138
|
-
###
|
|
147
|
+
### Individual components
|
|
139
148
|
|
|
140
149
|
```vue
|
|
141
150
|
<script setup>
|
|
@@ -144,41 +153,41 @@ import '@1337exp/taoui/styles.css'
|
|
|
144
153
|
</script>
|
|
145
154
|
|
|
146
155
|
<template>
|
|
147
|
-
<TaoButton variant="primary"
|
|
148
|
-
<TaoInput v-model="text" label="
|
|
149
|
-
<TaoModal v-model="isOpen" title="
|
|
150
|
-
|
|
156
|
+
<TaoButton variant="primary">Press me</TaoButton>
|
|
157
|
+
<TaoInput v-model="text" label="Your text" />
|
|
158
|
+
<TaoModal v-model="isOpen" title="Title">
|
|
159
|
+
Modal body
|
|
151
160
|
</TaoModal>
|
|
152
161
|
</template>
|
|
153
162
|
```
|
|
154
163
|
|
|
155
164
|
## Toast
|
|
156
165
|
|
|
157
|
-
|
|
166
|
+
The chain runs in the same tick; `setTimeout(0)` actually shows the toast.
|
|
158
167
|
|
|
159
168
|
```javascript
|
|
160
169
|
import { toast } from '@1337exp/taoui'
|
|
161
170
|
|
|
162
|
-
toast().success().message('
|
|
163
|
-
toast().error().title('
|
|
164
|
-
toast.success('
|
|
165
|
-
toast.warning('
|
|
171
|
+
toast().success().message('Saved')
|
|
172
|
+
toast().error().title('Network').timeout(5000).message('No connection')
|
|
173
|
+
toast.success('Saved')
|
|
174
|
+
toast.warning('Draft', { timeout: 1000 })
|
|
166
175
|
```
|
|
167
176
|
|
|
168
|
-
|
|
177
|
+
Default position is `topCenter`. Globally:
|
|
169
178
|
|
|
170
179
|
```javascript
|
|
171
180
|
toast.defaults({ position: 'bottomRight' })
|
|
172
181
|
toast.byBottomRight()
|
|
173
182
|
```
|
|
174
183
|
|
|
175
|
-
`question`
|
|
184
|
+
There is no overlay `question` in this kit — that is confirm, not toast. Buttons on a toast, if needed:
|
|
176
185
|
|
|
177
186
|
```javascript
|
|
178
|
-
toast().info().message('
|
|
187
|
+
toast().info().message('Delete the file?').action('Delete', onRemove)
|
|
179
188
|
```
|
|
180
189
|
|
|
181
|
-
|
|
190
|
+
You can skip the viewport: the first call creates it. For explicit control (tests, a custom layout):
|
|
182
191
|
|
|
183
192
|
```vue
|
|
184
193
|
<TaoToastViewport />
|
|
@@ -186,62 +195,62 @@ Viewport можно не вставлять: первый вызов сам со
|
|
|
186
195
|
|
|
187
196
|
## Confirm
|
|
188
197
|
|
|
189
|
-
|
|
198
|
+
An overlay question in the center of the screen. This is not a toast: no progress bar, no auto-close, `await`, Esc and overlay click = cancel.
|
|
190
199
|
|
|
191
200
|
```javascript
|
|
192
201
|
import { confirm } from '@1337exp/taoui'
|
|
193
202
|
|
|
194
|
-
if (await confirm().title('
|
|
203
|
+
if (await confirm().title('Delete the file?').message('This cannot be undone').danger()) {
|
|
195
204
|
remove()
|
|
196
205
|
}
|
|
197
206
|
|
|
198
|
-
const ok = await confirm('
|
|
199
|
-
ok: '
|
|
200
|
-
cancel: '
|
|
207
|
+
const ok = await confirm('Leave without saving?', {
|
|
208
|
+
ok: 'Leave',
|
|
209
|
+
cancel: 'Stay',
|
|
201
210
|
})
|
|
202
211
|
```
|
|
203
212
|
|
|
204
|
-
|
|
213
|
+
Queue: a second `confirm()` while the first is open will wait. Default labels are “OK” / “Cancel”:
|
|
205
214
|
|
|
206
215
|
```javascript
|
|
207
216
|
confirm.defaults({ ok: 'Yes', cancel: 'No' })
|
|
208
217
|
```
|
|
209
218
|
|
|
210
|
-
##
|
|
219
|
+
## Forms
|
|
211
220
|
|
|
212
|
-
`TaoFormField`
|
|
221
|
+
`TaoFormField` attaches a shared label / hint / error and forwards `id` to the nested control.
|
|
213
222
|
|
|
214
223
|
```vue
|
|
215
|
-
<TaoFormField label="
|
|
224
|
+
<TaoFormField label="City" hint="Optional">
|
|
216
225
|
<TaoSelect v-model="city" :options="cities" />
|
|
217
226
|
</TaoFormField>
|
|
218
227
|
|
|
219
|
-
<TaoSwitch v-model="dark" label="
|
|
228
|
+
<TaoSwitch v-model="dark" label="Dark theme" />
|
|
220
229
|
|
|
221
|
-
<TaoRadioGroup v-model="plan" legend="
|
|
230
|
+
<TaoRadioGroup v-model="plan" legend="Plan">
|
|
222
231
|
<TaoRadio value="free" label="Free" />
|
|
223
232
|
<TaoRadio value="pro" label="Pro" />
|
|
224
233
|
</TaoRadioGroup>
|
|
225
234
|
|
|
226
|
-
<TaoAlert type="warning" title="
|
|
235
|
+
<TaoAlert type="warning" title="Draft">Save before you leave.</TaoAlert>
|
|
227
236
|
```
|
|
228
237
|
|
|
229
|
-
`TaoSelect`
|
|
238
|
+
`TaoSelect` opens from the keyboard (arrows, Enter, Esc); the list flips at the viewport edge. Delete or “Clear” at the bottom of the list resets the value to `null`.
|
|
230
239
|
|
|
231
|
-
`TaoCombobox`
|
|
240
|
+
`TaoCombobox` is the same menu with a field. Typing filters options. `allow-create` writes the typed string into `v-model` when there is no exact match. The list does not mutate itself: listen to `create` and append an option from the parent.
|
|
232
241
|
|
|
233
|
-
`TaoFormField`
|
|
242
|
+
`TaoFormField` also wraps `TaoTextarea` and `TaoCheckbox` — id, hint, and error are forwarded for you.
|
|
234
243
|
|
|
235
|
-
##
|
|
244
|
+
## Table and pagination
|
|
236
245
|
|
|
237
|
-
|
|
246
|
+
The table renders what you pass in: it does not slice or sort the data. That works for both server-side and client-side paging — the page is cut outside.
|
|
238
247
|
|
|
239
248
|
```vue
|
|
240
249
|
<TaoTable
|
|
241
250
|
:columns="columns"
|
|
242
251
|
:rows="pageRows"
|
|
243
252
|
v-model:sort="sort"
|
|
244
|
-
empty-text="
|
|
253
|
+
empty-text="No records yet"
|
|
245
254
|
>
|
|
246
255
|
<template #cell-status="{ row }">
|
|
247
256
|
<TaoTag :type="row.status === 'active' ? 'success' : 'neutral'">
|
|
@@ -255,21 +264,21 @@ confirm.defaults({ ok: 'Yes', cancel: 'No' })
|
|
|
255
264
|
|
|
256
265
|
```javascript
|
|
257
266
|
const columns = [
|
|
258
|
-
{ key: 'name', label: '
|
|
259
|
-
{ key: 'city', label: '
|
|
260
|
-
{ key: 'status', label: '
|
|
267
|
+
{ key: 'name', label: 'Name', sortable: true },
|
|
268
|
+
{ key: 'city', label: 'City' },
|
|
269
|
+
{ key: 'status', label: 'Status' },
|
|
261
270
|
]
|
|
262
271
|
```
|
|
263
272
|
|
|
264
|
-
|
|
273
|
+
The `cell-<key>` slot replaces a cell. `loading` shows an overlay; an empty list shows text or the `#empty` slot. Clicking a `sortable` header cycles `asc → desc → off`.
|
|
265
274
|
|
|
266
|
-
##
|
|
275
|
+
## Empty states and loading
|
|
267
276
|
|
|
268
277
|
```vue
|
|
269
|
-
<TaoEmpty title="
|
|
270
|
-
|
|
278
|
+
<TaoEmpty title="Nothing found">
|
|
279
|
+
Change the filter or reset search.
|
|
271
280
|
<template #action>
|
|
272
|
-
<TaoButton variant="secondary"
|
|
281
|
+
<TaoButton variant="secondary">Reset</TaoButton>
|
|
273
282
|
</template>
|
|
274
283
|
</TaoEmpty>
|
|
275
284
|
|
|
@@ -278,14 +287,14 @@ const columns = [
|
|
|
278
287
|
<TaoSkeleton variant="circle" />
|
|
279
288
|
|
|
280
289
|
<TaoStages :items="[
|
|
281
|
-
{ key: 'pay', label: '
|
|
282
|
-
{ key: 'pack', label: '
|
|
283
|
-
{ key: 'ship', label: '
|
|
290
|
+
{ key: 'pay', label: 'Payment', status: 'ok' },
|
|
291
|
+
{ key: 'pack', label: 'Packing', status: 'work' },
|
|
292
|
+
{ key: 'ship', label: 'Shipping', status: 'wait' },
|
|
284
293
|
]" />
|
|
285
294
|
```
|
|
286
295
|
|
|
287
296
|
```vue
|
|
288
|
-
<TaoInput v-model="q" placeholder="
|
|
297
|
+
<TaoInput v-model="q" placeholder="Search…">
|
|
289
298
|
<template #prefix>⌕</template>
|
|
290
299
|
</TaoInput>
|
|
291
300
|
|
|
@@ -293,7 +302,7 @@ const columns = [
|
|
|
293
302
|
<template #before>https://</template>
|
|
294
303
|
<TaoInput v-model="host" placeholder="example.com" />
|
|
295
304
|
<template #after>
|
|
296
|
-
<TaoButton
|
|
305
|
+
<TaoButton>Check</TaoButton>
|
|
297
306
|
</template>
|
|
298
307
|
</TaoInputGroup>
|
|
299
308
|
|
|
@@ -301,19 +310,23 @@ const columns = [
|
|
|
301
310
|
<TaoFormField label="Email">
|
|
302
311
|
<TaoInput v-model="email" type="email" />
|
|
303
312
|
</TaoFormField>
|
|
304
|
-
<TaoButton type="submit"
|
|
313
|
+
<TaoButton type="submit">Save</TaoButton>
|
|
305
314
|
</form>
|
|
306
315
|
|
|
307
|
-
<TaoFormField label="
|
|
316
|
+
<TaoFormField label="Quantity">
|
|
308
317
|
<TaoInputNumber v-model="qty" :min="1" :max="99" />
|
|
309
318
|
</TaoFormField>
|
|
310
319
|
|
|
311
320
|
<TaoQuantity v-model="qty" :max="12" @dec="onDec" />
|
|
312
321
|
|
|
313
|
-
<TaoFormField label="
|
|
322
|
+
<TaoFormField label="Delivery day" hint="The model is always YYYY-MM-DD">
|
|
314
323
|
<TaoDate v-model="day" min="2026-09-01" max="2026-09-30" />
|
|
315
324
|
</TaoFormField>
|
|
316
325
|
|
|
326
|
+
<TaoFormField label="Stay">
|
|
327
|
+
<TaoDateRange v-model="stay" min="2026-09-01" max="2026-09-30" />
|
|
328
|
+
</TaoFormField>
|
|
329
|
+
|
|
317
330
|
<TaoCounter :value="score" :max-digits="6" />
|
|
318
331
|
|
|
319
332
|
<TaoCarousel :autoplay="4000" loop dots>
|
|
@@ -326,49 +339,48 @@ const columns = [
|
|
|
326
339
|
<TaoCarousel v-model="slide" :per-view="5" :peek="28">
|
|
327
340
|
<template #prev></template>
|
|
328
341
|
<template #next="{ go, disabled }">
|
|
329
|
-
<button type="button" :disabled="disabled" @click="go"
|
|
342
|
+
<button type="button" :disabled="disabled" @click="go">next</button>
|
|
330
343
|
</template>
|
|
331
344
|
<article v-for="item in products" :key="item.id">…</article>
|
|
332
345
|
</TaoCarousel>
|
|
333
346
|
```
|
|
334
347
|
|
|
335
|
-
`TaoDrawer`
|
|
348
|
+
`TaoDrawer` is a side sheet, not a centered modal:
|
|
336
349
|
|
|
337
350
|
```vue
|
|
338
|
-
<TaoDrawer v-model="open" title="
|
|
351
|
+
<TaoDrawer v-model="open" title="Filters">
|
|
339
352
|
...
|
|
340
353
|
</TaoDrawer>
|
|
341
354
|
```
|
|
342
355
|
|
|
343
|
-
##
|
|
356
|
+
## Design tokens and theming
|
|
344
357
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
внешний вид всех компонентов сразу, без правок самих компонентов.
|
|
358
|
+
Library styles are three layers. Components **never** touch raw colors or sizes —
|
|
359
|
+
only semantic variables. That is the theming mechanism: override 20–30 variables
|
|
360
|
+
and every component follows, with no edits inside the components themselves.
|
|
349
361
|
|
|
350
362
|
```
|
|
351
|
-
primitives.css → semantic.css → themes/*.css (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
363
|
+
primitives.css → semantic.css → themes/*.css (optional)
|
|
364
|
+
raw colors public theming ready-made themes on top
|
|
365
|
+
and scales, API: this is of semantic — light is
|
|
366
|
+
leave them alone what you change the example
|
|
355
367
|
```
|
|
356
368
|
|
|
357
|
-
###
|
|
369
|
+
### Layers
|
|
358
370
|
|
|
359
|
-
|
|
|
371
|
+
| File | Role | Touch it? |
|
|
360
372
|
|---|---|---|
|
|
361
|
-
| `primitives.css` |
|
|
362
|
-
| `semantic.css` |
|
|
363
|
-
| `themes/light.css` |
|
|
364
|
-
| `base.css` |
|
|
373
|
+
| `primitives.css` | Raw palette, space / radius / shadow scales (`--tao-orange-400`, `--tao-space-3`…) | Usually no |
|
|
374
|
+
| `semantic.css` | Default (dark) theme tokens: `--tao-color-accent`, `--tao-color-surface`, `--tao-color-danger`, etc. | **Yes — this is the theming API** |
|
|
375
|
+
| `themes/light.css` | Alternate theme via `[data-tao-theme="light"]` | Yes, as a sample |
|
|
376
|
+
| `base.css` | Global reset (scrollbar, links, box-sizing) | Rarely |
|
|
365
377
|
|
|
366
|
-
|
|
378
|
+
All four come in through `@1337exp/taoui/styles.css`.
|
|
367
379
|
|
|
368
|
-
###
|
|
380
|
+
### Your own theme
|
|
369
381
|
|
|
370
|
-
|
|
371
|
-
|
|
382
|
+
A theme is just semantic tokens under your selector.
|
|
383
|
+
Nothing in the components needs to change:
|
|
372
384
|
|
|
373
385
|
```css
|
|
374
386
|
/* my-brand-theme.css */
|
|
@@ -380,7 +392,7 @@ primitives.css → semantic.css → themes/*.css (опционально
|
|
|
380
392
|
--tao-color-surface-raised: #1a1a2e;
|
|
381
393
|
--tao-color-text: #d6d6e8;
|
|
382
394
|
--tao-color-text-strong: #ffffff;
|
|
383
|
-
/*
|
|
395
|
+
/* remaining tokens: see semantic.css */
|
|
384
396
|
}
|
|
385
397
|
```
|
|
386
398
|
|
|
@@ -393,40 +405,39 @@ primitives.css → semantic.css → themes/*.css (опционально
|
|
|
393
405
|
</template>
|
|
394
406
|
```
|
|
395
407
|
|
|
396
|
-
|
|
397
|
-
которые телепортируются в `body`:
|
|
408
|
+
Or switch the theme on `<html>` so modals/tooltips teleported to `body` pick it up:
|
|
398
409
|
|
|
399
410
|
```javascript
|
|
400
411
|
document.documentElement.setAttribute('data-tao-theme', 'light')
|
|
401
412
|
```
|
|
402
413
|
|
|
403
|
-
###
|
|
414
|
+
### Token groups
|
|
404
415
|
|
|
405
|
-
- `--tao-color-accent*` —
|
|
406
|
-
- `--tao-color-on-accent` —
|
|
407
|
-
- `--tao-color-selection`, `--tao-color-selection-text` —
|
|
408
|
-
- `--tao-color-surface*` —
|
|
409
|
-
- `--tao-color-border*` —
|
|
410
|
-
- `--tao-color-text*` —
|
|
411
|
-
- `--tao-color-danger*`, `--tao-color-success*`, `--tao-color-warning*`, `--tao-color-info*` —
|
|
412
|
-
- `--tao-color-input-*` —
|
|
413
|
-
- `--tao-radius-control`, `--tao-radius-panel` —
|
|
414
|
-
- `--tao-shadow-panel`, `--tao-shadow-overlay` —
|
|
416
|
+
- `--tao-color-accent*` — brand/accent (primary buttons, active tabs, links)
|
|
417
|
+
- `--tao-color-on-accent` — text on the accent (`--tao-color-text-on-accent` is an alias)
|
|
418
|
+
- `--tao-color-selection`, `--tao-color-selection-text` — text selection (`::selection`)
|
|
419
|
+
- `--tao-color-surface*` — container backgrounds (default / raised / sunken / hover)
|
|
420
|
+
- `--tao-color-border*` — borders
|
|
421
|
+
- `--tao-color-text*` — text (default / strong / muted / disabled)
|
|
422
|
+
- `--tao-color-danger*`, `--tao-color-success*`, `--tao-color-warning*`, `--tao-color-info*` — status colors
|
|
423
|
+
- `--tao-color-input-*` — fields, because input bg/text often differs from surface/text
|
|
424
|
+
- `--tao-radius-control`, `--tao-radius-panel` — radii (small controls vs large panels)
|
|
425
|
+
- `--tao-shadow-panel`, `--tao-shadow-overlay` — shadows
|
|
415
426
|
|
|
416
|
-
|
|
417
|
-
|
|
427
|
+
The full list lives in `src/styles/semantic.css` — the only file worth opening
|
|
428
|
+
to see the whole theming API.
|
|
418
429
|
|
|
419
|
-
###
|
|
430
|
+
### A theme from scratch, without primitives
|
|
420
431
|
|
|
421
432
|
```javascript
|
|
422
|
-
import '@1337exp/taoui/styles/primitives.css' //
|
|
423
|
-
import './my-semantic.css' //
|
|
433
|
+
import '@1337exp/taoui/styles/primitives.css' // keep the scales if you want
|
|
434
|
+
import './my-semantic.css' // your semantic layer instead of @1337exp/taoui/styles/semantic.css
|
|
424
435
|
import '@1337exp/taoui/styles/base.css'
|
|
425
436
|
```
|
|
426
437
|
|
|
427
|
-
##
|
|
438
|
+
## Showcase
|
|
428
439
|
|
|
429
|
-
|
|
440
|
+
To browse every component:
|
|
430
441
|
|
|
431
442
|
```bash
|
|
432
443
|
cd showcase
|
|
@@ -434,45 +445,43 @@ npm install
|
|
|
434
445
|
npm run dev
|
|
435
446
|
```
|
|
436
447
|
|
|
437
|
-
|
|
438
|
-
|
|
448
|
+
The showcase has a dark / light switch in the header, so you can see token
|
|
449
|
+
overrides without editing component code.
|
|
439
450
|
|
|
440
|
-
|
|
441
|
-
`npm run build`.
|
|
442
|
-
|
|
451
|
+
The showcase points at `src/` directly, so component edits show up without
|
|
452
|
+
`npm run build`. Building `dist/` is for publishing and for other projects
|
|
453
|
+
that install the package.
|
|
443
454
|
|
|
444
|
-
##
|
|
455
|
+
## Development
|
|
445
456
|
|
|
446
457
|
```bash
|
|
447
|
-
#
|
|
458
|
+
# Build the library
|
|
448
459
|
npm run build
|
|
449
460
|
|
|
450
|
-
#
|
|
461
|
+
# Watch mode
|
|
451
462
|
npm run dev
|
|
452
463
|
|
|
453
|
-
#
|
|
464
|
+
# Type check
|
|
454
465
|
npm run type-check
|
|
455
466
|
```
|
|
456
467
|
|
|
457
|
-
##
|
|
468
|
+
## Publishing to npm
|
|
458
469
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
репозитории; чтобы их получить, репозиторий клонируют.
|
|
470
|
+
Only `dist/` (the built library) and `src/styles/` (raw tokens, so you can
|
|
471
|
+
import `primitives.css` on its own for a custom theme) are published.
|
|
472
|
+
Component sources (`src/components/*.vue`), build configs, and `showcase/`
|
|
473
|
+
stay in the repo — clone it to get them.
|
|
464
474
|
|
|
465
|
-
`npm publish`
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
`npm publish` не нужно.
|
|
475
|
+
`npm publish` **itself** runs the type check and a full rebuild first
|
|
476
|
+
(`prepublishOnly` in `package.json`), so a stale or missing `dist/` cannot
|
|
477
|
+
reach the registry. You do not need to build by hand before `npm publish`.
|
|
469
478
|
|
|
470
|
-
|
|
479
|
+
See what would go into the tarball, without publishing:
|
|
471
480
|
|
|
472
481
|
```bash
|
|
473
482
|
npm pack --dry-run
|
|
474
483
|
```
|
|
475
484
|
|
|
476
|
-
##
|
|
485
|
+
## License
|
|
477
486
|
|
|
478
487
|
MIT
|