@umbra.ui/core 0.1.17 → 0.1.19
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/components/controls/Button/Button.vue +417 -0
- package/dist/components/controls/Button/README.md +348 -0
- package/dist/components/controls/Button/theme.css +200 -0
- package/dist/components/controls/Checkbox/Checkbox.vue +164 -0
- package/dist/components/controls/Checkbox/README.md +441 -0
- package/dist/components/controls/Checkbox/theme.css +36 -0
- package/dist/components/controls/Dropdown/Dropdown.vue +476 -0
- package/dist/components/controls/Dropdown/README.md +370 -0
- package/dist/components/controls/Dropdown/theme.css +50 -0
- package/dist/components/controls/Dropdown/types.ts +6 -0
- package/dist/components/controls/IconButton/IconButton.vue +267 -0
- package/dist/components/controls/IconButton/README.md +502 -0
- package/dist/components/controls/IconButton/theme.css +89 -0
- package/dist/components/controls/Radio/README.md +591 -0
- package/dist/components/controls/Radio/Radio.vue +89 -0
- package/dist/components/controls/Radio/theme.css +14 -0
- package/dist/components/controls/RangeSlider/README.md +608 -0
- package/dist/components/controls/RangeSlider/RangeSlider.vue +535 -0
- package/dist/components/controls/RangeSlider/theme.css +80 -0
- package/dist/components/controls/SegmentedControl/README.md +587 -0
- package/dist/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
- package/dist/components/controls/SegmentedControl/theme.css +60 -0
- package/dist/components/controls/SegmentedControl/types.ts +5 -0
- package/dist/components/controls/Slider/README.md +627 -0
- package/dist/components/controls/Slider/Slider.vue +260 -0
- package/dist/components/controls/Slider/theme.css +74 -0
- package/dist/components/controls/Stepper/README.md +601 -0
- package/dist/components/controls/Stepper/Stepper.vue +103 -0
- package/dist/components/controls/Stepper/theme.css +53 -0
- package/dist/components/controls/Switch/README.md +667 -0
- package/dist/components/controls/Switch/Switch.vue +127 -0
- package/dist/components/controls/Switch/theme.css +42 -0
- package/dist/components/dialogs/Alert/Alert.vue +218 -0
- package/dist/components/dialogs/Alert/README.md +450 -0
- package/dist/components/dialogs/Alert/theme.css +44 -0
- package/dist/components/dialogs/Alert/types.ts +11 -0
- package/dist/components/dialogs/Toast/README.md +522 -0
- package/dist/components/dialogs/Toast/Toast.vue +296 -0
- package/dist/components/dialogs/Toast/ToastContainer.vue +330 -0
- package/dist/components/dialogs/Toast/theme.css +44 -0
- package/dist/components/dialogs/Toast/types.ts +46 -0
- package/dist/components/dialogs/Toast/useToast.ts +127 -0
- package/dist/components/indicators/ProgressBar/ProgressBar.vue +98 -0
- package/dist/components/indicators/ProgressBar/README.md +744 -0
- package/dist/components/indicators/ProgressBar/theme.css +36 -0
- package/dist/components/indicators/Tooltip/README.md +723 -0
- package/dist/components/indicators/Tooltip/TooltipProvider.vue +142 -0
- package/dist/components/indicators/Tooltip/theme.css +18 -0
- package/dist/components/indicators/Tooltip/tooltip.ts +48 -0
- package/dist/components/indicators/Tooltip/types.ts +15 -0
- package/dist/components/indicators/Tooltip/useTooltip.ts +71 -0
- package/dist/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
- package/dist/components/inputs/AutogrowTextView/README.md +643 -0
- package/dist/components/inputs/AutogrowTextView/theme.css +28 -0
- package/dist/components/inputs/InputCard/InputCard.vue +600 -0
- package/dist/components/inputs/InputCard/README.md +636 -0
- package/dist/components/inputs/InputEmail/InputEmail.vue +698 -0
- package/dist/components/inputs/InputEmail/README.md +764 -0
- package/dist/components/inputs/InputNumber/InputNumber.vue +300 -0
- package/dist/components/inputs/InputNumber/README.md +749 -0
- package/dist/components/inputs/InputPhone/InputPhone.vue +645 -0
- package/dist/components/inputs/InputPhone/README.md +636 -0
- package/dist/components/inputs/InputSecure/InputSecure.vue +646 -0
- package/dist/components/inputs/InputSecure/README.md +771 -0
- package/dist/components/inputs/InputText/InputText.vue +225 -0
- package/dist/components/inputs/InputText/README.md +844 -0
- package/dist/components/inputs/OTP/OTP.vue +349 -0
- package/dist/components/inputs/OTP/README.md +736 -0
- package/dist/components/inputs/OTP/theme.css +50 -0
- package/dist/components/inputs/StringCapture/README.md +718 -0
- package/dist/components/inputs/StringCapture/StringCapture.vue +315 -0
- package/dist/components/inputs/StringCapture/theme.css +86 -0
- package/dist/components/inputs/Tags/README.md +897 -0
- package/dist/components/inputs/Tags/TagBar.vue +793 -0
- package/dist/components/inputs/Tags/TagCreation.vue +219 -0
- package/dist/components/inputs/Tags/TagPicker.vue +380 -0
- package/dist/components/inputs/Tags/tag-bar-styles.ts +354 -0
- package/dist/components/inputs/Tags/theme.css +121 -0
- package/dist/components/inputs/Tags/types.ts +346 -0
- package/dist/components/inputs/search/README.md +759 -0
- package/dist/components/inputs/search/SearchBar.vue +394 -0
- package/dist/components/inputs/search/SearchResults.vue +310 -0
- package/dist/components/inputs/search/theme.css +187 -0
- package/dist/components/inputs/search/types.ts +8 -0
- package/dist/components/inputs/theme.css +102 -0
- package/dist/components/menus/ActionMenu/ActionMenu.vue +383 -0
- package/dist/components/menus/ActionMenu/README.md +825 -0
- package/dist/components/menus/ActionMenu/theme.css +93 -0
- package/dist/components/models/Popover/Popover.vue +551 -0
- package/dist/components/models/Popover/README.md +885 -0
- package/dist/components/models/Popover/theme.css +52 -0
- package/dist/components/models/Sheet/README.md +1159 -0
- package/dist/components/models/Sheet/Sheet.vue +465 -0
- package/dist/components/models/Sheet/theme.css +72 -0
- package/dist/components/models/Sidebar/README.md +1228 -0
- package/dist/components/models/Sidebar/Sidebar.vue +480 -0
- package/dist/components/models/Sidebar/theme.css +90 -0
- package/dist/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
- package/dist/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
- package/dist/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
- package/dist/components/navigation/adaptive/README.md +768 -0
- package/dist/components/navigation/adaptive/types.ts +19 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
- package/dist/components/navigation/adaptive/useBreakpoints.ts +41 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.ts +214 -0
- package/dist/components/navigation/adaptive/useViewAnimation.ts +721 -0
- package/dist/components/navigation/adaptive/useViewResize.ts +211 -0
- package/dist/components/navigation/navstack/NavigationStack.vue +180 -0
- package/dist/components/navigation/navstack/README.md +994 -0
- package/dist/components/navigation/navstack/useNavigationStack.ts +164 -0
- package/dist/components/navigation/slideover/README.md +1275 -0
- package/dist/components/navigation/slideover/SlideoverController.vue +287 -0
- package/dist/components/navigation/slideover/useSlideoverController.ts +320 -0
- package/dist/components/navigation/splitview/README.md +1115 -0
- package/dist/components/navigation/splitview/SplitViewController.vue +176 -0
- package/dist/components/navigation/splitview/useSplitViewController.ts +388 -0
- package/dist/components/navigation/tabcontroller/README.md +919 -0
- package/dist/components/navigation/tabcontroller/TabController.vue +307 -0
- package/dist/components/navigation/tabcontroller/TabItem.vue +57 -0
- package/dist/components/navigation/tabcontroller/types.ts +24 -0
- package/dist/components/navigation/tabcontroller/useTabController.ts +18 -0
- package/dist/components/navigation/theme.css +91 -0
- package/dist/components/navigation/types.ts +7 -0
- package/dist/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
- package/dist/components/pickers/CollectionPicker/README.md +1115 -0
- package/dist/components/pickers/CollectionPicker/theme.css +14 -0
- package/dist/components/pickers/CollectionPicker/types.ts +11 -0
- package/dist/components/pickers/ColorPicker/ColorPicker.vue +376 -0
- package/dist/components/pickers/ColorPicker/README.md +1439 -0
- package/dist/components/pickers/ColorPicker/colors.ts +299 -0
- package/dist/components/pickers/ColorPicker/theme.css +32 -0
- package/dist/components/pickers/DatePicker/DatePicker.vue +660 -0
- package/dist/components/pickers/DatePicker/README.md +1195 -0
- package/dist/components/pickers/DatePicker/theme.css +22 -0
- package/dist/components/pickers/FilePicker/FilePicker.vue +534 -0
- package/dist/components/pickers/FilePicker/README.md +1542 -0
- package/dist/components/pickers/FilePicker/theme.css +48 -0
- package/dist/components/pickers/FilePicker/types.ts +10 -0
- package/dist/components/pickers/IconPicker/IconPicker.vue +327 -0
- package/dist/components/pickers/IconPicker/README.md +1161 -0
- package/dist/components/pickers/IconPicker/theme.css +28 -0
- package/dist/components/pickers/theme.css +82 -0
- package/dist/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
- package/dist/components/views/MarkdownViewer/README.md +833 -0
- package/dist/components/views/MarkdownViewer/theme.css +130 -0
- package/package.json +4 -3
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* Light theme using Colors */
|
|
2
|
+
:root {
|
|
3
|
+
/* Stepper container colors */
|
|
4
|
+
--stepper-container-bg: white;
|
|
5
|
+
--stepper-container-border: 1px solid #D9D9D9;
|
|
6
|
+
--stepper-container-shadow-dark: none; /* blackA4 - lighter shadow for light mode */
|
|
7
|
+
--stepper-container-shadow-light: none
|
|
8
|
+
|
|
9
|
+
/* Stepper value colors */
|
|
10
|
+
--stepper-value-color: #1a1d23; /* gray12 - dark text for light mode */
|
|
11
|
+
|
|
12
|
+
/* Stepper icon colors */
|
|
13
|
+
--stepper-icon-opacity: 0.6; /* slightly more visible in light mode */
|
|
14
|
+
--stepper-icon-hover-opacity: 1;
|
|
15
|
+
|
|
16
|
+
/* Stepper value border colors */
|
|
17
|
+
--stepper-value-border: #D9D9D9; /* gray5 - light background for light mode */
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Dark theme */
|
|
21
|
+
.dark,
|
|
22
|
+
.dark-theme {
|
|
23
|
+
/* Stepper container colors */
|
|
24
|
+
--stepper-container-bg: #484848; /* Original dark mode value */
|
|
25
|
+
--stepper-container-border: none;
|
|
26
|
+
--stepper-container-shadow-dark: rgba(
|
|
27
|
+
0,
|
|
28
|
+
0,
|
|
29
|
+
0,
|
|
30
|
+
0.21
|
|
31
|
+
); /* Original dark mode value */
|
|
32
|
+
--stepper-container-shadow-light: rgba(
|
|
33
|
+
255,
|
|
34
|
+
255,
|
|
35
|
+
255,
|
|
36
|
+
0.1
|
|
37
|
+
); /* Original dark mode value */
|
|
38
|
+
|
|
39
|
+
/* Stepper value colors */
|
|
40
|
+
--stepper-value-color: #eeeeee; /* Original dark mode value */
|
|
41
|
+
|
|
42
|
+
/* Stepper icon colors */
|
|
43
|
+
--stepper-icon-opacity: 0.5; /* Original dark mode value */
|
|
44
|
+
--stepper-icon-hover-opacity: 1;
|
|
45
|
+
|
|
46
|
+
/* Stepper value border colors */
|
|
47
|
+
--stepper-value-border: rgba(
|
|
48
|
+
255,
|
|
49
|
+
255,
|
|
50
|
+
255,
|
|
51
|
+
0.07
|
|
52
|
+
); /* Original dark mode value */
|
|
53
|
+
}
|
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
A toggle switch component built with Vue 3 Composition API and TypeScript. The Switch component provides an intuitive interface for boolean state management with customizable appearance, size, and color schemes.
|
|
4
|
+
|
|
5
|
+
## Installation/Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Switch } from "@umbra-ui/core";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Dependencies:**
|
|
12
|
+
|
|
13
|
+
- Vue 3.x
|
|
14
|
+
|
|
15
|
+
## Basic Usage
|
|
16
|
+
|
|
17
|
+
```vue
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { ref } from "vue";
|
|
20
|
+
import { Switch } from "@umbra-ui/core";
|
|
21
|
+
|
|
22
|
+
const isEnabled = ref(false);
|
|
23
|
+
|
|
24
|
+
const handleToggle = (checked: boolean) => {
|
|
25
|
+
console.log("Switch toggled:", checked);
|
|
26
|
+
isEnabled.value = checked;
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<Switch :isChecked="isEnabled" @update:isChecked="handleToggle" />
|
|
32
|
+
</template>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Props
|
|
36
|
+
|
|
37
|
+
| Prop Name | Type | Required | Default | Description |
|
|
38
|
+
| ------------ | ------------------------ | -------- | ------------------------------- | ---------------------------------------- |
|
|
39
|
+
| `switchType` | `"default" \| "outline"` | No | `"default"` | Visual style variant of the switch |
|
|
40
|
+
| `isChecked` | `boolean` | No | `false` | Current checked state of the switch |
|
|
41
|
+
| `size` | `number` | No | `24` | Size of the switch in pixels |
|
|
42
|
+
| `color` | `string` | No | `"var(--switch-default-color)"` | Custom color for the switch when checked |
|
|
43
|
+
|
|
44
|
+
## Events
|
|
45
|
+
|
|
46
|
+
| Event Name | Payload Type | Description |
|
|
47
|
+
| ------------------ | ------------ | ----------------------------------------------------------------- |
|
|
48
|
+
| `update:isChecked` | `boolean` | Emitted when the switch is toggled, returns the new checked state |
|
|
49
|
+
|
|
50
|
+
## Slots
|
|
51
|
+
|
|
52
|
+
This component does not use slots.
|
|
53
|
+
|
|
54
|
+
## Exposed Methods/Refs
|
|
55
|
+
|
|
56
|
+
This component does not expose any methods or refs.
|
|
57
|
+
|
|
58
|
+
## CSS Customization
|
|
59
|
+
|
|
60
|
+
The Switch component uses CSS custom properties for easy theming and customization:
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
/* Switch default colors */
|
|
64
|
+
--switch-default-bg: #e3e5e8;
|
|
65
|
+
--switch-default-border: rgba(0, 0, 0, 0.04);
|
|
66
|
+
--switch-default-switch: #8b8d98;
|
|
67
|
+
--switch-default-switch-checked: #ffffff;
|
|
68
|
+
|
|
69
|
+
/* Switch outline colors */
|
|
70
|
+
--switch-outline-border: #9b9ea6;
|
|
71
|
+
--switch-outline-switch: #8b8d98;
|
|
72
|
+
|
|
73
|
+
/* Switch default color scheme */
|
|
74
|
+
--switch-default-color: #0090ff;
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
### Different Switch Types
|
|
80
|
+
|
|
81
|
+
```vue
|
|
82
|
+
<script setup lang="ts">
|
|
83
|
+
import { ref } from "vue";
|
|
84
|
+
import { Switch } from "@umbra-ui/core";
|
|
85
|
+
|
|
86
|
+
const defaultSwitch = ref(false);
|
|
87
|
+
const outlineSwitch = ref(true);
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
<template>
|
|
91
|
+
<div class="switch-examples">
|
|
92
|
+
<div class="switch-group">
|
|
93
|
+
<label>Default Switch</label>
|
|
94
|
+
<Switch
|
|
95
|
+
switchType="default"
|
|
96
|
+
:isChecked="defaultSwitch"
|
|
97
|
+
@update:isChecked="defaultSwitch = $event"
|
|
98
|
+
/>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div class="switch-group">
|
|
102
|
+
<label>Outline Switch</label>
|
|
103
|
+
<Switch
|
|
104
|
+
switchType="outline"
|
|
105
|
+
:isChecked="outlineSwitch"
|
|
106
|
+
@update:isChecked="outlineSwitch = $event"
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
|
+
<style module>
|
|
113
|
+
.switch-examples {
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
gap: 1rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.switch-group {
|
|
120
|
+
display: flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: 0.5rem;
|
|
123
|
+
}
|
|
124
|
+
</style>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Different Sizes
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
import { ref } from "vue";
|
|
132
|
+
import { Switch } from "@umbra-ui/core";
|
|
133
|
+
|
|
134
|
+
const smallSwitch = ref(false);
|
|
135
|
+
const mediumSwitch = ref(true);
|
|
136
|
+
const largeSwitch = ref(false);
|
|
137
|
+
</script>
|
|
138
|
+
|
|
139
|
+
<template>
|
|
140
|
+
<div class="size-examples">
|
|
141
|
+
<div class="size-group">
|
|
142
|
+
<label>Small (16px)</label>
|
|
143
|
+
<Switch
|
|
144
|
+
:size="16"
|
|
145
|
+
:isChecked="smallSwitch"
|
|
146
|
+
@update:isChecked="smallSwitch = $event"
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<div class="size-group">
|
|
151
|
+
<label>Medium (24px)</label>
|
|
152
|
+
<Switch
|
|
153
|
+
:size="24"
|
|
154
|
+
:isChecked="mediumSwitch"
|
|
155
|
+
@update:isChecked="mediumSwitch = $event"
|
|
156
|
+
/>
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
<div class="size-group">
|
|
160
|
+
<label>Large (32px)</label>
|
|
161
|
+
<Switch
|
|
162
|
+
:size="32"
|
|
163
|
+
:isChecked="largeSwitch"
|
|
164
|
+
@update:isChecked="largeSwitch = $event"
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
</template>
|
|
169
|
+
|
|
170
|
+
<style module>
|
|
171
|
+
.size-examples {
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
gap: 1rem;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.size-group {
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: 0.5rem;
|
|
181
|
+
}
|
|
182
|
+
</style>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Custom Colors
|
|
186
|
+
|
|
187
|
+
```vue
|
|
188
|
+
<script setup lang="ts">
|
|
189
|
+
import { ref } from "vue";
|
|
190
|
+
import { Switch } from "@umbra-ui/core";
|
|
191
|
+
|
|
192
|
+
const redSwitch = ref(false);
|
|
193
|
+
const greenSwitch = ref(true);
|
|
194
|
+
const purpleSwitch = ref(false);
|
|
195
|
+
</script>
|
|
196
|
+
|
|
197
|
+
<template>
|
|
198
|
+
<div class="color-examples">
|
|
199
|
+
<div class="color-group">
|
|
200
|
+
<label>Red Switch</label>
|
|
201
|
+
<Switch
|
|
202
|
+
color="#ff4444"
|
|
203
|
+
:isChecked="redSwitch"
|
|
204
|
+
@update:isChecked="redSwitch = $event"
|
|
205
|
+
/>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
<div class="color-group">
|
|
209
|
+
<label>Green Switch</label>
|
|
210
|
+
<Switch
|
|
211
|
+
color="#44ff44"
|
|
212
|
+
:isChecked="greenSwitch"
|
|
213
|
+
@update:isChecked="greenSwitch = $event"
|
|
214
|
+
/>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<div class="color-group">
|
|
218
|
+
<label>Purple Switch</label>
|
|
219
|
+
<Switch
|
|
220
|
+
color="#8844ff"
|
|
221
|
+
:isChecked="purpleSwitch"
|
|
222
|
+
@update:isChecked="purpleSwitch = $event"
|
|
223
|
+
/>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</template>
|
|
227
|
+
|
|
228
|
+
<style module>
|
|
229
|
+
.color-examples {
|
|
230
|
+
display: flex;
|
|
231
|
+
flex-direction: column;
|
|
232
|
+
gap: 1rem;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.color-group {
|
|
236
|
+
display: flex;
|
|
237
|
+
align-items: center;
|
|
238
|
+
gap: 0.5rem;
|
|
239
|
+
}
|
|
240
|
+
</style>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Form Integration
|
|
244
|
+
|
|
245
|
+
```vue
|
|
246
|
+
<script setup lang="ts">
|
|
247
|
+
import { ref } from "vue";
|
|
248
|
+
import { Switch } from "@umbra-ui/core";
|
|
249
|
+
|
|
250
|
+
interface FormData {
|
|
251
|
+
notifications: boolean;
|
|
252
|
+
darkMode: boolean;
|
|
253
|
+
autoSave: boolean;
|
|
254
|
+
analytics: boolean;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const formData = ref<FormData>({
|
|
258
|
+
notifications: true,
|
|
259
|
+
darkMode: false,
|
|
260
|
+
autoSave: true,
|
|
261
|
+
analytics: false,
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
const handleSwitchChange = (field: keyof FormData, value: boolean) => {
|
|
265
|
+
formData.value[field] = value;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const submitForm = () => {
|
|
269
|
+
console.log("Form submitted:", formData.value);
|
|
270
|
+
};
|
|
271
|
+
</script>
|
|
272
|
+
|
|
273
|
+
<template>
|
|
274
|
+
<form @submit.prevent="submitForm" class="settings-form">
|
|
275
|
+
<h2>Application Settings</h2>
|
|
276
|
+
|
|
277
|
+
<div class="form-group">
|
|
278
|
+
<label>Push Notifications</label>
|
|
279
|
+
<Switch
|
|
280
|
+
:isChecked="formData.notifications"
|
|
281
|
+
@update:isChecked="
|
|
282
|
+
(value) => handleSwitchChange('notifications', value)
|
|
283
|
+
"
|
|
284
|
+
/>
|
|
285
|
+
</div>
|
|
286
|
+
|
|
287
|
+
<div class="form-group">
|
|
288
|
+
<label>Dark Mode</label>
|
|
289
|
+
<Switch
|
|
290
|
+
:isChecked="formData.darkMode"
|
|
291
|
+
@update:isChecked="(value) => handleSwitchChange('darkMode', value)"
|
|
292
|
+
/>
|
|
293
|
+
</div>
|
|
294
|
+
|
|
295
|
+
<div class="form-group">
|
|
296
|
+
<label>Auto Save</label>
|
|
297
|
+
<Switch
|
|
298
|
+
:isChecked="formData.autoSave"
|
|
299
|
+
@update:isChecked="(value) => handleSwitchChange('autoSave', value)"
|
|
300
|
+
/>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div class="form-group">
|
|
304
|
+
<label>Analytics Tracking</label>
|
|
305
|
+
<Switch
|
|
306
|
+
:isChecked="formData.analytics"
|
|
307
|
+
@update:isChecked="(value) => handleSwitchChange('analytics', value)"
|
|
308
|
+
/>
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
<button type="submit">Save Settings</button>
|
|
312
|
+
</form>
|
|
313
|
+
</template>
|
|
314
|
+
|
|
315
|
+
<style module>
|
|
316
|
+
.settings-form {
|
|
317
|
+
max-width: 400px;
|
|
318
|
+
padding: 1.5rem;
|
|
319
|
+
border: 1px solid #e0e0e0;
|
|
320
|
+
border-radius: 8px;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.form-group {
|
|
324
|
+
display: flex;
|
|
325
|
+
justify-content: space-between;
|
|
326
|
+
align-items: center;
|
|
327
|
+
margin-bottom: 1rem;
|
|
328
|
+
padding: 0.5rem 0;
|
|
329
|
+
border-bottom: 1px solid #f0f0f0;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.form-group:last-of-type {
|
|
333
|
+
border-bottom: none;
|
|
334
|
+
margin-bottom: 1.5rem;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
label {
|
|
338
|
+
font-weight: 500;
|
|
339
|
+
color: #333;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
button {
|
|
343
|
+
width: 100%;
|
|
344
|
+
padding: 0.75rem;
|
|
345
|
+
background-color: #007bff;
|
|
346
|
+
color: white;
|
|
347
|
+
border: none;
|
|
348
|
+
border-radius: 4px;
|
|
349
|
+
cursor: pointer;
|
|
350
|
+
font-size: 1rem;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
button:hover {
|
|
354
|
+
background-color: #0056b3;
|
|
355
|
+
}
|
|
356
|
+
</style>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Settings Panel
|
|
360
|
+
|
|
361
|
+
```vue
|
|
362
|
+
<script setup lang="ts">
|
|
363
|
+
import { ref } from "vue";
|
|
364
|
+
import { Switch } from "@umbra-ui/core";
|
|
365
|
+
|
|
366
|
+
const settings = ref({
|
|
367
|
+
wifi: true,
|
|
368
|
+
bluetooth: false,
|
|
369
|
+
location: true,
|
|
370
|
+
camera: false,
|
|
371
|
+
microphone: true,
|
|
372
|
+
storage: false,
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const toggleSetting = (key: keyof typeof settings.value) => {
|
|
376
|
+
settings.value[key] = !settings.value[key];
|
|
377
|
+
};
|
|
378
|
+
</script>
|
|
379
|
+
|
|
380
|
+
<template>
|
|
381
|
+
<div class="settings-panel">
|
|
382
|
+
<h2>Device Settings</h2>
|
|
383
|
+
|
|
384
|
+
<div class="setting-item">
|
|
385
|
+
<div class="setting-info">
|
|
386
|
+
<h3>Wi-Fi</h3>
|
|
387
|
+
<p>Connect to wireless networks</p>
|
|
388
|
+
</div>
|
|
389
|
+
<Switch
|
|
390
|
+
:isChecked="settings.wifi"
|
|
391
|
+
@update:isChecked="settings.wifi = $event"
|
|
392
|
+
/>
|
|
393
|
+
</div>
|
|
394
|
+
|
|
395
|
+
<div class="setting-item">
|
|
396
|
+
<div class="setting-info">
|
|
397
|
+
<h3>Bluetooth</h3>
|
|
398
|
+
<p>Connect to Bluetooth devices</p>
|
|
399
|
+
</div>
|
|
400
|
+
<Switch
|
|
401
|
+
:isChecked="settings.bluetooth"
|
|
402
|
+
@update:isChecked="settings.bluetooth = $event"
|
|
403
|
+
/>
|
|
404
|
+
</div>
|
|
405
|
+
|
|
406
|
+
<div class="setting-item">
|
|
407
|
+
<div class="setting-info">
|
|
408
|
+
<h3>Location Services</h3>
|
|
409
|
+
<p>Allow apps to access your location</p>
|
|
410
|
+
</div>
|
|
411
|
+
<Switch
|
|
412
|
+
:isChecked="settings.location"
|
|
413
|
+
@update:isChecked="settings.location = $event"
|
|
414
|
+
/>
|
|
415
|
+
</div>
|
|
416
|
+
|
|
417
|
+
<div class="setting-item">
|
|
418
|
+
<div class="setting-info">
|
|
419
|
+
<h3>Camera Access</h3>
|
|
420
|
+
<p>Allow apps to use your camera</p>
|
|
421
|
+
</div>
|
|
422
|
+
<Switch
|
|
423
|
+
:isChecked="settings.camera"
|
|
424
|
+
@update:isChecked="settings.camera = $event"
|
|
425
|
+
/>
|
|
426
|
+
</div>
|
|
427
|
+
|
|
428
|
+
<div class="setting-item">
|
|
429
|
+
<div class="setting-info">
|
|
430
|
+
<h3>Microphone Access</h3>
|
|
431
|
+
<p>Allow apps to use your microphone</p>
|
|
432
|
+
</div>
|
|
433
|
+
<Switch
|
|
434
|
+
:isChecked="settings.microphone"
|
|
435
|
+
@update:isChecked="settings.microphone = $event"
|
|
436
|
+
/>
|
|
437
|
+
</div>
|
|
438
|
+
|
|
439
|
+
<div class="setting-item">
|
|
440
|
+
<div class="setting-info">
|
|
441
|
+
<h3>Cloud Storage</h3>
|
|
442
|
+
<p>Sync data to cloud storage</p>
|
|
443
|
+
</div>
|
|
444
|
+
<Switch
|
|
445
|
+
:isChecked="settings.storage"
|
|
446
|
+
@update:isChecked="settings.storage = $event"
|
|
447
|
+
/>
|
|
448
|
+
</div>
|
|
449
|
+
</div>
|
|
450
|
+
</template>
|
|
451
|
+
|
|
452
|
+
<style module>
|
|
453
|
+
.settings-panel {
|
|
454
|
+
max-width: 500px;
|
|
455
|
+
padding: 1.5rem;
|
|
456
|
+
background: #f8f9fa;
|
|
457
|
+
border-radius: 12px;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.setting-item {
|
|
461
|
+
display: flex;
|
|
462
|
+
justify-content: space-between;
|
|
463
|
+
align-items: center;
|
|
464
|
+
padding: 1rem;
|
|
465
|
+
margin-bottom: 0.5rem;
|
|
466
|
+
background: white;
|
|
467
|
+
border-radius: 8px;
|
|
468
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.setting-info h3 {
|
|
472
|
+
margin: 0 0 0.25rem 0;
|
|
473
|
+
font-size: 1rem;
|
|
474
|
+
color: #333;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.setting-info p {
|
|
478
|
+
margin: 0;
|
|
479
|
+
font-size: 0.875rem;
|
|
480
|
+
color: #666;
|
|
481
|
+
}
|
|
482
|
+
</style>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Feature Toggle Dashboard
|
|
486
|
+
|
|
487
|
+
```vue
|
|
488
|
+
<script setup lang="ts">
|
|
489
|
+
import { ref } from "vue";
|
|
490
|
+
import { Switch } from "@umbra-ui/core";
|
|
491
|
+
|
|
492
|
+
interface Feature {
|
|
493
|
+
id: string;
|
|
494
|
+
name: string;
|
|
495
|
+
description: string;
|
|
496
|
+
enabled: boolean;
|
|
497
|
+
category: string;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const features = ref<Feature[]>([
|
|
501
|
+
{
|
|
502
|
+
id: "new-ui",
|
|
503
|
+
name: "New User Interface",
|
|
504
|
+
description: "Enable the redesigned user interface",
|
|
505
|
+
enabled: true,
|
|
506
|
+
category: "UI/UX",
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
id: "analytics",
|
|
510
|
+
name: "Advanced Analytics",
|
|
511
|
+
description: "Track user behavior and app performance",
|
|
512
|
+
enabled: false,
|
|
513
|
+
category: "Analytics",
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
id: "notifications",
|
|
517
|
+
name: "Push Notifications",
|
|
518
|
+
description: "Send real-time notifications to users",
|
|
519
|
+
enabled: true,
|
|
520
|
+
category: "Communication",
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
id: "dark-mode",
|
|
524
|
+
name: "Dark Mode",
|
|
525
|
+
description: "Enable dark theme for the application",
|
|
526
|
+
enabled: false,
|
|
527
|
+
category: "UI/UX",
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
id: "beta-features",
|
|
531
|
+
name: "Beta Features",
|
|
532
|
+
description: "Access to experimental features",
|
|
533
|
+
enabled: false,
|
|
534
|
+
category: "Experimental",
|
|
535
|
+
},
|
|
536
|
+
]);
|
|
537
|
+
|
|
538
|
+
const toggleFeature = (featureId: string) => {
|
|
539
|
+
const feature = features.value.find((f) => f.id === featureId);
|
|
540
|
+
if (feature) {
|
|
541
|
+
feature.enabled = !feature.enabled;
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const getFeaturesByCategory = (category: string) => {
|
|
546
|
+
return features.value.filter((f) => f.category === category);
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
const categories = ["UI/UX", "Analytics", "Communication", "Experimental"];
|
|
550
|
+
</script>
|
|
551
|
+
|
|
552
|
+
<template>
|
|
553
|
+
<div class="feature-dashboard">
|
|
554
|
+
<h1>Feature Toggle Dashboard</h1>
|
|
555
|
+
|
|
556
|
+
<div
|
|
557
|
+
v-for="category in categories"
|
|
558
|
+
:key="category"
|
|
559
|
+
class="category-section"
|
|
560
|
+
>
|
|
561
|
+
<h2>{{ category }}</h2>
|
|
562
|
+
<div class="features-grid">
|
|
563
|
+
<div
|
|
564
|
+
v-for="feature in getFeaturesByCategory(category)"
|
|
565
|
+
:key="feature.id"
|
|
566
|
+
class="feature-card"
|
|
567
|
+
>
|
|
568
|
+
<div class="feature-header">
|
|
569
|
+
<h3>{{ feature.name }}</h3>
|
|
570
|
+
<Switch
|
|
571
|
+
:isChecked="feature.enabled"
|
|
572
|
+
@update:isChecked="toggleFeature(feature.id)"
|
|
573
|
+
/>
|
|
574
|
+
</div>
|
|
575
|
+
<p class="feature-description">{{ feature.description }}</p>
|
|
576
|
+
<div class="feature-status">
|
|
577
|
+
<span
|
|
578
|
+
:class="[
|
|
579
|
+
'status-badge',
|
|
580
|
+
feature.enabled ? 'enabled' : 'disabled',
|
|
581
|
+
]"
|
|
582
|
+
>
|
|
583
|
+
{{ feature.enabled ? "Enabled" : "Disabled" }}
|
|
584
|
+
</span>
|
|
585
|
+
</div>
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
</div>
|
|
589
|
+
</div>
|
|
590
|
+
</template>
|
|
591
|
+
|
|
592
|
+
<style module>
|
|
593
|
+
.feature-dashboard {
|
|
594
|
+
max-width: 800px;
|
|
595
|
+
padding: 2rem;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.category-section {
|
|
599
|
+
margin-bottom: 2rem;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.features-grid {
|
|
603
|
+
display: grid;
|
|
604
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
605
|
+
gap: 1rem;
|
|
606
|
+
margin-top: 1rem;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.feature-card {
|
|
610
|
+
padding: 1.5rem;
|
|
611
|
+
border: 1px solid #e0e0e0;
|
|
612
|
+
border-radius: 8px;
|
|
613
|
+
background: white;
|
|
614
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.feature-header {
|
|
618
|
+
display: flex;
|
|
619
|
+
justify-content: space-between;
|
|
620
|
+
align-items: center;
|
|
621
|
+
margin-bottom: 0.5rem;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.feature-header h3 {
|
|
625
|
+
margin: 0;
|
|
626
|
+
font-size: 1.1rem;
|
|
627
|
+
color: #333;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.feature-description {
|
|
631
|
+
margin: 0 0 1rem 0;
|
|
632
|
+
color: #666;
|
|
633
|
+
font-size: 0.9rem;
|
|
634
|
+
line-height: 1.4;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
.feature-status {
|
|
638
|
+
display: flex;
|
|
639
|
+
justify-content: flex-end;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
.status-badge {
|
|
643
|
+
padding: 0.25rem 0.75rem;
|
|
644
|
+
border-radius: 12px;
|
|
645
|
+
font-size: 0.8rem;
|
|
646
|
+
font-weight: 500;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
.status-badge.enabled {
|
|
650
|
+
background-color: #d4edda;
|
|
651
|
+
color: #155724;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.status-badge.disabled {
|
|
655
|
+
background-color: #f8d7da;
|
|
656
|
+
color: #721c24;
|
|
657
|
+
}
|
|
658
|
+
</style>
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
## Notes
|
|
662
|
+
|
|
663
|
+
- The component automatically calculates dimensions based on the `size` prop
|
|
664
|
+
- The `color` prop affects both the background and border when the switch is checked
|
|
665
|
+
- The component supports both light and dark themes through CSS custom properties
|
|
666
|
+
- The switch uses smooth transitions for all state changes
|
|
667
|
+
- The component is fully accessible and supports keyboard navigation
|