@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.
Files changed (272) hide show
  1. package/dist/components/controls/Dropdown/types.d.ts +5 -0
  2. package/dist/components/controls/Dropdown/types.d.ts.map +1 -0
  3. package/dist/components/controls/Dropdown/types.js +1 -0
  4. package/dist/components/controls/SegmentedControl/types.d.ts +6 -0
  5. package/dist/components/controls/SegmentedControl/types.d.ts.map +1 -0
  6. package/dist/components/controls/SegmentedControl/types.js +1 -0
  7. package/dist/components/dialogs/Alert/types.d.ts +7 -0
  8. package/dist/components/dialogs/Alert/types.d.ts.map +1 -0
  9. package/dist/components/dialogs/Alert/types.js +1 -0
  10. package/dist/components/dialogs/Toast/types.d.ts +34 -0
  11. package/dist/components/dialogs/Toast/types.d.ts.map +1 -0
  12. package/dist/components/dialogs/Toast/types.js +10 -0
  13. package/dist/components/dialogs/Toast/useToast.d.ts +36 -0
  14. package/dist/components/dialogs/Toast/useToast.d.ts.map +1 -0
  15. package/dist/components/dialogs/Toast/useToast.js +90 -0
  16. package/dist/components/indicators/Tooltip/tooltip.d.ts +3 -0
  17. package/dist/components/indicators/Tooltip/tooltip.d.ts.map +1 -0
  18. package/dist/components/indicators/Tooltip/tooltip.js +33 -0
  19. package/dist/components/indicators/Tooltip/types.d.ts +14 -0
  20. package/dist/components/indicators/Tooltip/types.d.ts.map +1 -0
  21. package/dist/components/indicators/Tooltip/types.js +1 -0
  22. package/dist/components/indicators/Tooltip/useTooltip.d.ts +18 -0
  23. package/dist/components/indicators/Tooltip/useTooltip.d.ts.map +1 -0
  24. package/dist/components/indicators/Tooltip/useTooltip.js +57 -0
  25. package/dist/components/inputs/Tags/tag-bar-styles.d.ts +14 -0
  26. package/dist/components/inputs/Tags/tag-bar-styles.d.ts.map +1 -0
  27. package/dist/components/inputs/Tags/tag-bar-styles.js +313 -0
  28. package/dist/components/inputs/Tags/types.d.ts +93 -0
  29. package/dist/components/inputs/Tags/types.d.ts.map +1 -0
  30. package/dist/components/inputs/Tags/types.js +216 -0
  31. package/dist/components/inputs/search/types.d.ts +9 -0
  32. package/dist/components/inputs/search/types.d.ts.map +1 -0
  33. package/dist/components/inputs/search/types.js +1 -0
  34. package/dist/components/navigation/adaptive/types.d.ts +16 -0
  35. package/dist/components/navigation/adaptive/types.d.ts.map +1 -0
  36. package/dist/components/navigation/adaptive/types.js +1 -0
  37. package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts +27 -0
  38. package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts.map +1 -0
  39. package/dist/components/navigation/adaptive/useAdaptiveLayout.js +40 -0
  40. package/dist/components/navigation/adaptive/useBreakpoints.d.ts +6 -0
  41. package/dist/components/navigation/adaptive/useBreakpoints.d.ts.map +1 -0
  42. package/dist/components/navigation/adaptive/useBreakpoints.js +37 -0
  43. package/dist/components/navigation/adaptive/useContainerMonitor.d.ts +93 -0
  44. package/dist/components/navigation/adaptive/useContainerMonitor.d.ts.map +1 -0
  45. package/dist/components/navigation/adaptive/useContainerMonitor.js +145 -0
  46. package/dist/components/navigation/adaptive/useViewAnimation.d.ts +31 -0
  47. package/dist/components/navigation/adaptive/useViewAnimation.d.ts.map +1 -0
  48. package/dist/components/navigation/adaptive/useViewAnimation.js +591 -0
  49. package/dist/components/navigation/adaptive/useViewResize.d.ts +52 -0
  50. package/dist/components/navigation/adaptive/useViewResize.d.ts.map +1 -0
  51. package/dist/components/navigation/adaptive/useViewResize.js +146 -0
  52. package/dist/components/navigation/navstack/useNavigationStack.d.ts +25 -0
  53. package/dist/components/navigation/navstack/useNavigationStack.d.ts.map +1 -0
  54. package/dist/components/navigation/navstack/useNavigationStack.js +133 -0
  55. package/dist/components/navigation/slideover/useSlideoverController.d.ts +20 -0
  56. package/dist/components/navigation/slideover/useSlideoverController.d.ts.map +1 -0
  57. package/dist/components/navigation/slideover/useSlideoverController.js +267 -0
  58. package/dist/components/navigation/splitview/useSplitViewController.d.ts +20 -0
  59. package/dist/components/navigation/splitview/useSplitViewController.d.ts.map +1 -0
  60. package/dist/components/navigation/splitview/useSplitViewController.js +325 -0
  61. package/dist/components/navigation/tabcontroller/types.d.ts +21 -0
  62. package/dist/components/navigation/tabcontroller/types.d.ts.map +1 -0
  63. package/dist/components/navigation/tabcontroller/types.js +1 -0
  64. package/dist/components/navigation/tabcontroller/useTabController.d.ts +5 -0
  65. package/dist/components/navigation/tabcontroller/useTabController.d.ts.map +1 -0
  66. package/dist/components/navigation/tabcontroller/useTabController.js +10 -0
  67. package/dist/components/navigation/types.d.ts +8 -0
  68. package/dist/components/navigation/types.d.ts.map +1 -0
  69. package/dist/components/navigation/types.js +1 -0
  70. package/dist/components/pickers/CollectionPicker/types.d.ts +11 -0
  71. package/dist/components/pickers/CollectionPicker/types.d.ts.map +1 -0
  72. package/dist/components/pickers/CollectionPicker/types.js +1 -0
  73. package/dist/components/pickers/ColorPicker/colors.d.ts +13 -0
  74. package/dist/components/pickers/ColorPicker/colors.d.ts.map +1 -0
  75. package/dist/components/pickers/ColorPicker/colors.js +266 -0
  76. package/dist/components/pickers/FilePicker/types.d.ts +10 -0
  77. package/dist/components/pickers/FilePicker/types.d.ts.map +1 -0
  78. package/dist/components/pickers/FilePicker/types.js +1 -0
  79. package/dist/index.d.ts +91 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +196 -0
  82. package/dist/theme.d.ts +73 -0
  83. package/dist/theme.d.ts.map +1 -0
  84. package/dist/theme.js +279 -0
  85. package/dist/themes/blank.d.ts +7 -0
  86. package/dist/themes/blank.d.ts.map +1 -0
  87. package/dist/themes/blank.js +543 -0
  88. package/dist/themes/crimson-dark.d.ts +4 -0
  89. package/dist/themes/crimson-dark.d.ts.map +1 -0
  90. package/dist/themes/crimson-dark.js +552 -0
  91. package/dist/themes/cyan-light.d.ts +4 -0
  92. package/dist/themes/cyan-light.d.ts.map +1 -0
  93. package/dist/themes/cyan-light.js +552 -0
  94. package/dist/themes/dark.d.ts +4 -0
  95. package/dist/themes/dark.d.ts.map +1 -0
  96. package/dist/themes/dark.js +551 -0
  97. package/dist/themes/gold-dark.d.ts +4 -0
  98. package/dist/themes/gold-dark.d.ts.map +1 -0
  99. package/dist/themes/gold-dark.js +552 -0
  100. package/dist/themes/grass-dark.d.ts +4 -0
  101. package/dist/themes/grass-dark.d.ts.map +1 -0
  102. package/dist/themes/grass-dark.js +552 -0
  103. package/dist/themes/indigo.d.ts +4 -0
  104. package/dist/themes/indigo.d.ts.map +1 -0
  105. package/dist/themes/indigo.js +552 -0
  106. package/dist/themes/light.d.ts +4 -0
  107. package/dist/themes/light.d.ts.map +1 -0
  108. package/dist/themes/light.js +551 -0
  109. package/dist/themes/orange-dark.d.ts +4 -0
  110. package/dist/themes/orange-dark.d.ts.map +1 -0
  111. package/dist/themes/orange-dark.js +551 -0
  112. package/dist/themes/orange-light.d.ts +4 -0
  113. package/dist/themes/orange-light.d.ts.map +1 -0
  114. package/dist/themes/orange-light.js +551 -0
  115. package/package.json +62 -0
  116. package/src/components/controls/Button/Button.vue +417 -0
  117. package/src/components/controls/Button/README.md +348 -0
  118. package/src/components/controls/Button/theme.css +200 -0
  119. package/src/components/controls/Checkbox/Checkbox.vue +164 -0
  120. package/src/components/controls/Checkbox/README.md +441 -0
  121. package/src/components/controls/Checkbox/theme.css +36 -0
  122. package/src/components/controls/Dropdown/Dropdown.vue +476 -0
  123. package/src/components/controls/Dropdown/README.md +370 -0
  124. package/src/components/controls/Dropdown/theme.css +50 -0
  125. package/src/components/controls/Dropdown/types.ts +6 -0
  126. package/src/components/controls/IconButton/IconButton.vue +267 -0
  127. package/src/components/controls/IconButton/README.md +502 -0
  128. package/src/components/controls/IconButton/theme.css +89 -0
  129. package/src/components/controls/Radio/README.md +591 -0
  130. package/src/components/controls/Radio/Radio.vue +89 -0
  131. package/src/components/controls/Radio/theme.css +14 -0
  132. package/src/components/controls/RangeSlider/README.md +608 -0
  133. package/src/components/controls/RangeSlider/RangeSlider.vue +535 -0
  134. package/src/components/controls/RangeSlider/theme.css +80 -0
  135. package/src/components/controls/SegmentedControl/README.md +587 -0
  136. package/src/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
  137. package/src/components/controls/SegmentedControl/theme.css +60 -0
  138. package/src/components/controls/SegmentedControl/types.ts +5 -0
  139. package/src/components/controls/Slider/README.md +627 -0
  140. package/src/components/controls/Slider/Slider.vue +260 -0
  141. package/src/components/controls/Slider/theme.css +74 -0
  142. package/src/components/controls/Stepper/README.md +601 -0
  143. package/src/components/controls/Stepper/Stepper.vue +103 -0
  144. package/src/components/controls/Stepper/theme.css +53 -0
  145. package/src/components/controls/Switch/README.md +667 -0
  146. package/src/components/controls/Switch/Switch.vue +127 -0
  147. package/src/components/controls/Switch/theme.css +42 -0
  148. package/src/components/dialogs/Alert/Alert.vue +218 -0
  149. package/src/components/dialogs/Alert/README.md +450 -0
  150. package/src/components/dialogs/Alert/theme.css +44 -0
  151. package/src/components/dialogs/Alert/types.ts +11 -0
  152. package/src/components/dialogs/Toast/README.md +522 -0
  153. package/src/components/dialogs/Toast/Toast.vue +296 -0
  154. package/src/components/dialogs/Toast/ToastContainer.vue +330 -0
  155. package/src/components/dialogs/Toast/theme.css +44 -0
  156. package/src/components/dialogs/Toast/types.ts +46 -0
  157. package/src/components/dialogs/Toast/useToast.ts +127 -0
  158. package/src/components/indicators/ProgressBar/ProgressBar.vue +98 -0
  159. package/src/components/indicators/ProgressBar/README.md +744 -0
  160. package/src/components/indicators/ProgressBar/theme.css +36 -0
  161. package/src/components/indicators/Tooltip/README.md +723 -0
  162. package/src/components/indicators/Tooltip/TooltipProvider.vue +142 -0
  163. package/src/components/indicators/Tooltip/theme.css +18 -0
  164. package/src/components/indicators/Tooltip/tooltip.ts +48 -0
  165. package/src/components/indicators/Tooltip/types.ts +15 -0
  166. package/src/components/indicators/Tooltip/useTooltip.ts +71 -0
  167. package/src/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
  168. package/src/components/inputs/AutogrowTextView/README.md +643 -0
  169. package/src/components/inputs/AutogrowTextView/theme.css +28 -0
  170. package/src/components/inputs/InputCard/InputCard.vue +600 -0
  171. package/src/components/inputs/InputCard/README.md +636 -0
  172. package/src/components/inputs/InputEmail/InputEmail.vue +698 -0
  173. package/src/components/inputs/InputEmail/README.md +764 -0
  174. package/src/components/inputs/InputNumber/InputNumber.vue +300 -0
  175. package/src/components/inputs/InputNumber/README.md +749 -0
  176. package/src/components/inputs/InputPhone/InputPhone.vue +645 -0
  177. package/src/components/inputs/InputPhone/README.md +636 -0
  178. package/src/components/inputs/InputSecure/InputSecure.vue +646 -0
  179. package/src/components/inputs/InputSecure/README.md +771 -0
  180. package/src/components/inputs/InputText/InputText.vue +225 -0
  181. package/src/components/inputs/InputText/README.md +844 -0
  182. package/src/components/inputs/OTP/OTP.vue +349 -0
  183. package/src/components/inputs/OTP/README.md +736 -0
  184. package/src/components/inputs/OTP/theme.css +50 -0
  185. package/src/components/inputs/StringCapture/README.md +718 -0
  186. package/src/components/inputs/StringCapture/StringCapture.vue +315 -0
  187. package/src/components/inputs/StringCapture/theme.css +86 -0
  188. package/src/components/inputs/Tags/README.md +897 -0
  189. package/src/components/inputs/Tags/TagBar.vue +793 -0
  190. package/src/components/inputs/Tags/TagCreation.vue +219 -0
  191. package/src/components/inputs/Tags/TagPicker.vue +380 -0
  192. package/src/components/inputs/Tags/tag-bar-styles.ts +354 -0
  193. package/src/components/inputs/Tags/theme.css +121 -0
  194. package/src/components/inputs/Tags/types.ts +346 -0
  195. package/src/components/inputs/search/README.md +759 -0
  196. package/src/components/inputs/search/SearchBar.vue +394 -0
  197. package/src/components/inputs/search/SearchResults.vue +310 -0
  198. package/src/components/inputs/search/theme.css +187 -0
  199. package/src/components/inputs/search/types.ts +8 -0
  200. package/src/components/inputs/theme.css +102 -0
  201. package/src/components/menus/ActionMenu/ActionMenu.vue +383 -0
  202. package/src/components/menus/ActionMenu/README.md +825 -0
  203. package/src/components/menus/ActionMenu/theme.css +93 -0
  204. package/src/components/models/Popover/Popover.vue +551 -0
  205. package/src/components/models/Popover/README.md +885 -0
  206. package/src/components/models/Popover/theme.css +52 -0
  207. package/src/components/models/Sheet/README.md +1159 -0
  208. package/src/components/models/Sheet/Sheet.vue +465 -0
  209. package/src/components/models/Sheet/theme.css +72 -0
  210. package/src/components/models/Sidebar/README.md +1228 -0
  211. package/src/components/models/Sidebar/Sidebar.vue +480 -0
  212. package/src/components/models/Sidebar/theme.css +90 -0
  213. package/src/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
  214. package/src/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
  215. package/src/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
  216. package/src/components/navigation/adaptive/README.md +768 -0
  217. package/src/components/navigation/adaptive/types.ts +19 -0
  218. package/src/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
  219. package/src/components/navigation/adaptive/useBreakpoints.ts +41 -0
  220. package/src/components/navigation/adaptive/useContainerMonitor.ts +214 -0
  221. package/src/components/navigation/adaptive/useViewAnimation.ts +721 -0
  222. package/src/components/navigation/adaptive/useViewResize.ts +211 -0
  223. package/src/components/navigation/navstack/NavigationStack.vue +180 -0
  224. package/src/components/navigation/navstack/README.md +994 -0
  225. package/src/components/navigation/navstack/useNavigationStack.ts +164 -0
  226. package/src/components/navigation/slideover/README.md +1275 -0
  227. package/src/components/navigation/slideover/SlideoverController.vue +287 -0
  228. package/src/components/navigation/slideover/useSlideoverController.ts +320 -0
  229. package/src/components/navigation/splitview/README.md +1115 -0
  230. package/src/components/navigation/splitview/SplitViewController.vue +176 -0
  231. package/src/components/navigation/splitview/useSplitViewController.ts +388 -0
  232. package/src/components/navigation/tabcontroller/README.md +919 -0
  233. package/src/components/navigation/tabcontroller/TabController.vue +307 -0
  234. package/src/components/navigation/tabcontroller/TabItem.vue +57 -0
  235. package/src/components/navigation/tabcontroller/types.ts +24 -0
  236. package/src/components/navigation/tabcontroller/useTabController.ts +18 -0
  237. package/src/components/navigation/theme.css +91 -0
  238. package/src/components/navigation/types.ts +7 -0
  239. package/src/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
  240. package/src/components/pickers/CollectionPicker/README.md +1115 -0
  241. package/src/components/pickers/CollectionPicker/theme.css +14 -0
  242. package/src/components/pickers/CollectionPicker/types.ts +11 -0
  243. package/src/components/pickers/ColorPicker/ColorPicker.vue +376 -0
  244. package/src/components/pickers/ColorPicker/README.md +1439 -0
  245. package/src/components/pickers/ColorPicker/colors.ts +299 -0
  246. package/src/components/pickers/ColorPicker/theme.css +32 -0
  247. package/src/components/pickers/DatePicker/DatePicker.vue +660 -0
  248. package/src/components/pickers/DatePicker/README.md +1195 -0
  249. package/src/components/pickers/DatePicker/theme.css +22 -0
  250. package/src/components/pickers/FilePicker/FilePicker.vue +534 -0
  251. package/src/components/pickers/FilePicker/README.md +1542 -0
  252. package/src/components/pickers/FilePicker/theme.css +48 -0
  253. package/src/components/pickers/FilePicker/types.ts +10 -0
  254. package/src/components/pickers/IconPicker/IconPicker.vue +327 -0
  255. package/src/components/pickers/IconPicker/README.md +1161 -0
  256. package/src/components/pickers/IconPicker/theme.css +28 -0
  257. package/src/components/pickers/theme.css +82 -0
  258. package/src/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
  259. package/src/components/views/MarkdownViewer/README.md +833 -0
  260. package/src/components/views/MarkdownViewer/theme.css +130 -0
  261. package/src/index.ts +263 -0
  262. package/src/theme.ts +378 -0
  263. package/src/themes/crimson-dark.ts +556 -0
  264. package/src/themes/cyan-light.ts +556 -0
  265. package/src/themes/dark.ts +557 -0
  266. package/src/themes/gold-dark.ts +556 -0
  267. package/src/themes/grass-dark.ts +556 -0
  268. package/src/themes/indigo.ts +556 -0
  269. package/src/themes/light.ts +557 -0
  270. package/src/themes/orange-dark.ts +557 -0
  271. package/src/themes/orange-light.ts +557 -0
  272. package/src/vue.d.ts +45 -0
@@ -0,0 +1,1228 @@
1
+ # Sidebar
2
+
3
+ A flexible and animated sidebar component built with Vue 3 Composition API and TypeScript. The Sidebar component provides a powerful interface for displaying navigation panels, menus, and contextual content with smooth slide animations and comprehensive positioning options.
4
+
5
+ ## Installation/Import
6
+
7
+ ```typescript
8
+ import { Sidebar } from "@umbra-ui/core";
9
+ import type { SidebarProps } from "@umbra-ui/core";
10
+ ```
11
+
12
+ **Dependencies:**
13
+
14
+ - Vue 3.x
15
+ - gsap (for animations)
16
+
17
+ ## Basic Usage
18
+
19
+ ```vue
20
+ <script setup lang="ts">
21
+ import { ref } from "vue";
22
+ import { Sidebar, Button } from "@umbra-ui/core";
23
+
24
+ const isSidebarOpen = ref(false);
25
+
26
+ const handleOpen = () => {
27
+ console.log("Sidebar opened");
28
+ };
29
+
30
+ const handleClose = () => {
31
+ console.log("Sidebar closed");
32
+ };
33
+
34
+ const handleBackdropClick = () => {
35
+ console.log("Backdrop clicked");
36
+ };
37
+ </script>
38
+
39
+ <template>
40
+ <div>
41
+ <Button @click="isSidebarOpen = true">Open Sidebar</Button>
42
+
43
+ <Sidebar
44
+ v-model="isSidebarOpen"
45
+ side="left"
46
+ :dismiss-on-backdrop="true"
47
+ @open="handleOpen"
48
+ @close="handleClose"
49
+ @backdrop-click="handleBackdropClick"
50
+ >
51
+ <div class="sidebar-content">
52
+ <h2>Sidebar Title</h2>
53
+ <p>This is the sidebar content. It can contain any HTML elements.</p>
54
+ <Button @click="isSidebarOpen = false">Close</Button>
55
+ </div>
56
+ </Sidebar>
57
+ </div>
58
+ </template>
59
+
60
+ <style>
61
+ .sidebar-content {
62
+ padding: 2rem;
63
+ min-height: 200px;
64
+ }
65
+ </style>
66
+ ```
67
+
68
+ ## Props
69
+
70
+ | Prop Name | Type | Required | Default | Description |
71
+ | ------------------- | ---------------------------------------- | -------- | --------- | ------------------------------------------------ |
72
+ | `modelValue` | `boolean` | Yes | - | Controls the open/closed state of the sidebar |
73
+ | `side` | `"top" \| "bottom" \| "left" \| "right"` | No | `"left"` | The side where the sidebar appears |
74
+ | `dismissOnBackdrop` | `boolean` | No | `true` | Whether clicking the backdrop closes the sidebar |
75
+ | `width` | `string` | No | `"280px"` | Width of the sidebar (for left/right) |
76
+ | `height` | `string` | No | `"280px"` | Height of the sidebar (for top/bottom) |
77
+ | `minWidth` | `string` | No | `"280px"` | Minimum width of the sidebar |
78
+ | `minHeight` | `string` | No | `"280px"` | Minimum height of the sidebar |
79
+ | `maxWidth` | `string` | No | `"90vw"` | Maximum width of the sidebar |
80
+ | `maxHeight` | `string` | No | `"90vh"` | Maximum height of the sidebar |
81
+ | `animationDuration` | `number` | No | `0.4` | Animation duration in seconds |
82
+ | `backdropStyle` | `"blur" \| "dim"` | No | `"blur"` | Backdrop style: blur or dim |
83
+ | `zIndex` | `number` | No | `1000` | Z-index for the sidebar |
84
+ | `teleportTo` | `string \| HTMLElement` | No | `"body"` | Teleport target element |
85
+
86
+ ## Events
87
+
88
+ | Event Name | Payload Type | Description |
89
+ | ------------------- | ------------ | ------------------------------------------- |
90
+ | `update:modelValue` | `boolean` | Emitted when the sidebar open state changes |
91
+ | `backdrop-click` | `void` | Emitted when the backdrop is clicked |
92
+ | `open` | `void` | Emitted when the sidebar opens |
93
+ | `close` | `void` | Emitted when the sidebar closes |
94
+ | `after-enter` | `void` | Emitted after the open animation completes |
95
+ | `after-leave` | `void` | Emitted after the close animation completes |
96
+
97
+ ## Slots
98
+
99
+ | Slot Name | Description |
100
+ | --------- | ---------------------------------------- |
101
+ | `default` | The content displayed inside the sidebar |
102
+
103
+ ## Exposed Methods/Refs
104
+
105
+ The Sidebar component exposes the following methods and properties via template refs:
106
+
107
+ | Method/Property | Type | Description |
108
+ | --------------- | -------------- | -------------------------------------- |
109
+ | `open` | `() => void` | Opens the sidebar programmatically |
110
+ | `close` | `() => void` | Closes the sidebar programmatically |
111
+ | `isVisible` | `Ref<boolean>` | Reactive reference to visibility state |
112
+ | `isAnimating` | `Ref<boolean>` | Reactive reference to animation state |
113
+
114
+ ### Example Usage
115
+
116
+ ```vue
117
+ <script setup lang="ts">
118
+ import { ref } from "vue";
119
+ import { Sidebar } from "@umbra-ui/core";
120
+
121
+ const sidebarRef = ref<InstanceType<typeof Sidebar> | null>(null);
122
+
123
+ const openSidebar = () => {
124
+ sidebarRef.value?.open();
125
+ };
126
+
127
+ const closeSidebar = () => {
128
+ sidebarRef.value?.close();
129
+ };
130
+ </script>
131
+
132
+ <template>
133
+ <Sidebar ref="sidebarRef" :model-value="false">
134
+ <div class="content">
135
+ <p>Sidebar content</p>
136
+ <button @click="closeSidebar">Close</button>
137
+ </div>
138
+ </Sidebar>
139
+ </template>
140
+ ```
141
+
142
+ ## Positioning Options
143
+
144
+ ### Left Sidebar
145
+
146
+ - **Default position**
147
+ - Slides in from the left edge
148
+ - Full height with configurable width
149
+ - Best for navigation menus and main content panels
150
+
151
+ ### Right Sidebar
152
+
153
+ - Slides in from the right edge
154
+ - Full height with configurable width
155
+ - Good for secondary actions and settings panels
156
+
157
+ ### Top Sidebar
158
+
159
+ - Slides in from the top edge
160
+ - Full width with configurable height
161
+ - Useful for notification bars and top navigation
162
+
163
+ ### Bottom Sidebar
164
+
165
+ - Slides in from the bottom edge
166
+ - Full width with configurable height
167
+ - Good for mobile navigation and action sheets
168
+
169
+ ## Backdrop Styles
170
+
171
+ ### Blur Backdrop
172
+
173
+ - **Default backdrop style**
174
+ - Semi-transparent with blur effect
175
+ - Modern, iOS-like appearance
176
+ - Uses `backdrop-filter: blur(10px)`
177
+
178
+ ### Dim Backdrop
179
+
180
+ - Simple semi-transparent overlay
181
+ - No blur effect
182
+ - More traditional modal appearance
183
+ - Better performance on older devices
184
+
185
+ ## CSS Customization
186
+
187
+ The Sidebar component uses CSS custom properties for theming and customization:
188
+
189
+ ### Light Theme Variables
190
+
191
+ ```css
192
+ /* Sidebar colors */
193
+ --sidebar-bg: #ffffff;
194
+
195
+ /* Sidebar backdrop colors */
196
+ --sidebar-backdrop-blur-bg: rgba(0, 0, 0, 0.3);
197
+ --sidebar-backdrop-dim-bg: rgba(0, 0, 0, 0.7);
198
+
199
+ /* Sidebar shadow colors */
200
+ --sidebar-shadow-left: rgba(0, 0, 0, 0.15);
201
+ --sidebar-shadow-right: rgba(0, 0, 0, 0.15);
202
+ --sidebar-shadow-top: rgba(0, 0, 0, 0.15);
203
+ --sidebar-shadow-bottom: rgba(0, 0, 0, 0.15);
204
+
205
+ /* Sidebar scrollbar colors */
206
+ --sidebar-scrollbar-thumb: rgba(0, 0, 0, 0.2);
207
+ --sidebar-scrollbar-thumb-hover: rgba(0, 0, 0, 0.3);
208
+ ```
209
+
210
+ ### Dark Theme Variables
211
+
212
+ ```css
213
+ /* Sidebar colors */
214
+ --sidebar-bg: #111111;
215
+
216
+ /* Sidebar backdrop colors */
217
+ --sidebar-backdrop-blur-bg: rgba(0, 0, 0, 0.3);
218
+ --sidebar-backdrop-dim-bg: rgba(0, 0, 0, 0.85);
219
+
220
+ /* Sidebar shadow colors */
221
+ --sidebar-shadow-left: rgba(0, 0, 0, 0.5);
222
+ --sidebar-shadow-right: rgba(0, 0, 0, 0.5);
223
+ --sidebar-shadow-top: rgba(0, 0, 0, 0.5);
224
+ --sidebar-shadow-bottom: rgba(0, 0, 0, 0.5);
225
+
226
+ /* Sidebar scrollbar colors */
227
+ --sidebar-scrollbar-thumb: rgba(255, 255, 255, 0.2);
228
+ --sidebar-scrollbar-thumb-hover: rgba(255, 255, 255, 0.3);
229
+ ```
230
+
231
+ ## Key Features
232
+
233
+ ### Smart Positioning
234
+
235
+ - **Four Directions**: Slide in from top, bottom, left, or right
236
+ - **Responsive Sizing**: Configurable width, height, and constraints
237
+ - **Viewport Awareness**: Automatically respects viewport boundaries
238
+ - **Safe Area Support**: Handles mobile device safe areas
239
+
240
+ ### Animation System
241
+
242
+ - **GSAP Animations**: Smooth, performant animations using GSAP
243
+ - **Slide Animations**: Directional slide-in/out effects
244
+ - **GPU Acceleration**: Hardware-accelerated transforms
245
+ - **Customizable Duration**: Configurable animation timing
246
+
247
+ ### User Experience
248
+
249
+ - **Backdrop Interaction**: Click backdrop to dismiss (configurable)
250
+ - **Keyboard Support**: Escape key closes sidebar
251
+ - **Body Scroll Lock**: Prevents background scrolling when open
252
+ - **Teleport Support**: Renders outside component tree
253
+
254
+ ### Visual Features
255
+
256
+ - **Directional Shadows**: Shadows adapt to sidebar position
257
+ - **Custom Scrollbars**: Styled scrollbars for better UX
258
+ - **Backdrop Effects**: Blur or dim backdrop options
259
+ - **Safe Area Handling**: Proper mobile device support
260
+
261
+ ## Examples
262
+
263
+ ### Basic Sidebar
264
+
265
+ ```vue
266
+ <script setup lang="ts">
267
+ import { ref } from "vue";
268
+ import { Sidebar, Button } from "@umbra-ui/core";
269
+
270
+ const isOpen = ref(false);
271
+
272
+ const handleOpen = () => {
273
+ console.log("Sidebar opened");
274
+ };
275
+
276
+ const handleClose = () => {
277
+ console.log("Sidebar closed");
278
+ };
279
+ </script>
280
+
281
+ <template>
282
+ <div class="basic-sidebar">
283
+ <h3>Basic Sidebar</h3>
284
+
285
+ <Button @click="isOpen = true">Open Sidebar</Button>
286
+
287
+ <Sidebar
288
+ v-model="isOpen"
289
+ side="left"
290
+ :dismiss-on-backdrop="true"
291
+ @open="handleOpen"
292
+ @close="handleClose"
293
+ >
294
+ <div class="sidebar-content">
295
+ <h2>Sidebar Title</h2>
296
+ <p>This is a basic sidebar with default settings.</p>
297
+ <p>
298
+ It slides in from the left and can be dismissed by clicking the
299
+ backdrop.
300
+ </p>
301
+ <div class="actions">
302
+ <Button @click="isOpen = false">Close</Button>
303
+ </div>
304
+ </div>
305
+ </Sidebar>
306
+
307
+ <p class="status">Sidebar is {{ isOpen ? "open" : "closed" }}</p>
308
+ </div>
309
+ </template>
310
+
311
+ <style module>
312
+ .basic-sidebar {
313
+ padding: 2rem;
314
+ border: 1px solid #e0e0e0;
315
+ border-radius: 0.5rem;
316
+ max-width: 400px;
317
+ }
318
+
319
+ .sidebar-content {
320
+ padding: 2rem;
321
+ min-height: 200px;
322
+ }
323
+
324
+ .sidebar-content h2 {
325
+ margin: 0 0 1rem 0;
326
+ color: #333;
327
+ }
328
+
329
+ .sidebar-content p {
330
+ margin: 0 0 1rem 0;
331
+ color: #666;
332
+ line-height: 1.5;
333
+ }
334
+
335
+ .actions {
336
+ display: flex;
337
+ gap: 0.75rem;
338
+ justify-content: flex-end;
339
+ margin-top: 1.5rem;
340
+ }
341
+
342
+ .status {
343
+ margin-top: 1rem;
344
+ color: #666;
345
+ font-size: 0.875rem;
346
+ }
347
+ </style>
348
+ ```
349
+
350
+ ### Different Sides
351
+
352
+ ```vue
353
+ <script setup lang="ts">
354
+ import { ref } from "vue";
355
+ import { Sidebar, Button } from "@umbra-ui/core";
356
+
357
+ const sides = ["left", "right", "top", "bottom"];
358
+ const openSidebars = ref<Record<string, boolean>>({});
359
+
360
+ const toggleSidebar = (side: string) => {
361
+ openSidebars.value[side] = !openSidebars.value[side];
362
+ };
363
+ </script>
364
+
365
+ <template>
366
+ <div class="sides-demo">
367
+ <h3>Sidebar Sides</h3>
368
+ <p>Click the buttons to see different slide directions:</p>
369
+
370
+ <div class="sides-grid">
371
+ <div v-for="side in sides" :key="side" class="side-item">
372
+ <Button @click="toggleSidebar(side)" size="small">
373
+ {{ side }}
374
+ </Button>
375
+
376
+ <Sidebar
377
+ v-model="openSidebars[side]"
378
+ :side="side"
379
+ :dismiss-on-backdrop="true"
380
+ >
381
+ <div class="side-content">
382
+ <h4>{{ side }} Sidebar</h4>
383
+ <p>This sidebar slides in from the {{ side }}.</p>
384
+ <Button @click="openSidebars[side] = false" size="small">
385
+ Close
386
+ </Button>
387
+ </div>
388
+ </Sidebar>
389
+ </div>
390
+ </div>
391
+ </div>
392
+ </template>
393
+
394
+ <style module>
395
+ .sides-demo {
396
+ padding: 2rem;
397
+ border: 1px solid #e0e0e0;
398
+ border-radius: 0.5rem;
399
+ max-width: 600px;
400
+ }
401
+
402
+ .sides-grid {
403
+ display: grid;
404
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
405
+ gap: 1rem;
406
+ margin-top: 1rem;
407
+ }
408
+
409
+ .side-item {
410
+ display: flex;
411
+ justify-content: center;
412
+ align-items: center;
413
+ min-height: 60px;
414
+ }
415
+
416
+ .side-content {
417
+ padding: 1.5rem;
418
+ min-height: 150px;
419
+ text-align: center;
420
+ }
421
+
422
+ .side-content h4 {
423
+ margin: 0 0 1rem 0;
424
+ color: #333;
425
+ text-transform: capitalize;
426
+ }
427
+
428
+ .side-content p {
429
+ margin: 0 0 1rem 0;
430
+ color: #666;
431
+ }
432
+ </style>
433
+ ```
434
+
435
+ ### Navigation Sidebar
436
+
437
+ ```vue
438
+ <script setup lang="ts">
439
+ import { ref } from "vue";
440
+ import { Sidebar, Button } from "@umbra-ui/core";
441
+
442
+ const isNavOpen = ref(false);
443
+ const activeItem = ref("dashboard");
444
+
445
+ const navItems = [
446
+ { id: "dashboard", label: "Dashboard", icon: "🏠" },
447
+ { id: "projects", label: "Projects", icon: "📁" },
448
+ { id: "tasks", label: "Tasks", icon: "✅" },
449
+ { id: "calendar", label: "Calendar", icon: "📅" },
450
+ { id: "messages", label: "Messages", icon: "💬" },
451
+ { id: "settings", label: "Settings", icon: "⚙️" },
452
+ ];
453
+
454
+ const handleNavClick = (itemId: string) => {
455
+ activeItem.value = itemId;
456
+ console.log("Navigated to:", itemId);
457
+ };
458
+ </script>
459
+
460
+ <template>
461
+ <div class="nav-sidebar">
462
+ <h3>Navigation Sidebar</h3>
463
+
464
+ <Button @click="isNavOpen = true">Open Navigation</Button>
465
+
466
+ <Sidebar
467
+ v-model="isNavOpen"
468
+ side="left"
469
+ width="280px"
470
+ :dismiss-on-backdrop="true"
471
+ >
472
+ <div class="nav-content">
473
+ <div class="nav-header">
474
+ <h2>Navigation</h2>
475
+ <button @click="isNavOpen = false" class="close-btn">×</button>
476
+ </div>
477
+
478
+ <nav class="nav-menu">
479
+ <div
480
+ v-for="item in navItems"
481
+ :key="item.id"
482
+ :class="[
483
+ 'nav-item',
484
+ { 'nav-item--active': activeItem === item.id },
485
+ ]"
486
+ @click="handleNavClick(item.id)"
487
+ >
488
+ <span class="nav-icon">{{ item.icon }}</span>
489
+ <span class="nav-label">{{ item.label }}</span>
490
+ </div>
491
+ </nav>
492
+
493
+ <div class="nav-footer">
494
+ <div class="user-info">
495
+ <div class="user-avatar">👤</div>
496
+ <div class="user-details">
497
+ <div class="user-name">John Doe</div>
498
+ <div class="user-email">john@example.com</div>
499
+ </div>
500
+ </div>
501
+ </div>
502
+ </div>
503
+ </Sidebar>
504
+ </div>
505
+ </template>
506
+
507
+ <style module>
508
+ .nav-sidebar {
509
+ padding: 2rem;
510
+ border: 1px solid #e0e0e0;
511
+ border-radius: 0.5rem;
512
+ max-width: 400px;
513
+ }
514
+
515
+ .nav-content {
516
+ height: 100vh;
517
+ display: flex;
518
+ flex-direction: column;
519
+ }
520
+
521
+ .nav-header {
522
+ display: flex;
523
+ justify-content: space-between;
524
+ align-items: center;
525
+ padding: 1.5rem 2rem 1rem;
526
+ border-bottom: 1px solid #e0e0e0;
527
+ }
528
+
529
+ .nav-header h2 {
530
+ margin: 0;
531
+ color: #333;
532
+ }
533
+
534
+ .close-btn {
535
+ background: none;
536
+ border: none;
537
+ font-size: 1.5rem;
538
+ cursor: pointer;
539
+ padding: 0;
540
+ width: 32px;
541
+ height: 32px;
542
+ display: flex;
543
+ align-items: center;
544
+ justify-content: center;
545
+ border-radius: 50%;
546
+ color: #666;
547
+ transition: background-color 0.2s;
548
+ }
549
+
550
+ .close-btn:hover {
551
+ background-color: #f0f0f0;
552
+ }
553
+
554
+ .nav-menu {
555
+ flex: 1;
556
+ padding: 1rem 0;
557
+ }
558
+
559
+ .nav-item {
560
+ display: flex;
561
+ align-items: center;
562
+ gap: 1rem;
563
+ padding: 0.75rem 2rem;
564
+ cursor: pointer;
565
+ transition: background-color 0.2s;
566
+ color: #666;
567
+ }
568
+
569
+ .nav-item:hover {
570
+ background-color: #f8f9fa;
571
+ }
572
+
573
+ .nav-item--active {
574
+ background-color: #e3f2fd;
575
+ color: #1976d2;
576
+ border-right: 3px solid #1976d2;
577
+ }
578
+
579
+ .nav-icon {
580
+ font-size: 1.25rem;
581
+ width: 1.5rem;
582
+ text-align: center;
583
+ }
584
+
585
+ .nav-label {
586
+ font-weight: 500;
587
+ }
588
+
589
+ .nav-footer {
590
+ padding: 1.5rem 2rem;
591
+ border-top: 1px solid #e0e0e0;
592
+ }
593
+
594
+ .user-info {
595
+ display: flex;
596
+ align-items: center;
597
+ gap: 0.75rem;
598
+ }
599
+
600
+ .user-avatar {
601
+ width: 40px;
602
+ height: 40px;
603
+ background-color: #e0e0e0;
604
+ border-radius: 50%;
605
+ display: flex;
606
+ align-items: center;
607
+ justify-content: center;
608
+ font-size: 1.25rem;
609
+ }
610
+
611
+ .user-name {
612
+ font-weight: 600;
613
+ color: #333;
614
+ margin-bottom: 0.25rem;
615
+ }
616
+
617
+ .user-email {
618
+ font-size: 0.875rem;
619
+ color: #666;
620
+ }
621
+ </style>
622
+ ```
623
+
624
+ ### Settings Panel
625
+
626
+ ```vue
627
+ <script setup lang="ts">
628
+ import { ref } from "vue";
629
+ import { Sidebar, Button } from "@umbra-ui/core";
630
+
631
+ const isSettingsOpen = ref(false);
632
+ const settings = ref({
633
+ notifications: true,
634
+ darkMode: false,
635
+ autoSave: true,
636
+ language: "en",
637
+ });
638
+
639
+ const handleSave = () => {
640
+ console.log("Settings saved:", settings.value);
641
+ isSettingsOpen.value = false;
642
+ };
643
+ </script>
644
+
645
+ <template>
646
+ <div class="settings-sidebar">
647
+ <h3>Settings Panel</h3>
648
+
649
+ <Button @click="isSettingsOpen = true">Open Settings</Button>
650
+
651
+ <Sidebar
652
+ v-model="isSettingsOpen"
653
+ side="right"
654
+ width="350px"
655
+ :dismiss-on-backdrop="false"
656
+ >
657
+ <div class="settings-content">
658
+ <div class="settings-header">
659
+ <h2>Settings</h2>
660
+ <button @click="isSettingsOpen = false" class="close-btn">×</button>
661
+ </div>
662
+
663
+ <div class="settings-body">
664
+ <div class="setting-group">
665
+ <h3>Preferences</h3>
666
+
667
+ <div class="setting-item">
668
+ <div class="setting-info">
669
+ <h4>Notifications</h4>
670
+ <p>Receive push notifications</p>
671
+ </div>
672
+ <label class="toggle">
673
+ <input v-model="settings.notifications" type="checkbox" />
674
+ <span class="slider"></span>
675
+ </label>
676
+ </div>
677
+
678
+ <div class="setting-item">
679
+ <div class="setting-info">
680
+ <h4>Dark Mode</h4>
681
+ <p>Use dark theme</p>
682
+ </div>
683
+ <label class="toggle">
684
+ <input v-model="settings.darkMode" type="checkbox" />
685
+ <span class="slider"></span>
686
+ </label>
687
+ </div>
688
+
689
+ <div class="setting-item">
690
+ <div class="setting-info">
691
+ <h4>Auto Save</h4>
692
+ <p>Automatically save changes</p>
693
+ </div>
694
+ <label class="toggle">
695
+ <input v-model="settings.autoSave" type="checkbox" />
696
+ <span class="slider"></span>
697
+ </label>
698
+ </div>
699
+ </div>
700
+
701
+ <div class="setting-group">
702
+ <h3>Language</h3>
703
+
704
+ <div class="setting-item">
705
+ <div class="setting-info">
706
+ <h4>Language</h4>
707
+ <p>Select your preferred language</p>
708
+ </div>
709
+ <select v-model="settings.language" class="select">
710
+ <option value="en">English</option>
711
+ <option value="es">Spanish</option>
712
+ <option value="fr">French</option>
713
+ <option value="de">German</option>
714
+ </select>
715
+ </div>
716
+ </div>
717
+ </div>
718
+
719
+ <div class="settings-footer">
720
+ <Button @click="isSettingsOpen = false" variant="secondary">
721
+ Cancel
722
+ </Button>
723
+ <Button @click="handleSave">Save Changes</Button>
724
+ </div>
725
+ </div>
726
+ </Sidebar>
727
+ </div>
728
+ </template>
729
+
730
+ <style module>
731
+ .settings-sidebar {
732
+ padding: 2rem;
733
+ border: 1px solid #e0e0e0;
734
+ border-radius: 0.5rem;
735
+ max-width: 400px;
736
+ }
737
+
738
+ .settings-content {
739
+ height: 100vh;
740
+ display: flex;
741
+ flex-direction: column;
742
+ }
743
+
744
+ .settings-header {
745
+ display: flex;
746
+ justify-content: space-between;
747
+ align-items: center;
748
+ padding: 1.5rem 2rem 1rem;
749
+ border-bottom: 1px solid #e0e0e0;
750
+ }
751
+
752
+ .settings-header h2 {
753
+ margin: 0;
754
+ color: #333;
755
+ }
756
+
757
+ .close-btn {
758
+ background: none;
759
+ border: none;
760
+ font-size: 1.5rem;
761
+ cursor: pointer;
762
+ padding: 0;
763
+ width: 32px;
764
+ height: 32px;
765
+ display: flex;
766
+ align-items: center;
767
+ justify-content: center;
768
+ border-radius: 50%;
769
+ color: #666;
770
+ transition: background-color 0.2s;
771
+ }
772
+
773
+ .close-btn:hover {
774
+ background-color: #f0f0f0;
775
+ }
776
+
777
+ .settings-body {
778
+ flex: 1;
779
+ padding: 2rem;
780
+ overflow-y: auto;
781
+ }
782
+
783
+ .setting-group {
784
+ margin-bottom: 2rem;
785
+ }
786
+
787
+ .setting-group h3 {
788
+ margin: 0 0 1rem 0;
789
+ color: #333;
790
+ font-size: 1.125rem;
791
+ }
792
+
793
+ .setting-item {
794
+ display: flex;
795
+ justify-content: space-between;
796
+ align-items: center;
797
+ padding: 1rem 0;
798
+ border-bottom: 1px solid #f0f0f0;
799
+ }
800
+
801
+ .setting-info h4 {
802
+ margin: 0 0 0.25rem 0;
803
+ color: #333;
804
+ font-size: 1rem;
805
+ }
806
+
807
+ .setting-info p {
808
+ margin: 0;
809
+ color: #666;
810
+ font-size: 0.875rem;
811
+ }
812
+
813
+ .toggle {
814
+ position: relative;
815
+ display: inline-block;
816
+ width: 50px;
817
+ height: 24px;
818
+ }
819
+
820
+ .toggle input {
821
+ opacity: 0;
822
+ width: 0;
823
+ height: 0;
824
+ }
825
+
826
+ .slider {
827
+ position: absolute;
828
+ cursor: pointer;
829
+ top: 0;
830
+ left: 0;
831
+ right: 0;
832
+ bottom: 0;
833
+ background-color: #ccc;
834
+ transition: 0.2s;
835
+ border-radius: 24px;
836
+ }
837
+
838
+ .slider:before {
839
+ position: absolute;
840
+ content: "";
841
+ height: 18px;
842
+ width: 18px;
843
+ left: 3px;
844
+ bottom: 3px;
845
+ background-color: white;
846
+ transition: 0.2s;
847
+ border-radius: 50%;
848
+ }
849
+
850
+ input:checked + .slider {
851
+ background-color: #007bff;
852
+ }
853
+
854
+ input:checked + .slider:before {
855
+ transform: translateX(26px);
856
+ }
857
+
858
+ .select {
859
+ padding: 0.5rem;
860
+ border: 1px solid #ddd;
861
+ border-radius: 0.25rem;
862
+ background-color: white;
863
+ color: #333;
864
+ }
865
+
866
+ .settings-footer {
867
+ display: flex;
868
+ gap: 0.75rem;
869
+ justify-content: flex-end;
870
+ padding: 1.5rem 2rem;
871
+ border-top: 1px solid #e0e0e0;
872
+ }
873
+ </style>
874
+ ```
875
+
876
+ ### Custom Styled Sidebar
877
+
878
+ ```vue
879
+ <script setup lang="ts">
880
+ import { ref } from "vue";
881
+ import { Sidebar, Button } from "@umbra-ui/core";
882
+
883
+ const isCustomOpen = ref(false);
884
+ </script>
885
+
886
+ <template>
887
+ <div class="custom-sidebar">
888
+ <h3>Custom Styled Sidebar</h3>
889
+
890
+ <Button @click="isCustomOpen = true" class="custom-trigger">
891
+ Open Custom Sidebar
892
+ </Button>
893
+
894
+ <Sidebar
895
+ v-model="isCustomOpen"
896
+ side="right"
897
+ width="400px"
898
+ :animation-duration="0.6"
899
+ backdrop-style="dim"
900
+ >
901
+ <div class="custom-content">
902
+ <div class="custom-header">
903
+ <h2>Custom Sidebar</h2>
904
+ <p>This sidebar has custom styling and positioning.</p>
905
+ </div>
906
+
907
+ <div class="custom-body">
908
+ <div class="feature-list">
909
+ <div class="feature-item">
910
+ <div class="feature-icon">🎨</div>
911
+ <div class="feature-text">
912
+ <h4>Custom Colors</h4>
913
+ <p>Gradient backgrounds and custom styling</p>
914
+ </div>
915
+ </div>
916
+
917
+ <div class="feature-item">
918
+ <div class="feature-icon">⚡</div>
919
+ <div class="feature-text">
920
+ <h4>Right Side</h4>
921
+ <p>Slides in from the right side</p>
922
+ </div>
923
+ </div>
924
+
925
+ <div class="feature-item">
926
+ <div class="feature-icon">🔧</div>
927
+ <div class="feature-text">
928
+ <h4>Custom Size</h4>
929
+ <p>Fixed width and custom dimensions</p>
930
+ </div>
931
+ </div>
932
+ </div>
933
+ </div>
934
+
935
+ <div class="custom-footer">
936
+ <Button @click="isCustomOpen = false" class="custom-close">
937
+ Close
938
+ </Button>
939
+ </div>
940
+ </div>
941
+ </Sidebar>
942
+ </div>
943
+ </template>
944
+
945
+ <style module>
946
+ .custom-sidebar {
947
+ padding: 2rem;
948
+ border: 1px solid #e0e0e0;
949
+ border-radius: 0.5rem;
950
+ max-width: 400px;
951
+ }
952
+
953
+ .custom-trigger {
954
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
955
+ color: white;
956
+ border: none;
957
+ padding: 0.75rem 1.5rem;
958
+ border-radius: 0.5rem;
959
+ font-weight: 600;
960
+ transition: transform 0.2s;
961
+ }
962
+
963
+ .custom-trigger:hover {
964
+ transform: translateY(-2px);
965
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
966
+ }
967
+
968
+ .custom-content {
969
+ height: 100vh;
970
+ display: flex;
971
+ flex-direction: column;
972
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
973
+ color: white;
974
+ }
975
+
976
+ .custom-header {
977
+ padding: 2rem;
978
+ text-align: center;
979
+ background: rgba(255, 255, 255, 0.1);
980
+ backdrop-filter: blur(10px);
981
+ }
982
+
983
+ .custom-header h2 {
984
+ margin: 0 0 0.5rem 0;
985
+ font-size: 1.5rem;
986
+ }
987
+
988
+ .custom-header p {
989
+ margin: 0;
990
+ opacity: 0.9;
991
+ }
992
+
993
+ .custom-body {
994
+ flex: 1;
995
+ padding: 2rem;
996
+ overflow-y: auto;
997
+ }
998
+
999
+ .feature-list {
1000
+ display: flex;
1001
+ flex-direction: column;
1002
+ gap: 1.5rem;
1003
+ }
1004
+
1005
+ .feature-item {
1006
+ display: flex;
1007
+ align-items: flex-start;
1008
+ gap: 1rem;
1009
+ padding: 1rem;
1010
+ background: rgba(255, 255, 255, 0.1);
1011
+ border-radius: 0.5rem;
1012
+ backdrop-filter: blur(5px);
1013
+ }
1014
+
1015
+ .feature-icon {
1016
+ font-size: 1.5rem;
1017
+ width: 2rem;
1018
+ text-align: center;
1019
+ }
1020
+
1021
+ .feature-text h4 {
1022
+ margin: 0 0 0.25rem 0;
1023
+ font-size: 1rem;
1024
+ }
1025
+
1026
+ .feature-text p {
1027
+ margin: 0;
1028
+ font-size: 0.875rem;
1029
+ opacity: 0.8;
1030
+ }
1031
+
1032
+ .custom-footer {
1033
+ padding: 2rem;
1034
+ background: rgba(255, 255, 255, 0.1);
1035
+ backdrop-filter: blur(10px);
1036
+ display: flex;
1037
+ justify-content: center;
1038
+ }
1039
+
1040
+ .custom-close {
1041
+ background: rgba(255, 255, 255, 0.2);
1042
+ color: white;
1043
+ border: 1px solid rgba(255, 255, 255, 0.3);
1044
+ padding: 0.75rem 2rem;
1045
+ border-radius: 0.5rem;
1046
+ font-weight: 600;
1047
+ transition: all 0.2s;
1048
+ }
1049
+
1050
+ .custom-close:hover {
1051
+ background: rgba(255, 255, 255, 0.3);
1052
+ transform: translateY(-1px);
1053
+ }
1054
+
1055
+ /* Override sidebar CSS variables */
1056
+ :global(.custom-sidebar) {
1057
+ --sidebar-bg: transparent;
1058
+ --sidebar-backdrop-dim-bg: rgba(0, 0, 0, 0.8);
1059
+ }
1060
+ </style>
1061
+ ```
1062
+
1063
+ ### Mobile Action Sheet
1064
+
1065
+ ```vue
1066
+ <script setup lang="ts">
1067
+ import { ref } from "vue";
1068
+ import { Sidebar, Button } from "@umbra-ui/core";
1069
+
1070
+ const isActionSheetOpen = ref(false);
1071
+
1072
+ const actions = [
1073
+ { id: "edit", label: "Edit", icon: "✏️", color: "#007bff" },
1074
+ { id: "share", label: "Share", icon: "📤", color: "#28a745" },
1075
+ { id: "download", label: "Download", icon: "⬇️", color: "#6c757d" },
1076
+ { id: "delete", label: "Delete", icon: "🗑️", color: "#dc3545" },
1077
+ ];
1078
+
1079
+ const handleAction = (actionId: string) => {
1080
+ console.log("Action selected:", actionId);
1081
+ isActionSheetOpen.value = false;
1082
+ };
1083
+ </script>
1084
+
1085
+ <template>
1086
+ <div class="action-sheet">
1087
+ <h3>Mobile Action Sheet</h3>
1088
+ <p>
1089
+ This example shows a mobile-style action sheet using the bottom sidebar:
1090
+ </p>
1091
+
1092
+ <Button @click="isActionSheetOpen = true">Show Actions</Button>
1093
+
1094
+ <Sidebar
1095
+ v-model="isActionSheetOpen"
1096
+ side="bottom"
1097
+ height="auto"
1098
+ min-height="200px"
1099
+ max-height="400px"
1100
+ :dismiss-on-backdrop="true"
1101
+ >
1102
+ <div class="action-sheet-content">
1103
+ <div class="action-sheet-header">
1104
+ <h3>Choose an Action</h3>
1105
+ <p>Select what you'd like to do with this item</p>
1106
+ </div>
1107
+
1108
+ <div class="action-list">
1109
+ <button
1110
+ v-for="action in actions"
1111
+ :key="action.id"
1112
+ class="action-item"
1113
+ :style="{ '--action-color': action.color }"
1114
+ @click="handleAction(action.id)"
1115
+ >
1116
+ <span class="action-icon">{{ action.icon }}</span>
1117
+ <span class="action-label">{{ action.label }}</span>
1118
+ </button>
1119
+ </div>
1120
+
1121
+ <div class="action-sheet-footer">
1122
+ <Button
1123
+ @click="isActionSheetOpen = false"
1124
+ variant="secondary"
1125
+ class="cancel-btn"
1126
+ >
1127
+ Cancel
1128
+ </Button>
1129
+ </div>
1130
+ </div>
1131
+ </Sidebar>
1132
+ </div>
1133
+ </template>
1134
+
1135
+ <style module>
1136
+ .action-sheet {
1137
+ padding: 2rem;
1138
+ border: 1px solid #e0e0e0;
1139
+ border-radius: 0.5rem;
1140
+ max-width: 400px;
1141
+ }
1142
+
1143
+ .action-sheet-content {
1144
+ padding: 1rem;
1145
+ }
1146
+
1147
+ .action-sheet-header {
1148
+ text-align: center;
1149
+ padding: 1rem 0 2rem;
1150
+ border-bottom: 1px solid #e0e0e0;
1151
+ }
1152
+
1153
+ .action-sheet-header h3 {
1154
+ margin: 0 0 0.5rem 0;
1155
+ color: #333;
1156
+ }
1157
+
1158
+ .action-sheet-header p {
1159
+ margin: 0;
1160
+ color: #666;
1161
+ font-size: 0.875rem;
1162
+ }
1163
+
1164
+ .action-list {
1165
+ padding: 1rem 0;
1166
+ }
1167
+
1168
+ .action-item {
1169
+ display: flex;
1170
+ align-items: center;
1171
+ gap: 1rem;
1172
+ width: 100%;
1173
+ padding: 1rem;
1174
+ border: none;
1175
+ background: none;
1176
+ text-align: left;
1177
+ cursor: pointer;
1178
+ transition: background-color 0.2s;
1179
+ border-radius: 0.5rem;
1180
+ margin-bottom: 0.5rem;
1181
+ }
1182
+
1183
+ .action-item:hover {
1184
+ background-color: #f8f9fa;
1185
+ }
1186
+
1187
+ .action-item:last-child {
1188
+ margin-bottom: 0;
1189
+ }
1190
+
1191
+ .action-icon {
1192
+ font-size: 1.25rem;
1193
+ width: 2rem;
1194
+ text-align: center;
1195
+ }
1196
+
1197
+ .action-label {
1198
+ font-weight: 500;
1199
+ color: var(--action-color, #333);
1200
+ }
1201
+
1202
+ .action-sheet-footer {
1203
+ padding: 1rem 0 0;
1204
+ border-top: 1px solid #e0e0e0;
1205
+ text-align: center;
1206
+ }
1207
+
1208
+ .cancel-btn {
1209
+ width: 100%;
1210
+ }
1211
+ </style>
1212
+ ```
1213
+
1214
+ ## Technical Notes
1215
+
1216
+ - Sidebar provides a comprehensive overlay system with smooth animations and flexible positioning
1217
+ - GSAP animations ensure smooth, performant transitions with hardware acceleration
1218
+ - Teleport usage ensures proper z-index layering and positioning outside component tree
1219
+ - Body scroll locking prevents background scrolling when sidebar is open
1220
+ - Safe area support handles mobile device notches and home indicators
1221
+ - Directional shadows adapt to sidebar position for better visual depth
1222
+ - Custom scrollbar styling provides better visual consistency
1223
+ - Backdrop blur effects create modern, iOS-like appearance
1224
+ - Keyboard navigation includes Escape key support for accessibility
1225
+ - TypeScript interfaces ensure type safety for all props and events
1226
+ - CSS custom properties enable easy theming and customization
1227
+ - Responsive design adapts to different screen sizes and orientations
1228
+ - Animation cleanup prevents memory leaks and ensures smooth performance