@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,1439 @@
1
+ # ColorPicker
2
+
3
+ A comprehensive color picker component built with Vue 3 Composition API and TypeScript. The ColorPicker provides an intuitive interface for selecting colors from a curated palette with support for customizable dot styling, smart positioning using Floating UI, and comprehensive color information display.
4
+
5
+ ## Installation/Import
6
+
7
+ ```typescript
8
+ import { ColorPicker } from "@umbra-ui/core";
9
+ import type { Color, ColorGroup } from "@umbra-ui/core";
10
+ import { colors, colorPickerColors, colorGroups } from "@umbra-ui/core";
11
+ ```
12
+
13
+ **Dependencies:**
14
+
15
+ - Vue 3.x
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 { ColorPicker, colorPickerColors } from "@umbra-ui/core";
24
+ import type { Color } from "@umbra-ui/core";
25
+
26
+ const selectedColor = ref<Color>(colorPickerColors.gray700);
27
+
28
+ const handleColorChange = (color: Color) => {
29
+ console.log("Selected color:", color);
30
+ console.log("Color name:", color.name);
31
+ console.log("Color weight:", color.weight);
32
+ console.log("Color hex:", color.hex);
33
+ };
34
+ </script>
35
+
36
+ <template>
37
+ <div class="app">
38
+ <h2>Choose a Color</h2>
39
+
40
+ <ColorPicker
41
+ v-model:color="selectedColor"
42
+ @update:color="handleColorChange"
43
+ />
44
+
45
+ <div v-if="selectedColor" class="color-info">
46
+ <div
47
+ class="color-preview"
48
+ :style="{ backgroundColor: selectedColor.hex }"
49
+ />
50
+ <div class="color-details">
51
+ <h3>{{ selectedColor.name }}({{ selectedColor.weight }})</h3>
52
+ <p>{{ selectedColor.hex }}</p>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </template>
57
+
58
+ <style module>
59
+ .app {
60
+ padding: 24px;
61
+ max-width: 400px;
62
+ }
63
+
64
+ .color-info {
65
+ margin-top: 20px;
66
+ display: flex;
67
+ align-items: center;
68
+ gap: 16px;
69
+ padding: 16px;
70
+ background: #f8f9fa;
71
+ border-radius: 8px;
72
+ }
73
+
74
+ .color-preview {
75
+ width: 40px;
76
+ height: 40px;
77
+ border-radius: 50%;
78
+ border: 2px solid #e9ecef;
79
+ }
80
+
81
+ .color-details h3 {
82
+ margin: 0 0 4px 0;
83
+ font-size: 16px;
84
+ font-weight: 600;
85
+ }
86
+
87
+ .color-details p {
88
+ margin: 0;
89
+ color: #6c757d;
90
+ font-family: monospace;
91
+ }
92
+ </style>
93
+ ```
94
+
95
+ ## Props
96
+
97
+ | Prop Name | Type | Required | Default | Description |
98
+ | ---------------------- | ------------------ | -------- | ---------------------------------------------- | ----------------------------------------------- |
99
+ | `color` | `Color` | Yes | `colorPickerColors.gray700` | Currently selected color |
100
+ | `pickerOffsetX` | `number` | No | `0` | Horizontal offset for picker positioning |
101
+ | `preventPopup` | `boolean` | No | `false` | Whether to prevent the popup from opening |
102
+ | `dotSize` | `number \| string` | No | `"1.25rem"` | Size of the color dot |
103
+ | `dotRadius` | `number \| string` | No | `"999px"` | Border radius of the color dot |
104
+ | `dotBorderWidth` | `number` | No | `1` | Border width of the color dot |
105
+ | `dotBorderColor` | `string` | No | `"var(--colorpicker-dot-border-color)"` | Border color of the color dot |
106
+ | `dotBorderColorActive` | `string` | No | `"var(--colorpicker-dot-border-color-active)"` | Border color when picker is open |
107
+ | `showColorInfo` | `boolean` | No | `true` | Whether to show color information in the picker |
108
+
109
+ ## Color Interface
110
+
111
+ ```typescript
112
+ interface Color {
113
+ name: string | null;
114
+ hex: string;
115
+ weight: number | null;
116
+ }
117
+ ```
118
+
119
+ ### Color Properties
120
+
121
+ | Property | Type | Description |
122
+ | -------- | ---------------- | ----------------------------------------- |
123
+ | `name` | `string \| null` | Color name (e.g., "Gray", "Blue") |
124
+ | `hex` | `string` | Hexadecimal color value (e.g., "#374151") |
125
+ | `weight` | `number \| null` | Color weight/shade (e.g., 200, 500, 700) |
126
+
127
+ ## Events
128
+
129
+ | Event Name | Payload Type | Description |
130
+ | -------------- | ------------ | -------------------------------- |
131
+ | `update:color` | `Color` | Emitted when a color is selected |
132
+
133
+ ## Available Colors
134
+
135
+ The ColorPicker includes a comprehensive palette of 200 colors across 25 color groups:
136
+
137
+ ### Color Groups
138
+
139
+ - **Neutrals**: Gray, Zinc, Neutral, Stone
140
+ - **Warm Colors**: Red, Orange, Amber, Yellow
141
+ - **Cool Colors**: Lime, Green, Emerald, Teal, Cyan, Sky, Blue, Indigo
142
+ - **Purple Tones**: Violet, Purple, Fuchsia
143
+ - **Pink Tones**: Pink, Rose
144
+
145
+ ### Color Weights
146
+
147
+ Each color group includes 8 weight variations:
148
+
149
+ - **200**: Lightest shade
150
+ - **300**: Light shade
151
+ - **400**: Medium-light shade
152
+ - **500**: Medium shade (base color)
153
+ - **600**: Medium-dark shade
154
+ - **700**: Dark shade
155
+ - **800**: Darker shade
156
+ - **900**: Darkest shade
157
+
158
+ ### Accessing Colors
159
+
160
+ ```typescript
161
+ import { colorPickerColors, colors, colorGroups } from "@umbra-ui/core";
162
+
163
+ // Access by name and weight
164
+ const blue500 = colorPickerColors.blue500; // { name: "Blue", hex: "#3B82F6", weight: 500 }
165
+
166
+ // Access all colors
167
+ const allColors = colors; // Array of all 200 colors
168
+
169
+ // Access color groups
170
+ const blueGroup = colorGroups.find((group) => group.name === "Blue");
171
+ ```
172
+
173
+ ## CSS Customization
174
+
175
+ ### Layout Variables
176
+
177
+ ```css
178
+ .color-picker {
179
+ --picker-button-bg: #ffffff;
180
+ --picker-button-border: 1px solid #e9ecef;
181
+ --picker-button-hover-bg: #f8f9fa;
182
+ --picker-button-hover-border: 1px solid #dee2e6;
183
+ --picker-button-hover-shadow: rgba(0, 0, 0, 0.1);
184
+ --picker-button-hover-inset-shadow: rgba(255, 255, 255, 0.1);
185
+ --picker-button-selected-bg: #e3f2fd;
186
+ --picker-button-selected-shadow: rgba(0, 0, 0, 0.1);
187
+ --picker-button-selected-inset-shadow: rgba(255, 255, 255, 0.1);
188
+ --picker-picker-bg: #ffffff;
189
+ --picker-picker-border: 1px solid #e9ecef;
190
+ --picker-picker-shadow: rgba(0, 0, 0, 0.1);
191
+ --picker-picker-inset-shadow: rgba(255, 255, 255, 0.1);
192
+ --picker-selection-bar-bg: #f8f9fa;
193
+ --picker-selection-bar-text: #212529;
194
+ --picker-selection-bar-border: #e9ecef;
195
+ --picker-border-light: #e9ecef;
196
+ --picker-overlay-bg: rgba(0, 0, 0, 0.1);
197
+ --colorpicker-picker-shadow: none;
198
+ --colorpicker-color-cell-border: #838383;
199
+ --colorpicker-color-cell-selected-border: #ffffff;
200
+ --colorpicker-color-dot-bg: #ffffff;
201
+ --colorpicker-dot-border-color: #9ca3af;
202
+ --colorpicker-dot-border-color-active: #374151;
203
+ }
204
+ ```
205
+
206
+ ### Container Styling
207
+
208
+ ```css
209
+ .color-picker {
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ max-width: fit-content;
214
+ }
215
+ ```
216
+
217
+ ### Button Styling
218
+
219
+ ```css
220
+ .color-picker .button {
221
+ border-radius: 0.353rem;
222
+ padding: 0.588rem;
223
+ display: flex;
224
+ align-items: center;
225
+ justify-content: center;
226
+ cursor: pointer;
227
+ background-color: var(--picker-button-bg);
228
+ border: var(--picker-button-border);
229
+ transition: all 0.3s ease;
230
+ }
231
+ ```
232
+
233
+ ### Picker Styling
234
+
235
+ ```css
236
+ .color-picker .picker {
237
+ position: absolute;
238
+ background-color: var(--picker-picker-bg);
239
+ border-radius: 0.353rem;
240
+ z-index: 1000;
241
+ overflow: auto;
242
+ box-shadow: var(--colorpicker-picker-shadow);
243
+ border: var(--picker-picker-border);
244
+ }
245
+ ```
246
+
247
+ ### Color Grid Styling
248
+
249
+ ```css
250
+ .color-picker .color_list {
251
+ display: grid;
252
+ grid-template-columns: repeat(8, 1fr);
253
+ gap: 0.706rem;
254
+ padding: 0.706rem;
255
+ }
256
+
257
+ .color-picker .color_cell {
258
+ width: 1.412rem;
259
+ height: 1.412rem;
260
+ border: 1px solid var(--colorpicker-color-cell-border);
261
+ border-radius: 999px;
262
+ display: flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ transition: transform 0.3s ease, scale 0.3s ease;
266
+ }
267
+ ```
268
+
269
+ ## Examples
270
+
271
+ ### Theme Color Selector
272
+
273
+ ```vue
274
+ <script setup lang="ts">
275
+ import { ref } from "vue";
276
+ import { ColorPicker, colorPickerColors } from "@umbra-ui/core";
277
+ import type { Color } from "@umbra-ui/core";
278
+
279
+ const themeColors = [
280
+ colorPickerColors.blue500,
281
+ colorPickerColors.green500,
282
+ colorPickerColors.purple500,
283
+ colorPickerColors.orange500,
284
+ colorPickerColors.red500,
285
+ colorPickerColors.teal500,
286
+ ];
287
+
288
+ const selectedThemeColor = ref<Color>(colorPickerColors.blue500);
289
+
290
+ const handleThemeColorChange = (color: Color) => {
291
+ console.log("Theme color changed to:", color);
292
+ // Apply theme color to your application
293
+ document.documentElement.style.setProperty("--primary-color", color.hex);
294
+ };
295
+ </script>
296
+
297
+ <template>
298
+ <div class="theme-selector">
299
+ <div class="selector-header">
300
+ <h3>Theme Colors</h3>
301
+ <p>Choose your application's primary color</p>
302
+ </div>
303
+
304
+ <ColorPicker
305
+ v-model:color="selectedThemeColor"
306
+ :dot-size="32"
307
+ :dot-radius="8"
308
+ :dot-border-width="2"
309
+ @update:color="handleThemeColorChange"
310
+ />
311
+
312
+ <div class="theme-preview">
313
+ <div
314
+ class="preview-header"
315
+ :style="{ backgroundColor: selectedThemeColor.hex }"
316
+ >
317
+ <h4>Preview</h4>
318
+ </div>
319
+ <div class="preview-content">
320
+ <p>
321
+ This is how your theme will look with {{ selectedThemeColor.name }}({{
322
+ selectedThemeColor.weight
323
+ }})
324
+ </p>
325
+ </div>
326
+ </div>
327
+ </div>
328
+ </template>
329
+
330
+ <style module>
331
+ .theme-selector {
332
+ padding: 24px;
333
+ max-width: 500px;
334
+ background: #ffffff;
335
+ border-radius: 12px;
336
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
337
+ }
338
+
339
+ .selector-header {
340
+ margin-bottom: 24px;
341
+ }
342
+
343
+ .selector-header h3 {
344
+ font-size: 20px;
345
+ font-weight: 600;
346
+ color: #1a202c;
347
+ margin: 0 0 8px 0;
348
+ }
349
+
350
+ .selector-header p {
351
+ color: #718096;
352
+ margin: 0;
353
+ }
354
+
355
+ .theme-preview {
356
+ margin-top: 24px;
357
+ border-radius: 8px;
358
+ overflow: hidden;
359
+ border: 1px solid #e2e8f0;
360
+ }
361
+
362
+ .preview-header {
363
+ padding: 16px;
364
+ color: white;
365
+ }
366
+
367
+ .preview-header h4 {
368
+ margin: 0;
369
+ font-size: 16px;
370
+ font-weight: 600;
371
+ }
372
+
373
+ .preview-content {
374
+ padding: 16px;
375
+ background: #f7fafc;
376
+ }
377
+
378
+ .preview-content p {
379
+ margin: 0;
380
+ color: #4a5568;
381
+ }
382
+ </style>
383
+ ```
384
+
385
+ ### Custom Dot Styling
386
+
387
+ ```vue
388
+ <script setup lang="ts">
389
+ import { ref } from "vue";
390
+ import { ColorPicker, colorPickerColors } from "@umbra-ui/core";
391
+ import type { Color } from "@umbra-ui/core";
392
+
393
+ const selectedColor = ref<Color>(colorPickerColors.emerald500);
394
+
395
+ const handleColorChange = (color: Color) => {
396
+ console.log("Selected color:", color);
397
+ };
398
+ </script>
399
+
400
+ <template>
401
+ <div class="custom-styling">
402
+ <h3>Custom Dot Styling</h3>
403
+
404
+ <div class="picker-row">
405
+ <div class="picker-item">
406
+ <h4>Square Dot</h4>
407
+ <ColorPicker
408
+ v-model:color="selectedColor"
409
+ :dot-size="24"
410
+ :dot-radius="4"
411
+ :dot-border-width="2"
412
+ dot-border-color="#e2e8f0"
413
+ dot-border-color-active="#4299e1"
414
+ @update:color="handleColorChange"
415
+ />
416
+ </div>
417
+
418
+ <div class="picker-item">
419
+ <h4>Large Round Dot</h4>
420
+ <ColorPicker
421
+ v-model:color="selectedColor"
422
+ :dot-size="40"
423
+ :dot-radius="999"
424
+ :dot-border-width="3"
425
+ dot-border-color="#cbd5e0"
426
+ dot-border-color-active="#2b6cb0"
427
+ @update:color="handleColorChange"
428
+ />
429
+ </div>
430
+
431
+ <div class="picker-item">
432
+ <h4>Small Dot</h4>
433
+ <ColorPicker
434
+ v-model:color="selectedColor"
435
+ :dot-size="16"
436
+ :dot-radius="999"
437
+ :dot-border-width="1"
438
+ dot-border-color="#a0aec0"
439
+ dot-border-color-active="#1a365d"
440
+ @update:color="handleColorChange"
441
+ />
442
+ </div>
443
+ </div>
444
+ </div>
445
+ </template>
446
+
447
+ <style module>
448
+ .custom-styling {
449
+ padding: 24px;
450
+ max-width: 600px;
451
+ }
452
+
453
+ .picker-row {
454
+ display: flex;
455
+ gap: 32px;
456
+ margin-top: 20px;
457
+ }
458
+
459
+ .picker-item {
460
+ text-align: center;
461
+ }
462
+
463
+ .picker-item h4 {
464
+ font-size: 14px;
465
+ font-weight: 500;
466
+ color: #4a5568;
467
+ margin: 0 0 12px 0;
468
+ }
469
+ </style>
470
+ ```
471
+
472
+ ### Color Palette Builder
473
+
474
+ ```vue
475
+ <script setup lang="ts">
476
+ import { ref } from "vue";
477
+ import { ColorPicker, colorPickerColors, colorGroups } from "@umbra-ui/core";
478
+ import type { Color, ColorGroup } from "@umbra-ui/core";
479
+
480
+ const selectedColors = ref<Color[]>([
481
+ colorPickerColors.blue500,
482
+ colorPickerColors.green500,
483
+ colorPickerColors.orange500,
484
+ ]);
485
+
486
+ const addColor = (color: Color) => {
487
+ if (!selectedColors.value.find((c) => c.hex === color.hex)) {
488
+ selectedColors.value.push(color);
489
+ }
490
+ };
491
+
492
+ const removeColor = (colorToRemove: Color) => {
493
+ selectedColors.value = selectedColors.value.filter(
494
+ (color) => color.hex !== colorToRemove.hex
495
+ );
496
+ };
497
+
498
+ const clearPalette = () => {
499
+ selectedColors.value = [];
500
+ };
501
+ </script>
502
+
503
+ <template>
504
+ <div class="palette-builder">
505
+ <div class="builder-header">
506
+ <h3>Color Palette Builder</h3>
507
+ <p>Build your custom color palette</p>
508
+ </div>
509
+
510
+ <div class="color-picker-section">
511
+ <h4>Add Colors</h4>
512
+ <ColorPicker
513
+ :color="colorPickerColors.gray500"
514
+ @update:color="addColor"
515
+ />
516
+ </div>
517
+
518
+ <div class="palette-section">
519
+ <div class="palette-header">
520
+ <h4>Your Palette ({{ selectedColors.length }} colors)</h4>
521
+ <button
522
+ @click="clearPalette"
523
+ class="clear-btn"
524
+ v-if="selectedColors.length > 0"
525
+ >
526
+ Clear All
527
+ </button>
528
+ </div>
529
+
530
+ <div v-if="selectedColors.length === 0" class="empty-palette">
531
+ <p>
532
+ No colors selected yet. Choose colors above to build your palette.
533
+ </p>
534
+ </div>
535
+
536
+ <div v-else class="palette-grid">
537
+ <div
538
+ v-for="color in selectedColors"
539
+ :key="color.hex"
540
+ class="palette-item"
541
+ >
542
+ <div class="palette-color" :style="{ backgroundColor: color.hex }" />
543
+ <div class="palette-info">
544
+ <p class="color-name">{{ color.name }}({{ color.weight }})</p>
545
+ <p class="color-hex">{{ color.hex }}</p>
546
+ </div>
547
+ <button @click="removeColor(color)" class="remove-btn">×</button>
548
+ </div>
549
+ </div>
550
+ </div>
551
+ </div>
552
+ </template>
553
+
554
+ <style module>
555
+ .palette-builder {
556
+ padding: 24px;
557
+ max-width: 600px;
558
+ background: #ffffff;
559
+ border-radius: 12px;
560
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
561
+ }
562
+
563
+ .builder-header {
564
+ margin-bottom: 32px;
565
+ }
566
+
567
+ .builder-header h3 {
568
+ font-size: 20px;
569
+ font-weight: 600;
570
+ color: #1a202c;
571
+ margin: 0 0 8px 0;
572
+ }
573
+
574
+ .builder-header p {
575
+ color: #718096;
576
+ margin: 0;
577
+ }
578
+
579
+ .color-picker-section {
580
+ margin-bottom: 32px;
581
+ }
582
+
583
+ .color-picker-section h4 {
584
+ font-size: 16px;
585
+ font-weight: 500;
586
+ color: #2d3748;
587
+ margin: 0 0 16px 0;
588
+ }
589
+
590
+ .palette-header {
591
+ display: flex;
592
+ align-items: center;
593
+ justify-content: space-between;
594
+ margin-bottom: 16px;
595
+ }
596
+
597
+ .palette-header h4 {
598
+ font-size: 16px;
599
+ font-weight: 500;
600
+ color: #2d3748;
601
+ margin: 0;
602
+ }
603
+
604
+ .clear-btn {
605
+ padding: 6px 12px;
606
+ background: #fed7d7;
607
+ color: #c53030;
608
+ border: none;
609
+ border-radius: 4px;
610
+ font-size: 12px;
611
+ font-weight: 500;
612
+ cursor: pointer;
613
+ transition: background 0.2s ease;
614
+ }
615
+
616
+ .clear-btn:hover {
617
+ background: #feb2b2;
618
+ }
619
+
620
+ .empty-palette {
621
+ padding: 32px;
622
+ text-align: center;
623
+ background: #f7fafc;
624
+ border-radius: 8px;
625
+ border: 2px dashed #cbd5e0;
626
+ }
627
+
628
+ .empty-palette p {
629
+ color: #718096;
630
+ margin: 0;
631
+ }
632
+
633
+ .palette-grid {
634
+ display: grid;
635
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
636
+ gap: 16px;
637
+ }
638
+
639
+ .palette-item {
640
+ display: flex;
641
+ align-items: center;
642
+ gap: 12px;
643
+ padding: 12px;
644
+ background: #f7fafc;
645
+ border-radius: 8px;
646
+ border: 1px solid #e2e8f0;
647
+ }
648
+
649
+ .palette-color {
650
+ width: 32px;
651
+ height: 32px;
652
+ border-radius: 50%;
653
+ border: 2px solid #e2e8f0;
654
+ flex-shrink: 0;
655
+ }
656
+
657
+ .palette-info {
658
+ flex: 1;
659
+ }
660
+
661
+ .color-name {
662
+ font-size: 14px;
663
+ font-weight: 500;
664
+ color: #2d3748;
665
+ margin: 0 0 2px 0;
666
+ }
667
+
668
+ .color-hex {
669
+ font-size: 12px;
670
+ color: #718096;
671
+ font-family: monospace;
672
+ margin: 0;
673
+ }
674
+
675
+ .remove-btn {
676
+ width: 24px;
677
+ height: 24px;
678
+ background: #fed7d7;
679
+ color: #c53030;
680
+ border: none;
681
+ border-radius: 50%;
682
+ font-size: 16px;
683
+ font-weight: bold;
684
+ cursor: pointer;
685
+ display: flex;
686
+ align-items: center;
687
+ justify-content: center;
688
+ transition: background 0.2s ease;
689
+ }
690
+
691
+ .remove-btn:hover {
692
+ background: #feb2b2;
693
+ }
694
+ </style>
695
+ ```
696
+
697
+ ### Brand Color Selector
698
+
699
+ ```vue
700
+ <script setup lang="ts">
701
+ import { ref } from "vue";
702
+ import { ColorPicker, colorPickerColors } from "@umbra-ui/core";
703
+ import type { Color } from "@umbra-ui/core";
704
+
705
+ interface BrandColors {
706
+ primary: Color;
707
+ secondary: Color;
708
+ accent: Color;
709
+ neutral: Color;
710
+ }
711
+
712
+ const brandColors = ref<BrandColors>({
713
+ primary: colorPickerColors.blue600,
714
+ secondary: colorPickerColors.gray600,
715
+ accent: colorPickerColors.orange500,
716
+ neutral: colorPickerColors.gray300,
717
+ });
718
+
719
+ const updateBrandColor = (key: keyof BrandColors, color: Color) => {
720
+ brandColors.value[key] = color;
721
+ console.log(`Updated ${key} color:`, color);
722
+ };
723
+
724
+ const generateCSS = () => {
725
+ const css = `
726
+ :root {
727
+ --brand-primary: ${brandColors.value.primary.hex};
728
+ --brand-secondary: ${brandColors.value.secondary.hex};
729
+ --brand-accent: ${brandColors.value.accent.hex};
730
+ --brand-neutral: ${brandColors.value.neutral.hex};
731
+ }`;
732
+ console.log("Generated CSS:", css);
733
+ return css;
734
+ };
735
+ </script>
736
+
737
+ <template>
738
+ <div class="brand-selector">
739
+ <div class="selector-header">
740
+ <h3>Brand Color System</h3>
741
+ <p>Define your brand's color palette</p>
742
+ </div>
743
+
744
+ <div class="color-sections">
745
+ <div class="color-section">
746
+ <h4>Primary Color</h4>
747
+ <ColorPicker
748
+ :color="brandColors.primary"
749
+ @update:color="(color) => updateBrandColor('primary', color)"
750
+ />
751
+ <div class="color-details">
752
+ <p>
753
+ {{ brandColors.primary.name }}({{ brandColors.primary.weight }})
754
+ </p>
755
+ <p class="hex">{{ brandColors.primary.hex }}</p>
756
+ </div>
757
+ </div>
758
+
759
+ <div class="color-section">
760
+ <h4>Secondary Color</h4>
761
+ <ColorPicker
762
+ :color="brandColors.secondary"
763
+ @update:color="(color) => updateBrandColor('secondary', color)"
764
+ />
765
+ <div class="color-details">
766
+ <p>
767
+ {{ brandColors.secondary.name }}({{ brandColors.secondary.weight }})
768
+ </p>
769
+ <p class="hex">{{ brandColors.secondary.hex }}</p>
770
+ </div>
771
+ </div>
772
+
773
+ <div class="color-section">
774
+ <h4>Accent Color</h4>
775
+ <ColorPicker
776
+ :color="brandColors.accent"
777
+ @update:color="(color) => updateBrandColor('accent', color)"
778
+ />
779
+ <div class="color-details">
780
+ <p>{{ brandColors.accent.name }}({{ brandColors.accent.weight }})</p>
781
+ <p class="hex">{{ brandColors.accent.hex }}</p>
782
+ </div>
783
+ </div>
784
+
785
+ <div class="color-section">
786
+ <h4>Neutral Color</h4>
787
+ <ColorPicker
788
+ :color="brandColors.neutral"
789
+ @update:color="(color) => updateBrandColor('neutral', color)"
790
+ />
791
+ <div class="color-details">
792
+ <p>
793
+ {{ brandColors.neutral.name }}({{ brandColors.neutral.weight }})
794
+ </p>
795
+ <p class="hex">{{ brandColors.neutral.hex }}</p>
796
+ </div>
797
+ </div>
798
+ </div>
799
+
800
+ <div class="brand-preview">
801
+ <h4>Brand Preview</h4>
802
+ <div class="preview-card">
803
+ <div
804
+ class="preview-header"
805
+ :style="{ backgroundColor: brandColors.primary.hex }"
806
+ >
807
+ <h5>Your Brand</h5>
808
+ </div>
809
+ <div class="preview-content">
810
+ <p>This is how your brand colors work together.</p>
811
+ <button
812
+ class="preview-btn"
813
+ :style="{
814
+ backgroundColor: brandColors.accent.hex,
815
+ color: brandColors.neutral.hex,
816
+ }"
817
+ >
818
+ Call to Action
819
+ </button>
820
+ </div>
821
+ </div>
822
+ </div>
823
+
824
+ <div class="css-output">
825
+ <h4>Generated CSS</h4>
826
+ <pre class="css-code">{{ generateCSS() }}</pre>
827
+ </div>
828
+ </div>
829
+ </template>
830
+
831
+ <style module>
832
+ .brand-selector {
833
+ padding: 24px;
834
+ max-width: 800px;
835
+ background: #ffffff;
836
+ border-radius: 12px;
837
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
838
+ }
839
+
840
+ .selector-header {
841
+ margin-bottom: 32px;
842
+ }
843
+
844
+ .selector-header h3 {
845
+ font-size: 24px;
846
+ font-weight: 600;
847
+ color: #1a202c;
848
+ margin: 0 0 8px 0;
849
+ }
850
+
851
+ .selector-header p {
852
+ color: #718096;
853
+ margin: 0;
854
+ }
855
+
856
+ .color-sections {
857
+ display: grid;
858
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
859
+ gap: 24px;
860
+ margin-bottom: 32px;
861
+ }
862
+
863
+ .color-section {
864
+ text-align: center;
865
+ }
866
+
867
+ .color-section h4 {
868
+ font-size: 16px;
869
+ font-weight: 500;
870
+ color: #2d3748;
871
+ margin: 0 0 16px 0;
872
+ }
873
+
874
+ .color-details {
875
+ margin-top: 12px;
876
+ }
877
+
878
+ .color-details p {
879
+ margin: 0 0 4px 0;
880
+ font-size: 14px;
881
+ color: #4a5568;
882
+ }
883
+
884
+ .color-details .hex {
885
+ font-family: monospace;
886
+ font-size: 12px;
887
+ color: #718096;
888
+ }
889
+
890
+ .brand-preview {
891
+ margin-bottom: 32px;
892
+ }
893
+
894
+ .brand-preview h4 {
895
+ font-size: 18px;
896
+ font-weight: 500;
897
+ color: #2d3748;
898
+ margin: 0 0 16px 0;
899
+ }
900
+
901
+ .preview-card {
902
+ border-radius: 8px;
903
+ overflow: hidden;
904
+ border: 1px solid #e2e8f0;
905
+ }
906
+
907
+ .preview-header {
908
+ padding: 16px;
909
+ color: white;
910
+ }
911
+
912
+ .preview-header h5 {
913
+ margin: 0;
914
+ font-size: 18px;
915
+ font-weight: 600;
916
+ }
917
+
918
+ .preview-content {
919
+ padding: 16px;
920
+ background: #f7fafc;
921
+ }
922
+
923
+ .preview-content p {
924
+ margin: 0 0 16px 0;
925
+ color: #4a5568;
926
+ }
927
+
928
+ .preview-btn {
929
+ padding: 8px 16px;
930
+ border: none;
931
+ border-radius: 6px;
932
+ font-weight: 500;
933
+ cursor: pointer;
934
+ transition: opacity 0.2s ease;
935
+ }
936
+
937
+ .preview-btn:hover {
938
+ opacity: 0.9;
939
+ }
940
+
941
+ .css-output h4 {
942
+ font-size: 18px;
943
+ font-weight: 500;
944
+ color: #2d3748;
945
+ margin: 0 0 16px 0;
946
+ }
947
+
948
+ .css-code {
949
+ background: #1a202c;
950
+ color: #e2e8f0;
951
+ padding: 16px;
952
+ border-radius: 8px;
953
+ font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
954
+ font-size: 14px;
955
+ line-height: 1.5;
956
+ overflow-x: auto;
957
+ margin: 0;
958
+ }
959
+ </style>
960
+ ```
961
+
962
+ ### Disabled State Example
963
+
964
+ ```vue
965
+ <script setup lang="ts">
966
+ import { ref } from "vue";
967
+ import { ColorPicker, colorPickerColors } from "@umbra-ui/core";
968
+ import type { Color } from "@umbra-ui/core";
969
+
970
+ const selectedColor = ref<Color>(colorPickerColors.blue500);
971
+ const isDisabled = ref(false);
972
+
973
+ const toggleDisabled = () => {
974
+ isDisabled.value = !isDisabled.value;
975
+ };
976
+ </script>
977
+
978
+ <template>
979
+ <div class="disabled-example">
980
+ <h3>Disabled State</h3>
981
+
982
+ <div class="controls">
983
+ <button @click="toggleDisabled" class="toggle-btn">
984
+ {{ isDisabled ? "Enable" : "Disable" }} Color Picker
985
+ </button>
986
+ </div>
987
+
988
+ <ColorPicker
989
+ v-model:color="selectedColor"
990
+ :prevent-popup="isDisabled"
991
+ :dot-size="28"
992
+ :dot-border-width="2"
993
+ />
994
+
995
+ <div class="status">
996
+ <p>Status: {{ isDisabled ? "Disabled" : "Enabled" }}</p>
997
+ <p>Selected: {{ selectedColor.name }}({{ selectedColor.weight }})</p>
998
+ </div>
999
+ </div>
1000
+ </template>
1001
+
1002
+ <style module>
1003
+ .disabled-example {
1004
+ padding: 24px;
1005
+ max-width: 400px;
1006
+ }
1007
+
1008
+ .controls {
1009
+ margin-bottom: 20px;
1010
+ }
1011
+
1012
+ .toggle-btn {
1013
+ padding: 8px 16px;
1014
+ background: #4299e1;
1015
+ color: white;
1016
+ border: none;
1017
+ border-radius: 6px;
1018
+ cursor: pointer;
1019
+ font-weight: 500;
1020
+ transition: background 0.2s ease;
1021
+ }
1022
+
1023
+ .toggle-btn:hover {
1024
+ background: #3182ce;
1025
+ }
1026
+
1027
+ .status {
1028
+ margin-top: 20px;
1029
+ padding: 16px;
1030
+ background: #f7fafc;
1031
+ border-radius: 8px;
1032
+ }
1033
+
1034
+ .status p {
1035
+ margin: 0 0 8px 0;
1036
+ color: #4a5568;
1037
+ }
1038
+
1039
+ .status p:last-child {
1040
+ margin-bottom: 0;
1041
+ }
1042
+ </style>
1043
+ ```
1044
+
1045
+ ## Advanced Usage
1046
+
1047
+ ### Custom Color Palette
1048
+
1049
+ ```vue
1050
+ <script setup lang="ts">
1051
+ import { ref } from "vue";
1052
+ import { ColorPicker } from "@umbra-ui/core";
1053
+ import type { Color } from "@umbra-ui/core";
1054
+
1055
+ // Define custom colors
1056
+ const customColors: Color[] = [
1057
+ { name: "Brand Blue", hex: "#1e40af", weight: null },
1058
+ { name: "Brand Green", hex: "#059669", weight: null },
1059
+ { name: "Brand Orange", hex: "#ea580c", weight: null },
1060
+ { name: "Brand Purple", hex: "#7c3aed", weight: null },
1061
+ { name: "Brand Pink", hex: "#db2777", weight: null },
1062
+ { name: "Brand Teal", hex: "#0d9488", weight: null },
1063
+ ];
1064
+
1065
+ const selectedColor = ref<Color>(customColors[0]);
1066
+
1067
+ const handleColorChange = (color: Color) => {
1068
+ console.log("Custom color selected:", color);
1069
+ };
1070
+ </script>
1071
+
1072
+ <template>
1073
+ <div class="custom-palette">
1074
+ <h3>Custom Color Palette</h3>
1075
+
1076
+ <ColorPicker
1077
+ v-model:color="selectedColor"
1078
+ @update:color="handleColorChange"
1079
+ />
1080
+
1081
+ <div class="custom-colors">
1082
+ <h4>Available Custom Colors</h4>
1083
+ <div class="color-grid">
1084
+ <div
1085
+ v-for="color in customColors"
1086
+ :key="color.hex"
1087
+ class="color-item"
1088
+ :class="{ active: selectedColor.hex === color.hex }"
1089
+ @click="selectedColor = color"
1090
+ >
1091
+ <div class="color-swatch" :style="{ backgroundColor: color.hex }" />
1092
+ <p class="color-label">{{ color.name }}</p>
1093
+ </div>
1094
+ </div>
1095
+ </div>
1096
+ </div>
1097
+ </template>
1098
+
1099
+ <style module>
1100
+ .custom-palette {
1101
+ padding: 24px;
1102
+ max-width: 500px;
1103
+ }
1104
+
1105
+ .custom-colors {
1106
+ margin-top: 24px;
1107
+ }
1108
+
1109
+ .custom-colors h4 {
1110
+ font-size: 16px;
1111
+ font-weight: 500;
1112
+ color: #2d3748;
1113
+ margin: 0 0 16px 0;
1114
+ }
1115
+
1116
+ .color-grid {
1117
+ display: grid;
1118
+ grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
1119
+ gap: 16px;
1120
+ }
1121
+
1122
+ .color-item {
1123
+ text-align: center;
1124
+ cursor: pointer;
1125
+ padding: 12px;
1126
+ border-radius: 8px;
1127
+ transition: background 0.2s ease;
1128
+ }
1129
+
1130
+ .color-item:hover {
1131
+ background: #f7fafc;
1132
+ }
1133
+
1134
+ .color-item.active {
1135
+ background: #e6fffa;
1136
+ border: 2px solid #38b2ac;
1137
+ }
1138
+
1139
+ .color-swatch {
1140
+ width: 40px;
1141
+ height: 40px;
1142
+ border-radius: 50%;
1143
+ margin: 0 auto 8px;
1144
+ border: 2px solid #e2e8f0;
1145
+ }
1146
+
1147
+ .color-label {
1148
+ font-size: 12px;
1149
+ color: #4a5568;
1150
+ margin: 0;
1151
+ }
1152
+ </style>
1153
+ ```
1154
+
1155
+ ### Color Accessibility Checker
1156
+
1157
+ ```vue
1158
+ <script setup lang="ts">
1159
+ import { ref, computed } from "vue";
1160
+ import { ColorPicker, colorPickerColors } from "@umbra-ui/core";
1161
+ import type { Color } from "@umbra-ui/core";
1162
+
1163
+ const selectedColor = ref<Color>(colorPickerColors.blue500);
1164
+ const backgroundColor = ref<Color>(colorPickerColors.white);
1165
+
1166
+ // Simple contrast ratio calculation
1167
+ const getContrastRatio = (color1: string, color2: string) => {
1168
+ const getLuminance = (hex: string) => {
1169
+ const rgb = parseInt(hex.slice(1), 16);
1170
+ const r = (rgb >> 16) & 0xff;
1171
+ const g = (rgb >> 8) & 0xff;
1172
+ const b = (rgb >> 0) & 0xff;
1173
+
1174
+ const [rs, gs, bs] = [r, g, b].map((c) => {
1175
+ c = c / 255;
1176
+ return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
1177
+ });
1178
+
1179
+ return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
1180
+ };
1181
+
1182
+ const lum1 = getLuminance(color1);
1183
+ const lum2 = getLuminance(color2);
1184
+ const brightest = Math.max(lum1, lum2);
1185
+ const darkest = Math.min(lum1, lum2);
1186
+
1187
+ return (brightest + 0.05) / (darkest + 0.05);
1188
+ };
1189
+
1190
+ const contrastRatio = computed(() => {
1191
+ return getContrastRatio(selectedColor.value.hex, backgroundColor.value.hex);
1192
+ });
1193
+
1194
+ const accessibilityLevel = computed(() => {
1195
+ const ratio = contrastRatio.value;
1196
+ if (ratio >= 7) return { level: "AAA", color: "#059669" };
1197
+ if (ratio >= 4.5) return { level: "AA", color: "#d97706" };
1198
+ if (ratio >= 3) return { level: "AA Large", color: "#dc2626" };
1199
+ return { level: "Fail", color: "#dc2626" };
1200
+ });
1201
+ </script>
1202
+
1203
+ <template>
1204
+ <div class="accessibility-checker">
1205
+ <h3>Color Accessibility Checker</h3>
1206
+
1207
+ <div class="color-inputs">
1208
+ <div class="color-input">
1209
+ <h4>Text Color</h4>
1210
+ <ColorPicker v-model:color="selectedColor" :dot-size="24" />
1211
+ </div>
1212
+
1213
+ <div class="color-input">
1214
+ <h4>Background Color</h4>
1215
+ <ColorPicker v-model:color="backgroundColor" :dot-size="24" />
1216
+ </div>
1217
+ </div>
1218
+
1219
+ <div class="preview-section">
1220
+ <h4>Preview</h4>
1221
+ <div
1222
+ class="preview-text"
1223
+ :style="{
1224
+ color: selectedColor.hex,
1225
+ backgroundColor: backgroundColor.hex,
1226
+ }"
1227
+ >
1228
+ This is how your text will look with these colors.
1229
+ </div>
1230
+ </div>
1231
+
1232
+ <div class="accessibility-results">
1233
+ <h4>Accessibility Results</h4>
1234
+ <div class="results-grid">
1235
+ <div class="result-item">
1236
+ <span class="result-label">Contrast Ratio:</span>
1237
+ <span class="result-value">{{ contrastRatio.toFixed(2) }}:1</span>
1238
+ </div>
1239
+ <div class="result-item">
1240
+ <span class="result-label">WCAG Level:</span>
1241
+ <span
1242
+ class="result-value"
1243
+ :style="{ color: accessibilityLevel.color }"
1244
+ >
1245
+ {{ accessibilityLevel.level }}
1246
+ </span>
1247
+ </div>
1248
+ </div>
1249
+
1250
+ <div class="recommendations">
1251
+ <h5>Recommendations:</h5>
1252
+ <ul>
1253
+ <li v-if="contrastRatio < 4.5">
1254
+ Consider using a darker text color or lighter background for better
1255
+ readability
1256
+ </li>
1257
+ <li v-if="contrastRatio >= 4.5 && contrastRatio < 7">
1258
+ Good contrast! Consider aiming for AAA level (7:1) for even better
1259
+ accessibility
1260
+ </li>
1261
+ <li v-if="contrastRatio >= 7">
1262
+ Excellent contrast! This meets WCAG AAA standards
1263
+ </li>
1264
+ </ul>
1265
+ </div>
1266
+ </div>
1267
+ </div>
1268
+ </template>
1269
+
1270
+ <style module>
1271
+ .accessibility-checker {
1272
+ padding: 24px;
1273
+ max-width: 600px;
1274
+ background: #ffffff;
1275
+ border-radius: 12px;
1276
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1277
+ }
1278
+
1279
+ .color-inputs {
1280
+ display: grid;
1281
+ grid-template-columns: 1fr 1fr;
1282
+ gap: 24px;
1283
+ margin-bottom: 32px;
1284
+ }
1285
+
1286
+ .color-input {
1287
+ text-align: center;
1288
+ }
1289
+
1290
+ .color-input h4 {
1291
+ font-size: 16px;
1292
+ font-weight: 500;
1293
+ color: #2d3748;
1294
+ margin: 0 0 16px 0;
1295
+ }
1296
+
1297
+ .preview-section {
1298
+ margin-bottom: 32px;
1299
+ }
1300
+
1301
+ .preview-section h4 {
1302
+ font-size: 16px;
1303
+ font-weight: 500;
1304
+ color: #2d3748;
1305
+ margin: 0 0 16px 0;
1306
+ }
1307
+
1308
+ .preview-text {
1309
+ padding: 24px;
1310
+ border-radius: 8px;
1311
+ font-size: 18px;
1312
+ font-weight: 500;
1313
+ text-align: center;
1314
+ border: 2px solid #e2e8f0;
1315
+ }
1316
+
1317
+ .accessibility-results h4 {
1318
+ font-size: 16px;
1319
+ font-weight: 500;
1320
+ color: #2d3748;
1321
+ margin: 0 0 16px 0;
1322
+ }
1323
+
1324
+ .results-grid {
1325
+ display: grid;
1326
+ grid-template-columns: 1fr 1fr;
1327
+ gap: 16px;
1328
+ margin-bottom: 24px;
1329
+ }
1330
+
1331
+ .result-item {
1332
+ display: flex;
1333
+ justify-content: space-between;
1334
+ align-items: center;
1335
+ padding: 12px;
1336
+ background: #f7fafc;
1337
+ border-radius: 6px;
1338
+ }
1339
+
1340
+ .result-label {
1341
+ font-weight: 500;
1342
+ color: #4a5568;
1343
+ }
1344
+
1345
+ .result-value {
1346
+ font-weight: 600;
1347
+ color: #2d3748;
1348
+ }
1349
+
1350
+ .recommendations {
1351
+ padding: 16px;
1352
+ background: #f0f9ff;
1353
+ border-radius: 8px;
1354
+ border-left: 4px solid #0ea5e9;
1355
+ }
1356
+
1357
+ .recommendations h5 {
1358
+ font-size: 14px;
1359
+ font-weight: 600;
1360
+ color: #0c4a6e;
1361
+ margin: 0 0 8px 0;
1362
+ }
1363
+
1364
+ .recommendations ul {
1365
+ margin: 0;
1366
+ padding-left: 20px;
1367
+ }
1368
+
1369
+ .recommendations li {
1370
+ font-size: 14px;
1371
+ color: #0c4a6e;
1372
+ margin-bottom: 4px;
1373
+ }
1374
+ </style>
1375
+ ```
1376
+
1377
+ ## Performance Considerations
1378
+
1379
+ - **Floating UI**: Smart positioning with automatic updates and cleanup
1380
+ - **Teleport**: Overlay and picker are teleported to body for proper z-index management
1381
+ - **Event Cleanup**: Proper cleanup of auto-update listeners on unmount
1382
+ - **Color Grid**: Efficient 8-column grid layout for optimal performance
1383
+ - **Computed Styles**: Dot styles are computed reactively for smooth animations
1384
+
1385
+ ## Accessibility
1386
+
1387
+ - **Keyboard Navigation**: Support for keyboard interaction
1388
+ - **Screen Reader Support**: Proper ARIA labels and semantic structure
1389
+ - **Focus Management**: Focus is properly managed during interactions
1390
+ - **Color Information**: Displays color names, weights, and hex values
1391
+ - **High Contrast**: Supports high contrast mode with appropriate borders
1392
+
1393
+ ## Browser Support
1394
+
1395
+ - **Modern Browsers**: Chrome 88+, Firefox 85+, Safari 14+, Edge 88+
1396
+ - **Mobile Browsers**: iOS Safari 14+, Chrome Mobile 88+
1397
+ - **CSS Features**: Uses CSS Grid and modern layout features
1398
+ - **JavaScript**: Requires ES2020+ support
1399
+
1400
+ ## Troubleshooting
1401
+
1402
+ ### Common Issues
1403
+
1404
+ 1. **Picker not positioning correctly**: Ensure the trigger button has proper positioning context
1405
+ 2. **Colors not displaying**: Check that the colors array is properly imported
1406
+ 3. **Dot not updating**: Verify the v-model binding is correctly set up
1407
+ 4. **Overlay not closing**: Ensure the overlay click handler is properly bound
1408
+
1409
+ ### Debug Mode
1410
+
1411
+ ```vue
1412
+ <script setup lang="ts">
1413
+ import { ref, watch } from "vue";
1414
+ import { ColorPicker } from "@umbra-ui/core";
1415
+
1416
+ const selectedColor = ref(null);
1417
+
1418
+ // Watch for changes
1419
+ watch(selectedColor, (newColor) => {
1420
+ console.log("Selected color changed:", newColor);
1421
+ });
1422
+ </script>
1423
+ ```
1424
+
1425
+ ## Migration Guide
1426
+
1427
+ ### From v1 to v2
1428
+
1429
+ - `v-model` prop is now `v-model:color`
1430
+ - Event names have been updated to use kebab-case
1431
+ - Color system has been updated with comprehensive palette
1432
+ - Floating UI integration has been improved
1433
+
1434
+ ### Breaking Changes
1435
+
1436
+ - Removed `value` prop in favor of `v-model:color`
1437
+ - Changed event names from camelCase to kebab-case
1438
+ - Updated color prop to use Color interface instead of string
1439
+ - Modified CSS class naming convention