@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,825 @@
1
+ # ActionMenu
2
+
3
+ A versatile dropdown menu component built with Vue 3 Composition API and TypeScript. The ActionMenu component provides a flexible interface for displaying contextual actions with support for both click-triggered and right-click context menus, custom icons, destructive actions, and smart positioning.
4
+
5
+ ## Installation/Import
6
+
7
+ ```typescript
8
+ import { ActionMenu } from "@umbra-ui/core";
9
+ import type { ActionMenuItem } from "@umbra-ui/core";
10
+ ```
11
+
12
+ **Dependencies:**
13
+
14
+ - Vue 3.x
15
+ - @umbra-ui/core (for icon components)
16
+ - @floating-ui/vue (for positioning)
17
+
18
+ ## Basic Usage
19
+
20
+ ```vue
21
+ <script setup lang="ts">
22
+ import { ref } from "vue";
23
+ import { ActionMenu, Button } from "@umbra-ui/core";
24
+ import type { ActionMenuItem } from "@umbra-ui/core";
25
+
26
+ const isMenuOpen = ref(false);
27
+
28
+ const menuItems: ActionMenuItem[] = [
29
+ {
30
+ icon: "edit",
31
+ title: "Edit",
32
+ action: () => console.log("Edit clicked"),
33
+ },
34
+ {
35
+ icon: "copy",
36
+ title: "Copy",
37
+ action: () => console.log("Copy clicked"),
38
+ },
39
+ {
40
+ icon: "trash",
41
+ title: "Delete",
42
+ action: () => console.log("Delete clicked"),
43
+ isDestructive: true,
44
+ },
45
+ ];
46
+
47
+ const handleItemClick = (item: ActionMenuItem) => {
48
+ console.log("Menu item clicked:", item.title);
49
+ };
50
+ </script>
51
+
52
+ <template>
53
+ <div>
54
+ <ActionMenu
55
+ :items="menuItems"
56
+ v-model="isMenuOpen"
57
+ @item-click="handleItemClick"
58
+ >
59
+ <Button>Actions</Button>
60
+ </ActionMenu>
61
+ </div>
62
+ </template>
63
+ ```
64
+
65
+ ## Props
66
+
67
+ | Prop Name | Type | Required | Default | Description |
68
+ | ------------- | ------------------ | -------- | ------- | ---------------------------------------------- |
69
+ | `items` | `ActionMenuItem[]` | Yes | - | Array of menu items to display |
70
+ | `modelValue` | `boolean` | No | `false` | Controls the open/closed state of the menu |
71
+ | `contextMenu` | `boolean` | No | `false` | Enables right-click context menu functionality |
72
+
73
+ ## Events
74
+
75
+ | Event Name | Payload Type | Description |
76
+ | ------------------- | ---------------- | ---------------------------------------- |
77
+ | `update:modelValue` | `boolean` | Emitted when the menu open state changes |
78
+ | `item-click` | `ActionMenuItem` | Emitted when a menu item is clicked |
79
+
80
+ ## Slots
81
+
82
+ | Slot Name | Description |
83
+ | --------- | --------------------------------------- |
84
+ | `default` | The trigger element that opens the menu |
85
+
86
+ ## Exposed Methods/Refs
87
+
88
+ The ActionMenu component exposes the following methods via template refs:
89
+
90
+ | Method Name | Parameters | Description |
91
+ | --------------- | ---------- | ---------------------------------- |
92
+ | `togglePopover` | `()` | Toggles the menu open/closed state |
93
+
94
+ ### Example Usage
95
+
96
+ ```vue
97
+ <script setup lang="ts">
98
+ import { ref } from "vue";
99
+ import { ActionMenu } from "@umbra-ui/core";
100
+
101
+ const actionMenuRef = ref<InstanceType<typeof ActionMenu> | null>(null);
102
+
103
+ const openMenu = () => {
104
+ actionMenuRef.value?.togglePopover();
105
+ };
106
+ </script>
107
+
108
+ <template>
109
+ <ActionMenu ref="actionMenuRef" :items="menuItems">
110
+ <button @click="openMenu">Open Menu</button>
111
+ </ActionMenu>
112
+ </template>
113
+ ```
114
+
115
+ ## ActionMenuItem Interface
116
+
117
+ ```typescript
118
+ interface ActionMenuItem {
119
+ icon?: IconKey; // Optional icon from @umbra-ui/icons
120
+ title: string; // Display text for the menu item
121
+ action: () => void; // Function to execute when clicked
122
+ isDestructive?: boolean; // Whether this is a destructive action
123
+ }
124
+ ```
125
+
126
+ ## CSS Customization
127
+
128
+ The ActionMenu component uses CSS custom properties for theming and customization:
129
+
130
+ ### Light Theme Variables
131
+
132
+ ```css
133
+ /* ActionMenu popup colors */
134
+ --actionmenu-popup-bg: #ffffff;
135
+ --actionmenu-popup-border: 1px solid rgba(0, 0, 0, 0.1);
136
+ --actionmenu-popup-shadow: transparent;
137
+ --actionmenu-popup-inset-shadow: rgba(255, 255, 255, 0.8);
138
+
139
+ /* ActionMenu item colors */
140
+ --actionmenu-item-bg: #ffffff;
141
+ --actionmenu-item-hover-bg: rgba(0, 0, 0, 0.05);
142
+ --actionmenu-item-border: rgba(0, 0, 0, 0.1);
143
+ --actionmenu-item-text: #1f2937;
144
+ --actionmenu-item-icon: #6b7280;
145
+
146
+ /* ActionMenu destructive colors */
147
+ --actionmenu-destructive-text: #dc2626;
148
+ --actionmenu-destructive-icon: #dc2626;
149
+
150
+ /* ActionMenu overlay colors */
151
+ --actionmenu-overlay-bg: rgba(0, 0, 0, 0.1);
152
+ --actionmenu-overlay-blur-bg: rgba(0, 0, 0, 0.1);
153
+ ```
154
+
155
+ ### Dark Theme Variables
156
+
157
+ ```css
158
+ /* ActionMenu popup colors */
159
+ --actionmenu-popup-bg: #484848;
160
+ --actionmenu-popup-border: none;
161
+ --actionmenu-popup-shadow: rgba(0, 0, 0, 0.21);
162
+ --actionmenu-popup-inset-shadow: rgba(255, 255, 255, 0.1);
163
+
164
+ /* ActionMenu item colors */
165
+ --actionmenu-item-bg: #484848;
166
+ --actionmenu-item-hover-bg: rgba(255, 255, 255, 0.05);
167
+ --actionmenu-item-border: rgba(255, 255, 255, 0.1);
168
+ --actionmenu-item-text: #eeeeee;
169
+ --actionmenu-item-icon: #eeeeee;
170
+
171
+ /* ActionMenu destructive colors */
172
+ --actionmenu-destructive-text: #e5484d;
173
+ --actionmenu-destructive-icon: #e5484d;
174
+
175
+ /* ActionMenu overlay colors */
176
+ --actionmenu-overlay-bg: rgba(0, 0, 0, 0.7);
177
+ --actionmenu-overlay-blur-bg: rgba(0, 0, 0, 0.1);
178
+ ```
179
+
180
+ ## Key Features
181
+
182
+ ### Menu Types
183
+
184
+ - **Click Menu**: Standard dropdown menu triggered by clicking the trigger element
185
+ - **Context Menu**: Right-click context menu with smart positioning and blur overlay
186
+
187
+ ### Smart Positioning
188
+
189
+ - **Floating UI Integration**: Uses Floating UI for intelligent positioning
190
+ - **Auto-flip**: Automatically flips to opposite side if no space available
191
+ - **Auto-shift**: Shifts position to stay within viewport bounds
192
+ - **Size Constraints**: Respects viewport boundaries with padding
193
+
194
+ ### Visual Features
195
+
196
+ - **Smooth Animations**: Fade-in animations for menu and overlay
197
+ - **Hover Effects**: Interactive hover states with icon scaling
198
+ - **Destructive Actions**: Special styling for dangerous actions
199
+ - **Icon Support**: Full integration with @umbra-ui/icons
200
+ - **Backdrop Blur**: Context menus include backdrop blur effect
201
+
202
+ ### Accessibility
203
+
204
+ - **Keyboard Navigation**: Full keyboard support
205
+ - **Focus Management**: Proper focus handling
206
+ - **Screen Reader Support**: Semantic markup and ARIA attributes
207
+ - **Click Outside**: Closes menu when clicking outside
208
+
209
+ ## Examples
210
+
211
+ ### Basic Action Menu
212
+
213
+ ```vue
214
+ <script setup lang="ts">
215
+ import { ref } from "vue";
216
+ import { ActionMenu, Button } from "@umbra-ui/core";
217
+ import type { ActionMenuItem } from "@umbra-ui/core";
218
+
219
+ const isMenuOpen = ref(false);
220
+
221
+ const menuItems: ActionMenuItem[] = [
222
+ {
223
+ icon: "edit",
224
+ title: "Edit Item",
225
+ action: () => {
226
+ console.log("Editing item...");
227
+ isMenuOpen.value = false;
228
+ },
229
+ },
230
+ {
231
+ icon: "copy",
232
+ title: "Copy Link",
233
+ action: () => {
234
+ console.log("Copying link...");
235
+ isMenuOpen.value = false;
236
+ },
237
+ },
238
+ {
239
+ icon: "share",
240
+ title: "Share",
241
+ action: () => {
242
+ console.log("Sharing...");
243
+ isMenuOpen.value = false;
244
+ },
245
+ },
246
+ ];
247
+
248
+ const handleItemClick = (item: ActionMenuItem) => {
249
+ console.log("Menu item clicked:", item.title);
250
+ };
251
+ </script>
252
+
253
+ <template>
254
+ <div class="basic-menu">
255
+ <h3>Basic Action Menu</h3>
256
+
257
+ <ActionMenu
258
+ :items="menuItems"
259
+ v-model="isMenuOpen"
260
+ @item-click="handleItemClick"
261
+ >
262
+ <Button>Show Actions</Button>
263
+ </ActionMenu>
264
+
265
+ <p class="status">Menu is {{ isMenuOpen ? "open" : "closed" }}</p>
266
+ </div>
267
+ </template>
268
+
269
+ <style module>
270
+ .basic-menu {
271
+ padding: 2rem;
272
+ border: 1px solid #e0e0e0;
273
+ border-radius: 0.5rem;
274
+ max-width: 400px;
275
+ }
276
+
277
+ .status {
278
+ margin-top: 1rem;
279
+ color: #666;
280
+ font-size: 0.875rem;
281
+ }
282
+ </style>
283
+ ```
284
+
285
+ ### Context Menu
286
+
287
+ ```vue
288
+ <script setup lang="ts">
289
+ import { ref } from "vue";
290
+ import { ActionMenu } from "@umbra-ui/core";
291
+ import type { ActionMenuItem } from "@umbra-ui/core";
292
+
293
+ const isContextMenuOpen = ref(false);
294
+
295
+ const contextMenuItems: ActionMenuItem[] = [
296
+ {
297
+ icon: "edit",
298
+ title: "Edit",
299
+ action: () => {
300
+ console.log("Edit from context menu");
301
+ isContextMenuOpen.value = false;
302
+ },
303
+ },
304
+ {
305
+ icon: "copy",
306
+ title: "Copy",
307
+ action: () => {
308
+ console.log("Copy from context menu");
309
+ isContextMenuOpen.value = false;
310
+ },
311
+ },
312
+ {
313
+ icon: "move",
314
+ title: "Move",
315
+ action: () => {
316
+ console.log("Move from context menu");
317
+ isContextMenuOpen.value = false;
318
+ },
319
+ },
320
+ {
321
+ icon: "trash",
322
+ title: "Delete",
323
+ action: () => {
324
+ console.log("Delete from context menu");
325
+ isContextMenuOpen.value = false;
326
+ },
327
+ isDestructive: true,
328
+ },
329
+ ];
330
+
331
+ const handleContextItemClick = (item: ActionMenuItem) => {
332
+ console.log("Context menu item clicked:", item.title);
333
+ };
334
+ </script>
335
+
336
+ <template>
337
+ <div class="context-menu-demo">
338
+ <h3>Context Menu Demo</h3>
339
+ <p>Right-click on the box below to see the context menu:</p>
340
+
341
+ <ActionMenu
342
+ :items="contextMenuItems"
343
+ v-model="isContextMenuOpen"
344
+ :context-menu="true"
345
+ @item-click="handleContextItemClick"
346
+ >
347
+ <div class="context-target">
348
+ <h4>Right-click me!</h4>
349
+ <p>This box has a context menu attached.</p>
350
+ </div>
351
+ </ActionMenu>
352
+ </div>
353
+ </template>
354
+
355
+ <style module>
356
+ .context-menu-demo {
357
+ padding: 2rem;
358
+ border: 1px solid #e0e0e0;
359
+ border-radius: 0.5rem;
360
+ max-width: 500px;
361
+ }
362
+
363
+ .context-target {
364
+ padding: 2rem;
365
+ background-color: #f8f9fa;
366
+ border: 2px dashed #dee2e6;
367
+ border-radius: 0.5rem;
368
+ text-align: center;
369
+ cursor: context-menu;
370
+ transition: background-color 0.2s;
371
+ }
372
+
373
+ .context-target:hover {
374
+ background-color: #e9ecef;
375
+ }
376
+
377
+ .context-target h4 {
378
+ margin: 0 0 0.5rem 0;
379
+ color: #495057;
380
+ }
381
+
382
+ .context-target p {
383
+ margin: 0;
384
+ color: #6c757d;
385
+ font-size: 0.875rem;
386
+ }
387
+ </style>
388
+ ```
389
+
390
+ ### File Actions Menu
391
+
392
+ ```vue
393
+ <script setup lang="ts">
394
+ import { ref } from "vue";
395
+ import { ActionMenu, Button } from "@umbra-ui/core";
396
+ import type { ActionMenuItem } from "@umbra-ui/core";
397
+
398
+ interface FileItem {
399
+ id: string;
400
+ name: string;
401
+ type: "file" | "folder";
402
+ size?: string;
403
+ }
404
+
405
+ const files = ref<FileItem[]>([
406
+ { id: "1", name: "document.pdf", type: "file", size: "2.3 MB" },
407
+ { id: "2", name: "images", type: "folder" },
408
+ { id: "3", name: "report.docx", type: "file", size: "1.1 MB" },
409
+ { id: "4", name: "data", type: "folder" },
410
+ ]);
411
+
412
+ const selectedFile = ref<FileItem | null>(null);
413
+ const isMenuOpen = ref(false);
414
+
415
+ const getFileMenuItems = (file: FileItem): ActionMenuItem[] => {
416
+ const baseItems: ActionMenuItem[] = [
417
+ {
418
+ icon: "download",
419
+ title: "Download",
420
+ action: () => {
421
+ console.log(`Downloading ${file.name}`);
422
+ isMenuOpen.value = false;
423
+ },
424
+ },
425
+ {
426
+ icon: "copy",
427
+ title: "Copy",
428
+ action: () => {
429
+ console.log(`Copying ${file.name}`);
430
+ isMenuOpen.value = false;
431
+ },
432
+ },
433
+ {
434
+ icon: "edit",
435
+ title: "Rename",
436
+ action: () => {
437
+ console.log(`Renaming ${file.name}`);
438
+ isMenuOpen.value = false;
439
+ },
440
+ },
441
+ ];
442
+
443
+ if (file.type === "file") {
444
+ baseItems.push({
445
+ icon: "share",
446
+ title: "Share",
447
+ action: () => {
448
+ console.log(`Sharing ${file.name}`);
449
+ isMenuOpen.value = false;
450
+ },
451
+ });
452
+ }
453
+
454
+ baseItems.push({
455
+ icon: "trash",
456
+ title: "Delete",
457
+ action: () => {
458
+ console.log(`Deleting ${file.name}`);
459
+ isMenuOpen.value = false;
460
+ },
461
+ isDestructive: true,
462
+ });
463
+
464
+ return baseItems;
465
+ };
466
+
467
+ const handleFileClick = (file: FileItem) => {
468
+ selectedFile.value = file;
469
+ isMenuOpen.value = true;
470
+ };
471
+
472
+ const handleItemClick = (item: ActionMenuItem) => {
473
+ console.log("File action:", item.title);
474
+ };
475
+ </script>
476
+
477
+ <template>
478
+ <div class="file-actions">
479
+ <h3>File Actions Menu</h3>
480
+ <p>Click on a file to see its action menu:</p>
481
+
482
+ <div class="file-list">
483
+ <div
484
+ v-for="file in files"
485
+ :key="file.id"
486
+ class="file-item"
487
+ @click="handleFileClick(file)"
488
+ >
489
+ <div class="file-icon">
490
+ {{ file.type === "folder" ? "📁" : "📄" }}
491
+ </div>
492
+ <div class="file-info">
493
+ <div class="file-name">{{ file.name }}</div>
494
+ <div v-if="file.size" class="file-size">{{ file.size }}</div>
495
+ </div>
496
+ </div>
497
+ </div>
498
+
499
+ <ActionMenu
500
+ v-if="selectedFile"
501
+ :items="getFileMenuItems(selectedFile)"
502
+ v-model="isMenuOpen"
503
+ @item-click="handleItemClick"
504
+ >
505
+ <div style="display: none;"></div>
506
+ </ActionMenu>
507
+ </div>
508
+ </template>
509
+
510
+ <style module>
511
+ .file-actions {
512
+ padding: 2rem;
513
+ border: 1px solid #e0e0e0;
514
+ border-radius: 0.5rem;
515
+ max-width: 500px;
516
+ }
517
+
518
+ .file-list {
519
+ margin-top: 1rem;
520
+ }
521
+
522
+ .file-item {
523
+ display: flex;
524
+ align-items: center;
525
+ gap: 0.75rem;
526
+ padding: 0.75rem;
527
+ border: 1px solid #e0e0e0;
528
+ border-radius: 0.25rem;
529
+ margin-bottom: 0.5rem;
530
+ cursor: pointer;
531
+ transition: background-color 0.2s;
532
+ }
533
+
534
+ .file-item:hover {
535
+ background-color: #f8f9fa;
536
+ }
537
+
538
+ .file-icon {
539
+ font-size: 1.5rem;
540
+ width: 2rem;
541
+ text-align: center;
542
+ }
543
+
544
+ .file-info {
545
+ flex: 1;
546
+ }
547
+
548
+ .file-name {
549
+ font-weight: 500;
550
+ color: #333;
551
+ }
552
+
553
+ .file-size {
554
+ font-size: 0.875rem;
555
+ color: #666;
556
+ margin-top: 0.25rem;
557
+ }
558
+ </style>
559
+ ```
560
+
561
+ ### User Profile Menu
562
+
563
+ ```vue
564
+ <script setup lang="ts">
565
+ import { ref } from "vue";
566
+ import { ActionMenu, Button } from "@umbra-ui/core";
567
+ import type { ActionMenuItem } from "@umbra-ui/core";
568
+
569
+ const user = ref({
570
+ name: "John Doe",
571
+ email: "john@example.com",
572
+ avatar: "👤",
573
+ });
574
+
575
+ const isProfileMenuOpen = ref(false);
576
+
577
+ const profileMenuItems: ActionMenuItem[] = [
578
+ {
579
+ icon: "user",
580
+ title: "View Profile",
581
+ action: () => {
582
+ console.log("Viewing profile...");
583
+ isProfileMenuOpen.value = false;
584
+ },
585
+ },
586
+ {
587
+ icon: "settings",
588
+ title: "Settings",
589
+ action: () => {
590
+ console.log("Opening settings...");
591
+ isProfileMenuOpen.value = false;
592
+ },
593
+ },
594
+ {
595
+ icon: "bell",
596
+ title: "Notifications",
597
+ action: () => {
598
+ console.log("Opening notifications...");
599
+ isProfileMenuOpen.value = false;
600
+ },
601
+ },
602
+ {
603
+ icon: "help",
604
+ title: "Help & Support",
605
+ action: () => {
606
+ console.log("Opening help...");
607
+ isProfileMenuOpen.value = false;
608
+ },
609
+ },
610
+ {
611
+ icon: "logout",
612
+ title: "Sign Out",
613
+ action: () => {
614
+ console.log("Signing out...");
615
+ isProfileMenuOpen.value = false;
616
+ },
617
+ isDestructive: true,
618
+ },
619
+ ];
620
+
621
+ const handleProfileItemClick = (item: ActionMenuItem) => {
622
+ console.log("Profile menu item clicked:", item.title);
623
+ };
624
+ </script>
625
+
626
+ <template>
627
+ <div class="profile-menu">
628
+ <h3>User Profile Menu</h3>
629
+
630
+ <div class="user-info">
631
+ <div class="user-avatar">{{ user.avatar }}</div>
632
+ <div class="user-details">
633
+ <div class="user-name">{{ user.name }}</div>
634
+ <div class="user-email">{{ user.email }}</div>
635
+ </div>
636
+ </div>
637
+
638
+ <ActionMenu
639
+ :items="profileMenuItems"
640
+ v-model="isProfileMenuOpen"
641
+ @item-click="handleProfileItemClick"
642
+ >
643
+ <Button class="profile-button">
644
+ <span class="profile-avatar">{{ user.avatar }}</span>
645
+ <span>{{ user.name }}</span>
646
+ <span class="dropdown-arrow">▼</span>
647
+ </Button>
648
+ </ActionMenu>
649
+ </div>
650
+ </template>
651
+
652
+ <style module>
653
+ .profile-menu {
654
+ padding: 2rem;
655
+ border: 1px solid #e0e0e0;
656
+ border-radius: 0.5rem;
657
+ max-width: 400px;
658
+ }
659
+
660
+ .user-info {
661
+ display: flex;
662
+ align-items: center;
663
+ gap: 1rem;
664
+ margin-bottom: 1.5rem;
665
+ padding: 1rem;
666
+ background-color: #f8f9fa;
667
+ border-radius: 0.5rem;
668
+ }
669
+
670
+ .user-avatar {
671
+ font-size: 2rem;
672
+ width: 3rem;
673
+ height: 3rem;
674
+ display: flex;
675
+ align-items: center;
676
+ justify-content: center;
677
+ background-color: #e9ecef;
678
+ border-radius: 50%;
679
+ }
680
+
681
+ .user-details {
682
+ flex: 1;
683
+ }
684
+
685
+ .user-name {
686
+ font-weight: 600;
687
+ color: #333;
688
+ margin-bottom: 0.25rem;
689
+ }
690
+
691
+ .user-email {
692
+ color: #666;
693
+ font-size: 0.875rem;
694
+ }
695
+
696
+ .profile-button {
697
+ display: flex;
698
+ align-items: center;
699
+ gap: 0.5rem;
700
+ width: 100%;
701
+ justify-content: space-between;
702
+ }
703
+
704
+ .profile-avatar {
705
+ font-size: 1.25rem;
706
+ }
707
+
708
+ .dropdown-arrow {
709
+ font-size: 0.75rem;
710
+ opacity: 0.6;
711
+ }
712
+ </style>
713
+ ```
714
+
715
+ ### Custom Styled Menu
716
+
717
+ ```vue
718
+ <script setup lang="ts">
719
+ import { ref } from "vue";
720
+ import { ActionMenu, Button } from "@umbra-ui/core";
721
+ import type { ActionMenuItem } from "@umbra-ui/core";
722
+
723
+ const isCustomMenuOpen = ref(false);
724
+
725
+ const customMenuItems: ActionMenuItem[] = [
726
+ {
727
+ icon: "star",
728
+ title: "Add to Favorites",
729
+ action: () => {
730
+ console.log("Added to favorites");
731
+ isCustomMenuOpen.value = false;
732
+ },
733
+ },
734
+ {
735
+ icon: "bookmark",
736
+ title: "Bookmark",
737
+ action: () => {
738
+ console.log("Bookmarked");
739
+ isCustomMenuOpen.value = false;
740
+ },
741
+ },
742
+ {
743
+ icon: "flag",
744
+ title: "Report",
745
+ action: () => {
746
+ console.log("Reported");
747
+ isCustomMenuOpen.value = false;
748
+ },
749
+ isDestructive: true,
750
+ },
751
+ ];
752
+
753
+ const handleCustomItemClick = (item: ActionMenuItem) => {
754
+ console.log("Custom menu item clicked:", item.title);
755
+ };
756
+ </script>
757
+
758
+ <template>
759
+ <div class="custom-styled-menu">
760
+ <h3>Custom Styled Action Menu</h3>
761
+
762
+ <ActionMenu
763
+ :items="customMenuItems"
764
+ v-model="isCustomMenuOpen"
765
+ @item-click="handleCustomItemClick"
766
+ >
767
+ <Button class="custom-trigger">Custom Menu</Button>
768
+ </ActionMenu>
769
+ </div>
770
+ </template>
771
+
772
+ <style module>
773
+ .custom-styled-menu {
774
+ padding: 2rem;
775
+ border: 1px solid #e0e0e0;
776
+ border-radius: 0.5rem;
777
+ max-width: 400px;
778
+ }
779
+
780
+ .custom-trigger {
781
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
782
+ color: white;
783
+ border: none;
784
+ padding: 0.75rem 1.5rem;
785
+ border-radius: 0.5rem;
786
+ font-weight: 600;
787
+ transition: transform 0.2s;
788
+ }
789
+
790
+ .custom-trigger:hover {
791
+ transform: translateY(-2px);
792
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
793
+ }
794
+
795
+ /* Custom CSS variables for the menu */
796
+ :global(.custom-styled-menu) {
797
+ --actionmenu-popup-bg: #ffffff;
798
+ --actionmenu-popup-border: 2px solid #667eea;
799
+ --actionmenu-popup-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
800
+
801
+ --actionmenu-item-hover-bg: rgba(102, 126, 234, 0.1);
802
+ --actionmenu-item-text: #333333;
803
+ --actionmenu-item-icon: #667eea;
804
+
805
+ --actionmenu-destructive-text: #e74c3c;
806
+ --actionmenu-destructive-icon: #e74c3c;
807
+
808
+ --actionmenu-overlay-bg: rgba(102, 126, 234, 0.2);
809
+ }
810
+ </style>
811
+ ```
812
+
813
+ ## Technical Notes
814
+
815
+ - ActionMenu provides a flexible dropdown menu system with both click and context menu support
816
+ - Floating UI integration ensures smart positioning that adapts to viewport constraints
817
+ - Context menus include backdrop blur effects for better visual separation
818
+ - Destructive actions are visually distinguished with red coloring
819
+ - Full icon integration with @umbra-ui/icons for consistent visual language
820
+ - Smooth animations and hover effects enhance user experience
821
+ - TypeScript interfaces ensure type safety for menu items and actions
822
+ - CSS custom properties enable easy theming and customization
823
+ - Teleport usage ensures proper z-index layering and positioning
824
+ - Auto-cleanup of positioning listeners prevents memory leaks
825
+ - Responsive design adapts to different screen sizes and orientations