@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,885 @@
1
+ # Popover
2
+
3
+ A flexible and feature-rich popover component built with Vue 3 Composition API and TypeScript. The Popover component provides a powerful interface for displaying contextual content with smart positioning, smooth animations, and comprehensive customization options.
4
+
5
+ ## Installation/Import
6
+
7
+ ```typescript
8
+ import { Popover } from "@umbra-ui/core";
9
+ import type { PopoverProps } from "@umbra-ui/core";
10
+ ```
11
+
12
+ **Dependencies:**
13
+
14
+ - Vue 3.x
15
+ - @floating-ui/vue (for positioning)
16
+ - gsap (for animations)
17
+
18
+ ## Basic Usage
19
+
20
+ ```vue
21
+ <script setup lang="ts">
22
+ import { ref } from "vue";
23
+ import { Popover, Button } from "@umbra-ui/core";
24
+
25
+ const isPopoverOpen = ref(false);
26
+
27
+ const handleOpen = () => {
28
+ console.log("Popover opened");
29
+ };
30
+
31
+ const handleClose = () => {
32
+ console.log("Popover closed");
33
+ };
34
+ </script>
35
+
36
+ <template>
37
+ <div>
38
+ <Popover
39
+ v-model="isPopoverOpen"
40
+ placement="bottom"
41
+ :show-arrow="true"
42
+ @open="handleOpen"
43
+ @close="handleClose"
44
+ >
45
+ <template #trigger>
46
+ <Button>Open Popover</Button>
47
+ </template>
48
+
49
+ <div class="popover-content">
50
+ <h3>Popover Title</h3>
51
+ <p>This is the popover content. It can contain any HTML elements.</p>
52
+ <Button @click="isPopoverOpen = false">Close</Button>
53
+ </div>
54
+ </Popover>
55
+ </div>
56
+ </template>
57
+
58
+ <style>
59
+ .popover-content {
60
+ padding: 1rem;
61
+ min-width: 200px;
62
+ }
63
+ </style>
64
+ ```
65
+
66
+ ## Props
67
+
68
+ | Prop Name | Type | Required | Default | Description |
69
+ | ----------------------- | -------------------- | -------- | ---------- | --------------------------------------------- |
70
+ | `modelValue` | `boolean` | Yes | - | Controls the open/closed state of the popover |
71
+ | `placement` | `Placement` | No | `"bottom"` | Placement relative to trigger element |
72
+ | `offsetDistance` | `number` | No | `8` | Distance from trigger element in pixels |
73
+ | `dismissOnClickOutside` | `boolean` | No | `true` | Whether clicking outside closes the popover |
74
+ | `showArrow` | `boolean` | No | `true` | Whether to show an arrow pointing to trigger |
75
+ | `showOverlay` | `boolean` | No | `false` | Whether to show a backdrop overlay |
76
+ | `overlayOpacity` | `number` | No | `0.5` | Overlay opacity (0-1) |
77
+ | `animationDuration` | `number` | No | `0.2` | Animation duration in seconds |
78
+ | `zIndex` | `number` | No | `1000` | Z-index for the popover |
79
+ | `viewportPadding` | `number` | No | `16` | Padding from viewport edges |
80
+ | `maxWidth` | `string` | No | `"none"` | Maximum width of the popover |
81
+ | `maxHeight` | `string` | No | `"none"` | Maximum height of the popover |
82
+ | `trigger` | `"click" \| "hover"` | No | `"click"` | Trigger event type |
83
+ | `hoverShowDelay` | `number` | No | `0` | Delay before showing on hover (ms) |
84
+ | `hoverHideDelay` | `number` | No | `0` | Delay before hiding on hover (ms) |
85
+
86
+ ## Events
87
+
88
+ | Event Name | Payload Type | Description |
89
+ | ------------------- | ------------ | ------------------------------------------- |
90
+ | `update:modelValue` | `boolean` | Emitted when the popover open state changes |
91
+ | `open` | `void` | Emitted when the popover opens |
92
+ | `close` | `void` | Emitted when the popover closes |
93
+ | `after-enter` | `void` | Emitted after the open animation completes |
94
+ | `after-leave` | `void` | Emitted after the close animation completes |
95
+
96
+ ## Slots
97
+
98
+ | Slot Name | Description |
99
+ | --------- | ---------------------------------------- |
100
+ | `trigger` | The element that triggers the popover |
101
+ | `default` | The content displayed inside the popover |
102
+
103
+ ## Exposed Methods/Refs
104
+
105
+ The Popover component exposes the following methods and properties via template refs:
106
+
107
+ | Method/Property | Type | Description |
108
+ | ---------------- | -------------- | -------------------------------------- |
109
+ | `open` | `() => void` | Opens the popover programmatically |
110
+ | `close` | `() => void` | Closes the popover programmatically |
111
+ | `isVisible` | `Ref<boolean>` | Reactive reference to visibility state |
112
+ | `isAnimating` | `Ref<boolean>` | Reactive reference to animation state |
113
+ | `updatePosition` | `() => void` | Updates the popover position |
114
+
115
+ ### Example Usage
116
+
117
+ ```vue
118
+ <script setup lang="ts">
119
+ import { ref } from "vue";
120
+ import { Popover } from "@umbra-ui/core";
121
+
122
+ const popoverRef = ref<InstanceType<typeof Popover> | null>(null);
123
+
124
+ const openPopover = () => {
125
+ popoverRef.value?.open();
126
+ };
127
+
128
+ const closePopover = () => {
129
+ popoverRef.value?.close();
130
+ };
131
+
132
+ const updatePosition = () => {
133
+ popoverRef.value?.updatePosition();
134
+ };
135
+ </script>
136
+
137
+ <template>
138
+ <Popover ref="popoverRef" :model-value="false">
139
+ <template #trigger>
140
+ <button @click="openPopover">Open</button>
141
+ </template>
142
+
143
+ <div class="content">
144
+ <p>Popover content</p>
145
+ <button @click="closePopover">Close</button>
146
+ </div>
147
+ </Popover>
148
+ </template>
149
+ ```
150
+
151
+ ## Placement Options
152
+
153
+ The `placement` prop accepts the following values from Floating UI:
154
+
155
+ - `"top"` - Above the trigger
156
+ - `"top-start"` - Above the trigger, aligned to start
157
+ - `"top-end"` - Above the trigger, aligned to end
158
+ - `"bottom"` - Below the trigger (default)
159
+ - `"bottom-start"` - Below the trigger, aligned to start
160
+ - `"bottom-end"` - Below the trigger, aligned to end
161
+ - `"left"` - To the left of the trigger
162
+ - `"left-start"` - To the left of the trigger, aligned to start
163
+ - `"left-end"` - To the left of the trigger, aligned to end
164
+ - `"right"` - To the right of the trigger
165
+ - `"right-start"` - To the right of the trigger, aligned to start
166
+ - `"right-end"` - To the right of the trigger, aligned to end
167
+
168
+ ## CSS Customization
169
+
170
+ The Popover component uses CSS custom properties for theming and customization:
171
+
172
+ ### Light Theme Variables
173
+
174
+ ```css
175
+ /* Popover colors */
176
+ --popover-bg: #ffffff;
177
+ --popover-border: 1px solid rgba(0, 0, 0, 0.1);
178
+ --popover-shadow: none;
179
+ --popover-inset-shadow: rgba(255, 255, 255, 0.8);
180
+
181
+ /* Popover arrow colors */
182
+ --popover-arrow-bg: #ffffff;
183
+ --popover-arrow-shadow: rgba(0, 0, 0, 0.05);
184
+
185
+ /* Popover overlay colors */
186
+ --popover-overlay-bg: rgba(0, 0, 0, 0.5);
187
+ ```
188
+
189
+ ### Dark Theme Variables
190
+
191
+ ```css
192
+ /* Popover colors */
193
+ --popover-bg: #484848;
194
+ --popover-border: none;
195
+ --popover-shadow: rgba(0, 0, 0, 0.21);
196
+ --popover-inset-shadow: rgba(255, 255, 255, 0.1);
197
+
198
+ /* Popover arrow colors */
199
+ --popover-arrow-bg: #484848;
200
+ --popover-arrow-shadow: rgba(0, 0, 0, 0.05);
201
+
202
+ /* Popover overlay colors */
203
+ --popover-overlay-bg: rgba(0, 0, 0, 0.5);
204
+ ```
205
+
206
+ ## Key Features
207
+
208
+ ### Smart Positioning
209
+
210
+ - **Floating UI Integration**: Uses Floating UI for intelligent positioning
211
+ - **Auto-flip**: Automatically flips to opposite side if no space available
212
+ - **Auto-shift**: Shifts position to stay within viewport bounds
213
+ - **Viewport Padding**: Respects viewport boundaries with configurable padding
214
+
215
+ ### Animation System
216
+
217
+ - **GSAP Animations**: Smooth, performant animations using GSAP
218
+ - **Directional Animations**: Animations adapt to popover placement
219
+ - **Customizable Duration**: Configurable animation timing
220
+ - **Easing Functions**: Professional easing for natural motion
221
+
222
+ ### Trigger Options
223
+
224
+ - **Click Trigger**: Standard click-to-toggle behavior
225
+ - **Hover Trigger**: Hover to show with configurable delays
226
+ - **Keyboard Support**: Escape key closes popover
227
+ - **Click Outside**: Configurable click-outside-to-close
228
+
229
+ ### Visual Features
230
+
231
+ - **Arrow Support**: Optional arrow pointing to trigger element
232
+ - **Overlay Backdrop**: Optional semi-transparent overlay
233
+ - **Custom Styling**: Full CSS customization support
234
+ - **Z-index Management**: Configurable layering
235
+
236
+ ## Examples
237
+
238
+ ### Basic Popover
239
+
240
+ ```vue
241
+ <script setup lang="ts">
242
+ import { ref } from "vue";
243
+ import { Popover, Button } from "@umbra-ui/core";
244
+
245
+ const isOpen = ref(false);
246
+
247
+ const handleOpen = () => {
248
+ console.log("Popover opened");
249
+ };
250
+
251
+ const handleClose = () => {
252
+ console.log("Popover closed");
253
+ };
254
+ </script>
255
+
256
+ <template>
257
+ <div class="basic-popover">
258
+ <h3>Basic Popover</h3>
259
+
260
+ <Popover
261
+ v-model="isOpen"
262
+ placement="bottom"
263
+ :show-arrow="true"
264
+ @open="handleOpen"
265
+ @close="handleClose"
266
+ >
267
+ <template #trigger>
268
+ <Button>Click to Open</Button>
269
+ </template>
270
+
271
+ <div class="popover-content">
272
+ <h4>Popover Title</h4>
273
+ <p>This is a basic popover with default settings.</p>
274
+ <div class="actions">
275
+ <Button @click="isOpen = false" size="small">Close</Button>
276
+ </div>
277
+ </div>
278
+ </Popover>
279
+
280
+ <p class="status">Popover is {{ isOpen ? "open" : "closed" }}</p>
281
+ </div>
282
+ </template>
283
+
284
+ <style module>
285
+ .basic-popover {
286
+ padding: 2rem;
287
+ border: 1px solid #e0e0e0;
288
+ border-radius: 0.5rem;
289
+ max-width: 400px;
290
+ }
291
+
292
+ .popover-content {
293
+ padding: 1rem;
294
+ min-width: 200px;
295
+ }
296
+
297
+ .popover-content h4 {
298
+ margin: 0 0 0.5rem 0;
299
+ color: #333;
300
+ }
301
+
302
+ .popover-content p {
303
+ margin: 0 0 1rem 0;
304
+ color: #666;
305
+ line-height: 1.5;
306
+ }
307
+
308
+ .actions {
309
+ display: flex;
310
+ gap: 0.5rem;
311
+ justify-content: flex-end;
312
+ }
313
+
314
+ .status {
315
+ margin-top: 1rem;
316
+ color: #666;
317
+ font-size: 0.875rem;
318
+ }
319
+ </style>
320
+ ```
321
+
322
+ ### Hover Popover
323
+
324
+ ```vue
325
+ <script setup lang="ts">
326
+ import { ref } from "vue";
327
+ import { Popover, Button } from "@umbra-ui/core";
328
+
329
+ const isHoverOpen = ref(false);
330
+ </script>
331
+
332
+ <template>
333
+ <div class="hover-popover">
334
+ <h3>Hover Popover</h3>
335
+ <p>Hover over the button to see the popover:</p>
336
+
337
+ <Popover
338
+ v-model="isHoverOpen"
339
+ trigger="hover"
340
+ placement="top"
341
+ :hover-show-delay="300"
342
+ :hover-hide-delay="200"
343
+ :show-arrow="true"
344
+ >
345
+ <template #trigger>
346
+ <Button>Hover Me</Button>
347
+ </template>
348
+
349
+ <div class="popover-content">
350
+ <h4>Hover Popover</h4>
351
+ <p>This popover appears on hover with a delay.</p>
352
+ <ul>
353
+ <li>300ms delay before showing</li>
354
+ <li>200ms delay before hiding</li>
355
+ <li>Stays open while hovering over content</li>
356
+ </ul>
357
+ </div>
358
+ </Popover>
359
+ </div>
360
+ </template>
361
+
362
+ <style module>
363
+ .hover-popover {
364
+ padding: 2rem;
365
+ border: 1px solid #e0e0e0;
366
+ border-radius: 0.5rem;
367
+ max-width: 400px;
368
+ }
369
+
370
+ .popover-content {
371
+ padding: 1rem;
372
+ min-width: 250px;
373
+ }
374
+
375
+ .popover-content h4 {
376
+ margin: 0 0 0.5rem 0;
377
+ color: #333;
378
+ }
379
+
380
+ .popover-content p {
381
+ margin: 0 0 0.75rem 0;
382
+ color: #666;
383
+ }
384
+
385
+ .popover-content ul {
386
+ margin: 0;
387
+ padding-left: 1.25rem;
388
+ color: #666;
389
+ }
390
+
391
+ .popover-content li {
392
+ margin-bottom: 0.25rem;
393
+ }
394
+ </style>
395
+ ```
396
+
397
+ ### Popover with Overlay
398
+
399
+ ```vue
400
+ <script setup lang="ts">
401
+ import { ref } from "vue";
402
+ import { Popover, Button } from "@umbra-ui/core";
403
+
404
+ const isOverlayOpen = ref(false);
405
+ </script>
406
+
407
+ <template>
408
+ <div class="overlay-popover">
409
+ <h3>Popover with Overlay</h3>
410
+
411
+ <Popover
412
+ v-model="isOverlayOpen"
413
+ placement="center"
414
+ :show-overlay="true"
415
+ :overlay-opacity="0.7"
416
+ :dismiss-on-click-outside="true"
417
+ :show-arrow="false"
418
+ >
419
+ <template #trigger>
420
+ <Button>Open Modal Popover</Button>
421
+ </template>
422
+
423
+ <div class="modal-content">
424
+ <h4>Modal Popover</h4>
425
+ <p>This popover has a backdrop overlay and behaves like a modal.</p>
426
+ <p>Click outside or press Escape to close.</p>
427
+ <div class="actions">
428
+ <Button @click="isOverlayOpen = false" variant="secondary"
429
+ >Cancel</Button
430
+ >
431
+ <Button @click="isOverlayOpen = false">Confirm</Button>
432
+ </div>
433
+ </div>
434
+ </Popover>
435
+ </div>
436
+ </template>
437
+
438
+ <style module>
439
+ .overlay-popover {
440
+ padding: 2rem;
441
+ border: 1px solid #e0e0e0;
442
+ border-radius: 0.5rem;
443
+ max-width: 400px;
444
+ }
445
+
446
+ .modal-content {
447
+ padding: 1.5rem;
448
+ min-width: 300px;
449
+ text-align: center;
450
+ }
451
+
452
+ .modal-content h4 {
453
+ margin: 0 0 1rem 0;
454
+ color: #333;
455
+ }
456
+
457
+ .modal-content p {
458
+ margin: 0 0 0.75rem 0;
459
+ color: #666;
460
+ line-height: 1.5;
461
+ }
462
+
463
+ .actions {
464
+ display: flex;
465
+ gap: 0.75rem;
466
+ justify-content: center;
467
+ margin-top: 1.5rem;
468
+ }
469
+ </style>
470
+ ```
471
+
472
+ ### Different Placements
473
+
474
+ ```vue
475
+ <script setup lang="ts">
476
+ import { ref } from "vue";
477
+ import { Popover, Button } from "@umbra-ui/core";
478
+
479
+ const placements = [
480
+ "top",
481
+ "top-start",
482
+ "top-end",
483
+ "bottom",
484
+ "bottom-start",
485
+ "bottom-end",
486
+ "left",
487
+ "left-start",
488
+ "left-end",
489
+ "right",
490
+ "right-start",
491
+ "right-end",
492
+ ];
493
+
494
+ const openPopovers = ref<Record<string, boolean>>({});
495
+
496
+ const togglePopover = (placement: string) => {
497
+ openPopovers.value[placement] = !openPopovers.value[placement];
498
+ };
499
+ </script>
500
+
501
+ <template>
502
+ <div class="placement-demo">
503
+ <h3>Popover Placements</h3>
504
+ <p>Click the buttons to see different placement options:</p>
505
+
506
+ <div class="placement-grid">
507
+ <div
508
+ v-for="placement in placements"
509
+ :key="placement"
510
+ class="placement-item"
511
+ >
512
+ <Popover
513
+ v-model="openPopovers[placement]"
514
+ :placement="placement"
515
+ :show-arrow="true"
516
+ >
517
+ <template #trigger>
518
+ <Button @click="togglePopover(placement)" size="small">
519
+ {{ placement }}
520
+ </Button>
521
+ </template>
522
+
523
+ <div class="placement-content">
524
+ <h5>{{ placement }}</h5>
525
+ <p>This popover is positioned {{ placement }} of the trigger.</p>
526
+ </div>
527
+ </Popover>
528
+ </div>
529
+ </div>
530
+ </div>
531
+ </template>
532
+
533
+ <style module>
534
+ .placement-demo {
535
+ padding: 2rem;
536
+ border: 1px solid #e0e0e0;
537
+ border-radius: 0.5rem;
538
+ max-width: 800px;
539
+ }
540
+
541
+ .placement-grid {
542
+ display: grid;
543
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
544
+ gap: 1rem;
545
+ margin-top: 1rem;
546
+ }
547
+
548
+ .placement-item {
549
+ display: flex;
550
+ justify-content: center;
551
+ align-items: center;
552
+ min-height: 60px;
553
+ }
554
+
555
+ .placement-content {
556
+ padding: 1rem;
557
+ min-width: 200px;
558
+ text-align: center;
559
+ }
560
+
561
+ .placement-content h5 {
562
+ margin: 0 0 0.5rem 0;
563
+ color: #333;
564
+ text-transform: capitalize;
565
+ }
566
+
567
+ .placement-content p {
568
+ margin: 0;
569
+ color: #666;
570
+ font-size: 0.875rem;
571
+ }
572
+ </style>
573
+ ```
574
+
575
+ ### Custom Styled Popover
576
+
577
+ ```vue
578
+ <script setup lang="ts">
579
+ import { ref } from "vue";
580
+ import { Popover, Button } from "@umbra-ui/core";
581
+
582
+ const isCustomOpen = ref(false);
583
+ </script>
584
+
585
+ <template>
586
+ <div class="custom-popover">
587
+ <h3>Custom Styled Popover</h3>
588
+
589
+ <Popover
590
+ v-model="isCustomOpen"
591
+ placement="bottom"
592
+ :show-arrow="true"
593
+ :animation-duration="0.3"
594
+ max-width="400px"
595
+ >
596
+ <template #trigger>
597
+ <Button class="custom-trigger">Custom Style</Button>
598
+ </template>
599
+
600
+ <div class="custom-content">
601
+ <div class="custom-header">
602
+ <h4>Custom Popover</h4>
603
+ <button @click="isCustomOpen = false" class="close-btn">×</button>
604
+ </div>
605
+ <div class="custom-body">
606
+ <p>This popover has custom styling with:</p>
607
+ <ul>
608
+ <li>Custom colors and gradients</li>
609
+ <li>Rounded corners and shadows</li>
610
+ <li>Custom header with close button</li>
611
+ <li>Longer animation duration</li>
612
+ </ul>
613
+ </div>
614
+ <div class="custom-footer">
615
+ <Button @click="isCustomOpen = false" size="small">Got it!</Button>
616
+ </div>
617
+ </div>
618
+ </Popover>
619
+ </div>
620
+ </template>
621
+
622
+ <style module>
623
+ .custom-popover {
624
+ padding: 2rem;
625
+ border: 1px solid #e0e0e0;
626
+ border-radius: 0.5rem;
627
+ max-width: 400px;
628
+ }
629
+
630
+ .custom-trigger {
631
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
632
+ color: white;
633
+ border: none;
634
+ padding: 0.75rem 1.5rem;
635
+ border-radius: 0.5rem;
636
+ font-weight: 600;
637
+ transition: transform 0.2s;
638
+ }
639
+
640
+ .custom-trigger:hover {
641
+ transform: translateY(-2px);
642
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
643
+ }
644
+
645
+ .custom-content {
646
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
647
+ color: white;
648
+ border-radius: 1rem;
649
+ overflow: hidden;
650
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
651
+ }
652
+
653
+ .custom-header {
654
+ display: flex;
655
+ justify-content: space-between;
656
+ align-items: center;
657
+ padding: 1rem 1.5rem;
658
+ background: rgba(255, 255, 255, 0.1);
659
+ backdrop-filter: blur(10px);
660
+ }
661
+
662
+ .custom-header h4 {
663
+ margin: 0;
664
+ font-size: 1.125rem;
665
+ }
666
+
667
+ .close-btn {
668
+ background: none;
669
+ border: none;
670
+ color: white;
671
+ font-size: 1.5rem;
672
+ cursor: pointer;
673
+ padding: 0;
674
+ width: 24px;
675
+ height: 24px;
676
+ display: flex;
677
+ align-items: center;
678
+ justify-content: center;
679
+ border-radius: 50%;
680
+ transition: background-color 0.2s;
681
+ }
682
+
683
+ .close-btn:hover {
684
+ background: rgba(255, 255, 255, 0.2);
685
+ }
686
+
687
+ .custom-body {
688
+ padding: 1.5rem;
689
+ }
690
+
691
+ .custom-body p {
692
+ margin: 0 0 1rem 0;
693
+ opacity: 0.9;
694
+ }
695
+
696
+ .custom-body ul {
697
+ margin: 0;
698
+ padding-left: 1.25rem;
699
+ opacity: 0.9;
700
+ }
701
+
702
+ .custom-body li {
703
+ margin-bottom: 0.5rem;
704
+ }
705
+
706
+ .custom-footer {
707
+ padding: 1rem 1.5rem;
708
+ background: rgba(255, 255, 255, 0.1);
709
+ backdrop-filter: blur(10px);
710
+ display: flex;
711
+ justify-content: flex-end;
712
+ }
713
+
714
+ /* Override popover CSS variables */
715
+ :global(.custom-popover) {
716
+ --popover-bg: transparent;
717
+ --popover-border: none;
718
+ --popover-shadow: none;
719
+ --popover-inset-shadow: none;
720
+ --popover-arrow-bg: #f5576c;
721
+ }
722
+ </style>
723
+ ```
724
+
725
+ ### Form in Popover
726
+
727
+ ```vue
728
+ <script setup lang="ts">
729
+ import { ref } from "vue";
730
+ import { Popover, Button } from "@umbra-ui/core";
731
+
732
+ const isFormOpen = ref(false);
733
+ const formData = ref({
734
+ name: "",
735
+ email: "",
736
+ message: "",
737
+ });
738
+
739
+ const handleSubmit = () => {
740
+ console.log("Form submitted:", formData.value);
741
+ isFormOpen.value = false;
742
+ // Reset form
743
+ formData.value = { name: "", email: "", message: "" };
744
+ };
745
+
746
+ const handleCancel = () => {
747
+ isFormOpen.value = false;
748
+ // Reset form
749
+ formData.value = { name: "", email: "", message: "" };
750
+ };
751
+ </script>
752
+
753
+ <template>
754
+ <div class="form-popover">
755
+ <h3>Form in Popover</h3>
756
+
757
+ <Popover
758
+ v-model="isFormOpen"
759
+ placement="bottom-start"
760
+ :show-arrow="true"
761
+ :dismiss-on-click-outside="false"
762
+ max-width="400px"
763
+ >
764
+ <template #trigger>
765
+ <Button>Contact Us</Button>
766
+ </template>
767
+
768
+ <div class="form-content">
769
+ <h4>Send us a message</h4>
770
+ <form @submit.prevent="handleSubmit">
771
+ <div class="form-group">
772
+ <label for="name">Name</label>
773
+ <input
774
+ id="name"
775
+ v-model="formData.name"
776
+ type="text"
777
+ required
778
+ placeholder="Your name"
779
+ />
780
+ </div>
781
+
782
+ <div class="form-group">
783
+ <label for="email">Email</label>
784
+ <input
785
+ id="email"
786
+ v-model="formData.email"
787
+ type="email"
788
+ required
789
+ placeholder="your@email.com"
790
+ />
791
+ </div>
792
+
793
+ <div class="form-group">
794
+ <label for="message">Message</label>
795
+ <textarea
796
+ id="message"
797
+ v-model="formData.message"
798
+ required
799
+ placeholder="Your message..."
800
+ rows="3"
801
+ ></textarea>
802
+ </div>
803
+
804
+ <div class="form-actions">
805
+ <Button type="button" @click="handleCancel" variant="secondary">
806
+ Cancel
807
+ </Button>
808
+ <Button type="submit">Send Message</Button>
809
+ </div>
810
+ </form>
811
+ </div>
812
+ </Popover>
813
+ </div>
814
+ </template>
815
+
816
+ <style module>
817
+ .form-popover {
818
+ padding: 2rem;
819
+ border: 1px solid #e0e0e0;
820
+ border-radius: 0.5rem;
821
+ max-width: 400px;
822
+ }
823
+
824
+ .form-content {
825
+ padding: 1.5rem;
826
+ }
827
+
828
+ .form-content h4 {
829
+ margin: 0 0 1.5rem 0;
830
+ color: #333;
831
+ text-align: center;
832
+ }
833
+
834
+ .form-group {
835
+ margin-bottom: 1rem;
836
+ }
837
+
838
+ .form-group label {
839
+ display: block;
840
+ margin-bottom: 0.5rem;
841
+ font-weight: 500;
842
+ color: #333;
843
+ }
844
+
845
+ .form-group input,
846
+ .form-group textarea {
847
+ width: 100%;
848
+ padding: 0.75rem;
849
+ border: 1px solid #ddd;
850
+ border-radius: 0.25rem;
851
+ font-size: 1rem;
852
+ font-family: inherit;
853
+ box-sizing: border-box;
854
+ }
855
+
856
+ .form-group input:focus,
857
+ .form-group textarea:focus {
858
+ outline: none;
859
+ border-color: #007bff;
860
+ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
861
+ }
862
+
863
+ .form-actions {
864
+ display: flex;
865
+ gap: 0.75rem;
866
+ justify-content: flex-end;
867
+ margin-top: 1.5rem;
868
+ }
869
+ </style>
870
+ ```
871
+
872
+ ## Technical Notes
873
+
874
+ - Popover provides a comprehensive floating content system with advanced positioning and animation
875
+ - Floating UI integration ensures smart positioning that adapts to viewport constraints and available space
876
+ - GSAP animations provide smooth, performant transitions with directional awareness
877
+ - Teleport usage ensures proper z-index layering and positioning outside component tree
878
+ - Auto-cleanup of positioning listeners and event handlers prevents memory leaks
879
+ - Hover triggers with configurable delays provide flexible interaction patterns
880
+ - Click-outside detection with configurable behavior for different use cases
881
+ - Arrow positioning automatically adjusts based on popover placement and available space
882
+ - TypeScript interfaces ensure type safety for all props and events
883
+ - CSS custom properties enable easy theming and customization
884
+ - Responsive design adapts to different screen sizes and orientations
885
+ - Accessibility features include keyboard navigation and proper focus management