@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,759 @@
1
+ # Search Components
2
+
3
+ A comprehensive search system built with Vue 3 Composition API and TypeScript. The search components provide a powerful search interface with real-time filtering, animated results display, and advanced features like pagination, highlighting, and keyboard navigation.
4
+
5
+ ## Installation/Import
6
+
7
+ ```typescript
8
+ import { SearchBar, SearchResults } from "@umbra-ui/core";
9
+ import type { SearchResult } from "@umbra-ui/core";
10
+ ```
11
+
12
+ **Dependencies:**
13
+
14
+ - Vue 3.x
15
+ - @umbra-ui/icons (for magnifier and chevron icons)
16
+ - gsap (for animations)
17
+ - @floating-ui/vue (for positioning)
18
+
19
+ ## Basic Usage
20
+
21
+ ```vue
22
+ <script setup lang="ts">
23
+ import { ref } from "vue";
24
+ import { SearchBar, SearchResults } from "@umbra-ui/core";
25
+ import type { SearchResult } from "@umbra-ui/core";
26
+
27
+ const searchQuery = ref("");
28
+ const searchItems = ref<SearchResult[]>([
29
+ {
30
+ id: "1",
31
+ title: "Example Item",
32
+ description: "This is an example search result",
33
+ caption: "Category",
34
+ footnote: "Tag",
35
+ icon: "📄",
36
+ },
37
+ ]);
38
+
39
+ const handleSearchSelect = (result: SearchResult) => {
40
+ console.log("Selected:", result);
41
+ searchQuery.value = result.title;
42
+ };
43
+
44
+ const handleSearchFocus = () => {
45
+ console.log("Search focused");
46
+ };
47
+ </script>
48
+
49
+ <template>
50
+ <div>
51
+ <SearchBar
52
+ v-model:query="searchQuery"
53
+ :items="searchItems"
54
+ type="documents"
55
+ placeholder="Search documents..."
56
+ @onSelect="handleSearchSelect"
57
+ @onFocus="handleSearchFocus"
58
+ />
59
+ </div>
60
+ </template>
61
+ ```
62
+
63
+ ## Components
64
+
65
+ ### SearchBar
66
+
67
+ The main search input component with dropdown results.
68
+
69
+ #### Props
70
+
71
+ | Prop Name | Type | Required | Default | Description |
72
+ | ------------- | ---------------- | -------- | ---------- | ------------------------------------------ |
73
+ | `type` | `string` | No | `"items"` | Type of items being searched (for display) |
74
+ | `query` | `string` | No | `""` | The search query value |
75
+ | `items` | `SearchResult[]` | No | `[]` | Array of searchable items |
76
+ | `placeholder` | `string` | No | `"Search"` | Placeholder text for the search input |
77
+
78
+ #### Events
79
+
80
+ | Event Name | Payload Type | Description |
81
+ | -------------- | -------------- | -------------------------------------------- |
82
+ | `update:query` | `string` | Emitted when the search query changes |
83
+ | `onSelect` | `SearchResult` | Emitted when a search result is selected |
84
+ | `onFocus` | `void` | Emitted when the search input receives focus |
85
+
86
+ ### SearchResults
87
+
88
+ The results display component (used internally by SearchBar).
89
+
90
+ #### Props
91
+
92
+ | Prop Name | Type | Required | Description |
93
+ | --------- | ---------------- | -------- | ---------------------------- |
94
+ | `type` | `string` | Yes | Type of items being searched |
95
+ | `query` | `string` | Yes | Current search query |
96
+ | `matches` | `SearchResult[]` | Yes | Filtered search results |
97
+
98
+ #### Events
99
+
100
+ | Event Name | Payload Type | Description |
101
+ | ---------- | -------------- | ---------------------------------------- |
102
+ | `onSelect` | `SearchResult` | Emitted when a search result is selected |
103
+
104
+ ## SearchResult Interface
105
+
106
+ ```typescript
107
+ interface SearchResult {
108
+ id: string;
109
+ icon?: string;
110
+ title: string;
111
+ description: string;
112
+ caption: string;
113
+ footnote: string;
114
+ }
115
+ ```
116
+
117
+ ## CSS Customization
118
+
119
+ The search components use CSS custom properties for theming and customization:
120
+
121
+ ### SearchBar Variables
122
+
123
+ ```css
124
+ /* Search Bar Colors */
125
+ --search-bar-bg: var(--search-bar-background);
126
+ --search-bar-text: var(--search-bar-text-color);
127
+ --search-bar-placeholder: var(--search-bar-placeholder-color);
128
+ --search-bar-border: var(--search-bar-border-color);
129
+ --search-bar-focus-border: var(--search-bar-focus-border-color);
130
+ --search-bar-shadow: var(--search-bar-shadow-color);
131
+ --search-bar-inset-shadow: var(--search-bar-inset-shadow-color);
132
+
133
+ /* Search Overlay */
134
+ --search-overlay-bg: var(--search-overlay-background);
135
+ ```
136
+
137
+ ### SearchResults Variables
138
+
139
+ ```css
140
+ /* Results Container */
141
+ --search-results-bg: var(--search-results-background);
142
+ --search-results-border: var(--search-results-border-color);
143
+ --search-results-shadow: var(--search-results-shadow-color);
144
+ --search-results-inset-shadow: var(--search-results-inset-shadow-color);
145
+
146
+ /* Subheader */
147
+ --search-subheader-bg: var(--search-subheader-background);
148
+ --search-subheader-border: var(--search-subheader-border-color);
149
+ --search-subheader-text: var(--search-subheader-text-color);
150
+
151
+ /* Result Items */
152
+ --search-result-bg: var(--search-result-background);
153
+ --search-result-hover-bg: var(--search-result-hover-background);
154
+ --search-result-border: var(--search-result-border-color);
155
+ --search-result-text: var(--search-result-text-color);
156
+
157
+ /* Icons */
158
+ --search-icon-bg: var(--search-icon-background);
159
+ --search-icon-border: var(--search-icon-border-color);
160
+
161
+ /* Footnotes */
162
+ --search-footnote-bg: var(--search-footnote-background);
163
+
164
+ /* Empty State */
165
+ --search-nothing-text: var(--search-nothing-text-color);
166
+
167
+ /* Load More */
168
+ --search-load-more-bg: var(--search-load-more-background);
169
+ --search-load-more-hover-bg: var(--search-load-more-hover-background);
170
+ --search-load-more-text: var(--search-load-more-text-color);
171
+
172
+ /* Highlighting */
173
+ --search-highlight-bg: var(--search-highlight-background);
174
+ ```
175
+
176
+ ## Key Features
177
+
178
+ ### Search Functionality
179
+
180
+ - **Real-time Filtering**: Results update as you type
181
+ - **Multi-field Search**: Searches across title, description, caption, and footnote
182
+ - **Case-insensitive**: Search is not case-sensitive
183
+ - **Highlighting**: Query terms are highlighted in results
184
+
185
+ ### User Experience
186
+
187
+ - **Animated Dropdown**: Smooth animations for showing/hiding results
188
+ - **Floating Positioning**: Results are positioned using Floating UI
189
+ - **Keyboard Navigation**: Full keyboard support with escape to close
190
+ - **Click Outside**: Clicking outside closes the search results
191
+ - **Loading States**: Shows loading indicator while building search index
192
+
193
+ ### Results Display
194
+
195
+ - **Pagination**: Load more results with pagination
196
+ - **Rich Content**: Support for icons, titles, descriptions, captions, and footnotes
197
+ - **Icon Support**: Both emoji and image icons
198
+ - **Hover Effects**: Visual feedback on result hover
199
+ - **Empty States**: Proper handling of no results
200
+
201
+ ### Accessibility
202
+
203
+ - **ARIA Labels**: Proper labeling for screen readers
204
+ - **Keyboard Navigation**: Full keyboard support
205
+ - **Focus Management**: Proper focus handling
206
+ - **Screen Reader Support**: Accessible result announcements
207
+
208
+ ## Examples
209
+
210
+ ### Basic Search
211
+
212
+ ```vue
213
+ <script setup lang="ts">
214
+ import { ref } from "vue";
215
+ import { SearchBar } from "@umbra-ui/core";
216
+ import type { SearchResult } from "@umbra-ui/core";
217
+
218
+ const searchQuery = ref("");
219
+ const searchItems = ref<SearchResult[]>([
220
+ {
221
+ id: "1",
222
+ title: "Getting Started Guide",
223
+ description: "Learn how to get started with our platform",
224
+ caption: "Documentation",
225
+ footnote: "Guide",
226
+ icon: "📚",
227
+ },
228
+ {
229
+ id: "2",
230
+ title: "API Reference",
231
+ description: "Complete API documentation and examples",
232
+ caption: "Documentation",
233
+ footnote: "API",
234
+ icon: "🔧",
235
+ },
236
+ {
237
+ id: "3",
238
+ title: "User Manual",
239
+ description: "Detailed user manual with step-by-step instructions",
240
+ caption: "Documentation",
241
+ footnote: "Manual",
242
+ icon: "📖",
243
+ },
244
+ ]);
245
+
246
+ const handleSearchSelect = (result: SearchResult) => {
247
+ console.log("Selected:", result);
248
+ searchQuery.value = result.title;
249
+ };
250
+ </script>
251
+
252
+ <template>
253
+ <div class="basic-search">
254
+ <h3>Documentation Search</h3>
255
+
256
+ <SearchBar
257
+ v-model:query="searchQuery"
258
+ :items="searchItems"
259
+ type="documents"
260
+ placeholder="Search documentation..."
261
+ @onSelect="handleSearchSelect"
262
+ />
263
+
264
+ <div v-if="searchQuery" class="search-info">
265
+ <p>Searching for: "{{ searchQuery }}"</p>
266
+ </div>
267
+ </div>
268
+ </template>
269
+
270
+ <style module>
271
+ .basic-search {
272
+ max-width: 500px;
273
+ padding: 2rem;
274
+ border: 1px solid #e0e0e0;
275
+ border-radius: 0.5rem;
276
+ }
277
+
278
+ .search-info {
279
+ margin-top: 1rem;
280
+ padding: 1rem;
281
+ background-color: #f8f9fa;
282
+ border-radius: 0.25rem;
283
+ }
284
+
285
+ .search-info p {
286
+ margin: 0;
287
+ color: #666;
288
+ font-size: 0.875rem;
289
+ }
290
+ </style>
291
+ ```
292
+
293
+ ### Advanced Search with Custom Data
294
+
295
+ ```vue
296
+ <script setup lang="ts">
297
+ import { ref, computed } from "vue";
298
+ import { SearchBar } from "@umbra-ui/core";
299
+ import type { SearchResult } from "@umbra-ui/core";
300
+
301
+ const searchQuery = ref("");
302
+ const allItems = ref<SearchResult[]>([
303
+ {
304
+ id: "1",
305
+ title: "Vue.js Framework",
306
+ description:
307
+ "Progressive JavaScript framework for building user interfaces",
308
+ caption: "Framework",
309
+ footnote: "JavaScript",
310
+ icon: "🟢",
311
+ },
312
+ {
313
+ id: "2",
314
+ title: "React Library",
315
+ description: "A JavaScript library for building user interfaces",
316
+ caption: "Library",
317
+ footnote: "JavaScript",
318
+ icon: "⚛️",
319
+ },
320
+ {
321
+ id: "3",
322
+ title: "Angular Platform",
323
+ description: "Platform for building mobile and desktop web applications",
324
+ caption: "Platform",
325
+ footnote: "TypeScript",
326
+ icon: "🔴",
327
+ },
328
+ {
329
+ id: "4",
330
+ title: "Svelte Compiler",
331
+ description:
332
+ "Cybernetically enhanced web apps with compile-time optimizations",
333
+ caption: "Compiler",
334
+ footnote: "JavaScript",
335
+ icon: "🧡",
336
+ },
337
+ ]);
338
+
339
+ const filteredItems = computed(() => {
340
+ if (!searchQuery.value.trim()) {
341
+ return allItems.value;
342
+ }
343
+
344
+ const query = searchQuery.value.toLowerCase();
345
+ return allItems.value.filter((item) => {
346
+ const searchText =
347
+ `${item.title} ${item.description} ${item.caption} ${item.footnote}`.toLowerCase();
348
+ return searchText.includes(query);
349
+ });
350
+ });
351
+
352
+ const handleSearchSelect = (result: SearchResult) => {
353
+ console.log("Selected framework:", result);
354
+ searchQuery.value = result.title;
355
+ };
356
+
357
+ const handleSearchFocus = () => {
358
+ console.log("Search focused - showing all items");
359
+ };
360
+ </script>
361
+
362
+ <template>
363
+ <div class="advanced-search">
364
+ <h3>Framework Search</h3>
365
+
366
+ <SearchBar
367
+ v-model:query="searchQuery"
368
+ :items="filteredItems"
369
+ type="frameworks"
370
+ placeholder="Search JavaScript frameworks..."
371
+ @onSelect="handleSearchSelect"
372
+ @onFocus="handleSearchFocus"
373
+ />
374
+
375
+ <div class="search-stats">
376
+ <p>Total items: {{ allItems.length }}</p>
377
+ <p v-if="searchQuery">Filtered results: {{ filteredItems.length }}</p>
378
+ </div>
379
+ </div>
380
+ </template>
381
+
382
+ <style module>
383
+ .advanced-search {
384
+ max-width: 600px;
385
+ padding: 2rem;
386
+ border: 1px solid #e0e0e0;
387
+ border-radius: 0.5rem;
388
+ }
389
+
390
+ .search-stats {
391
+ margin-top: 1rem;
392
+ padding: 1rem;
393
+ background-color: #f8f9fa;
394
+ border-radius: 0.25rem;
395
+ display: flex;
396
+ gap: 2rem;
397
+ }
398
+
399
+ .search-stats p {
400
+ margin: 0;
401
+ color: #666;
402
+ font-size: 0.875rem;
403
+ }
404
+ </style>
405
+ ```
406
+
407
+ ### Search with API Integration
408
+
409
+ ```vue
410
+ <script setup lang="ts">
411
+ import { ref, watch } from "vue";
412
+ import { SearchBar } from "@umbra-ui/core";
413
+ import type { SearchResult } from "@umbra-ui/core";
414
+
415
+ const searchQuery = ref("");
416
+ const searchItems = ref<SearchResult[]>([]);
417
+ const isLoading = ref(false);
418
+ const error = ref("");
419
+
420
+ const searchAPI = async (query: string) => {
421
+ if (!query.trim()) {
422
+ searchItems.value = [];
423
+ return;
424
+ }
425
+
426
+ isLoading.value = true;
427
+ error.value = "";
428
+
429
+ try {
430
+ // Simulate API call
431
+ await new Promise((resolve) => setTimeout(resolve, 1000));
432
+
433
+ // Simulate API response
434
+ const mockResults: SearchResult[] = [
435
+ {
436
+ id: "1",
437
+ title: `Search Result for "${query}"`,
438
+ description: `This is a mock result for the query "${query}"`,
439
+ caption: "API Result",
440
+ footnote: "Mock",
441
+ icon: "🔍",
442
+ },
443
+ {
444
+ id: "2",
445
+ title: `Another Result for "${query}"`,
446
+ description: `Another mock result for the query "${query}"`,
447
+ caption: "API Result",
448
+ footnote: "Mock",
449
+ icon: "📄",
450
+ },
451
+ ];
452
+
453
+ searchItems.value = mockResults;
454
+ } catch (err) {
455
+ error.value = "Failed to search. Please try again.";
456
+ searchItems.value = [];
457
+ } finally {
458
+ isLoading.value = false;
459
+ }
460
+ };
461
+
462
+ // Debounced search
463
+ let searchTimeout: NodeJS.Timeout;
464
+ watch(searchQuery, (newQuery) => {
465
+ clearTimeout(searchTimeout);
466
+ searchTimeout = setTimeout(() => {
467
+ searchAPI(newQuery);
468
+ }, 300);
469
+ });
470
+
471
+ const handleSearchSelect = (result: SearchResult) => {
472
+ console.log("Selected from API:", result);
473
+ searchQuery.value = result.title;
474
+ };
475
+ </script>
476
+
477
+ <template>
478
+ <div class="api-search">
479
+ <h3>API-Powered Search</h3>
480
+
481
+ <SearchBar
482
+ v-model:query="searchQuery"
483
+ :items="searchItems"
484
+ type="api-results"
485
+ placeholder="Search with API..."
486
+ @onSelect="handleSearchSelect"
487
+ />
488
+
489
+ <div v-if="isLoading" class="loading-state">
490
+ <p>Searching...</p>
491
+ </div>
492
+
493
+ <div v-if="error" class="error-state">
494
+ <p>{{ error }}</p>
495
+ </div>
496
+
497
+ <div v-if="searchQuery && !isLoading && !error" class="search-info">
498
+ <p>Found {{ searchItems.length }} results for "{{ searchQuery }}"</p>
499
+ </div>
500
+ </div>
501
+ </template>
502
+
503
+ <style module>
504
+ .api-search {
505
+ max-width: 500px;
506
+ padding: 2rem;
507
+ border: 1px solid #e0e0e0;
508
+ border-radius: 0.5rem;
509
+ }
510
+
511
+ .loading-state {
512
+ margin-top: 1rem;
513
+ padding: 1rem;
514
+ background-color: #e3f2fd;
515
+ border-radius: 0.25rem;
516
+ text-align: center;
517
+ }
518
+
519
+ .loading-state p {
520
+ margin: 0;
521
+ color: #1976d2;
522
+ font-weight: 500;
523
+ }
524
+
525
+ .error-state {
526
+ margin-top: 1rem;
527
+ padding: 1rem;
528
+ background-color: #ffebee;
529
+ border-radius: 0.25rem;
530
+ text-align: center;
531
+ }
532
+
533
+ .error-state p {
534
+ margin: 0;
535
+ color: #d32f2f;
536
+ font-weight: 500;
537
+ }
538
+
539
+ .search-info {
540
+ margin-top: 1rem;
541
+ padding: 1rem;
542
+ background-color: #f8f9fa;
543
+ border-radius: 0.25rem;
544
+ }
545
+
546
+ .search-info p {
547
+ margin: 0;
548
+ color: #666;
549
+ font-size: 0.875rem;
550
+ }
551
+ </style>
552
+ ```
553
+
554
+ ### Search with Custom Styling
555
+
556
+ ```vue
557
+ <script setup lang="ts">
558
+ import { ref } from "vue";
559
+ import { SearchBar } from "@umbra-ui/core";
560
+ import type { SearchResult } from "@umbra-ui/core";
561
+
562
+ const searchQuery = ref("");
563
+ const searchItems = ref<SearchResult[]>([
564
+ {
565
+ id: "1",
566
+ title: "Custom Styled Search",
567
+ description: "This search has custom styling applied",
568
+ caption: "Custom",
569
+ footnote: "Styled",
570
+ icon: "🎨",
571
+ },
572
+ {
573
+ id: "2",
574
+ title: "Themed Results",
575
+ description: "Results with custom theme colors",
576
+ caption: "Theme",
577
+ footnote: "Custom",
578
+ icon: "🌈",
579
+ },
580
+ ]);
581
+
582
+ const handleSearchSelect = (result: SearchResult) => {
583
+ console.log("Selected:", result);
584
+ searchQuery.value = result.title;
585
+ };
586
+ </script>
587
+
588
+ <template>
589
+ <div class="custom-search">
590
+ <h3>Custom Styled Search</h3>
591
+
592
+ <SearchBar
593
+ v-model:query="searchQuery"
594
+ :items="searchItems"
595
+ type="custom-items"
596
+ placeholder="Search with custom styling..."
597
+ @onSelect="handleSearchSelect"
598
+ />
599
+ </div>
600
+ </template>
601
+
602
+ <style module>
603
+ .custom-search {
604
+ max-width: 500px;
605
+ padding: 2rem;
606
+ border: 1px solid #e0e0e0;
607
+ border-radius: 0.5rem;
608
+ }
609
+
610
+ /* Custom CSS variables for theming */
611
+ .custom-search {
612
+ --search-bar-bg: #f8f9fa;
613
+ --search-bar-text: #495057;
614
+ --search-bar-placeholder: #6c757d;
615
+ --search-bar-border: 2px solid #dee2e6;
616
+ --search-bar-focus-border: #007bff;
617
+
618
+ --search-results-bg: #ffffff;
619
+ --search-results-border: 1px solid #dee2e6;
620
+ --search-results-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
621
+
622
+ --search-subheader-bg: #e9ecef;
623
+ --search-subheader-text: #495057;
624
+
625
+ --search-result-bg: #ffffff;
626
+ --search-result-hover-bg: #f8f9fa;
627
+ --search-result-text: #212529;
628
+
629
+ --search-icon-bg: #e9ecef;
630
+ --search-icon-border: #dee2e6;
631
+
632
+ --search-highlight-bg: rgba(255, 193, 7, 0.3);
633
+ --search-overlay-bg: rgba(0, 0, 0, 0.5);
634
+ }
635
+ </style>
636
+ ```
637
+
638
+ ### Search with Keyboard Shortcuts
639
+
640
+ ```vue
641
+ <script setup lang="ts">
642
+ import { ref, onMounted, onUnmounted } from "vue";
643
+ import { SearchBar } from "@umbra-ui/core";
644
+ import type { SearchResult } from "@umbra-ui/core";
645
+
646
+ const searchQuery = ref("");
647
+ const searchItems = ref<SearchResult[]>([
648
+ {
649
+ id: "1",
650
+ title: "Keyboard Shortcuts",
651
+ description: "Learn about keyboard shortcuts in our application",
652
+ caption: "Help",
653
+ footnote: "Shortcuts",
654
+ icon: "⌨️",
655
+ },
656
+ {
657
+ id: "2",
658
+ title: "Search Tips",
659
+ description: "Tips and tricks for better search results",
660
+ caption: "Help",
661
+ footnote: "Tips",
662
+ icon: "💡",
663
+ },
664
+ ]);
665
+
666
+ const searchBarRef = ref();
667
+
668
+ const handleKeyDown = (event: KeyboardEvent) => {
669
+ // Ctrl/Cmd + K to focus search
670
+ if ((event.ctrlKey || event.metaKey) && event.key === "k") {
671
+ event.preventDefault();
672
+ searchBarRef.value?.focus();
673
+ }
674
+
675
+ // Escape to clear search
676
+ if (event.key === "Escape" && searchQuery.value) {
677
+ searchQuery.value = "";
678
+ }
679
+ };
680
+
681
+ onMounted(() => {
682
+ document.addEventListener("keydown", handleKeyDown);
683
+ });
684
+
685
+ onUnmounted(() => {
686
+ document.removeEventListener("keydown", handleKeyDown);
687
+ });
688
+
689
+ const handleSearchSelect = (result: SearchResult) => {
690
+ console.log("Selected:", result);
691
+ searchQuery.value = result.title;
692
+ };
693
+ </script>
694
+
695
+ <template>
696
+ <div class="keyboard-search">
697
+ <h3>Search with Keyboard Shortcuts</h3>
698
+
699
+ <div class="shortcuts-info">
700
+ <p><kbd>Ctrl</kbd> + <kbd>K</kbd> to focus search</p>
701
+ <p><kbd>Escape</kbd> to clear search</p>
702
+ </div>
703
+
704
+ <SearchBar
705
+ ref="searchBarRef"
706
+ v-model:query="searchQuery"
707
+ :items="searchItems"
708
+ type="help-items"
709
+ placeholder="Search help articles..."
710
+ @onSelect="handleSearchSelect"
711
+ />
712
+ </div>
713
+ </template>
714
+
715
+ <style module>
716
+ .keyboard-search {
717
+ max-width: 500px;
718
+ padding: 2rem;
719
+ border: 1px solid #e0e0e0;
720
+ border-radius: 0.5rem;
721
+ }
722
+
723
+ .shortcuts-info {
724
+ margin-bottom: 1rem;
725
+ padding: 1rem;
726
+ background-color: #f8f9fa;
727
+ border-radius: 0.25rem;
728
+ }
729
+
730
+ .shortcuts-info p {
731
+ margin: 0.25rem 0;
732
+ color: #666;
733
+ font-size: 0.875rem;
734
+ }
735
+
736
+ kbd {
737
+ background-color: #f8f9fa;
738
+ border: 1px solid #dee2e6;
739
+ border-radius: 0.25rem;
740
+ padding: 0.125rem 0.25rem;
741
+ font-size: 0.75rem;
742
+ font-family: monospace;
743
+ }
744
+ </style>
745
+ ```
746
+
747
+ ## Technical Notes
748
+
749
+ - Search components provide a comprehensive search interface with real-time filtering
750
+ - Floating UI is used for precise positioning of search results
751
+ - GSAP animations provide smooth transitions for showing/hiding results
752
+ - Search results support pagination with "Load More" functionality
753
+ - Query highlighting uses regex to highlight matching terms in results
754
+ - Keyboard navigation includes escape to close and full arrow key support
755
+ - Click outside functionality closes the search results
756
+ - Responsive design adapts to different screen sizes
757
+ - CSS custom properties enable easy theming for light and dark modes
758
+ - TypeScript interfaces ensure type safety for search results
759
+ - Accessibility features include ARIA labels and screen reader support