@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,1161 @@
1
+ # IconPicker
2
+
3
+ A comprehensive icon picker component built with Vue 3 Composition API and TypeScript. The IconPicker provides an intuitive interface for selecting icons from the @umbra-ui/icons library with support for custom icon lists, smart positioning using Floating UI, and smooth animations.
4
+
5
+ ## Installation/Import
6
+
7
+ ```typescript
8
+ import { IconPicker } from "@umbra-ui/core";
9
+ import type { IconKey } from "@umbra-ui/icons";
10
+ ```
11
+
12
+ **Dependencies:**
13
+
14
+ - Vue 3.x
15
+ - @floating-ui/vue (for positioning)
16
+ - @umbra-ui/icons (for icon library)
17
+
18
+ ## Basic Usage
19
+
20
+ ```vue
21
+ <script setup lang="ts">
22
+ import { ref } from "vue";
23
+ import { IconPicker } from "@umbra-ui/core";
24
+ import type { IconKey } from "@umbra-ui/icons";
25
+
26
+ const selectedIcon = ref<IconKey>("home");
27
+
28
+ const handleIconChange = (icon: IconKey) => {
29
+ console.log("Selected icon:", icon);
30
+ };
31
+ </script>
32
+
33
+ <template>
34
+ <div class="app">
35
+ <h2>Choose an Icon</h2>
36
+
37
+ <IconPicker v-model:icon="selectedIcon" @update:icon="handleIconChange" />
38
+
39
+ <div v-if="selectedIcon" class="icon-info">
40
+ <p>
41
+ Selected icon: <strong>{{ selectedIcon }}</strong>
42
+ </p>
43
+ </div>
44
+ </div>
45
+ </template>
46
+
47
+ <style module>
48
+ .app {
49
+ padding: 24px;
50
+ max-width: 400px;
51
+ }
52
+
53
+ .icon-info {
54
+ margin-top: 20px;
55
+ padding: 16px;
56
+ background: #f8f9fa;
57
+ border-radius: 8px;
58
+ }
59
+
60
+ .icon-info p {
61
+ margin: 0;
62
+ color: #495057;
63
+ }
64
+ </style>
65
+ ```
66
+
67
+ ## Props
68
+
69
+ | Prop Name | Type | Required | Default | Description |
70
+ | --------------- | ----------- | -------- | ----------- | ----------------------------------------- |
71
+ | `icon` | `string` | Yes | `""` | Currently selected icon key |
72
+ | `pickerOffsetX` | `number` | No | `0` | Horizontal offset for picker positioning |
73
+ | `preventPopup` | `boolean` | No | `false` | Whether to prevent the popup from opening |
74
+ | `iconList` | `IconKey[]` | No | `undefined` | Custom list of available icons |
75
+ | `iconSize` | `number` | No | `18` | Size of the displayed icon |
76
+
77
+ ## Events
78
+
79
+ | Event Name | Payload Type | Description |
80
+ | ------------- | ------------ | -------------------------------- |
81
+ | `update:icon` | `string` | Emitted when an icon is selected |
82
+
83
+ ## Available Icons
84
+
85
+ The IconPicker includes access to the complete @umbra-ui/icons library with over 250 icons across various categories:
86
+
87
+ ### Icon Categories
88
+
89
+ - **Navigation**: home, search, menu, back, forward, etc.
90
+ - **Actions**: edit, delete, save, copy, paste, etc.
91
+ - **Communication**: mail, phone, message, notification, etc.
92
+ - **Media**: play, pause, stop, volume, image, video, etc.
93
+ - **Files**: folder, file, document, download, upload, etc.
94
+ - **Interface**: settings, user, lock, unlock, eye, etc.
95
+ - **Arrows**: up, down, left, right, chevron variants, etc.
96
+ - **Shapes**: circle, square, triangle, star, heart, etc.
97
+
98
+ ### Accessing Icons
99
+
100
+ ```typescript
101
+ import { icons, type IconKey } from "@umbra-ui/icons";
102
+
103
+ // Get all available icon keys
104
+ const allIcons = Object.keys(icons) as IconKey[];
105
+
106
+ // Filter icons by category
107
+ const navigationIcons = allIcons.filter((key) =>
108
+ ["home", "search", "menu", "back", "forward"].includes(key)
109
+ );
110
+
111
+ // Use specific icons
112
+ const homeIcon = icons.home;
113
+ const searchIcon = icons.search;
114
+ ```
115
+
116
+ ## CSS Customization
117
+
118
+ ### Layout Variables
119
+
120
+ ```css
121
+ .icon-picker {
122
+ --picker-button-bg: #ffffff;
123
+ --picker-button-border: 1px solid #e9ecef;
124
+ --picker-button-hover-bg: #f8f9fa;
125
+ --picker-button-hover-border: 1px solid #dee2e6;
126
+ --picker-button-hover-shadow: rgba(0, 0, 0, 0.1);
127
+ --picker-button-hover-inset-shadow: rgba(255, 255, 255, 0.1);
128
+ --picker-picker-bg: #ffffff;
129
+ --picker-picker-border: 1px solid #e9ecef;
130
+ --picker-picker-shadow: rgba(0, 0, 0, 0.1);
131
+ --picker-picker-inset-shadow: rgba(255, 255, 255, 0.1);
132
+ --picker-selection-bar-bg: #f8f9fa;
133
+ --picker-selection-bar-text: #212529;
134
+ --picker-selection-bar-border: #e9ecef;
135
+ --picker-overlay-bg: rgba(0, 0, 0, 0.1);
136
+ --iconpicker-icon-cell-bg: #f3f4f6;
137
+ --iconpicker-icon-cell-border: #d1d5db;
138
+ --iconpicker-icon-cell-hover-bg: #e5e7eb;
139
+ --iconpicker-icon-cell-selected-bg: #acd8fc;
140
+ --iconpicker-icon-cell-selected-border: #5eb1ef;
141
+ --iconpicker-icon-color: #374151;
142
+ }
143
+ ```
144
+
145
+ ### Container Styling
146
+
147
+ ```css
148
+ .icon-picker {
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ max-width: fit-content;
153
+ }
154
+ ```
155
+
156
+ ### Button Styling
157
+
158
+ ```css
159
+ .icon-picker .button {
160
+ padding: 0.588rem;
161
+ border-radius: 0.353rem;
162
+ cursor: pointer;
163
+ display: flex;
164
+ align-items: center;
165
+ justify-content: center;
166
+ gap: 0;
167
+ transition: all 0.3s ease;
168
+ background-color: var(--picker-button-bg);
169
+ border: var(--picker-button-border);
170
+ }
171
+ ```
172
+
173
+ ### Icon Grid Styling
174
+
175
+ ```css
176
+ .icon-picker .icon_list {
177
+ display: grid;
178
+ grid-template-columns: repeat(7, 1fr);
179
+ gap: 0.588rem;
180
+ padding: 0.588rem;
181
+ }
182
+
183
+ .icon-picker .icon_cell {
184
+ width: 2rem;
185
+ height: 2rem;
186
+ border-radius: 0.353rem;
187
+ display: flex;
188
+ align-items: center;
189
+ justify-content: center;
190
+ background-color: var(--iconpicker-icon-cell-bg);
191
+ cursor: pointer;
192
+ transition: border 0.3s ease;
193
+ }
194
+ ```
195
+
196
+ ## Examples
197
+
198
+ ### Navigation Icon Selector
199
+
200
+ ```vue
201
+ <script setup lang="ts">
202
+ import { ref } from "vue";
203
+ import { IconPicker } from "@umbra-ui/core";
204
+ import type { IconKey } from "@umbra-ui/icons";
205
+
206
+ const navigationIcons: IconKey[] = [
207
+ "home",
208
+ "search",
209
+ "menu",
210
+ "back",
211
+ "forward",
212
+ "up",
213
+ "down",
214
+ "left",
215
+ "right",
216
+ "chevron-up",
217
+ "chevron-down",
218
+ "chevron-left",
219
+ "chevron-right",
220
+ "arrow-up",
221
+ "arrow-down",
222
+ "arrow-left",
223
+ "arrow-right",
224
+ "external-link",
225
+ "link",
226
+ ];
227
+
228
+ const selectedNavIcon = ref<IconKey>("home");
229
+
230
+ const handleNavIconChange = (icon: IconKey) => {
231
+ console.log("Navigation icon changed to:", icon);
232
+ };
233
+ </script>
234
+
235
+ <template>
236
+ <div class="navigation-selector">
237
+ <div class="selector-header">
238
+ <h3>Navigation Icon</h3>
239
+ <p>Choose an icon for your navigation menu</p>
240
+ </div>
241
+
242
+ <IconPicker
243
+ v-model:icon="selectedNavIcon"
244
+ :icon-list="navigationIcons"
245
+ :icon-size="20"
246
+ @update:icon="handleNavIconChange"
247
+ />
248
+
249
+ <div class="icon-preview">
250
+ <h4>Preview</h4>
251
+ <div class="preview-nav">
252
+ <div class="nav-item">
253
+ <IconPicker
254
+ v-model:icon="selectedNavIcon"
255
+ :icon-list="navigationIcons"
256
+ :icon-size="16"
257
+ :prevent-popup="true"
258
+ />
259
+ <span>Home</span>
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+ </template>
265
+
266
+ <style module>
267
+ .navigation-selector {
268
+ padding: 24px;
269
+ max-width: 500px;
270
+ background: #ffffff;
271
+ border-radius: 12px;
272
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
273
+ }
274
+
275
+ .selector-header {
276
+ margin-bottom: 24px;
277
+ }
278
+
279
+ .selector-header h3 {
280
+ font-size: 24px;
281
+ font-weight: 600;
282
+ color: #1a202c;
283
+ margin: 0 0 8px 0;
284
+ }
285
+
286
+ .selector-header p {
287
+ color: #718096;
288
+ margin: 0;
289
+ }
290
+
291
+ .icon-preview {
292
+ margin-top: 32px;
293
+ padding-top: 24px;
294
+ border-top: 1px solid #e5e7eb;
295
+ }
296
+
297
+ .icon-preview h4 {
298
+ font-size: 18px;
299
+ font-weight: 500;
300
+ color: #2d3748;
301
+ margin: 0 0 16px 0;
302
+ }
303
+
304
+ .preview-nav {
305
+ padding: 16px;
306
+ background: #f7fafc;
307
+ border-radius: 8px;
308
+ }
309
+
310
+ .nav-item {
311
+ display: flex;
312
+ align-items: center;
313
+ gap: 12px;
314
+ padding: 8px 12px;
315
+ background: white;
316
+ border-radius: 6px;
317
+ border: 1px solid #e2e8f0;
318
+ }
319
+
320
+ .nav-item span {
321
+ font-size: 14px;
322
+ font-weight: 500;
323
+ color: #374151;
324
+ }
325
+ </style>
326
+ ```
327
+
328
+ ### Action Icon Selector
329
+
330
+ ```vue
331
+ <script setup lang="ts">
332
+ import { ref } from "vue";
333
+ import { IconPicker } from "@umbra-ui/core";
334
+ import type { IconKey } from "@umbra-ui/icons";
335
+
336
+ const actionIcons: IconKey[] = [
337
+ "edit",
338
+ "delete",
339
+ "save",
340
+ "copy",
341
+ "paste",
342
+ "cut",
343
+ "undo",
344
+ "redo",
345
+ "plus",
346
+ "minus",
347
+ "check",
348
+ "x",
349
+ "trash",
350
+ "download",
351
+ "upload",
352
+ "refresh",
353
+ "reload",
354
+ "sync",
355
+ "settings",
356
+ "gear",
357
+ ];
358
+
359
+ const selectedActionIcon = ref<IconKey>("edit");
360
+
361
+ const handleActionIconChange = (icon: IconKey) => {
362
+ console.log("Action icon changed to:", icon);
363
+ };
364
+ </script>
365
+
366
+ <template>
367
+ <div class="action-selector">
368
+ <div class="selector-header">
369
+ <h3>Action Icon</h3>
370
+ <p>Choose an icon for your action button</p>
371
+ </div>
372
+
373
+ <IconPicker
374
+ v-model:icon="selectedActionIcon"
375
+ :icon-list="actionIcons"
376
+ :icon-size="18"
377
+ @update:icon="handleActionIconChange"
378
+ />
379
+
380
+ <div class="action-preview">
381
+ <h4>Button Preview</h4>
382
+ <div class="preview-buttons">
383
+ <button class="action-btn primary">
384
+ <IconPicker
385
+ v-model:icon="selectedActionIcon"
386
+ :icon-list="actionIcons"
387
+ :icon-size="16"
388
+ :prevent-popup="true"
389
+ />
390
+ Action
391
+ </button>
392
+ <button class="action-btn secondary">
393
+ <IconPicker
394
+ v-model:icon="selectedActionIcon"
395
+ :icon-list="actionIcons"
396
+ :icon-size="16"
397
+ :prevent-popup="true"
398
+ />
399
+ Secondary
400
+ </button>
401
+ </div>
402
+ </div>
403
+ </div>
404
+ </template>
405
+
406
+ <style module>
407
+ .action-selector {
408
+ padding: 24px;
409
+ max-width: 500px;
410
+ background: #ffffff;
411
+ border-radius: 12px;
412
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
413
+ }
414
+
415
+ .selector-header {
416
+ margin-bottom: 24px;
417
+ }
418
+
419
+ .selector-header h3 {
420
+ font-size: 24px;
421
+ font-weight: 600;
422
+ color: #1a202c;
423
+ margin: 0 0 8px 0;
424
+ }
425
+
426
+ .selector-header p {
427
+ color: #718096;
428
+ margin: 0;
429
+ }
430
+
431
+ .action-preview {
432
+ margin-top: 32px;
433
+ padding-top: 24px;
434
+ border-top: 1px solid #e5e7eb;
435
+ }
436
+
437
+ .action-preview h4 {
438
+ font-size: 18px;
439
+ font-weight: 500;
440
+ color: #2d3748;
441
+ margin: 0 0 16px 0;
442
+ }
443
+
444
+ .preview-buttons {
445
+ display: flex;
446
+ gap: 12px;
447
+ }
448
+
449
+ .action-btn {
450
+ display: flex;
451
+ align-items: center;
452
+ gap: 8px;
453
+ padding: 8px 16px;
454
+ border: none;
455
+ border-radius: 6px;
456
+ font-size: 14px;
457
+ font-weight: 500;
458
+ cursor: pointer;
459
+ transition: all 0.2s ease;
460
+ }
461
+
462
+ .action-btn.primary {
463
+ background: #3b82f6;
464
+ color: white;
465
+ }
466
+
467
+ .action-btn.primary:hover {
468
+ background: #2563eb;
469
+ }
470
+
471
+ .action-btn.secondary {
472
+ background: #f3f4f6;
473
+ color: #374151;
474
+ border: 1px solid #d1d5db;
475
+ }
476
+
477
+ .action-btn.secondary:hover {
478
+ background: #e5e7eb;
479
+ }
480
+ </style>
481
+ ```
482
+
483
+ ### Media Icon Selector
484
+
485
+ ```vue
486
+ <script setup lang="ts">
487
+ import { ref } from "vue";
488
+ import { IconPicker } from "@umbra-ui/core";
489
+ import type { IconKey } from "@umbra-ui/icons";
490
+
491
+ const mediaIcons: IconKey[] = [
492
+ "play",
493
+ "pause",
494
+ "stop",
495
+ "skip-back",
496
+ "skip-forward",
497
+ "volume-high",
498
+ "volume-low",
499
+ "volume-mute",
500
+ "image",
501
+ "video",
502
+ "camera",
503
+ "microphone",
504
+ "headphones",
505
+ "speaker",
506
+ "music",
507
+ "film",
508
+ "tv",
509
+ "radio",
510
+ ];
511
+
512
+ const selectedMediaIcon = ref<IconKey>("play");
513
+
514
+ const handleMediaIconChange = (icon: IconKey) => {
515
+ console.log("Media icon changed to:", icon);
516
+ };
517
+ </script>
518
+
519
+ <template>
520
+ <div class="media-selector">
521
+ <div class="selector-header">
522
+ <h3>Media Icon</h3>
523
+ <p>Choose an icon for your media controls</p>
524
+ </div>
525
+
526
+ <IconPicker
527
+ v-model:icon="selectedMediaIcon"
528
+ :icon-list="mediaIcons"
529
+ :icon-size="22"
530
+ @update:icon="handleMediaIconChange"
531
+ />
532
+
533
+ <div class="media-preview">
534
+ <h4>Media Player Preview</h4>
535
+ <div class="preview-player">
536
+ <div class="player-controls">
537
+ <button class="control-btn">
538
+ <IconPicker
539
+ v-model:icon="selectedMediaIcon"
540
+ :icon-list="mediaIcons"
541
+ :icon-size="20"
542
+ :prevent-popup="true"
543
+ />
544
+ </button>
545
+ <div class="progress-bar">
546
+ <div class="progress-fill"></div>
547
+ </div>
548
+ <div class="time-display">2:34 / 4:12</div>
549
+ </div>
550
+ </div>
551
+ </div>
552
+ </div>
553
+ </template>
554
+
555
+ <style module>
556
+ .media-selector {
557
+ padding: 24px;
558
+ max-width: 500px;
559
+ background: #ffffff;
560
+ border-radius: 12px;
561
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
562
+ }
563
+
564
+ .selector-header {
565
+ margin-bottom: 24px;
566
+ }
567
+
568
+ .selector-header h3 {
569
+ font-size: 24px;
570
+ font-weight: 600;
571
+ color: #1a202c;
572
+ margin: 0 0 8px 0;
573
+ }
574
+
575
+ .selector-header p {
576
+ color: #718096;
577
+ margin: 0;
578
+ }
579
+
580
+ .media-preview {
581
+ margin-top: 32px;
582
+ padding-top: 24px;
583
+ border-top: 1px solid #e5e7eb;
584
+ }
585
+
586
+ .media-preview h4 {
587
+ font-size: 18px;
588
+ font-weight: 500;
589
+ color: #2d3748;
590
+ margin: 0 0 16px 0;
591
+ }
592
+
593
+ .preview-player {
594
+ padding: 20px;
595
+ background: #1f2937;
596
+ border-radius: 8px;
597
+ }
598
+
599
+ .player-controls {
600
+ display: flex;
601
+ align-items: center;
602
+ gap: 16px;
603
+ }
604
+
605
+ .control-btn {
606
+ width: 40px;
607
+ height: 40px;
608
+ background: #3b82f6;
609
+ color: white;
610
+ border: none;
611
+ border-radius: 50%;
612
+ display: flex;
613
+ align-items: center;
614
+ justify-content: center;
615
+ cursor: pointer;
616
+ transition: background 0.2s ease;
617
+ }
618
+
619
+ .control-btn:hover {
620
+ background: #2563eb;
621
+ }
622
+
623
+ .progress-bar {
624
+ flex: 1;
625
+ height: 4px;
626
+ background: #374151;
627
+ border-radius: 2px;
628
+ overflow: hidden;
629
+ }
630
+
631
+ .progress-fill {
632
+ width: 60%;
633
+ height: 100%;
634
+ background: #3b82f6;
635
+ border-radius: 2px;
636
+ }
637
+
638
+ .time-display {
639
+ color: #9ca3af;
640
+ font-size: 12px;
641
+ font-weight: 500;
642
+ min-width: 60px;
643
+ text-align: right;
644
+ }
645
+ </style>
646
+ ```
647
+
648
+ ### Custom Icon Set
649
+
650
+ ```vue
651
+ <script setup lang="ts">
652
+ import { ref } from "vue";
653
+ import { IconPicker } from "@umbra-ui/core";
654
+ import type { IconKey } from "@umbra-ui/icons";
655
+
656
+ const customIcons: IconKey[] = [
657
+ "star",
658
+ "heart",
659
+ "thumbs-up",
660
+ "thumbs-down",
661
+ "bookmark",
662
+ "flag",
663
+ "bell",
664
+ "mail",
665
+ "phone",
666
+ "message",
667
+ "chat",
668
+ "comment",
669
+ "user",
670
+ "users",
671
+ "user-plus",
672
+ "user-minus",
673
+ "shield",
674
+ "lock",
675
+ ];
676
+
677
+ const selectedCustomIcon = ref<IconKey>("star");
678
+
679
+ const handleCustomIconChange = (icon: IconKey) => {
680
+ console.log("Custom icon changed to:", icon);
681
+ };
682
+
683
+ const addToFavorites = () => {
684
+ console.log("Added to favorites with icon:", selectedCustomIcon.value);
685
+ };
686
+
687
+ const shareContent = () => {
688
+ console.log("Shared content with icon:", selectedCustomIcon.value);
689
+ };
690
+ </script>
691
+
692
+ <template>
693
+ <div class="custom-icon-selector">
694
+ <div class="selector-header">
695
+ <h3>Custom Icon Set</h3>
696
+ <p>Choose from a curated set of social and interaction icons</p>
697
+ </div>
698
+
699
+ <IconPicker
700
+ v-model:icon="selectedCustomIcon"
701
+ :icon-list="customIcons"
702
+ :icon-size="20"
703
+ @update:icon="handleCustomIconChange"
704
+ />
705
+
706
+ <div class="custom-preview">
707
+ <h4>Interactive Elements</h4>
708
+ <div class="preview-elements">
709
+ <button class="interactive-btn" @click="addToFavorites">
710
+ <IconPicker
711
+ v-model:icon="selectedCustomIcon"
712
+ :icon-list="customIcons"
713
+ :icon-size="16"
714
+ :prevent-popup="true"
715
+ />
716
+ Add to Favorites
717
+ </button>
718
+
719
+ <button class="interactive-btn" @click="shareContent">
720
+ <IconPicker
721
+ v-model:icon="selectedCustomIcon"
722
+ :icon-list="customIcons"
723
+ :icon-size="16"
724
+ :prevent-popup="true"
725
+ />
726
+ Share
727
+ </button>
728
+
729
+ <div class="social-stats">
730
+ <div class="stat-item">
731
+ <IconPicker
732
+ v-model:icon="selectedCustomIcon"
733
+ :icon-list="customIcons"
734
+ :icon-size="14"
735
+ :prevent-popup="true"
736
+ />
737
+ <span>1.2k</span>
738
+ </div>
739
+ </div>
740
+ </div>
741
+ </div>
742
+ </div>
743
+ </template>
744
+
745
+ <style module>
746
+ .custom-icon-selector {
747
+ padding: 24px;
748
+ max-width: 600px;
749
+ background: #ffffff;
750
+ border-radius: 12px;
751
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
752
+ }
753
+
754
+ .selector-header {
755
+ margin-bottom: 24px;
756
+ }
757
+
758
+ .selector-header h3 {
759
+ font-size: 24px;
760
+ font-weight: 600;
761
+ color: #1a202c;
762
+ margin: 0 0 8px 0;
763
+ }
764
+
765
+ .selector-header p {
766
+ color: #718096;
767
+ margin: 0;
768
+ }
769
+
770
+ .custom-preview {
771
+ margin-top: 32px;
772
+ padding-top: 24px;
773
+ border-top: 1px solid #e5e7eb;
774
+ }
775
+
776
+ .custom-preview h4 {
777
+ font-size: 18px;
778
+ font-weight: 500;
779
+ color: #2d3748;
780
+ margin: 0 0 16px 0;
781
+ }
782
+
783
+ .preview-elements {
784
+ display: flex;
785
+ flex-direction: column;
786
+ gap: 16px;
787
+ }
788
+
789
+ .interactive-btn {
790
+ display: flex;
791
+ align-items: center;
792
+ gap: 8px;
793
+ padding: 12px 16px;
794
+ background: #f8fafc;
795
+ border: 1px solid #e2e8f0;
796
+ border-radius: 8px;
797
+ font-size: 14px;
798
+ font-weight: 500;
799
+ color: #374151;
800
+ cursor: pointer;
801
+ transition: all 0.2s ease;
802
+ }
803
+
804
+ .interactive-btn:hover {
805
+ background: #f1f5f9;
806
+ border-color: #cbd5e1;
807
+ }
808
+
809
+ .social-stats {
810
+ display: flex;
811
+ gap: 16px;
812
+ }
813
+
814
+ .stat-item {
815
+ display: flex;
816
+ align-items: center;
817
+ gap: 6px;
818
+ padding: 8px 12px;
819
+ background: #fef3c7;
820
+ border-radius: 6px;
821
+ font-size: 12px;
822
+ font-weight: 600;
823
+ color: #92400e;
824
+ }
825
+
826
+ .stat-item span {
827
+ font-size: 14px;
828
+ }
829
+ </style>
830
+ ```
831
+
832
+ ### Disabled State Example
833
+
834
+ ```vue
835
+ <script setup lang="ts">
836
+ import { ref } from "vue";
837
+ import { IconPicker } from "@umbra-ui/core";
838
+ import type { IconKey } from "@umbra-ui/icons";
839
+
840
+ const selectedIcon = ref<IconKey>("home");
841
+ const isDisabled = ref(false);
842
+
843
+ const toggleDisabled = () => {
844
+ isDisabled.value = !isDisabled.value;
845
+ };
846
+
847
+ const handleIconChange = (icon: IconKey) => {
848
+ console.log("Icon changed to:", icon);
849
+ };
850
+ </script>
851
+
852
+ <template>
853
+ <div class="disabled-example">
854
+ <h3>Disabled State</h3>
855
+
856
+ <div class="controls">
857
+ <button @click="toggleDisabled" class="toggle-btn">
858
+ {{ isDisabled ? "Enable" : "Disable" }} Icon Picker
859
+ </button>
860
+ </div>
861
+
862
+ <IconPicker
863
+ v-model:icon="selectedIcon"
864
+ :prevent-popup="isDisabled"
865
+ :icon-size="20"
866
+ @update:icon="handleIconChange"
867
+ />
868
+
869
+ <div class="status">
870
+ <p>Status: {{ isDisabled ? "Disabled" : "Enabled" }}</p>
871
+ <p>Selected: {{ selectedIcon || "None" }}</p>
872
+ </div>
873
+ </div>
874
+ </template>
875
+
876
+ <style module>
877
+ .disabled-example {
878
+ padding: 24px;
879
+ max-width: 400px;
880
+ }
881
+
882
+ .controls {
883
+ margin-bottom: 20px;
884
+ }
885
+
886
+ .toggle-btn {
887
+ padding: 8px 16px;
888
+ background: #4299e1;
889
+ color: white;
890
+ border: none;
891
+ border-radius: 6px;
892
+ cursor: pointer;
893
+ font-weight: 500;
894
+ transition: background 0.2s ease;
895
+ }
896
+
897
+ .toggle-btn:hover {
898
+ background: #3182ce;
899
+ }
900
+
901
+ .status {
902
+ margin-top: 20px;
903
+ padding: 16px;
904
+ background: #f7fafc;
905
+ border-radius: 8px;
906
+ }
907
+
908
+ .status p {
909
+ margin: 0 0 8px 0;
910
+ color: #4a5568;
911
+ }
912
+
913
+ .status p:last-child {
914
+ margin-bottom: 0;
915
+ }
916
+ </style>
917
+ ```
918
+
919
+ ## Advanced Usage
920
+
921
+ ### Dynamic Icon Filtering
922
+
923
+ ```vue
924
+ <script setup lang="ts">
925
+ import { ref, computed } from "vue";
926
+ import { IconPicker } from "@umbra-ui/core";
927
+ import type { IconKey } from "@umbra-ui/icons";
928
+ import { icons } from "@umbra-ui/icons";
929
+
930
+ const searchQuery = ref("");
931
+ const selectedIcon = ref<IconKey>("home");
932
+
933
+ const allIcons = Object.keys(icons) as IconKey[];
934
+
935
+ const filteredIcons = computed(() => {
936
+ if (!searchQuery.value) return allIcons;
937
+
938
+ return allIcons.filter((iconKey) =>
939
+ iconKey.toLowerCase().includes(searchQuery.value.toLowerCase())
940
+ );
941
+ });
942
+
943
+ const handleIconChange = (icon: IconKey) => {
944
+ selectedIcon.value = icon;
945
+ console.log("Selected icon:", icon);
946
+ };
947
+
948
+ const clearSearch = () => {
949
+ searchQuery.value = "";
950
+ };
951
+ </script>
952
+
953
+ <template>
954
+ <div class="dynamic-filtering">
955
+ <h3>Dynamic Icon Filtering</h3>
956
+
957
+ <div class="search-section">
958
+ <div class="search-input">
959
+ <input
960
+ v-model="searchQuery"
961
+ type="text"
962
+ placeholder="Search icons..."
963
+ class="search-field"
964
+ />
965
+ <button @click="clearSearch" class="clear-btn">×</button>
966
+ </div>
967
+ <p class="search-results">{{ filteredIcons.length }} icons found</p>
968
+ </div>
969
+
970
+ <IconPicker
971
+ v-model:icon="selectedIcon"
972
+ :icon-list="filteredIcons"
973
+ :icon-size="18"
974
+ @update:icon="handleIconChange"
975
+ />
976
+
977
+ <div class="icon-info">
978
+ <h4>Selected Icon</h4>
979
+ <div class="icon-display">
980
+ <IconPicker
981
+ v-model:icon="selectedIcon"
982
+ :icon-list="filteredIcons"
983
+ :icon-size="32"
984
+ :prevent-popup="true"
985
+ />
986
+ <div class="icon-details">
987
+ <p class="icon-name">{{ selectedIcon }}</p>
988
+ <p class="icon-category">
989
+ Category: {{ getIconCategory(selectedIcon) }}
990
+ </p>
991
+ </div>
992
+ </div>
993
+ </div>
994
+ </div>
995
+ </template>
996
+
997
+ <style module>
998
+ .dynamic-filtering {
999
+ padding: 24px;
1000
+ max-width: 600px;
1001
+ }
1002
+
1003
+ .search-section {
1004
+ margin-bottom: 24px;
1005
+ }
1006
+
1007
+ .search-input {
1008
+ position: relative;
1009
+ margin-bottom: 8px;
1010
+ }
1011
+
1012
+ .search-field {
1013
+ width: 100%;
1014
+ padding: 12px 40px 12px 12px;
1015
+ border: 1px solid #d1d5db;
1016
+ border-radius: 6px;
1017
+ font-size: 14px;
1018
+ transition: border-color 0.2s ease;
1019
+ }
1020
+
1021
+ .search-field:focus {
1022
+ outline: none;
1023
+ border-color: #3b82f6;
1024
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
1025
+ }
1026
+
1027
+ .clear-btn {
1028
+ position: absolute;
1029
+ right: 8px;
1030
+ top: 50%;
1031
+ transform: translateY(-50%);
1032
+ width: 24px;
1033
+ height: 24px;
1034
+ background: #6b7280;
1035
+ color: white;
1036
+ border: none;
1037
+ border-radius: 50%;
1038
+ font-size: 16px;
1039
+ font-weight: bold;
1040
+ cursor: pointer;
1041
+ display: flex;
1042
+ align-items: center;
1043
+ justify-content: center;
1044
+ transition: background 0.2s ease;
1045
+ }
1046
+
1047
+ .clear-btn:hover {
1048
+ background: #4b5563;
1049
+ }
1050
+
1051
+ .search-results {
1052
+ color: #6b7280;
1053
+ font-size: 12px;
1054
+ margin: 0;
1055
+ }
1056
+
1057
+ .icon-info {
1058
+ margin-top: 32px;
1059
+ padding-top: 24px;
1060
+ border-top: 1px solid #e5e7eb;
1061
+ }
1062
+
1063
+ .icon-info h4 {
1064
+ font-size: 18px;
1065
+ font-weight: 500;
1066
+ color: #2d3748;
1067
+ margin: 0 0 16px 0;
1068
+ }
1069
+
1070
+ .icon-display {
1071
+ display: flex;
1072
+ align-items: center;
1073
+ gap: 16px;
1074
+ padding: 20px;
1075
+ background: #f9fafb;
1076
+ border-radius: 8px;
1077
+ border: 1px solid #e5e7eb;
1078
+ }
1079
+
1080
+ .icon-details {
1081
+ flex: 1;
1082
+ }
1083
+
1084
+ .icon-name {
1085
+ font-size: 16px;
1086
+ font-weight: 600;
1087
+ color: #374151;
1088
+ margin: 0 0 4px 0;
1089
+ }
1090
+
1091
+ .icon-category {
1092
+ font-size: 14px;
1093
+ color: #6b7280;
1094
+ margin: 0;
1095
+ }
1096
+ </style>
1097
+ ```
1098
+
1099
+ ## Performance Considerations
1100
+
1101
+ - **Floating UI**: Smart positioning with automatic updates and cleanup
1102
+ - **Teleport**: Overlay and picker are teleported to body for proper z-index management
1103
+ - **Event Cleanup**: Proper cleanup of auto-update listeners on unmount
1104
+ - **Icon Filtering**: Efficient filtering of animated icons from the default list
1105
+ - **Computed Properties**: Reactive icon list computation for optimal performance
1106
+
1107
+ ## Accessibility
1108
+
1109
+ - **Keyboard Navigation**: Support for keyboard interaction
1110
+ - **Screen Reader Support**: Proper ARIA labels and semantic structure
1111
+ - **Focus Management**: Focus is properly managed during interactions
1112
+ - **Icon Information**: Displays icon names for screen readers
1113
+ - **High Contrast**: Supports high contrast mode with appropriate styling
1114
+
1115
+ ## Browser Support
1116
+
1117
+ - **Modern Browsers**: Chrome 88+, Firefox 85+, Safari 14+, Edge 88+
1118
+ - **Mobile Browsers**: iOS Safari 14+, Chrome Mobile 88+
1119
+ - **CSS Features**: Uses CSS Grid and modern layout features
1120
+ - **JavaScript**: Requires ES2020+ support
1121
+
1122
+ ## Troubleshooting
1123
+
1124
+ ### Common Issues
1125
+
1126
+ 1. **Icons not displaying**: Check that @umbra-ui/icons is properly installed
1127
+ 2. **Picker not positioning correctly**: Ensure the trigger button has proper positioning context
1128
+ 3. **Icon not updating**: Verify the v-model binding is correctly set up
1129
+ 4. **Custom icon list not working**: Ensure the iconList prop contains valid IconKey values
1130
+
1131
+ ### Debug Mode
1132
+
1133
+ ```vue
1134
+ <script setup lang="ts">
1135
+ import { ref, watch } from "vue";
1136
+ import { IconPicker } from "@umbra-ui/core";
1137
+
1138
+ const selectedIcon = ref("");
1139
+
1140
+ // Watch for changes
1141
+ watch(selectedIcon, (newIcon) => {
1142
+ console.log("Selected icon changed:", newIcon);
1143
+ });
1144
+ </script>
1145
+ ```
1146
+
1147
+ ## Migration Guide
1148
+
1149
+ ### From v1 to v2
1150
+
1151
+ - `v-model` prop is now `v-model:icon`
1152
+ - Event names have been updated to use kebab-case
1153
+ - Icon system has been updated to use @umbra-ui/icons
1154
+ - Floating UI integration has been improved
1155
+
1156
+ ### Breaking Changes
1157
+
1158
+ - Removed `value` prop in favor of `v-model:icon`
1159
+ - Changed event names from camelCase to kebab-case
1160
+ - Updated icon prop to use string keys instead of components
1161
+ - Modified CSS class naming convention