@cfasim-ui/components 0.7.8 → 0.8.1
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/dist/Box/Box.d.ts +7 -11
- package/dist/Button/Button.d.ts +7 -11
- package/dist/ButtonGroup/ButtonGroup.d.ts +8 -12
- package/dist/Container/Container.d.ts +7 -11
- package/dist/Expander/Expander.d.ts +12 -14
- package/dist/Grid/Grid.d.ts +6 -5
- package/dist/Hint/Hint.d.ts +2 -1
- package/dist/Icon/Icon.d.ts +3 -2
- package/dist/LightDarkToggle/LightDarkToggle.d.ts +2 -1
- package/dist/MultiSelect/MultiSelect.d.ts +6 -6
- package/dist/NumberInput/NumberInput.d.ts +13 -11
- package/dist/ParamEditor/ParamEditor.d.ts +3 -2
- package/dist/ParamEditor/ParamEditorImpl.d.ts +3 -5
- package/dist/{ParamEditorImpl-D0xZTyAN.js → ParamEditorImpl-CkElC6PI.js} +3075 -3041
- package/dist/SelectBox/SelectBox.d.ts +8 -6
- package/dist/{SelectBox-CByXZfaC.js → SelectBox-Df8dE2r-.js} +6 -6
- package/dist/SidebarLayout/SidebarLayout.d.ts +21 -20
- package/dist/Spinner/Spinner.d.ts +3 -2
- package/dist/TextInput/TextInput.d.ts +7 -5
- package/dist/Toggle/Toggle.d.ts +8 -6
- package/dist/ToggleGroup/ToggleGroup.d.ts +8 -6
- package/dist/_internal/FieldLabel.d.ts +2 -1
- package/dist/index.js +20 -20
- package/docs/Box.md +49 -0
- package/docs/Button.md +67 -0
- package/docs/ButtonGroup.md +64 -0
- package/docs/Container.md +103 -0
- package/docs/Expander.md +34 -0
- package/docs/Grid.md +170 -0
- package/docs/Hint.md +29 -0
- package/docs/Icon.md +188 -0
- package/docs/MultiSelect.md +143 -0
- package/docs/NumberInput.md +485 -0
- package/docs/ParamEditor.md +97 -0
- package/docs/SelectBox.md +182 -0
- package/docs/SidebarLayout.md +106 -0
- package/docs/Spinner.md +51 -0
- package/docs/TextInput.md +83 -0
- package/docs/Toggle.md +81 -0
- package/docs/ToggleGroup.md +163 -0
- package/docs/index.json +194 -0
- package/package.json +24 -20
- package/src/Box/Box.md +41 -0
- package/src/Box/Box.vue +52 -0
- package/src/Button/Button.md +59 -0
- package/src/Button/Button.vue +81 -0
- package/src/ButtonGroup/ButtonGroup.md +62 -0
- package/src/ButtonGroup/ButtonGroup.vue +91 -0
- package/src/Container/Container.md +99 -0
- package/src/Container/Container.vue +62 -0
- package/src/Expander/Expander.md +23 -0
- package/src/Expander/Expander.vue +95 -0
- package/src/Grid/Grid.md +175 -0
- package/src/Grid/Grid.vue +145 -0
- package/src/Hint/Hint.md +24 -0
- package/src/Hint/Hint.vue +83 -0
- package/src/Icon/Icon.md +176 -0
- package/src/Icon/Icon.vue +104 -0
- package/src/Icon/defaultIcons.ts +92 -0
- package/src/Icon/github.svg +1 -0
- package/src/Icon/registry.ts +68 -0
- package/src/LightDarkToggle/LightDarkToggle.vue +49 -0
- package/src/MultiSelect/MultiSelect.md +142 -0
- package/src/MultiSelect/MultiSelect.vue +279 -0
- package/src/NumberInput/NumberInput.md +455 -0
- package/src/NumberInput/NumberInput.vue +575 -0
- package/src/ParamEditor/ParamEditor.md +87 -0
- package/src/ParamEditor/ParamEditor.vue +43 -0
- package/src/ParamEditor/ParamEditorImpl.vue +358 -0
- package/src/SelectBox/SelectBox.md +169 -0
- package/src/SelectBox/SelectBox.vue +260 -0
- package/src/SidebarLayout/SidebarLayout.md +106 -0
- package/src/SidebarLayout/SidebarLayout.vue +468 -0
- package/src/Spinner/Spinner.md +45 -0
- package/src/Spinner/Spinner.vue +55 -0
- package/src/TextInput/TextInput.md +68 -0
- package/src/TextInput/TextInput.vue +54 -0
- package/src/Toggle/Toggle.md +68 -0
- package/src/Toggle/Toggle.vue +81 -0
- package/src/ToggleGroup/ToggleGroup.md +158 -0
- package/src/ToggleGroup/ToggleGroup.vue +138 -0
- package/src/_internal/FieldLabel.vue +27 -0
- package/src/_internal/field.ts +27 -0
- package/src/_internal/gap.ts +17 -0
- package/src/_internal/input.css +54 -0
- package/src/_internal/listbox.css +53 -0
- package/src/env.d.ts +4 -0
- package/src/index.ts +33 -0
- package/src/svg.d.ts +5 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# SelectBox
|
|
2
|
+
|
|
3
|
+
A single-select dropdown built on reka-ui. Set `autocomplete` to turn it into a
|
|
4
|
+
filterable single-select combobox: type to narrow the options, just like
|
|
5
|
+
[MultiSelect](./multi-select) but bound to a single `string`.
|
|
6
|
+
|
|
7
|
+
## Examples
|
|
8
|
+
|
|
9
|
+
<script setup>
|
|
10
|
+
import { ref } from 'vue'
|
|
11
|
+
const interval = ref('weekly')
|
|
12
|
+
const state = ref('')
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<ComponentDemo>
|
|
16
|
+
<div style="width: 200px">
|
|
17
|
+
<SelectBox
|
|
18
|
+
v-model="interval"
|
|
19
|
+
label="Interval"
|
|
20
|
+
:options="[
|
|
21
|
+
{ value: 'daily', label: 'Daily' },
|
|
22
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
23
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
24
|
+
]"
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<template #code>
|
|
29
|
+
|
|
30
|
+
```vue
|
|
31
|
+
<script setup>
|
|
32
|
+
import { ref } from "vue";
|
|
33
|
+
const interval = ref("weekly");
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<SelectBox
|
|
37
|
+
v-model="interval"
|
|
38
|
+
label="Interval"
|
|
39
|
+
:options="[
|
|
40
|
+
{ value: 'daily', label: 'Daily' },
|
|
41
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
42
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
43
|
+
]"
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
</template>
|
|
48
|
+
</ComponentDemo>
|
|
49
|
+
|
|
50
|
+
### Hidden label
|
|
51
|
+
|
|
52
|
+
Use `hide-label` to visually hide the label while keeping it available to
|
|
53
|
+
screen readers. Prefer this over `aria-label` whenever you have label text,
|
|
54
|
+
since a real `<label>` is translated by browsers and keeps the naming in the
|
|
55
|
+
DOM.
|
|
56
|
+
|
|
57
|
+
<ComponentDemo>
|
|
58
|
+
<div style="width: 200px">
|
|
59
|
+
<SelectBox
|
|
60
|
+
v-model="interval"
|
|
61
|
+
label="Interval"
|
|
62
|
+
hide-label
|
|
63
|
+
:options="[
|
|
64
|
+
{ value: 'daily', label: 'Daily' },
|
|
65
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
66
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
67
|
+
]"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<template #code>
|
|
72
|
+
|
|
73
|
+
```vue
|
|
74
|
+
<SelectBox
|
|
75
|
+
v-model="interval"
|
|
76
|
+
label="Interval"
|
|
77
|
+
hide-label
|
|
78
|
+
:options="[
|
|
79
|
+
{ value: 'daily', label: 'Daily' },
|
|
80
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
81
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
82
|
+
]"
|
|
83
|
+
/>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
</template>
|
|
87
|
+
</ComponentDemo>
|
|
88
|
+
|
|
89
|
+
### Autocomplete
|
|
90
|
+
|
|
91
|
+
Add `autocomplete` to make the field filterable. Type to narrow the list; the
|
|
92
|
+
selected option's label fills the input. `v-model` is still a single `string`.
|
|
93
|
+
|
|
94
|
+
<ComponentDemo>
|
|
95
|
+
<div style="width: 240px">
|
|
96
|
+
<SelectBox
|
|
97
|
+
v-model="state"
|
|
98
|
+
autocomplete
|
|
99
|
+
label="State"
|
|
100
|
+
placeholder="Search states…"
|
|
101
|
+
:options="[
|
|
102
|
+
{ value: 'ca', label: 'California' },
|
|
103
|
+
{ value: 'ny', label: 'New York' },
|
|
104
|
+
{ value: 'tx', label: 'Texas' },
|
|
105
|
+
{ value: 'wa', label: 'Washington' },
|
|
106
|
+
{ value: 'fl', label: 'Florida' },
|
|
107
|
+
]"
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<template #code>
|
|
112
|
+
|
|
113
|
+
```vue
|
|
114
|
+
<script setup>
|
|
115
|
+
import { ref } from "vue";
|
|
116
|
+
const state = ref("");
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<SelectBox
|
|
120
|
+
v-model="state"
|
|
121
|
+
autocomplete
|
|
122
|
+
label="State"
|
|
123
|
+
placeholder="Search states…"
|
|
124
|
+
:options="[
|
|
125
|
+
{ value: 'ca', label: 'California' },
|
|
126
|
+
{ value: 'ny', label: 'New York' },
|
|
127
|
+
{ value: 'tx', label: 'Texas' },
|
|
128
|
+
{ value: 'wa', label: 'Washington' },
|
|
129
|
+
{ value: 'fl', label: 'Florida' },
|
|
130
|
+
]"
|
|
131
|
+
/>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
</template>
|
|
135
|
+
</ComponentDemo>
|
|
136
|
+
|
|
137
|
+
## Accessibility
|
|
138
|
+
|
|
139
|
+
In the default mode the field is a reka-ui Select; with `autocomplete` it's a
|
|
140
|
+
reka-ui Combobox following the
|
|
141
|
+
[ARIA combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/):
|
|
142
|
+
|
|
143
|
+
- The input has `role="combobox"` with `aria-expanded`, `aria-controls`, and
|
|
144
|
+
`aria-autocomplete="list"`; the popup is a `role="listbox"` and each option a
|
|
145
|
+
`role="option"` that reflects its state via `aria-selected`.
|
|
146
|
+
- Keyboard support is handled for you: type to filter, ↑/↓ to move through the
|
|
147
|
+
list, Enter to select the highlighted option, and Escape to close.
|
|
148
|
+
- Pass `label` so the field is named by a real `<label>`. In autocomplete mode
|
|
149
|
+
the label is also wired to the input via `for`/`id`, so clicking it focuses
|
|
150
|
+
the field; use `hide-label` to keep the label for screen readers while hiding
|
|
151
|
+
it visually, or `aria-label` when there's no visible label text.
|
|
152
|
+
- The chevron is a labelled toggle (`aria-label="Toggle options"`) kept out of
|
|
153
|
+
the tab order, and native browser autofill is disabled so it can't cover the
|
|
154
|
+
option list.
|
|
155
|
+
|
|
156
|
+
## Model
|
|
157
|
+
|
|
158
|
+
| Name | Type |
|
|
159
|
+
|------|------|
|
|
160
|
+
| `v-model` | `string` |
|
|
161
|
+
|
|
162
|
+
## Props
|
|
163
|
+
|
|
164
|
+
| Prop | Type | Required | Default |
|
|
165
|
+
|------|------|----------|---------|
|
|
166
|
+
| `label` | `string` | No | — |
|
|
167
|
+
| `hideLabel` | `boolean` | No | — |
|
|
168
|
+
| `ariaLabel` | `string` | No | — |
|
|
169
|
+
| `hint` | `string` | No | — |
|
|
170
|
+
| `options` | `SelectOption[]` | Yes | — |
|
|
171
|
+
| `placeholder` | `string` | No | — |
|
|
172
|
+
| `autocomplete` | `boolean` | No | — |
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
### SelectOption
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
interface SelectOption {
|
|
179
|
+
value: string;
|
|
180
|
+
label: string;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# SidebarLayout
|
|
2
|
+
|
|
3
|
+
A responsive two-panel layout with a collapsible sidebar and main content area. On mobile, the sidebar becomes an overlay.
|
|
4
|
+
|
|
5
|
+
When the sidebar is collapsed it is marked [`inert`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert), so its contents (including the collapse button) are removed from the tab order and the accessibility tree while visually hidden. The expand button is likewise `inert` while the sidebar is open. This keeps keyboard and screen-reader focus on whichever control is actually visible.
|
|
6
|
+
|
|
7
|
+
## Demo
|
|
8
|
+
|
|
9
|
+
<a href="/cfa-simulator/docs/demos/sidebar-layout/index.html" target="_blank">Open in full window ↗</a>
|
|
10
|
+
|
|
11
|
+
<div style="border: 1px solid var(--vp-c-border); border-radius: 8px; overflow: hidden; height: 500px;">
|
|
12
|
+
<iframe src="/cfa-simulator/docs/demos/sidebar-layout/index.html" style="width: 100%; height: 100%; border: none;" />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
## Tabs Demo (Router Mode)
|
|
16
|
+
|
|
17
|
+
<a href="/cfa-simulator/docs/demos/sidebar-tabs/index.html" target="_blank">Open in full window ↗</a>
|
|
18
|
+
|
|
19
|
+
<div style="border: 1px solid var(--vp-c-border); border-radius: 8px; overflow: hidden; height: 500px;">
|
|
20
|
+
<iframe src="/cfa-simulator/docs/demos/sidebar-tabs/index.html" style="width: 100%; height: 100%; border: none;" />
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```vue
|
|
26
|
+
<SidebarLayout>
|
|
27
|
+
<template #sidebar>
|
|
28
|
+
<h2>Controls</h2>
|
|
29
|
+
<NumberInput v-model="value" label="Parameter" slider live />
|
|
30
|
+
</template>
|
|
31
|
+
<h1>Main Content</h1>
|
|
32
|
+
<p>Your charts and data go here.</p>
|
|
33
|
+
</SidebarLayout>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Slots
|
|
37
|
+
|
|
38
|
+
| Slot | Description |
|
|
39
|
+
| --------- | ------------------------------------------ |
|
|
40
|
+
| `sidebar` | Content rendered in the left sidebar panel |
|
|
41
|
+
| `default` | Main content area |
|
|
42
|
+
|
|
43
|
+
## Props
|
|
44
|
+
|
|
45
|
+
| Prop | Type | Default | Description |
|
|
46
|
+
| ------------- | --------- | ----------- | ---------------------------------------------------- |
|
|
47
|
+
| `hideTopbar` | `boolean` | `false` | Hides the topbar that contains the light/dark toggle |
|
|
48
|
+
| `tabs` | `Tab[]` | `undefined` | Array of tab definitions to render in the main area |
|
|
49
|
+
| `v-model:tab` | `string` | `undefined` | The active tab value (two-way binding) |
|
|
50
|
+
|
|
51
|
+
### Tab type
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
interface Tab {
|
|
55
|
+
value: string; // unique identifier
|
|
56
|
+
label: string; // display text
|
|
57
|
+
to?: string; // optional route path for vue-router integration
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Tabs
|
|
62
|
+
|
|
63
|
+
When the `tabs` prop is provided, a tab bar renders at the top of the main content area. Tabs support two modes:
|
|
64
|
+
|
|
65
|
+
### Local mode
|
|
66
|
+
|
|
67
|
+
Use `v-model:tab` to control which tab is active. Render content conditionally in the default slot.
|
|
68
|
+
|
|
69
|
+
```vue
|
|
70
|
+
<script setup>
|
|
71
|
+
import { ref } from "vue";
|
|
72
|
+
const activeTab = ref("chart");
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<SidebarLayout
|
|
76
|
+
v-model:tab="activeTab"
|
|
77
|
+
:tabs="[
|
|
78
|
+
{ value: 'chart', label: 'Chart' },
|
|
79
|
+
{ value: 'data', label: 'Data' },
|
|
80
|
+
]"
|
|
81
|
+
>
|
|
82
|
+
<template #sidebar>
|
|
83
|
+
<h2>Controls</h2>
|
|
84
|
+
</template>
|
|
85
|
+
<div v-if="activeTab === 'chart'">Chart content</div>
|
|
86
|
+
<div v-if="activeTab === 'data'">Data table</div>
|
|
87
|
+
</SidebarLayout>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Router mode
|
|
91
|
+
|
|
92
|
+
When tabs include a `to` property and vue-router is installed, clicking a tab navigates to that route. The active tab is automatically determined from the current route.
|
|
93
|
+
|
|
94
|
+
```vue
|
|
95
|
+
<SidebarLayout
|
|
96
|
+
:tabs="[
|
|
97
|
+
{ value: 'chart', label: 'Chart', to: '/model/chart' },
|
|
98
|
+
{ value: 'data', label: 'Data', to: '/model/data' },
|
|
99
|
+
]"
|
|
100
|
+
>
|
|
101
|
+
<template #sidebar>
|
|
102
|
+
<h2>Controls</h2>
|
|
103
|
+
</template>
|
|
104
|
+
<RouterView />
|
|
105
|
+
</SidebarLayout>
|
|
106
|
+
```
|
package/docs/Spinner.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Spinner
|
|
2
|
+
|
|
3
|
+
A loading indicator with accessible labeling.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### Sizes
|
|
8
|
+
|
|
9
|
+
<ComponentDemo>
|
|
10
|
+
<Spinner size="sm" label="Loading" />
|
|
11
|
+
<Spinner size="md" label="Loading" />
|
|
12
|
+
<Spinner size="lg" label="Loading" />
|
|
13
|
+
|
|
14
|
+
<template #code>
|
|
15
|
+
|
|
16
|
+
```vue
|
|
17
|
+
<Spinner size="sm" label="Loading" />
|
|
18
|
+
<Spinner size="md" label="Loading" />
|
|
19
|
+
<Spinner size="lg" label="Loading" />
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
</template>
|
|
23
|
+
</ComponentDemo>
|
|
24
|
+
|
|
25
|
+
### In context
|
|
26
|
+
|
|
27
|
+
<ComponentDemo>
|
|
28
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
29
|
+
<Spinner size="sm" label="Running model" />
|
|
30
|
+
<span>Running model...</span>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<template #code>
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
37
|
+
<Spinner size="sm" label="Running model" />
|
|
38
|
+
<span>Running model...</span>
|
|
39
|
+
</div>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
</template>
|
|
43
|
+
</ComponentDemo>
|
|
44
|
+
|
|
45
|
+
## Props
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Required | Default |
|
|
48
|
+
|------|------|----------|---------|
|
|
49
|
+
| `size` | `SpinnerSize` | No | `"sm"` |
|
|
50
|
+
| `label` | `string` | No | — |
|
|
51
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# TextInput
|
|
2
|
+
|
|
3
|
+
A text input field with optional label and hint.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
<script setup>
|
|
8
|
+
import { ref } from 'vue'
|
|
9
|
+
const name = ref('')
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<ComponentDemo>
|
|
13
|
+
<div style="width: 300px">
|
|
14
|
+
<TextInput
|
|
15
|
+
v-model="name"
|
|
16
|
+
label="Model name"
|
|
17
|
+
placeholder="e.g. my-model"
|
|
18
|
+
hint="A short identifier used in URLs"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<template #code>
|
|
23
|
+
|
|
24
|
+
```vue
|
|
25
|
+
<script setup>
|
|
26
|
+
import { ref } from "vue";
|
|
27
|
+
const name = ref("");
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<TextInput
|
|
31
|
+
v-model="name"
|
|
32
|
+
label="Model name"
|
|
33
|
+
placeholder="e.g. my-model"
|
|
34
|
+
hint="A short identifier used in URLs"
|
|
35
|
+
/>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
</template>
|
|
39
|
+
</ComponentDemo>
|
|
40
|
+
|
|
41
|
+
### Hidden label
|
|
42
|
+
|
|
43
|
+
Use `hide-label` to visually hide the label while keeping it available to screen
|
|
44
|
+
readers. The label is still a real `<label>` in the DOM, so clicking the input
|
|
45
|
+
area still works and the control is properly named for assistive tech. Prefer
|
|
46
|
+
this over omitting the label whenever the input has no visible text describing
|
|
47
|
+
it.
|
|
48
|
+
|
|
49
|
+
<ComponentDemo>
|
|
50
|
+
<div style="width: 300px">
|
|
51
|
+
<TextInput
|
|
52
|
+
v-model="name"
|
|
53
|
+
label="Search"
|
|
54
|
+
placeholder="Search…"
|
|
55
|
+
hide-label
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<template #code>
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<TextInput v-model="name" label="Search" placeholder="Search…" hide-label />
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
</template>
|
|
66
|
+
</ComponentDemo>
|
|
67
|
+
|
|
68
|
+
## Model
|
|
69
|
+
|
|
70
|
+
| Name | Type |
|
|
71
|
+
|------|------|
|
|
72
|
+
| `v-model` | `string` |
|
|
73
|
+
|
|
74
|
+
## Props
|
|
75
|
+
|
|
76
|
+
| Prop | Type | Required | Default |
|
|
77
|
+
|------|------|----------|---------|
|
|
78
|
+
| `label` | `string` | No | — |
|
|
79
|
+
| `hideLabel` | `boolean` | No | — |
|
|
80
|
+
| `ariaLabel` | `string` | No | — |
|
|
81
|
+
| `hint` | `string` | No | — |
|
|
82
|
+
| `placeholder` | `string` | No | — |
|
|
83
|
+
|
package/docs/Toggle.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Toggle
|
|
2
|
+
|
|
3
|
+
A boolean switch built on reka-ui.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
<script setup>
|
|
8
|
+
import { ref } from 'vue'
|
|
9
|
+
const enabled = ref(false)
|
|
10
|
+
const disabled = ref(true)
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
### Basic
|
|
14
|
+
|
|
15
|
+
<ComponentDemo>
|
|
16
|
+
<Toggle v-model="enabled" label="Enable vaccination" />
|
|
17
|
+
|
|
18
|
+
<template #code>
|
|
19
|
+
|
|
20
|
+
```vue
|
|
21
|
+
<script setup>
|
|
22
|
+
import { ref } from "vue";
|
|
23
|
+
const enabled = ref(false);
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<Toggle v-model="enabled" label="Enable vaccination" />
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
</template>
|
|
30
|
+
</ComponentDemo>
|
|
31
|
+
|
|
32
|
+
### With hint
|
|
33
|
+
|
|
34
|
+
<ComponentDemo>
|
|
35
|
+
<Toggle
|
|
36
|
+
v-model="enabled"
|
|
37
|
+
label="Enable isolation"
|
|
38
|
+
hint="Whether symptomatic individuals are isolated"
|
|
39
|
+
/>
|
|
40
|
+
|
|
41
|
+
<template #code>
|
|
42
|
+
|
|
43
|
+
```vue
|
|
44
|
+
<Toggle
|
|
45
|
+
v-model="enabled"
|
|
46
|
+
label="Enable isolation"
|
|
47
|
+
hint="Whether symptomatic individuals are isolated"
|
|
48
|
+
/>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
</template>
|
|
52
|
+
</ComponentDemo>
|
|
53
|
+
|
|
54
|
+
### Disabled
|
|
55
|
+
|
|
56
|
+
<ComponentDemo>
|
|
57
|
+
<Toggle v-model="disabled" label="Locked setting" :disabled="true" />
|
|
58
|
+
|
|
59
|
+
<template #code>
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<Toggle v-model="value" label="Locked setting" :disabled="true" />
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
</template>
|
|
66
|
+
</ComponentDemo>
|
|
67
|
+
|
|
68
|
+
## Model
|
|
69
|
+
|
|
70
|
+
| Name | Type |
|
|
71
|
+
|------|------|
|
|
72
|
+
| `v-model` | `boolean` |
|
|
73
|
+
|
|
74
|
+
## Props
|
|
75
|
+
|
|
76
|
+
| Prop | Type | Required | Default |
|
|
77
|
+
|------|------|----------|---------|
|
|
78
|
+
| `label` | `string` | Yes | — |
|
|
79
|
+
| `hint` | `string` | No | — |
|
|
80
|
+
| `disabled` | `boolean` | No | — |
|
|
81
|
+
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# ToggleGroup
|
|
2
|
+
|
|
3
|
+
A segmented control that looks like a [`ButtonGroup`](./button-group) but tracks
|
|
4
|
+
which item(s) are pressed. By default it is single-select (like a radio group);
|
|
5
|
+
add `multiple` to let several items be pressed at once. Built on
|
|
6
|
+
[reka-ui's ToggleGroup](https://reka-ui.com/docs/components/toggle-group).
|
|
7
|
+
|
|
8
|
+
## Examples
|
|
9
|
+
|
|
10
|
+
### Single select
|
|
11
|
+
|
|
12
|
+
`v-model` holds the pressed value (a `string`). Clicking the active item again
|
|
13
|
+
clears the selection.
|
|
14
|
+
|
|
15
|
+
<script setup>
|
|
16
|
+
import { ref } from 'vue'
|
|
17
|
+
const interval = ref('weekly')
|
|
18
|
+
const days = ref(['mon', 'wed'])
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<ComponentDemo>
|
|
22
|
+
<ToggleGroup
|
|
23
|
+
v-model="interval"
|
|
24
|
+
label="Interval"
|
|
25
|
+
:options="[
|
|
26
|
+
{ value: 'daily', label: 'Daily' },
|
|
27
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
28
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
29
|
+
]"
|
|
30
|
+
/>
|
|
31
|
+
<p>Selected: {{ interval }}</p>
|
|
32
|
+
|
|
33
|
+
<template #code>
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<script setup>
|
|
37
|
+
import { ref } from "vue";
|
|
38
|
+
const interval = ref("weekly");
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<ToggleGroup
|
|
42
|
+
v-model="interval"
|
|
43
|
+
label="Interval"
|
|
44
|
+
:options="[
|
|
45
|
+
{ value: 'daily', label: 'Daily' },
|
|
46
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
47
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
48
|
+
]"
|
|
49
|
+
/>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
</template>
|
|
53
|
+
</ComponentDemo>
|
|
54
|
+
|
|
55
|
+
### Multiple select
|
|
56
|
+
|
|
57
|
+
With `multiple`, `v-model` is a `string[]` and any number of items can be
|
|
58
|
+
pressed at once.
|
|
59
|
+
|
|
60
|
+
<ComponentDemo>
|
|
61
|
+
<ToggleGroup
|
|
62
|
+
v-model="days"
|
|
63
|
+
multiple
|
|
64
|
+
label="Active days"
|
|
65
|
+
:options="[
|
|
66
|
+
{ value: 'mon', label: 'Mon' },
|
|
67
|
+
{ value: 'tue', label: 'Tue' },
|
|
68
|
+
{ value: 'wed', label: 'Wed' },
|
|
69
|
+
{ value: 'thu', label: 'Thu' },
|
|
70
|
+
{ value: 'fri', label: 'Fri' },
|
|
71
|
+
]"
|
|
72
|
+
/>
|
|
73
|
+
<p>Selected: {{ days.join(', ') || 'none' }}</p>
|
|
74
|
+
|
|
75
|
+
<template #code>
|
|
76
|
+
|
|
77
|
+
```vue
|
|
78
|
+
<script setup>
|
|
79
|
+
import { ref } from "vue";
|
|
80
|
+
const days = ref(["mon", "wed"]);
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<ToggleGroup
|
|
84
|
+
v-model="days"
|
|
85
|
+
multiple
|
|
86
|
+
label="Active days"
|
|
87
|
+
:options="[
|
|
88
|
+
{ value: 'mon', label: 'Mon' },
|
|
89
|
+
{ value: 'tue', label: 'Tue' },
|
|
90
|
+
{ value: 'wed', label: 'Wed' },
|
|
91
|
+
{ value: 'thu', label: 'Thu' },
|
|
92
|
+
{ value: 'fri', label: 'Fri' },
|
|
93
|
+
]"
|
|
94
|
+
/>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
</template>
|
|
98
|
+
</ComponentDemo>
|
|
99
|
+
|
|
100
|
+
### Vertical and disabled options
|
|
101
|
+
|
|
102
|
+
Set `orientation="vertical"` to stack the items, and mark individual options
|
|
103
|
+
`disabled`.
|
|
104
|
+
|
|
105
|
+
<ComponentDemo>
|
|
106
|
+
<ToggleGroup
|
|
107
|
+
model-value="map"
|
|
108
|
+
orientation="vertical"
|
|
109
|
+
aria-label="View"
|
|
110
|
+
:options="[
|
|
111
|
+
{ value: 'map', label: 'Map' },
|
|
112
|
+
{ value: 'chart', label: 'Chart' },
|
|
113
|
+
{ value: 'table', label: 'Table', disabled: true },
|
|
114
|
+
]"
|
|
115
|
+
/>
|
|
116
|
+
|
|
117
|
+
<template #code>
|
|
118
|
+
|
|
119
|
+
```vue
|
|
120
|
+
<ToggleGroup
|
|
121
|
+
v-model="view"
|
|
122
|
+
orientation="vertical"
|
|
123
|
+
aria-label="View"
|
|
124
|
+
:options="[
|
|
125
|
+
{ value: 'map', label: 'Map' },
|
|
126
|
+
{ value: 'chart', label: 'Chart' },
|
|
127
|
+
{ value: 'table', label: 'Table', disabled: true },
|
|
128
|
+
]"
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
</template>
|
|
133
|
+
</ComponentDemo>
|
|
134
|
+
|
|
135
|
+
## Model
|
|
136
|
+
|
|
137
|
+
| Name | Type |
|
|
138
|
+
|------|------|
|
|
139
|
+
| `v-model` | `string \| string[]` |
|
|
140
|
+
|
|
141
|
+
## Props
|
|
142
|
+
|
|
143
|
+
| Prop | Type | Required | Default |
|
|
144
|
+
|------|------|----------|---------|
|
|
145
|
+
| `label` | `string` | No | — |
|
|
146
|
+
| `hideLabel` | `boolean` | No | — |
|
|
147
|
+
| `ariaLabel` | `string` | No | — |
|
|
148
|
+
| `hint` | `string` | No | — |
|
|
149
|
+
| `options` | `ToggleGroupOption[]` | Yes | — |
|
|
150
|
+
| `multiple` | `boolean` | No | — |
|
|
151
|
+
| `disabled` | `boolean` | No | — |
|
|
152
|
+
| `orientation` | `"horizontal" \| "vertical"` | No | `"horizontal"` |
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
### ToggleGroupOption
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
interface ToggleGroupOption {
|
|
159
|
+
value: string;
|
|
160
|
+
label: string;
|
|
161
|
+
disabled?: boolean;
|
|
162
|
+
}
|
|
163
|
+
```
|