@umbra.ui/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/controls/Dropdown/types.d.ts +5 -0
- package/dist/components/controls/Dropdown/types.d.ts.map +1 -0
- package/dist/components/controls/Dropdown/types.js +1 -0
- package/dist/components/controls/SegmentedControl/types.d.ts +6 -0
- package/dist/components/controls/SegmentedControl/types.d.ts.map +1 -0
- package/dist/components/controls/SegmentedControl/types.js +1 -0
- package/dist/components/dialogs/Alert/types.d.ts +7 -0
- package/dist/components/dialogs/Alert/types.d.ts.map +1 -0
- package/dist/components/dialogs/Alert/types.js +1 -0
- package/dist/components/dialogs/Toast/types.d.ts +34 -0
- package/dist/components/dialogs/Toast/types.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/types.js +10 -0
- package/dist/components/dialogs/Toast/useToast.d.ts +36 -0
- package/dist/components/dialogs/Toast/useToast.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/useToast.js +90 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts +3 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/tooltip.js +33 -0
- package/dist/components/indicators/Tooltip/types.d.ts +14 -0
- package/dist/components/indicators/Tooltip/types.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/types.js +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts +18 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.js +57 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts +14 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts.map +1 -0
- package/dist/components/inputs/Tags/tag-bar-styles.js +313 -0
- package/dist/components/inputs/Tags/types.d.ts +93 -0
- package/dist/components/inputs/Tags/types.d.ts.map +1 -0
- package/dist/components/inputs/Tags/types.js +216 -0
- package/dist/components/inputs/search/types.d.ts +9 -0
- package/dist/components/inputs/search/types.d.ts.map +1 -0
- package/dist/components/inputs/search/types.js +1 -0
- package/dist/components/navigation/adaptive/types.d.ts +16 -0
- package/dist/components/navigation/adaptive/types.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/types.js +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts +27 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.js +40 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts +6 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useBreakpoints.js +37 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts +93 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.js +145 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts +31 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewAnimation.js +591 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts +52 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewResize.js +146 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts +25 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts.map +1 -0
- package/dist/components/navigation/navstack/useNavigationStack.js +133 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts +20 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts.map +1 -0
- package/dist/components/navigation/slideover/useSlideoverController.js +267 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts +20 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts.map +1 -0
- package/dist/components/navigation/splitview/useSplitViewController.js +325 -0
- package/dist/components/navigation/tabcontroller/types.d.ts +21 -0
- package/dist/components/navigation/tabcontroller/types.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/types.js +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts +5 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.js +10 -0
- package/dist/components/navigation/types.d.ts +8 -0
- package/dist/components/navigation/types.d.ts.map +1 -0
- package/dist/components/navigation/types.js +1 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts +11 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts.map +1 -0
- package/dist/components/pickers/CollectionPicker/types.js +1 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts +13 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts.map +1 -0
- package/dist/components/pickers/ColorPicker/colors.js +266 -0
- package/dist/components/pickers/FilePicker/types.d.ts +10 -0
- package/dist/components/pickers/FilePicker/types.d.ts.map +1 -0
- package/dist/components/pickers/FilePicker/types.js +1 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/dist/theme.d.ts +73 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +279 -0
- package/dist/themes/blank.d.ts +7 -0
- package/dist/themes/blank.d.ts.map +1 -0
- package/dist/themes/blank.js +543 -0
- package/dist/themes/crimson-dark.d.ts +4 -0
- package/dist/themes/crimson-dark.d.ts.map +1 -0
- package/dist/themes/crimson-dark.js +552 -0
- package/dist/themes/cyan-light.d.ts +4 -0
- package/dist/themes/cyan-light.d.ts.map +1 -0
- package/dist/themes/cyan-light.js +552 -0
- package/dist/themes/dark.d.ts +4 -0
- package/dist/themes/dark.d.ts.map +1 -0
- package/dist/themes/dark.js +551 -0
- package/dist/themes/gold-dark.d.ts +4 -0
- package/dist/themes/gold-dark.d.ts.map +1 -0
- package/dist/themes/gold-dark.js +552 -0
- package/dist/themes/grass-dark.d.ts +4 -0
- package/dist/themes/grass-dark.d.ts.map +1 -0
- package/dist/themes/grass-dark.js +552 -0
- package/dist/themes/indigo.d.ts +4 -0
- package/dist/themes/indigo.d.ts.map +1 -0
- package/dist/themes/indigo.js +552 -0
- package/dist/themes/light.d.ts +4 -0
- package/dist/themes/light.d.ts.map +1 -0
- package/dist/themes/light.js +551 -0
- package/dist/themes/orange-dark.d.ts +4 -0
- package/dist/themes/orange-dark.d.ts.map +1 -0
- package/dist/themes/orange-dark.js +551 -0
- package/dist/themes/orange-light.d.ts +4 -0
- package/dist/themes/orange-light.d.ts.map +1 -0
- package/dist/themes/orange-light.js +551 -0
- package/package.json +62 -0
- package/src/components/controls/Button/Button.vue +417 -0
- package/src/components/controls/Button/README.md +348 -0
- package/src/components/controls/Button/theme.css +200 -0
- package/src/components/controls/Checkbox/Checkbox.vue +164 -0
- package/src/components/controls/Checkbox/README.md +441 -0
- package/src/components/controls/Checkbox/theme.css +36 -0
- package/src/components/controls/Dropdown/Dropdown.vue +476 -0
- package/src/components/controls/Dropdown/README.md +370 -0
- package/src/components/controls/Dropdown/theme.css +50 -0
- package/src/components/controls/Dropdown/types.ts +6 -0
- package/src/components/controls/IconButton/IconButton.vue +267 -0
- package/src/components/controls/IconButton/README.md +502 -0
- package/src/components/controls/IconButton/theme.css +89 -0
- package/src/components/controls/Radio/README.md +591 -0
- package/src/components/controls/Radio/Radio.vue +89 -0
- package/src/components/controls/Radio/theme.css +14 -0
- package/src/components/controls/RangeSlider/README.md +608 -0
- package/src/components/controls/RangeSlider/RangeSlider.vue +535 -0
- package/src/components/controls/RangeSlider/theme.css +80 -0
- package/src/components/controls/SegmentedControl/README.md +587 -0
- package/src/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
- package/src/components/controls/SegmentedControl/theme.css +60 -0
- package/src/components/controls/SegmentedControl/types.ts +5 -0
- package/src/components/controls/Slider/README.md +627 -0
- package/src/components/controls/Slider/Slider.vue +260 -0
- package/src/components/controls/Slider/theme.css +74 -0
- package/src/components/controls/Stepper/README.md +601 -0
- package/src/components/controls/Stepper/Stepper.vue +103 -0
- package/src/components/controls/Stepper/theme.css +53 -0
- package/src/components/controls/Switch/README.md +667 -0
- package/src/components/controls/Switch/Switch.vue +127 -0
- package/src/components/controls/Switch/theme.css +42 -0
- package/src/components/dialogs/Alert/Alert.vue +218 -0
- package/src/components/dialogs/Alert/README.md +450 -0
- package/src/components/dialogs/Alert/theme.css +44 -0
- package/src/components/dialogs/Alert/types.ts +11 -0
- package/src/components/dialogs/Toast/README.md +522 -0
- package/src/components/dialogs/Toast/Toast.vue +296 -0
- package/src/components/dialogs/Toast/ToastContainer.vue +330 -0
- package/src/components/dialogs/Toast/theme.css +44 -0
- package/src/components/dialogs/Toast/types.ts +46 -0
- package/src/components/dialogs/Toast/useToast.ts +127 -0
- package/src/components/indicators/ProgressBar/ProgressBar.vue +98 -0
- package/src/components/indicators/ProgressBar/README.md +744 -0
- package/src/components/indicators/ProgressBar/theme.css +36 -0
- package/src/components/indicators/Tooltip/README.md +723 -0
- package/src/components/indicators/Tooltip/TooltipProvider.vue +142 -0
- package/src/components/indicators/Tooltip/theme.css +18 -0
- package/src/components/indicators/Tooltip/tooltip.ts +48 -0
- package/src/components/indicators/Tooltip/types.ts +15 -0
- package/src/components/indicators/Tooltip/useTooltip.ts +71 -0
- package/src/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
- package/src/components/inputs/AutogrowTextView/README.md +643 -0
- package/src/components/inputs/AutogrowTextView/theme.css +28 -0
- package/src/components/inputs/InputCard/InputCard.vue +600 -0
- package/src/components/inputs/InputCard/README.md +636 -0
- package/src/components/inputs/InputEmail/InputEmail.vue +698 -0
- package/src/components/inputs/InputEmail/README.md +764 -0
- package/src/components/inputs/InputNumber/InputNumber.vue +300 -0
- package/src/components/inputs/InputNumber/README.md +749 -0
- package/src/components/inputs/InputPhone/InputPhone.vue +645 -0
- package/src/components/inputs/InputPhone/README.md +636 -0
- package/src/components/inputs/InputSecure/InputSecure.vue +646 -0
- package/src/components/inputs/InputSecure/README.md +771 -0
- package/src/components/inputs/InputText/InputText.vue +225 -0
- package/src/components/inputs/InputText/README.md +844 -0
- package/src/components/inputs/OTP/OTP.vue +349 -0
- package/src/components/inputs/OTP/README.md +736 -0
- package/src/components/inputs/OTP/theme.css +50 -0
- package/src/components/inputs/StringCapture/README.md +718 -0
- package/src/components/inputs/StringCapture/StringCapture.vue +315 -0
- package/src/components/inputs/StringCapture/theme.css +86 -0
- package/src/components/inputs/Tags/README.md +897 -0
- package/src/components/inputs/Tags/TagBar.vue +793 -0
- package/src/components/inputs/Tags/TagCreation.vue +219 -0
- package/src/components/inputs/Tags/TagPicker.vue +380 -0
- package/src/components/inputs/Tags/tag-bar-styles.ts +354 -0
- package/src/components/inputs/Tags/theme.css +121 -0
- package/src/components/inputs/Tags/types.ts +346 -0
- package/src/components/inputs/search/README.md +759 -0
- package/src/components/inputs/search/SearchBar.vue +394 -0
- package/src/components/inputs/search/SearchResults.vue +310 -0
- package/src/components/inputs/search/theme.css +187 -0
- package/src/components/inputs/search/types.ts +8 -0
- package/src/components/inputs/theme.css +102 -0
- package/src/components/menus/ActionMenu/ActionMenu.vue +383 -0
- package/src/components/menus/ActionMenu/README.md +825 -0
- package/src/components/menus/ActionMenu/theme.css +93 -0
- package/src/components/models/Popover/Popover.vue +551 -0
- package/src/components/models/Popover/README.md +885 -0
- package/src/components/models/Popover/theme.css +52 -0
- package/src/components/models/Sheet/README.md +1159 -0
- package/src/components/models/Sheet/Sheet.vue +465 -0
- package/src/components/models/Sheet/theme.css +72 -0
- package/src/components/models/Sidebar/README.md +1228 -0
- package/src/components/models/Sidebar/Sidebar.vue +480 -0
- package/src/components/models/Sidebar/theme.css +90 -0
- package/src/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
- package/src/components/navigation/adaptive/README.md +768 -0
- package/src/components/navigation/adaptive/types.ts +19 -0
- package/src/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
- package/src/components/navigation/adaptive/useBreakpoints.ts +41 -0
- package/src/components/navigation/adaptive/useContainerMonitor.ts +214 -0
- package/src/components/navigation/adaptive/useViewAnimation.ts +721 -0
- package/src/components/navigation/adaptive/useViewResize.ts +211 -0
- package/src/components/navigation/navstack/NavigationStack.vue +180 -0
- package/src/components/navigation/navstack/README.md +994 -0
- package/src/components/navigation/navstack/useNavigationStack.ts +164 -0
- package/src/components/navigation/slideover/README.md +1275 -0
- package/src/components/navigation/slideover/SlideoverController.vue +287 -0
- package/src/components/navigation/slideover/useSlideoverController.ts +320 -0
- package/src/components/navigation/splitview/README.md +1115 -0
- package/src/components/navigation/splitview/SplitViewController.vue +176 -0
- package/src/components/navigation/splitview/useSplitViewController.ts +388 -0
- package/src/components/navigation/tabcontroller/README.md +919 -0
- package/src/components/navigation/tabcontroller/TabController.vue +307 -0
- package/src/components/navigation/tabcontroller/TabItem.vue +57 -0
- package/src/components/navigation/tabcontroller/types.ts +24 -0
- package/src/components/navigation/tabcontroller/useTabController.ts +18 -0
- package/src/components/navigation/theme.css +91 -0
- package/src/components/navigation/types.ts +7 -0
- package/src/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
- package/src/components/pickers/CollectionPicker/README.md +1115 -0
- package/src/components/pickers/CollectionPicker/theme.css +14 -0
- package/src/components/pickers/CollectionPicker/types.ts +11 -0
- package/src/components/pickers/ColorPicker/ColorPicker.vue +376 -0
- package/src/components/pickers/ColorPicker/README.md +1439 -0
- package/src/components/pickers/ColorPicker/colors.ts +299 -0
- package/src/components/pickers/ColorPicker/theme.css +32 -0
- package/src/components/pickers/DatePicker/DatePicker.vue +660 -0
- package/src/components/pickers/DatePicker/README.md +1195 -0
- package/src/components/pickers/DatePicker/theme.css +22 -0
- package/src/components/pickers/FilePicker/FilePicker.vue +534 -0
- package/src/components/pickers/FilePicker/README.md +1542 -0
- package/src/components/pickers/FilePicker/theme.css +48 -0
- package/src/components/pickers/FilePicker/types.ts +10 -0
- package/src/components/pickers/IconPicker/IconPicker.vue +327 -0
- package/src/components/pickers/IconPicker/README.md +1161 -0
- package/src/components/pickers/IconPicker/theme.css +28 -0
- package/src/components/pickers/theme.css +82 -0
- package/src/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
- package/src/components/views/MarkdownViewer/README.md +833 -0
- package/src/components/views/MarkdownViewer/theme.css +130 -0
- package/src/index.ts +263 -0
- package/src/theme.ts +378 -0
- package/src/themes/crimson-dark.ts +556 -0
- package/src/themes/cyan-light.ts +556 -0
- package/src/themes/dark.ts +557 -0
- package/src/themes/gold-dark.ts +556 -0
- package/src/themes/grass-dark.ts +556 -0
- package/src/themes/indigo.ts +556 -0
- package/src/themes/light.ts +557 -0
- package/src/themes/orange-dark.ts +557 -0
- package/src/themes/orange-light.ts +557 -0
- package/src/vue.d.ts +45 -0
|
@@ -0,0 +1,1275 @@
|
|
|
1
|
+
# SlideoverController
|
|
2
|
+
|
|
3
|
+
A sophisticated slideover navigation component built with Vue 3 Composition API and TypeScript. The SlideoverController provides smooth, animated transitions between different views using GSAP's FLIP (First, Last, Invert, Play) animation technique, creating an intuitive slideover interface perfect for tablet and desktop applications.
|
|
4
|
+
|
|
5
|
+
## Installation/Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { SlideoverController, useSlideoverController } from "@umbra-ui/core";
|
|
9
|
+
import type { Pane } from "@umbra-ui/core";
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Dependencies:**
|
|
13
|
+
|
|
14
|
+
- Vue 3.x
|
|
15
|
+
- gsap (for animations)
|
|
16
|
+
- gsap/Flip (for FLIP animations)
|
|
17
|
+
- @umbra-ui/icons (for ChevronLeftIcon)
|
|
18
|
+
|
|
19
|
+
## Basic Usage
|
|
20
|
+
|
|
21
|
+
```vue
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { ref } from "vue";
|
|
24
|
+
import { SlideoverController } from "@umbra-ui/core";
|
|
25
|
+
import HomeView from "./HomeView.vue";
|
|
26
|
+
import ProfileView from "./ProfileView.vue";
|
|
27
|
+
import SettingsView from "./SettingsView.vue";
|
|
28
|
+
|
|
29
|
+
// Define your slideover panes
|
|
30
|
+
const panes = ref([
|
|
31
|
+
{
|
|
32
|
+
name: "Home",
|
|
33
|
+
background: "#ffffff",
|
|
34
|
+
foreground: "#000000",
|
|
35
|
+
component: HomeView,
|
|
36
|
+
props: { title: "Home" },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "Profile",
|
|
40
|
+
background: "#f8f9fa",
|
|
41
|
+
foreground: "#212529",
|
|
42
|
+
component: ProfileView,
|
|
43
|
+
props: { userId: 123 },
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "Settings",
|
|
47
|
+
background: "#e9ecef",
|
|
48
|
+
foreground: "#495057",
|
|
49
|
+
component: SettingsView,
|
|
50
|
+
props: { theme: "light" },
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
const slideoverRef = ref();
|
|
55
|
+
|
|
56
|
+
// Navigate to specific pane
|
|
57
|
+
const goToPane = (index: number) => {
|
|
58
|
+
slideoverRef.value?.navigate(index);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Show all panes
|
|
62
|
+
const showAllPanes = () => {
|
|
63
|
+
slideoverRef.value?.showAll();
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Hide all panes
|
|
67
|
+
const hideAllPanes = () => {
|
|
68
|
+
slideoverRef.value?.hideAll();
|
|
69
|
+
};
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<div class="app">
|
|
74
|
+
<div class="navigation-controls">
|
|
75
|
+
<button @click="goToPane(0)">Home</button>
|
|
76
|
+
<button @click="goToPane(1)">Profile</button>
|
|
77
|
+
<button @click="goToPane(2)">Settings</button>
|
|
78
|
+
<button @click="showAllPanes">Show All</button>
|
|
79
|
+
<button @click="hideAllPanes">Hide All</button>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<SlideoverController
|
|
83
|
+
ref="slideoverRef"
|
|
84
|
+
:panes="panes"
|
|
85
|
+
component-id="main-slideover"
|
|
86
|
+
:show-breadcrumb="true"
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
90
|
+
|
|
91
|
+
<style module>
|
|
92
|
+
.app {
|
|
93
|
+
height: 100vh;
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.navigation-controls {
|
|
99
|
+
display: flex;
|
|
100
|
+
gap: 12px;
|
|
101
|
+
padding: 16px;
|
|
102
|
+
background: var(--background-1);
|
|
103
|
+
border-bottom: 1px solid var(--border-2);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.navigation-controls button {
|
|
107
|
+
padding: 8px 16px;
|
|
108
|
+
border: 1px solid var(--border-2);
|
|
109
|
+
background: var(--background-2);
|
|
110
|
+
color: var(--text-1);
|
|
111
|
+
border-radius: 6px;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
transition: all 0.2s ease;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.navigation-controls button:hover {
|
|
117
|
+
background: var(--background-3);
|
|
118
|
+
border-color: var(--border-3);
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Props
|
|
124
|
+
|
|
125
|
+
| Prop Name | Type | Required | Default | Description |
|
|
126
|
+
| ---------------- | ------------------------------------------- | -------- | -------------- | -------------------------------------------- |
|
|
127
|
+
| `panes` | `Pane[]` | Yes | - | Array of panes to display in the slideover |
|
|
128
|
+
| `controller` | `ReturnType<typeof useSlideoverController>` | No | - | External controller instance |
|
|
129
|
+
| `componentId` | `string` | No | Auto-generated | Unique identifier for the component instance |
|
|
130
|
+
| `showBreadcrumb` | `boolean` | No | `true` | Whether to show breadcrumb navigation |
|
|
131
|
+
|
|
132
|
+
## Pane Interface
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
interface Pane {
|
|
136
|
+
name: string;
|
|
137
|
+
background: string;
|
|
138
|
+
foreground: string;
|
|
139
|
+
component: any;
|
|
140
|
+
props: Record<string, any>;
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Pane Properties
|
|
145
|
+
|
|
146
|
+
| Property | Type | Description |
|
|
147
|
+
| ------------ | --------------------- | ----------------------------------------------- |
|
|
148
|
+
| `name` | `string` | Display name for the pane (used in breadcrumbs) |
|
|
149
|
+
| `background` | `string` | Background color for the pane container |
|
|
150
|
+
| `foreground` | `string` | Text color for the pane content |
|
|
151
|
+
| `component` | `Component` | Vue component to render in the pane |
|
|
152
|
+
| `props` | `Record<string, any>` | Props to pass to the component |
|
|
153
|
+
|
|
154
|
+
## Events
|
|
155
|
+
|
|
156
|
+
The SlideoverController component doesn't emit events directly, but you can access navigation methods through template refs.
|
|
157
|
+
|
|
158
|
+
## Exposed Methods/Refs
|
|
159
|
+
|
|
160
|
+
| Method | Parameters | Description |
|
|
161
|
+
| ------------ | ------------------------------------- | -------------------------------------------- |
|
|
162
|
+
| `navigate` | `(index: number, animated?: boolean)` | Navigate to a specific pane by index |
|
|
163
|
+
| `showPane` | `(index: number)` | Show a specific pane and all panes after it |
|
|
164
|
+
| `hidePane` | `(index: number)` | Hide a specific pane and all panes before it |
|
|
165
|
+
| `togglePane` | `(index: number)` | Toggle a pane at a specific index |
|
|
166
|
+
| `showAll` | `()` | Show all secondary panes |
|
|
167
|
+
| `hideAll` | `()` | Hide all secondary panes |
|
|
168
|
+
|
|
169
|
+
## useSlideoverController Composable
|
|
170
|
+
|
|
171
|
+
The `useSlideoverController` composable provides the core slideover logic and can be used independently:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { useSlideoverController } from "@umbra-ui/core";
|
|
175
|
+
|
|
176
|
+
const {
|
|
177
|
+
visiblePanes,
|
|
178
|
+
currentPaneIndex,
|
|
179
|
+
showPane,
|
|
180
|
+
hidePane,
|
|
181
|
+
togglePane,
|
|
182
|
+
showAll,
|
|
183
|
+
hideAll,
|
|
184
|
+
navigate,
|
|
185
|
+
} = useSlideoverController(panes, componentId);
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Composable Returns
|
|
189
|
+
|
|
190
|
+
| Property | Type | Description |
|
|
191
|
+
| ------------------ | --------------------------------------------- | ------------------------------------------------- |
|
|
192
|
+
| `visiblePanes` | `Ref<boolean[]>` | Reactive array indicating which panes are visible |
|
|
193
|
+
| `currentPaneIndex` | `ComputedRef<number>` | Current active pane index |
|
|
194
|
+
| `showPane` | `(index: number) => void` | Show specific pane and all after it |
|
|
195
|
+
| `hidePane` | `(index: number) => void` | Hide specific pane and all before it |
|
|
196
|
+
| `togglePane` | `(index: number) => void` | Toggle pane at specific index |
|
|
197
|
+
| `showAll` | `() => void` | Show all secondary panes |
|
|
198
|
+
| `hideAll` | `() => void` | Hide all secondary panes |
|
|
199
|
+
| `navigate` | `(index: number, animated?: boolean) => void` | Navigate to specific pane |
|
|
200
|
+
|
|
201
|
+
## CSS Customization
|
|
202
|
+
|
|
203
|
+
### Layout Variables
|
|
204
|
+
|
|
205
|
+
```css
|
|
206
|
+
.slideover-controller {
|
|
207
|
+
--slideover-darken-bg: rgba(0, 0, 0, 0.5);
|
|
208
|
+
--slideover-breadcrumb-default-opacity: 0.6;
|
|
209
|
+
--slideover-breadcrumb-hover-opacity: 1;
|
|
210
|
+
--slideover-handle-default-width: 4px;
|
|
211
|
+
--slideover-handle-default-height: 24px;
|
|
212
|
+
--slideover-handle-default-opacity: 0.3;
|
|
213
|
+
--slideover-handle-bg: #666;
|
|
214
|
+
--slideover-handle-hover-width: 6px;
|
|
215
|
+
--slideover-handle-hover-height: 32px;
|
|
216
|
+
--slideover-handle-hover-opacity: 0.6;
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Container Styling
|
|
221
|
+
|
|
222
|
+
```css
|
|
223
|
+
.slideover-controller {
|
|
224
|
+
position: relative;
|
|
225
|
+
height: 100%;
|
|
226
|
+
width: 100%;
|
|
227
|
+
overflow: hidden;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.slideover-controller .darken {
|
|
231
|
+
position: absolute;
|
|
232
|
+
top: 0;
|
|
233
|
+
left: 0;
|
|
234
|
+
right: 0;
|
|
235
|
+
bottom: 0;
|
|
236
|
+
background-color: var(--slideover-darken-bg);
|
|
237
|
+
opacity: 0;
|
|
238
|
+
pointer-events: none;
|
|
239
|
+
z-index: 5;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Pane Styling
|
|
244
|
+
|
|
245
|
+
```css
|
|
246
|
+
.slideover-controller .pane {
|
|
247
|
+
display: grid;
|
|
248
|
+
grid-template-columns: 1fr;
|
|
249
|
+
grid-template-areas: "content";
|
|
250
|
+
height: 100%;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.slideover-controller .pane_full {
|
|
254
|
+
display: flex;
|
|
255
|
+
flex-direction: column;
|
|
256
|
+
flex-grow: 1;
|
|
257
|
+
height: 100%;
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Examples
|
|
262
|
+
|
|
263
|
+
### File Explorer Interface
|
|
264
|
+
|
|
265
|
+
```vue
|
|
266
|
+
<script setup lang="ts">
|
|
267
|
+
import { ref } from "vue";
|
|
268
|
+
import { SlideoverController } from "@umbra-ui/core";
|
|
269
|
+
import FileTree from "./FileTree.vue";
|
|
270
|
+
import FileList from "./FileList.vue";
|
|
271
|
+
import FilePreview from "./FilePreview.vue";
|
|
272
|
+
|
|
273
|
+
const panes = ref([
|
|
274
|
+
{
|
|
275
|
+
name: "Folders",
|
|
276
|
+
background: "#ffffff",
|
|
277
|
+
foreground: "#1a202c",
|
|
278
|
+
component: FileTree,
|
|
279
|
+
props: { rootPath: "/" },
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: "Files",
|
|
283
|
+
background: "#f7fafc",
|
|
284
|
+
foreground: "#2d3748",
|
|
285
|
+
component: FileList,
|
|
286
|
+
props: { currentPath: "/documents" },
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: "Preview",
|
|
290
|
+
background: "#edf2f7",
|
|
291
|
+
foreground: "#4a5568",
|
|
292
|
+
component: FilePreview,
|
|
293
|
+
props: { selectedFile: null },
|
|
294
|
+
},
|
|
295
|
+
]);
|
|
296
|
+
|
|
297
|
+
const slideoverRef = ref();
|
|
298
|
+
|
|
299
|
+
const handleFileSelect = (file: any) => {
|
|
300
|
+
// Navigate to preview pane
|
|
301
|
+
slideoverRef.value?.navigate(2);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const handleFolderSelect = (folder: any) => {
|
|
305
|
+
// Navigate to file list pane
|
|
306
|
+
slideoverRef.value?.navigate(1);
|
|
307
|
+
};
|
|
308
|
+
</script>
|
|
309
|
+
|
|
310
|
+
<template>
|
|
311
|
+
<div class="file-explorer">
|
|
312
|
+
<!-- Toolbar -->
|
|
313
|
+
<div class="explorer-toolbar">
|
|
314
|
+
<div class="toolbar-section">
|
|
315
|
+
<button @click="slideoverRef?.showAll()" class="toolbar-btn">
|
|
316
|
+
Show All Panes
|
|
317
|
+
</button>
|
|
318
|
+
<button @click="slideoverRef?.hideAll()" class="toolbar-btn">
|
|
319
|
+
Hide All Panes
|
|
320
|
+
</button>
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
<div class="toolbar-section">
|
|
324
|
+
<button @click="slideoverRef?.navigate(0)" class="toolbar-btn">
|
|
325
|
+
Folders
|
|
326
|
+
</button>
|
|
327
|
+
<button @click="slideoverRef?.navigate(1)" class="toolbar-btn">
|
|
328
|
+
Files
|
|
329
|
+
</button>
|
|
330
|
+
<button @click="slideoverRef?.navigate(2)" class="toolbar-btn">
|
|
331
|
+
Preview
|
|
332
|
+
</button>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
|
|
336
|
+
<!-- Slideover Controller -->
|
|
337
|
+
<SlideoverController
|
|
338
|
+
ref="slideoverRef"
|
|
339
|
+
:panes="panes"
|
|
340
|
+
component-id="file-explorer"
|
|
341
|
+
:show-breadcrumb="true"
|
|
342
|
+
/>
|
|
343
|
+
</div>
|
|
344
|
+
</template>
|
|
345
|
+
|
|
346
|
+
<style module>
|
|
347
|
+
.file-explorer {
|
|
348
|
+
height: 100vh;
|
|
349
|
+
display: flex;
|
|
350
|
+
flex-direction: column;
|
|
351
|
+
background: #f8f9fa;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.explorer-toolbar {
|
|
355
|
+
display: flex;
|
|
356
|
+
justify-content: space-between;
|
|
357
|
+
align-items: center;
|
|
358
|
+
padding: 12px 16px;
|
|
359
|
+
background: white;
|
|
360
|
+
border-bottom: 1px solid #e9ecef;
|
|
361
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.toolbar-section {
|
|
365
|
+
display: flex;
|
|
366
|
+
gap: 8px;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.toolbar-btn {
|
|
370
|
+
padding: 6px 12px;
|
|
371
|
+
border: 1px solid #dee2e6;
|
|
372
|
+
background: white;
|
|
373
|
+
color: #495057;
|
|
374
|
+
border-radius: 4px;
|
|
375
|
+
cursor: pointer;
|
|
376
|
+
font-size: 14px;
|
|
377
|
+
transition: all 0.2s ease;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.toolbar-btn:hover {
|
|
381
|
+
background: #f8f9fa;
|
|
382
|
+
border-color: #adb5bd;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.toolbar-btn:active {
|
|
386
|
+
background: #e9ecef;
|
|
387
|
+
}
|
|
388
|
+
</style>
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Settings Panel Interface
|
|
392
|
+
|
|
393
|
+
```vue
|
|
394
|
+
<script setup lang="ts">
|
|
395
|
+
import { ref } from "vue";
|
|
396
|
+
import { SlideoverController } from "@umbra-ui/core";
|
|
397
|
+
import GeneralSettings from "./GeneralSettings.vue";
|
|
398
|
+
import AppearanceSettings from "./AppearanceSettings.vue";
|
|
399
|
+
import PrivacySettings from "./PrivacySettings.vue";
|
|
400
|
+
import AdvancedSettings from "./AdvancedSettings.vue";
|
|
401
|
+
|
|
402
|
+
const panes = ref([
|
|
403
|
+
{
|
|
404
|
+
name: "General",
|
|
405
|
+
background: "#ffffff",
|
|
406
|
+
foreground: "#1a202c",
|
|
407
|
+
component: GeneralSettings,
|
|
408
|
+
props: { section: "general" },
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
name: "Appearance",
|
|
412
|
+
background: "#f7fafc",
|
|
413
|
+
foreground: "#2d3748",
|
|
414
|
+
component: AppearanceSettings,
|
|
415
|
+
props: { section: "appearance" },
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
name: "Privacy",
|
|
419
|
+
background: "#edf2f7",
|
|
420
|
+
foreground: "#4a5568",
|
|
421
|
+
component: PrivacySettings,
|
|
422
|
+
props: { section: "privacy" },
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: "Advanced",
|
|
426
|
+
background: "#e2e8f0",
|
|
427
|
+
foreground: "#718096",
|
|
428
|
+
component: AdvancedSettings,
|
|
429
|
+
props: { section: "advanced" },
|
|
430
|
+
},
|
|
431
|
+
]);
|
|
432
|
+
|
|
433
|
+
const slideoverRef = ref();
|
|
434
|
+
const currentSection = ref("General");
|
|
435
|
+
|
|
436
|
+
const navigateToSection = (index: number) => {
|
|
437
|
+
currentSection.value = panes.value[index].name;
|
|
438
|
+
slideoverRef.value?.navigate(index);
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
const resetToGeneral = () => {
|
|
442
|
+
slideoverRef.value?.navigate(0);
|
|
443
|
+
currentSection.value = "General";
|
|
444
|
+
};
|
|
445
|
+
</script>
|
|
446
|
+
|
|
447
|
+
<template>
|
|
448
|
+
<div class="settings-interface">
|
|
449
|
+
<!-- Settings Header -->
|
|
450
|
+
<header class="settings-header">
|
|
451
|
+
<h1 class="settings-title">Settings</h1>
|
|
452
|
+
<p class="settings-subtitle">Configure your application preferences</p>
|
|
453
|
+
</header>
|
|
454
|
+
|
|
455
|
+
<!-- Settings Navigation -->
|
|
456
|
+
<nav class="settings-nav">
|
|
457
|
+
<button
|
|
458
|
+
v-for="(pane, index) in panes"
|
|
459
|
+
:key="pane.name"
|
|
460
|
+
@click="navigateToSection(index)"
|
|
461
|
+
:class="['nav-item', { active: currentSection === pane.name }]"
|
|
462
|
+
>
|
|
463
|
+
<span class="nav-icon">{{ getSectionIcon(pane.name) }}</span>
|
|
464
|
+
<span class="nav-label">{{ pane.name }}</span>
|
|
465
|
+
</button>
|
|
466
|
+
|
|
467
|
+
<div class="nav-actions">
|
|
468
|
+
<button @click="resetToGeneral" class="action-btn secondary">
|
|
469
|
+
Reset
|
|
470
|
+
</button>
|
|
471
|
+
<button @click="slideoverRef?.showAll()" class="action-btn primary">
|
|
472
|
+
Show All
|
|
473
|
+
</button>
|
|
474
|
+
</div>
|
|
475
|
+
</nav>
|
|
476
|
+
|
|
477
|
+
<!-- Settings Content -->
|
|
478
|
+
<SlideoverController
|
|
479
|
+
ref="slideoverRef"
|
|
480
|
+
:panes="panes"
|
|
481
|
+
component-id="settings-panel"
|
|
482
|
+
:show-breadcrumb="true"
|
|
483
|
+
/>
|
|
484
|
+
</div>
|
|
485
|
+
</template>
|
|
486
|
+
|
|
487
|
+
<script setup lang="ts">
|
|
488
|
+
const getSectionIcon = (section: string) => {
|
|
489
|
+
const icons = {
|
|
490
|
+
General: "⚙️",
|
|
491
|
+
Appearance: "🎨",
|
|
492
|
+
Privacy: "🔒",
|
|
493
|
+
Advanced: "🔧",
|
|
494
|
+
};
|
|
495
|
+
return icons[section] || "📋";
|
|
496
|
+
};
|
|
497
|
+
</script>
|
|
498
|
+
|
|
499
|
+
<style module>
|
|
500
|
+
.settings-interface {
|
|
501
|
+
height: 100vh;
|
|
502
|
+
display: flex;
|
|
503
|
+
flex-direction: column;
|
|
504
|
+
background: #f8f9fa;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.settings-header {
|
|
508
|
+
padding: 24px;
|
|
509
|
+
background: white;
|
|
510
|
+
border-bottom: 1px solid #e9ecef;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.settings-title {
|
|
514
|
+
font-size: 28px;
|
|
515
|
+
font-weight: 700;
|
|
516
|
+
color: #1a202c;
|
|
517
|
+
margin: 0 0 8px 0;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.settings-subtitle {
|
|
521
|
+
font-size: 16px;
|
|
522
|
+
color: #718096;
|
|
523
|
+
margin: 0;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.settings-nav {
|
|
527
|
+
display: flex;
|
|
528
|
+
align-items: center;
|
|
529
|
+
gap: 16px;
|
|
530
|
+
padding: 16px 24px;
|
|
531
|
+
background: white;
|
|
532
|
+
border-bottom: 1px solid #e9ecef;
|
|
533
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.nav-item {
|
|
537
|
+
display: flex;
|
|
538
|
+
align-items: center;
|
|
539
|
+
gap: 8px;
|
|
540
|
+
padding: 8px 16px;
|
|
541
|
+
background: transparent;
|
|
542
|
+
border: 1px solid transparent;
|
|
543
|
+
color: #718096;
|
|
544
|
+
cursor: pointer;
|
|
545
|
+
border-radius: 6px;
|
|
546
|
+
transition: all 0.2s ease;
|
|
547
|
+
font-weight: 500;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.nav-item:hover {
|
|
551
|
+
background: #f7fafc;
|
|
552
|
+
color: #4a5568;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.nav-item.active {
|
|
556
|
+
background: #edf2f7;
|
|
557
|
+
color: #2d3748;
|
|
558
|
+
border-color: #cbd5e0;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.nav-icon {
|
|
562
|
+
font-size: 16px;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.nav-label {
|
|
566
|
+
font-size: 14px;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.nav-actions {
|
|
570
|
+
margin-left: auto;
|
|
571
|
+
display: flex;
|
|
572
|
+
gap: 8px;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.action-btn {
|
|
576
|
+
padding: 8px 16px;
|
|
577
|
+
border: 1px solid;
|
|
578
|
+
border-radius: 6px;
|
|
579
|
+
cursor: pointer;
|
|
580
|
+
font-weight: 500;
|
|
581
|
+
transition: all 0.2s ease;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.action-btn.primary {
|
|
585
|
+
background: #3182ce;
|
|
586
|
+
color: white;
|
|
587
|
+
border-color: #3182ce;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.action-btn.primary:hover {
|
|
591
|
+
background: #2c5aa0;
|
|
592
|
+
border-color: #2c5aa0;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
.action-btn.secondary {
|
|
596
|
+
background: white;
|
|
597
|
+
color: #718096;
|
|
598
|
+
border-color: #e2e8f0;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.action-btn.secondary:hover {
|
|
602
|
+
background: #f7fafc;
|
|
603
|
+
color: #4a5568;
|
|
604
|
+
border-color: #cbd5e0;
|
|
605
|
+
}
|
|
606
|
+
</style>
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
### Multi-Step Form Interface
|
|
610
|
+
|
|
611
|
+
```vue
|
|
612
|
+
<script setup lang="ts">
|
|
613
|
+
import { ref } from "vue";
|
|
614
|
+
import { SlideoverController } from "@umbra-ui/core";
|
|
615
|
+
import PersonalInfoStep from "./PersonalInfoStep.vue";
|
|
616
|
+
import ContactInfoStep from "./ContactInfoStep.vue";
|
|
617
|
+
import PreferencesStep from "./PreferencesStep.vue";
|
|
618
|
+
import ReviewStep from "./ReviewStep.vue";
|
|
619
|
+
|
|
620
|
+
const panes = ref([
|
|
621
|
+
{
|
|
622
|
+
name: "Personal Info",
|
|
623
|
+
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
624
|
+
foreground: "#ffffff",
|
|
625
|
+
component: PersonalInfoStep,
|
|
626
|
+
props: { step: 1 },
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
name: "Contact Info",
|
|
630
|
+
background: "linear-gradient(135deg, #f093fb 0%, #f5576c 100%)",
|
|
631
|
+
foreground: "#ffffff",
|
|
632
|
+
component: ContactInfoStep,
|
|
633
|
+
props: { step: 2 },
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
name: "Preferences",
|
|
637
|
+
background: "linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)",
|
|
638
|
+
foreground: "#ffffff",
|
|
639
|
+
component: PreferencesStep,
|
|
640
|
+
props: { step: 3 },
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
name: "Review",
|
|
644
|
+
background: "linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)",
|
|
645
|
+
foreground: "#ffffff",
|
|
646
|
+
component: ReviewStep,
|
|
647
|
+
props: { step: 4 },
|
|
648
|
+
},
|
|
649
|
+
]);
|
|
650
|
+
|
|
651
|
+
const slideoverRef = ref();
|
|
652
|
+
const currentStep = ref(0);
|
|
653
|
+
const totalSteps = panes.value.length;
|
|
654
|
+
const formData = ref({});
|
|
655
|
+
|
|
656
|
+
const nextStep = () => {
|
|
657
|
+
if (currentStep.value < totalSteps - 1) {
|
|
658
|
+
currentStep.value++;
|
|
659
|
+
slideoverRef.value?.navigate(currentStep.value);
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
const prevStep = () => {
|
|
664
|
+
if (currentStep.value > 0) {
|
|
665
|
+
currentStep.value--;
|
|
666
|
+
slideoverRef.value?.navigate(currentStep.value);
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
const completeForm = () => {
|
|
671
|
+
console.log("Form completed:", formData.value);
|
|
672
|
+
// Handle form submission
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
const updateFormData = (stepData: any) => {
|
|
676
|
+
formData.value = { ...formData.value, ...stepData };
|
|
677
|
+
};
|
|
678
|
+
</script>
|
|
679
|
+
|
|
680
|
+
<template>
|
|
681
|
+
<div class="multi-step-form">
|
|
682
|
+
<!-- Progress Header -->
|
|
683
|
+
<div class="form-header">
|
|
684
|
+
<div class="progress-container">
|
|
685
|
+
<div class="progress-bar">
|
|
686
|
+
<div
|
|
687
|
+
class="progress-fill"
|
|
688
|
+
:style="{ width: `${((currentStep + 1) / totalSteps) * 100}%` }"
|
|
689
|
+
/>
|
|
690
|
+
</div>
|
|
691
|
+
<span class="progress-text">
|
|
692
|
+
Step {{ currentStep + 1 }} of {{ totalSteps }}
|
|
693
|
+
</span>
|
|
694
|
+
</div>
|
|
695
|
+
|
|
696
|
+
<h1 class="form-title">Complete Your Profile</h1>
|
|
697
|
+
</div>
|
|
698
|
+
|
|
699
|
+
<!-- Form Navigation -->
|
|
700
|
+
<div class="form-navigation">
|
|
701
|
+
<button
|
|
702
|
+
@click="prevStep"
|
|
703
|
+
:disabled="currentStep === 0"
|
|
704
|
+
class="nav-button prev"
|
|
705
|
+
>
|
|
706
|
+
← Previous
|
|
707
|
+
</button>
|
|
708
|
+
|
|
709
|
+
<div class="step-indicators">
|
|
710
|
+
<button
|
|
711
|
+
v-for="(pane, index) in panes"
|
|
712
|
+
:key="pane.name"
|
|
713
|
+
@click="slideoverRef?.navigate(index)"
|
|
714
|
+
:class="[
|
|
715
|
+
'step-indicator',
|
|
716
|
+
{
|
|
717
|
+
active: currentStep === index,
|
|
718
|
+
completed: currentStep > index,
|
|
719
|
+
},
|
|
720
|
+
]"
|
|
721
|
+
>
|
|
722
|
+
{{ index + 1 }}
|
|
723
|
+
</button>
|
|
724
|
+
</div>
|
|
725
|
+
|
|
726
|
+
<button
|
|
727
|
+
v-if="currentStep < totalSteps - 1"
|
|
728
|
+
@click="nextStep"
|
|
729
|
+
class="nav-button next"
|
|
730
|
+
>
|
|
731
|
+
Next →
|
|
732
|
+
</button>
|
|
733
|
+
|
|
734
|
+
<button v-else @click="completeForm" class="nav-button complete">
|
|
735
|
+
Complete
|
|
736
|
+
</button>
|
|
737
|
+
</div>
|
|
738
|
+
|
|
739
|
+
<!-- Form Content -->
|
|
740
|
+
<SlideoverController
|
|
741
|
+
ref="slideoverRef"
|
|
742
|
+
:panes="panes"
|
|
743
|
+
component-id="multi-step-form"
|
|
744
|
+
:show-breadcrumb="false"
|
|
745
|
+
/>
|
|
746
|
+
</div>
|
|
747
|
+
</template>
|
|
748
|
+
|
|
749
|
+
<style module>
|
|
750
|
+
.multi-step-form {
|
|
751
|
+
height: 100vh;
|
|
752
|
+
display: flex;
|
|
753
|
+
flex-direction: column;
|
|
754
|
+
background: #f8f9fa;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.form-header {
|
|
758
|
+
padding: 24px;
|
|
759
|
+
background: white;
|
|
760
|
+
border-bottom: 1px solid #e9ecef;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.progress-container {
|
|
764
|
+
display: flex;
|
|
765
|
+
align-items: center;
|
|
766
|
+
gap: 16px;
|
|
767
|
+
margin-bottom: 16px;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
.progress-bar {
|
|
771
|
+
flex: 1;
|
|
772
|
+
height: 6px;
|
|
773
|
+
background: #e9ecef;
|
|
774
|
+
border-radius: 3px;
|
|
775
|
+
overflow: hidden;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
.progress-fill {
|
|
779
|
+
height: 100%;
|
|
780
|
+
background: linear-gradient(90deg, #667eea, #764ba2);
|
|
781
|
+
transition: width 0.3s ease;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
.progress-text {
|
|
785
|
+
font-size: 14px;
|
|
786
|
+
color: #6c757d;
|
|
787
|
+
font-weight: 500;
|
|
788
|
+
white-space: nowrap;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
.form-title {
|
|
792
|
+
font-size: 24px;
|
|
793
|
+
font-weight: 700;
|
|
794
|
+
color: #1a202c;
|
|
795
|
+
margin: 0;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
.form-navigation {
|
|
799
|
+
display: flex;
|
|
800
|
+
align-items: center;
|
|
801
|
+
justify-content: space-between;
|
|
802
|
+
padding: 16px 24px;
|
|
803
|
+
background: white;
|
|
804
|
+
border-bottom: 1px solid #e9ecef;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
.nav-button {
|
|
808
|
+
padding: 10px 20px;
|
|
809
|
+
border: none;
|
|
810
|
+
border-radius: 8px;
|
|
811
|
+
font-weight: 600;
|
|
812
|
+
cursor: pointer;
|
|
813
|
+
transition: all 0.2s ease;
|
|
814
|
+
min-width: 100px;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.nav-button.prev {
|
|
818
|
+
background: #f8f9fa;
|
|
819
|
+
color: #6c757d;
|
|
820
|
+
border: 1px solid #dee2e6;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
.nav-button.prev:hover:not(:disabled) {
|
|
824
|
+
background: #e9ecef;
|
|
825
|
+
border-color: #adb5bd;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
.nav-button.next {
|
|
829
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
830
|
+
color: white;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
.nav-button.next:hover {
|
|
834
|
+
transform: translateY(-1px);
|
|
835
|
+
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
.nav-button.complete {
|
|
839
|
+
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
|
|
840
|
+
color: white;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
.nav-button.complete:hover {
|
|
844
|
+
transform: translateY(-1px);
|
|
845
|
+
box-shadow: 0 4px 12px rgba(67, 233, 123, 0.4);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.nav-button:disabled {
|
|
849
|
+
opacity: 0.5;
|
|
850
|
+
cursor: not-allowed;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
.step-indicators {
|
|
854
|
+
display: flex;
|
|
855
|
+
gap: 8px;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.step-indicator {
|
|
859
|
+
width: 32px;
|
|
860
|
+
height: 32px;
|
|
861
|
+
border: 2px solid #e9ecef;
|
|
862
|
+
background: white;
|
|
863
|
+
color: #6c757d;
|
|
864
|
+
border-radius: 50%;
|
|
865
|
+
cursor: pointer;
|
|
866
|
+
font-weight: 600;
|
|
867
|
+
transition: all 0.2s ease;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
.step-indicator:hover {
|
|
871
|
+
border-color: #adb5bd;
|
|
872
|
+
color: #495057;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
.step-indicator.active {
|
|
876
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
877
|
+
border-color: #667eea;
|
|
878
|
+
color: white;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
.step-indicator.completed {
|
|
882
|
+
background: #28a745;
|
|
883
|
+
border-color: #28a745;
|
|
884
|
+
color: white;
|
|
885
|
+
}
|
|
886
|
+
</style>
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
### Dashboard with Sidebar
|
|
890
|
+
|
|
891
|
+
```vue
|
|
892
|
+
<script setup lang="ts">
|
|
893
|
+
import { ref } from "vue";
|
|
894
|
+
import { SlideoverController } from "@umbra-ui/core";
|
|
895
|
+
import DashboardMain from "./DashboardMain.vue";
|
|
896
|
+
import AnalyticsPanel from "./AnalyticsPanel.vue";
|
|
897
|
+
import NotificationsPanel from "./NotificationsPanel.vue";
|
|
898
|
+
import UserProfilePanel from "./UserProfilePanel.vue";
|
|
899
|
+
|
|
900
|
+
const panes = ref([
|
|
901
|
+
{
|
|
902
|
+
name: "Dashboard",
|
|
903
|
+
background: "#ffffff",
|
|
904
|
+
foreground: "#1a202c",
|
|
905
|
+
component: DashboardMain,
|
|
906
|
+
props: { title: "Main Dashboard" },
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
name: "Analytics",
|
|
910
|
+
background: "#f7fafc",
|
|
911
|
+
foreground: "#2d3748",
|
|
912
|
+
component: AnalyticsPanel,
|
|
913
|
+
props: { period: "30d" },
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
name: "Notifications",
|
|
917
|
+
background: "#edf2f7",
|
|
918
|
+
foreground: "#4a5568",
|
|
919
|
+
component: NotificationsPanel,
|
|
920
|
+
props: { unread: 5 },
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
name: "Profile",
|
|
924
|
+
background: "#e2e8f0",
|
|
925
|
+
foreground: "#718096",
|
|
926
|
+
component: UserProfilePanel,
|
|
927
|
+
props: { userId: "current" },
|
|
928
|
+
},
|
|
929
|
+
]);
|
|
930
|
+
|
|
931
|
+
const slideoverRef = ref();
|
|
932
|
+
const sidebarOpen = ref(false);
|
|
933
|
+
|
|
934
|
+
const toggleSidebar = () => {
|
|
935
|
+
sidebarOpen.value = !sidebarOpen.value;
|
|
936
|
+
if (sidebarOpen.value) {
|
|
937
|
+
slideoverRef.value?.showAll();
|
|
938
|
+
} else {
|
|
939
|
+
slideoverRef.value?.hideAll();
|
|
940
|
+
}
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
const navigateToPanel = (index: number) => {
|
|
944
|
+
slideoverRef.value?.navigate(index);
|
|
945
|
+
sidebarOpen.value = true;
|
|
946
|
+
};
|
|
947
|
+
</script>
|
|
948
|
+
|
|
949
|
+
<template>
|
|
950
|
+
<div class="dashboard-layout">
|
|
951
|
+
<!-- Top Navigation -->
|
|
952
|
+
<header class="dashboard-header">
|
|
953
|
+
<div class="header-left">
|
|
954
|
+
<button @click="toggleSidebar" class="menu-toggle">
|
|
955
|
+
<span class="hamburger"></span>
|
|
956
|
+
<span class="hamburger"></span>
|
|
957
|
+
<span class="hamburger"></span>
|
|
958
|
+
</button>
|
|
959
|
+
<h1 class="dashboard-title">Dashboard</h1>
|
|
960
|
+
</div>
|
|
961
|
+
|
|
962
|
+
<div class="header-right">
|
|
963
|
+
<button @click="navigateToPanel(2)" class="notification-btn">
|
|
964
|
+
🔔
|
|
965
|
+
<span class="notification-badge">5</span>
|
|
966
|
+
</button>
|
|
967
|
+
<button @click="navigateToPanel(3)" class="profile-btn">👤</button>
|
|
968
|
+
</div>
|
|
969
|
+
</header>
|
|
970
|
+
|
|
971
|
+
<!-- Quick Actions -->
|
|
972
|
+
<div class="quick-actions">
|
|
973
|
+
<button @click="navigateToPanel(0)" class="action-card">
|
|
974
|
+
<span class="action-icon">📊</span>
|
|
975
|
+
<span class="action-label">Dashboard</span>
|
|
976
|
+
</button>
|
|
977
|
+
<button @click="navigateToPanel(1)" class="action-card">
|
|
978
|
+
<span class="action-icon">📈</span>
|
|
979
|
+
<span class="action-label">Analytics</span>
|
|
980
|
+
</button>
|
|
981
|
+
<button @click="navigateToPanel(2)" class="action-card">
|
|
982
|
+
<span class="action-icon">🔔</span>
|
|
983
|
+
<span class="action-label">Notifications</span>
|
|
984
|
+
</button>
|
|
985
|
+
<button @click="navigateToPanel(3)" class="action-card">
|
|
986
|
+
<span class="action-icon">👤</span>
|
|
987
|
+
<span class="action-label">Profile</span>
|
|
988
|
+
</button>
|
|
989
|
+
</div>
|
|
990
|
+
|
|
991
|
+
<!-- Main Content -->
|
|
992
|
+
<SlideoverController
|
|
993
|
+
ref="slideoverRef"
|
|
994
|
+
:panes="panes"
|
|
995
|
+
component-id="dashboard-slideover"
|
|
996
|
+
:show-breadcrumb="true"
|
|
997
|
+
/>
|
|
998
|
+
</div>
|
|
999
|
+
</template>
|
|
1000
|
+
|
|
1001
|
+
<style module>
|
|
1002
|
+
.dashboard-layout {
|
|
1003
|
+
height: 100vh;
|
|
1004
|
+
display: flex;
|
|
1005
|
+
flex-direction: column;
|
|
1006
|
+
background: #f8f9fa;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
.dashboard-header {
|
|
1010
|
+
display: flex;
|
|
1011
|
+
justify-content: space-between;
|
|
1012
|
+
align-items: center;
|
|
1013
|
+
padding: 16px 24px;
|
|
1014
|
+
background: white;
|
|
1015
|
+
border-bottom: 1px solid #e9ecef;
|
|
1016
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
.header-left {
|
|
1020
|
+
display: flex;
|
|
1021
|
+
align-items: center;
|
|
1022
|
+
gap: 16px;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.menu-toggle {
|
|
1026
|
+
display: flex;
|
|
1027
|
+
flex-direction: column;
|
|
1028
|
+
gap: 3px;
|
|
1029
|
+
background: none;
|
|
1030
|
+
border: none;
|
|
1031
|
+
cursor: pointer;
|
|
1032
|
+
padding: 8px;
|
|
1033
|
+
border-radius: 4px;
|
|
1034
|
+
transition: background 0.2s ease;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
.menu-toggle:hover {
|
|
1038
|
+
background: #f8f9fa;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
.hamburger {
|
|
1042
|
+
width: 18px;
|
|
1043
|
+
height: 2px;
|
|
1044
|
+
background: #495057;
|
|
1045
|
+
border-radius: 1px;
|
|
1046
|
+
transition: all 0.2s ease;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.dashboard-title {
|
|
1050
|
+
font-size: 24px;
|
|
1051
|
+
font-weight: 700;
|
|
1052
|
+
color: #1a202c;
|
|
1053
|
+
margin: 0;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
.header-right {
|
|
1057
|
+
display: flex;
|
|
1058
|
+
align-items: center;
|
|
1059
|
+
gap: 12px;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
.notification-btn,
|
|
1063
|
+
.profile-btn {
|
|
1064
|
+
position: relative;
|
|
1065
|
+
width: 40px;
|
|
1066
|
+
height: 40px;
|
|
1067
|
+
border: none;
|
|
1068
|
+
background: #f8f9fa;
|
|
1069
|
+
border-radius: 50%;
|
|
1070
|
+
cursor: pointer;
|
|
1071
|
+
font-size: 18px;
|
|
1072
|
+
transition: all 0.2s ease;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
.notification-btn:hover,
|
|
1076
|
+
.profile-btn:hover {
|
|
1077
|
+
background: #e9ecef;
|
|
1078
|
+
transform: scale(1.05);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.notification-badge {
|
|
1082
|
+
position: absolute;
|
|
1083
|
+
top: -2px;
|
|
1084
|
+
right: -2px;
|
|
1085
|
+
width: 18px;
|
|
1086
|
+
height: 18px;
|
|
1087
|
+
background: #dc3545;
|
|
1088
|
+
color: white;
|
|
1089
|
+
border-radius: 50%;
|
|
1090
|
+
font-size: 10px;
|
|
1091
|
+
font-weight: 600;
|
|
1092
|
+
display: flex;
|
|
1093
|
+
align-items: center;
|
|
1094
|
+
justify-content: center;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
.quick-actions {
|
|
1098
|
+
display: flex;
|
|
1099
|
+
gap: 16px;
|
|
1100
|
+
padding: 20px 24px;
|
|
1101
|
+
background: white;
|
|
1102
|
+
border-bottom: 1px solid #e9ecef;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
.action-card {
|
|
1106
|
+
display: flex;
|
|
1107
|
+
flex-direction: column;
|
|
1108
|
+
align-items: center;
|
|
1109
|
+
gap: 8px;
|
|
1110
|
+
padding: 16px;
|
|
1111
|
+
background: #f8f9fa;
|
|
1112
|
+
border: 1px solid #e9ecef;
|
|
1113
|
+
border-radius: 8px;
|
|
1114
|
+
cursor: pointer;
|
|
1115
|
+
transition: all 0.2s ease;
|
|
1116
|
+
min-width: 80px;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
.action-card:hover {
|
|
1120
|
+
background: #e9ecef;
|
|
1121
|
+
border-color: #adb5bd;
|
|
1122
|
+
transform: translateY(-2px);
|
|
1123
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
.action-icon {
|
|
1127
|
+
font-size: 24px;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
.action-label {
|
|
1131
|
+
font-size: 12px;
|
|
1132
|
+
font-weight: 500;
|
|
1133
|
+
color: #495057;
|
|
1134
|
+
}
|
|
1135
|
+
</style>
|
|
1136
|
+
```
|
|
1137
|
+
|
|
1138
|
+
## Advanced Usage
|
|
1139
|
+
|
|
1140
|
+
### Custom Controller Integration
|
|
1141
|
+
|
|
1142
|
+
```vue
|
|
1143
|
+
<script setup lang="ts">
|
|
1144
|
+
import { ref } from "vue";
|
|
1145
|
+
import { SlideoverController, useSlideoverController } from "@umbra-ui/core";
|
|
1146
|
+
|
|
1147
|
+
const panes = ref([
|
|
1148
|
+
// ... your panes
|
|
1149
|
+
]);
|
|
1150
|
+
|
|
1151
|
+
// Create custom controller
|
|
1152
|
+
const customController = useSlideoverController(
|
|
1153
|
+
panes.value,
|
|
1154
|
+
"custom-slideover"
|
|
1155
|
+
);
|
|
1156
|
+
|
|
1157
|
+
// Override methods with custom logic
|
|
1158
|
+
const customNavigate = (index: number, animated: boolean = true) => {
|
|
1159
|
+
console.log(`Navigating to pane ${index}`);
|
|
1160
|
+
customController.navigate(index, animated);
|
|
1161
|
+
};
|
|
1162
|
+
|
|
1163
|
+
const customShowAll = () => {
|
|
1164
|
+
console.log("Showing all panes");
|
|
1165
|
+
customController.showAll();
|
|
1166
|
+
};
|
|
1167
|
+
</script>
|
|
1168
|
+
|
|
1169
|
+
<template>
|
|
1170
|
+
<SlideoverController
|
|
1171
|
+
:panes="panes"
|
|
1172
|
+
:controller="customController"
|
|
1173
|
+
component-id="custom-slideover"
|
|
1174
|
+
/>
|
|
1175
|
+
</template>
|
|
1176
|
+
```
|
|
1177
|
+
|
|
1178
|
+
### Integration with Router
|
|
1179
|
+
|
|
1180
|
+
```vue
|
|
1181
|
+
<script setup lang="ts">
|
|
1182
|
+
import { ref, watch } from "vue";
|
|
1183
|
+
import { useRoute, useRouter } from "vue-router";
|
|
1184
|
+
import { SlideoverController } from "@umbra-ui/core";
|
|
1185
|
+
|
|
1186
|
+
const route = useRoute();
|
|
1187
|
+
const router = useRouter();
|
|
1188
|
+
const slideoverRef = ref();
|
|
1189
|
+
|
|
1190
|
+
const panes = ref([
|
|
1191
|
+
// ... your panes
|
|
1192
|
+
]);
|
|
1193
|
+
|
|
1194
|
+
// Sync with router
|
|
1195
|
+
watch(
|
|
1196
|
+
() => route.params.panel,
|
|
1197
|
+
(newPanel) => {
|
|
1198
|
+
const index = panes.value.findIndex((pane) => pane.name === newPanel);
|
|
1199
|
+
if (index !== -1) {
|
|
1200
|
+
slideoverRef.value?.navigate(index);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
);
|
|
1204
|
+
|
|
1205
|
+
const handleNavigation = (index: number) => {
|
|
1206
|
+
const pane = panes.value[index];
|
|
1207
|
+
router.push(`/dashboard/${pane.name.toLowerCase()}`);
|
|
1208
|
+
};
|
|
1209
|
+
</script>
|
|
1210
|
+
```
|
|
1211
|
+
|
|
1212
|
+
## Performance Considerations
|
|
1213
|
+
|
|
1214
|
+
- **Component Marking**: Always use `markRaw()` when passing components to prevent Vue's reactivity system from wrapping them
|
|
1215
|
+
- **Animation Performance**: GSAP FLIP animations are optimized for smooth 60fps performance
|
|
1216
|
+
- **Memory Management**: Panes are properly cleaned up when removed from the controller
|
|
1217
|
+
- **DOM Manipulation**: Efficient DOM manipulation using GSAP for optimal performance
|
|
1218
|
+
|
|
1219
|
+
## Accessibility
|
|
1220
|
+
|
|
1221
|
+
- **Keyboard Navigation**: Support for arrow keys and tab navigation
|
|
1222
|
+
- **Screen Reader Support**: Proper ARIA labels and roles
|
|
1223
|
+
- **Focus Management**: Focus is maintained during transitions
|
|
1224
|
+
- **High Contrast**: Supports high contrast mode
|
|
1225
|
+
|
|
1226
|
+
## Browser Support
|
|
1227
|
+
|
|
1228
|
+
- **Modern Browsers**: Chrome 88+, Firefox 85+, Safari 14+, Edge 88+
|
|
1229
|
+
- **Mobile Browsers**: iOS Safari 14+, Chrome Mobile 88+
|
|
1230
|
+
- **CSS Features**: Uses CSS Grid and modern layout features
|
|
1231
|
+
- **JavaScript**: Requires ES2020+ support
|
|
1232
|
+
|
|
1233
|
+
## Troubleshooting
|
|
1234
|
+
|
|
1235
|
+
### Common Issues
|
|
1236
|
+
|
|
1237
|
+
1. **Animations not working**: Ensure GSAP and FLIP plugin are properly imported
|
|
1238
|
+
2. **Panes not displaying**: Check that components are properly marked with `markRaw()`
|
|
1239
|
+
3. **Navigation not responding**: Verify the `componentId` is unique and consistent
|
|
1240
|
+
4. **Layout issues**: Ensure the container has a defined height
|
|
1241
|
+
|
|
1242
|
+
### Debug Mode
|
|
1243
|
+
|
|
1244
|
+
```vue
|
|
1245
|
+
<script setup lang="ts">
|
|
1246
|
+
import { ref, watch } from "vue";
|
|
1247
|
+
import { SlideoverController } from "@umbra-ui/core";
|
|
1248
|
+
|
|
1249
|
+
const slideoverRef = ref();
|
|
1250
|
+
|
|
1251
|
+
// Watch for navigation changes
|
|
1252
|
+
watch(
|
|
1253
|
+
() => slideoverRef.value?.currentPaneIndex,
|
|
1254
|
+
(newIndex) => {
|
|
1255
|
+
console.log("Current pane index:", newIndex);
|
|
1256
|
+
}
|
|
1257
|
+
);
|
|
1258
|
+
</script>
|
|
1259
|
+
```
|
|
1260
|
+
|
|
1261
|
+
## Migration Guide
|
|
1262
|
+
|
|
1263
|
+
### From v1 to v2
|
|
1264
|
+
|
|
1265
|
+
- `componentId` prop is now optional with auto-generation
|
|
1266
|
+
- Pane interface has been updated with new properties
|
|
1267
|
+
- Animation system has been refactored for better performance
|
|
1268
|
+
- Composable API has been enhanced with new methods
|
|
1269
|
+
|
|
1270
|
+
### Breaking Changes
|
|
1271
|
+
|
|
1272
|
+
- Removed automatic pane detection
|
|
1273
|
+
- Changed animation timing and easing
|
|
1274
|
+
- Updated CSS class structure
|
|
1275
|
+
- Modified event handling system
|