kabzvue 3.27.11

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 (273) hide show
  1. package/README.md +2153 -0
  2. package/dist/favicon.ico +0 -0
  3. package/dist/index.esm.js +18804 -0
  4. package/dist/index.js +604 -0
  5. package/dist/kabzvue.css +1 -0
  6. package/dist/logo.png +0 -0
  7. package/dist/src/App.vue.d.ts +4 -0
  8. package/dist/src/App.vue.d.ts.map +1 -0
  9. package/dist/src/__tests__/Alert.spec.d.ts +2 -0
  10. package/dist/src/__tests__/Alert.spec.d.ts.map +1 -0
  11. package/dist/src/__tests__/App.spec.d.ts +2 -0
  12. package/dist/src/__tests__/App.spec.d.ts.map +1 -0
  13. package/dist/src/__tests__/Badge.spec.d.ts +2 -0
  14. package/dist/src/__tests__/Badge.spec.d.ts.map +1 -0
  15. package/dist/src/__tests__/Button.spec.d.ts +2 -0
  16. package/dist/src/__tests__/Button.spec.d.ts.map +1 -0
  17. package/dist/src/__tests__/Card.spec.d.ts +2 -0
  18. package/dist/src/__tests__/Card.spec.d.ts.map +1 -0
  19. package/dist/src/__tests__/Checkbox.spec.d.ts +2 -0
  20. package/dist/src/__tests__/Checkbox.spec.d.ts.map +1 -0
  21. package/dist/src/__tests__/Dropdown.spec.d.ts +2 -0
  22. package/dist/src/__tests__/Dropdown.spec.d.ts.map +1 -0
  23. package/dist/src/__tests__/Input.spec.d.ts +2 -0
  24. package/dist/src/__tests__/Input.spec.d.ts.map +1 -0
  25. package/dist/src/__tests__/Modal.spec.d.ts +2 -0
  26. package/dist/src/__tests__/Modal.spec.d.ts.map +1 -0
  27. package/dist/src/__tests__/Radio.spec.d.ts +2 -0
  28. package/dist/src/__tests__/Radio.spec.d.ts.map +1 -0
  29. package/dist/src/__tests__/Tabs.spec.d.ts +2 -0
  30. package/dist/src/__tests__/Tabs.spec.d.ts.map +1 -0
  31. package/dist/src/__tests__/integration/CardIntegration.spec.d.ts +2 -0
  32. package/dist/src/__tests__/integration/CardIntegration.spec.d.ts.map +1 -0
  33. package/dist/src/__tests__/integration/FormIntegration.spec.d.ts +2 -0
  34. package/dist/src/__tests__/integration/FormIntegration.spec.d.ts.map +1 -0
  35. package/dist/src/__tests__/integration/ModalIntegration.spec.d.ts +2 -0
  36. package/dist/src/__tests__/integration/ModalIntegration.spec.d.ts.map +1 -0
  37. package/dist/src/__tests__/integration/NavigationIntegration.spec.d.ts +2 -0
  38. package/dist/src/__tests__/integration/NavigationIntegration.spec.d.ts.map +1 -0
  39. package/dist/src/components/Accordion.vue.d.ts +43 -0
  40. package/dist/src/components/Accordion.vue.d.ts.map +1 -0
  41. package/dist/src/components/AccordionItem.vue.d.ts +25 -0
  42. package/dist/src/components/AccordionItem.vue.d.ts.map +1 -0
  43. package/dist/src/components/AddReminderModal.vue.d.ts +18 -0
  44. package/dist/src/components/AddReminderModal.vue.d.ts.map +1 -0
  45. package/dist/src/components/Alert.vue.d.ts +35 -0
  46. package/dist/src/components/Alert.vue.d.ts.map +1 -0
  47. package/dist/src/components/Avatar.vue.d.ts +20 -0
  48. package/dist/src/components/Avatar.vue.d.ts.map +1 -0
  49. package/dist/src/components/Badge.vue.d.ts +29 -0
  50. package/dist/src/components/Badge.vue.d.ts.map +1 -0
  51. package/dist/src/components/Breadcrumb.vue.d.ts +16 -0
  52. package/dist/src/components/Breadcrumb.vue.d.ts.map +1 -0
  53. package/dist/src/components/Button.vue.d.ts +27 -0
  54. package/dist/src/components/Button.vue.d.ts.map +1 -0
  55. package/dist/src/components/ButtonGroup.vue.d.ts +23 -0
  56. package/dist/src/components/ButtonGroup.vue.d.ts.map +1 -0
  57. package/dist/src/components/Calendar.vue.d.ts +34 -0
  58. package/dist/src/components/Calendar.vue.d.ts.map +1 -0
  59. package/dist/src/components/Card.vue.d.ts +59 -0
  60. package/dist/src/components/Card.vue.d.ts.map +1 -0
  61. package/dist/src/components/CardBody.vue.d.ts +17 -0
  62. package/dist/src/components/CardBody.vue.d.ts.map +1 -0
  63. package/dist/src/components/CardContent.vue.d.ts +11 -0
  64. package/dist/src/components/CardContent.vue.d.ts.map +1 -0
  65. package/dist/src/components/CardFooter.vue.d.ts +17 -0
  66. package/dist/src/components/CardFooter.vue.d.ts.map +1 -0
  67. package/dist/src/components/CardHeader.vue.d.ts +27 -0
  68. package/dist/src/components/CardHeader.vue.d.ts.map +1 -0
  69. package/dist/src/components/CardTitle.vue.d.ts +11 -0
  70. package/dist/src/components/CardTitle.vue.d.ts.map +1 -0
  71. package/dist/src/components/Checkbox.vue.d.ts +39 -0
  72. package/dist/src/components/Checkbox.vue.d.ts.map +1 -0
  73. package/dist/src/components/CircularProgress.vue.d.ts +24 -0
  74. package/dist/src/components/CircularProgress.vue.d.ts.map +1 -0
  75. package/dist/src/components/DataTable.vue.d.ts +128 -0
  76. package/dist/src/components/DataTable.vue.d.ts.map +1 -0
  77. package/dist/src/components/DataTableCell.vue.d.ts +31 -0
  78. package/dist/src/components/DataTableCell.vue.d.ts.map +1 -0
  79. package/dist/src/components/DataTableFilters.vue.d.ts +71 -0
  80. package/dist/src/components/DataTableFilters.vue.d.ts.map +1 -0
  81. package/dist/src/components/DataTableHeader.vue.d.ts +25 -0
  82. package/dist/src/components/DataTableHeader.vue.d.ts.map +1 -0
  83. package/dist/src/components/DataTablePagination.vue.d.ts +39 -0
  84. package/dist/src/components/DataTablePagination.vue.d.ts.map +1 -0
  85. package/dist/src/components/DataTableRow.vue.d.ts +47 -0
  86. package/dist/src/components/DataTableRow.vue.d.ts.map +1 -0
  87. package/dist/src/components/DataTableToolBar.vue.d.ts +41 -0
  88. package/dist/src/components/DataTableToolBar.vue.d.ts.map +1 -0
  89. package/dist/src/components/DatePicker.vue.d.ts +36 -0
  90. package/dist/src/components/DatePicker.vue.d.ts.map +1 -0
  91. package/dist/src/components/Divider.vue.d.ts +20 -0
  92. package/dist/src/components/Divider.vue.d.ts.map +1 -0
  93. package/dist/src/components/Dropdown.vue.d.ts +23 -0
  94. package/dist/src/components/Dropdown.vue.d.ts.map +1 -0
  95. package/dist/src/components/DropdownItem.vue.d.ts +27 -0
  96. package/dist/src/components/DropdownItem.vue.d.ts.map +1 -0
  97. package/dist/src/components/EventsCalendar.vue.d.ts +74 -0
  98. package/dist/src/components/EventsCalendar.vue.d.ts.map +1 -0
  99. package/dist/src/components/FileUpload.vue.d.ts +20 -0
  100. package/dist/src/components/FileUpload.vue.d.ts.map +1 -0
  101. package/dist/src/components/Footer.vue.d.ts +25 -0
  102. package/dist/src/components/Footer.vue.d.ts.map +1 -0
  103. package/dist/src/components/FormField.vue.d.ts +43 -0
  104. package/dist/src/components/FormField.vue.d.ts.map +1 -0
  105. package/dist/src/components/Graph.vue.d.ts +33 -0
  106. package/dist/src/components/Graph.vue.d.ts.map +1 -0
  107. package/dist/src/components/GraphFilters.vue.d.ts +31 -0
  108. package/dist/src/components/GraphFilters.vue.d.ts.map +1 -0
  109. package/dist/src/components/Header.vue.d.ts +64 -0
  110. package/dist/src/components/Header.vue.d.ts.map +1 -0
  111. package/dist/src/components/Icon.vue.d.ts +20 -0
  112. package/dist/src/components/Icon.vue.d.ts.map +1 -0
  113. package/dist/src/components/Image.vue.d.ts +24 -0
  114. package/dist/src/components/Image.vue.d.ts.map +1 -0
  115. package/dist/src/components/Input.vue.d.ts +43 -0
  116. package/dist/src/components/Input.vue.d.ts.map +1 -0
  117. package/dist/src/components/InputGroup.vue.d.ts +21 -0
  118. package/dist/src/components/InputGroup.vue.d.ts.map +1 -0
  119. package/dist/src/components/Label.vue.d.ts +25 -0
  120. package/dist/src/components/Label.vue.d.ts.map +1 -0
  121. package/dist/src/components/Link.vue.d.ts +43 -0
  122. package/dist/src/components/Link.vue.d.ts.map +1 -0
  123. package/dist/src/components/ListItem.vue.d.ts +33 -0
  124. package/dist/src/components/ListItem.vue.d.ts.map +1 -0
  125. package/dist/src/components/Loader.vue.d.ts +26 -0
  126. package/dist/src/components/Loader.vue.d.ts.map +1 -0
  127. package/dist/src/components/Logo.vue.d.ts +20 -0
  128. package/dist/src/components/Logo.vue.d.ts.map +1 -0
  129. package/dist/src/components/MenuItem.vue.d.ts +29 -0
  130. package/dist/src/components/MenuItem.vue.d.ts.map +1 -0
  131. package/dist/src/components/Modal.vue.d.ts +29 -0
  132. package/dist/src/components/Modal.vue.d.ts.map +1 -0
  133. package/dist/src/components/ModalBody.vue.d.ts +17 -0
  134. package/dist/src/components/ModalBody.vue.d.ts.map +1 -0
  135. package/dist/src/components/ModalFooter.vue.d.ts +17 -0
  136. package/dist/src/components/ModalFooter.vue.d.ts.map +1 -0
  137. package/dist/src/components/ModalHeader.vue.d.ts +19 -0
  138. package/dist/src/components/ModalHeader.vue.d.ts.map +1 -0
  139. package/dist/src/components/MultiSelect.vue.d.ts +22 -0
  140. package/dist/src/components/MultiSelect.vue.d.ts.map +1 -0
  141. package/dist/src/components/Notification.vue.d.ts +29 -0
  142. package/dist/src/components/Notification.vue.d.ts.map +1 -0
  143. package/dist/src/components/Option.vue.d.ts +23 -0
  144. package/dist/src/components/Option.vue.d.ts.map +1 -0
  145. package/dist/src/components/Progress.vue.d.ts +16 -0
  146. package/dist/src/components/Progress.vue.d.ts.map +1 -0
  147. package/dist/src/components/ProgressBar.vue.d.ts +20 -0
  148. package/dist/src/components/ProgressBar.vue.d.ts.map +1 -0
  149. package/dist/src/components/Radio.vue.d.ts +22 -0
  150. package/dist/src/components/Radio.vue.d.ts.map +1 -0
  151. package/dist/src/components/ReminderConfig.vue.d.ts +16 -0
  152. package/dist/src/components/ReminderConfig.vue.d.ts.map +1 -0
  153. package/dist/src/components/ReusableForm.vue.d.ts +30 -0
  154. package/dist/src/components/ReusableForm.vue.d.ts.map +1 -0
  155. package/dist/src/components/ReusableFormModal.vue.d.ts +30 -0
  156. package/dist/src/components/ReusableFormModal.vue.d.ts.map +1 -0
  157. package/dist/src/components/Search.vue.d.ts +43 -0
  158. package/dist/src/components/Search.vue.d.ts.map +1 -0
  159. package/dist/src/components/Select.vue.d.ts +37 -0
  160. package/dist/src/components/Select.vue.d.ts.map +1 -0
  161. package/dist/src/components/Sidebar.vue.d.ts +38 -0
  162. package/dist/src/components/Sidebar.vue.d.ts.map +1 -0
  163. package/dist/src/components/Slider.vue.d.ts +18 -0
  164. package/dist/src/components/Slider.vue.d.ts.map +1 -0
  165. package/dist/src/components/Spinner.vue.d.ts +16 -0
  166. package/dist/src/components/Spinner.vue.d.ts.map +1 -0
  167. package/dist/src/components/Stepper.vue.d.ts +11 -0
  168. package/dist/src/components/Stepper.vue.d.ts.map +1 -0
  169. package/dist/src/components/StepperItem.vue.d.ts +18 -0
  170. package/dist/src/components/StepperItem.vue.d.ts.map +1 -0
  171. package/dist/src/components/Switch.vue.d.ts +18 -0
  172. package/dist/src/components/Switch.vue.d.ts.map +1 -0
  173. package/dist/src/components/Tab.vue.d.ts +25 -0
  174. package/dist/src/components/Tab.vue.d.ts.map +1 -0
  175. package/dist/src/components/TabPanel.vue.d.ts +23 -0
  176. package/dist/src/components/TabPanel.vue.d.ts.map +1 -0
  177. package/dist/src/components/Text.vue.d.ts +27 -0
  178. package/dist/src/components/Text.vue.d.ts.map +1 -0
  179. package/dist/src/components/Textarea.vue.d.ts +39 -0
  180. package/dist/src/components/Textarea.vue.d.ts.map +1 -0
  181. package/dist/src/components/ThemeConfigurator.vue.d.ts +4 -0
  182. package/dist/src/components/ThemeConfigurator.vue.d.ts.map +1 -0
  183. package/dist/src/components/Timeline.vue.d.ts +17 -0
  184. package/dist/src/components/Timeline.vue.d.ts.map +1 -0
  185. package/dist/src/components/TimelineItem.vue.d.ts +27 -0
  186. package/dist/src/components/TimelineItem.vue.d.ts.map +1 -0
  187. package/dist/src/components/Toast.vue.d.ts +20 -0
  188. package/dist/src/components/Toast.vue.d.ts.map +1 -0
  189. package/dist/src/components/Tooltip.vue.d.ts +23 -0
  190. package/dist/src/components/Tooltip.vue.d.ts.map +1 -0
  191. package/dist/src/components/Typography.vue.d.ts +53 -0
  192. package/dist/src/components/Typography.vue.d.ts.map +1 -0
  193. package/dist/src/components/charts/BarChart.vue.d.ts +40 -0
  194. package/dist/src/components/charts/BarChart.vue.d.ts.map +1 -0
  195. package/dist/src/components/charts/LineChart.vue.d.ts +58 -0
  196. package/dist/src/components/charts/LineChart.vue.d.ts.map +1 -0
  197. package/dist/src/components/charts/PieChart.vue.d.ts +50 -0
  198. package/dist/src/components/charts/PieChart.vue.d.ts.map +1 -0
  199. package/dist/src/components/charts/StackedBarChart.vue.d.ts +42 -0
  200. package/dist/src/components/charts/StackedBarChart.vue.d.ts.map +1 -0
  201. package/dist/src/components/widgets/DashboardWidget.vue.d.ts +55 -0
  202. package/dist/src/components/widgets/DashboardWidget.vue.d.ts.map +1 -0
  203. package/dist/src/directives/tooltip.d.ts +6 -0
  204. package/dist/src/directives/tooltip.d.ts.map +1 -0
  205. package/dist/src/helpers/calendarHelper.d.ts +107 -0
  206. package/dist/src/helpers/calendarHelper.d.ts.map +1 -0
  207. package/dist/src/index.d.ts +97 -0
  208. package/dist/src/index.d.ts.map +1 -0
  209. package/dist/src/layouts/AuthLayout.vue.d.ts +136 -0
  210. package/dist/src/layouts/AuthLayout.vue.d.ts.map +1 -0
  211. package/dist/src/layouts/DashboardLayout.vue.d.ts +18 -0
  212. package/dist/src/layouts/DashboardLayout.vue.d.ts.map +1 -0
  213. package/dist/src/layouts/DefaultLayout.vue.d.ts +31 -0
  214. package/dist/src/layouts/DefaultLayout.vue.d.ts.map +1 -0
  215. package/dist/src/layouts/ErrorLayout.vue.d.ts +219 -0
  216. package/dist/src/layouts/ErrorLayout.vue.d.ts.map +1 -0
  217. package/dist/src/lib/theme.d.ts +6 -0
  218. package/dist/src/lib/theme.d.ts.map +1 -0
  219. package/dist/src/lib/toast.d.ts +16 -0
  220. package/dist/src/lib/toast.d.ts.map +1 -0
  221. package/dist/src/main.d.ts +2 -0
  222. package/dist/src/main.d.ts.map +1 -0
  223. package/dist/src/router/AuthRoutes.d.ts +25 -0
  224. package/dist/src/router/AuthRoutes.d.ts.map +1 -0
  225. package/dist/src/router/DashboardRoutes.d.ts +15 -0
  226. package/dist/src/router/DashboardRoutes.d.ts.map +1 -0
  227. package/dist/src/router/index.d.ts +3 -0
  228. package/dist/src/router/index.d.ts.map +1 -0
  229. package/dist/src/stores/counter.d.ts +14 -0
  230. package/dist/src/stores/counter.d.ts.map +1 -0
  231. package/dist/src/utils/cn.d.ts +7 -0
  232. package/dist/src/utils/cn.d.ts.map +1 -0
  233. package/dist/src/views/AnalyticsPage.vue.d.ts +192 -0
  234. package/dist/src/views/AnalyticsPage.vue.d.ts.map +1 -0
  235. package/dist/src/views/DashboardPage.vue.d.ts +4 -0
  236. package/dist/src/views/DashboardPage.vue.d.ts.map +1 -0
  237. package/dist/src/views/DataTableTest.vue.d.ts +10 -0
  238. package/dist/src/views/DataTableTest.vue.d.ts.map +1 -0
  239. package/dist/src/views/WidgetsTest.vue.d.ts +4 -0
  240. package/dist/src/views/WidgetsTest.vue.d.ts.map +1 -0
  241. package/dist/src/views/authentication/ForgotPasswordPage.vue.d.ts +4 -0
  242. package/dist/src/views/authentication/ForgotPasswordPage.vue.d.ts.map +1 -0
  243. package/dist/src/views/authentication/LoginPage.vue.d.ts +4 -0
  244. package/dist/src/views/authentication/LoginPage.vue.d.ts.map +1 -0
  245. package/dist/src/views/docs/DocsLayout.vue.d.ts +4 -0
  246. package/dist/src/views/docs/DocsLayout.vue.d.ts.map +1 -0
  247. package/dist/src/views/docs/DocsSidebar.vue.d.ts +4 -0
  248. package/dist/src/views/docs/DocsSidebar.vue.d.ts.map +1 -0
  249. package/dist/src/views/docs/componentDocs.d.ts +36 -0
  250. package/dist/src/views/docs/componentDocs.d.ts.map +1 -0
  251. package/dist/src/views/docs/pages/ComponentDetailPage.vue.d.ts +4 -0
  252. package/dist/src/views/docs/pages/ComponentDetailPage.vue.d.ts.map +1 -0
  253. package/dist/src/views/docs/pages/ComponentsPage.vue.d.ts +4 -0
  254. package/dist/src/views/docs/pages/ComponentsPage.vue.d.ts.map +1 -0
  255. package/dist/src/views/docs/pages/GettingStartedPage.vue.d.ts +4 -0
  256. package/dist/src/views/docs/pages/GettingStartedPage.vue.d.ts.map +1 -0
  257. package/dist/src/views/docs/pages/InstallationPage.vue.d.ts +4 -0
  258. package/dist/src/views/docs/pages/InstallationPage.vue.d.ts.map +1 -0
  259. package/dist/src/views/docs/pages/SupportPage.vue.d.ts +4 -0
  260. package/dist/src/views/docs/pages/SupportPage.vue.d.ts.map +1 -0
  261. package/dist/src/views/docs/pages/ThemingPage.vue.d.ts +4 -0
  262. package/dist/src/views/docs/pages/ThemingPage.vue.d.ts.map +1 -0
  263. package/dist/src/views/templates/DashboardAnalytics.vue.d.ts +4 -0
  264. package/dist/src/views/templates/DashboardAnalytics.vue.d.ts.map +1 -0
  265. package/dist/src/views/templates/DashboardOverview.vue.d.ts +4 -0
  266. package/dist/src/views/templates/DashboardOverview.vue.d.ts.map +1 -0
  267. package/dist/src/views/templates/DashboardShell.vue.d.ts +31 -0
  268. package/dist/src/views/templates/DashboardShell.vue.d.ts.map +1 -0
  269. package/dist/src/views/templates/DashboardUsers.vue.d.ts +4 -0
  270. package/dist/src/views/templates/DashboardUsers.vue.d.ts.map +1 -0
  271. package/dist/stlbacklogo.png +0 -0
  272. package/dist/tsconfig.tsbuildinfo +1 -0
  273. package/package.json +93 -0
package/README.md ADDED
@@ -0,0 +1,2153 @@
1
+ # STL Horizon Vue Atomic UI Library
2
+
3
+ A comprehensive Vue.js component library with Tailwind CSS styling, featuring automated testing, semantic versioning, and CI/CD pipelines.
4
+
5
+ ## Development & Release Workflow
6
+
7
+ ### Development
8
+
9
+ ```bash
10
+ # Install dependencies
11
+ npm install
12
+
13
+ # Start development server
14
+ npm run dev
15
+
16
+ # Run tests
17
+ npm run test:unit
18
+
19
+ # Run tests with coverage
20
+ npm run test:coverage
21
+
22
+ # Build for production
23
+ npm run build
24
+
25
+ # Preview production build
26
+ npm run preview
27
+ ```
28
+
29
+ ### Commit Convention
30
+
31
+ This project uses [Conventional Commits](https://conventionalcommits.org/) for automatic semantic versioning:
32
+
33
+ ```bash
34
+ # Features (minor version bump: 1.2.3 → 1.3.0)
35
+ git commit -m "feat: add new component"
36
+
37
+ # Bug fixes (patch version bump: 1.2.3 → 1.2.4)
38
+ git commit -m "fix: resolve button click issue"
39
+
40
+ # Breaking changes (major version bump: 1.2.3 → 2.0.0)
41
+ git commit -m "feat!: redesign component API
42
+
43
+ BREAKING CHANGE: component props have changed"
44
+
45
+ # Other changes (patch version bump)
46
+ git commit -m "docs: update component documentation"
47
+ git commit -m "refactor: improve component performance"
48
+ git commit -m "test: add component tests"
49
+ ```
50
+
51
+ ### Automatic Versioning & Publishing
52
+
53
+ The project uses GitHub Actions for automated semantic versioning and NPM publishing:
54
+
55
+ - **Triggers**: Push to `main` branch after tests pass
56
+ - **Version Bumps**:
57
+ - `major`: Breaking changes (BREAKING CHANGE or `!:` in commit)
58
+ - `minor`: New features (`feat:` commits)
59
+ - `patch`: Bug fixes (`fix:` commits) or other changes
60
+ - **Process**:
61
+ 1. Run comprehensive test suite
62
+ 2. Analyze commits since last release
63
+ 3. Bump version automatically
64
+ 4. Create git tag and commit
65
+ 5. Publish to NPM with public access
66
+
67
+ ## Testing
68
+
69
+ This library includes comprehensive testing with both unit and integration tests.
70
+
71
+ ### Test Structure
72
+
73
+ ```
74
+ src/__tests__/
75
+ ├── *.spec.js # Unit tests for individual components
76
+ └── integration/ # Integration tests for component combinations
77
+ ├── FormIntegration.spec.js
78
+ ├── ModalIntegration.spec.js
79
+ ├── CardIntegration.spec.js
80
+ └── NavigationIntegration.spec.js
81
+ ```
82
+
83
+ ### Testing Types
84
+
85
+ #### Unit Tests
86
+ - Individual component functionality
87
+ - Props, events, and styling validation
88
+ - Accessibility testing
89
+ - Error handling
90
+
91
+ #### Integration Tests
92
+ - **Form Integration**: Complete form workflows with Input, Button, Select, Checkbox
93
+ - **Modal Integration**: Modal with form submission and alert interactions
94
+ - **Card Integration**: Cards with headers, content, footers, and actions
95
+ - **Navigation Integration**: Dropdown menus and breadcrumb navigation
96
+
97
+ ### CI/CD Pipeline
98
+
99
+ The project uses GitHub Actions for automated testing and releases:
100
+
101
+ - **Triggers**: Push/PR to `main` and `develop` branches
102
+ - **Node.js versions**: 18.x, 20.x, 22.x
103
+ - **Checks**: Linting, unit tests, integration tests, build verification
104
+ - **Coverage**: Uploaded to Codecov with 70% threshold requirements
105
+ - **Release**: Automatic semantic versioning and NPM publishing
106
+
107
+ ### Coverage Requirements
108
+
109
+ - Branches: 70%
110
+ - Functions: 70%
111
+ - Lines: 70%
112
+ - Statements: 70%
113
+
114
+ ### Running Tests Locally
115
+
116
+ ```bash
117
+ # Run all tests
118
+ npm run test:unit
119
+
120
+ # Run tests once (CI mode)
121
+ npm run test:unit:run
122
+
123
+ # Run with coverage
124
+ npm run test:coverage
125
+
126
+ # Run only integration tests
127
+ npm run test:unit -- --testPathPattern=integration
128
+
129
+ # Run specific test file
130
+ npm run test:unit -- Button.spec.js
131
+ ```
132
+
133
+ ### Test Configuration
134
+
135
+ - **Framework**: Vitest with jsdom environment
136
+ - **Coverage**: V8 provider with HTML, JSON, and text reports
137
+ - **Mocking**: FontAwesome icons and other external dependencies
138
+ - **Assertions**: Built-in Vitest matchers
139
+
140
+ ### Writing Tests
141
+
142
+ When adding new components, follow these patterns:
143
+
144
+ 1. **Unit Tests**: Test component props, events, slots, and styling
145
+ 2. **Integration Tests**: Test component combinations and workflows
146
+ 3. **Accessibility**: Include ARIA attributes and keyboard navigation tests
147
+ 4. **Edge Cases**: Test disabled states, loading states, and error conditions
148
+
149
+ Example test structure:
150
+ ```javascript
151
+ import { describe, it, expect } from 'vitest'
152
+ import { mount } from '@vue/test-utils'
153
+ import Component from '../components/Component.vue'
154
+
155
+ describe('Component', () => {
156
+ it('renders with default props', () => {
157
+ const wrapper = mount(Component)
158
+ expect(wrapper.exists()).toBe(true)
159
+ })
160
+
161
+ it('handles user interactions', async () => {
162
+ const wrapper = mount(Component)
163
+ await wrapper.find('button').trigger('click')
164
+ expect(wrapper.emitted('click')).toHaveLength(1)
165
+ })
166
+ })
167
+ ```
168
+
169
+ ---
170
+
171
+ # Component Usage Documentation
172
+
173
+ This document provides comprehensive usage examples and API reference for all Vue components and directives in the STL Horizon Vue Atomic UI library.
174
+
175
+ ## Tooltip Directive
176
+
177
+ A custom Vue directive for displaying tooltips on hover with customizable positioning and styling.
178
+
179
+ ### Usage
180
+
181
+ ```vue
182
+ <template>
183
+ <div>
184
+ <!-- Basic tooltip -->
185
+ <Button v-tooltip="'This is a tooltip'">Hover me</Button>
186
+
187
+ <!-- Tooltip with position modifier -->
188
+ <Button v-tooltip.bottom="'Tooltip at bottom'">Hover me</Button>
189
+ <Button v-tooltip.left="'Tooltip on left'">Hover me</Button>
190
+ <Button v-tooltip.right="'Tooltip on right'">Hover me</Button>
191
+ <Button v-tooltip.top="'Tooltip on top'">Hover me</Button>
192
+ </div>
193
+ </template>
194
+
195
+ <script setup>
196
+ import Button from '@/components/Button.vue'
197
+ </script>
198
+ ```
199
+
200
+ ### Position Modifiers
201
+
202
+ - `v-tooltip` or `v-tooltip.top` - Tooltip appears above the element
203
+ - `v-tooltip.bottom` - Tooltip appears below the element
204
+ - `v-tooltip.left` - Tooltip appears to the left of the element
205
+ - `v-tooltip.right` - Tooltip appears to the right of the element
206
+
207
+ ### Features
208
+
209
+ - **Automatic positioning**: Tooltips are positioned automatically based on available space
210
+ - **Smooth animations**: Fade in/out transitions for better UX
211
+ - **Arrow indicators**: Visual arrows pointing to the target element
212
+ - **Accessibility**: Proper ARIA attributes and keyboard support
213
+ - **Customizable styling**: Black background with white text, easily customizable via CSS
214
+ - **Event handling**: Shows on mouseenter, hides on mouseleave and click
215
+
216
+ ### Styling
217
+
218
+ The tooltip uses the following default styles:
219
+ - Background: Semi-transparent black (`rgba(0, 0, 0, 0.9)`)
220
+ - Text color: White
221
+ - Padding: 6px 12px
222
+ - Border radius: 4px
223
+ - Font size: 14px
224
+ - Z-index: 9999
225
+
226
+ You can customize the appearance by targeting the `.tooltip-custom` class in your CSS.
227
+
228
+ ### Implementation Details
229
+
230
+ The directive creates a tooltip element dynamically and positions it relative to the viewport. It includes cleanup on component unmount to prevent memory leaks.
231
+
232
+ or else import in the main.js as
233
+ ### app.directive('tooltip', tooltip)
234
+
235
+ ## Table of Contents
236
+
237
+ - [Tooltip Directive](#tooltip-directive)
238
+ - [Accordion](#accordion)
239
+ - [AccordionItem](#accordionitem)
240
+ - [Alert](#alert)
241
+ - [Avatar](#avatar)
242
+ - [Badge](#badge)
243
+ - [Breadcrumb](#breadcrumb)
244
+ - [Button](#button)
245
+ - [ButtonGroup](#buttongroup)
246
+ - [Calendar](#calendar)
247
+ - [Card](#card)
248
+ - [CardBody](#cardbody)
249
+ - [CardContent](#cardcontent)
250
+ - [CardFooter](#cardfooter)
251
+ - [CardHeader](#cardheader)
252
+ - [CardTitle](#cardtitle)
253
+ - [Checkbox](#checkbox)
254
+ - [DataTable](#datatable)
255
+ - [DatePicker](#datepicker)
256
+ - [Divider](#divider)
257
+ - [Dropdown](#dropdown)
258
+ - [DropdownItem](#dropdownitem)
259
+ - [FormField](#formfield)
260
+ - [Icon](#icon)
261
+ - [Image](#image)
262
+ - [Input](#input)
263
+ - [Label](#label)
264
+ - [Modal](#modal)
265
+ - [Progress](#progress)
266
+ - [Radio](#radio)
267
+ - [ReusableFormModal](#reusableformmodal)
268
+ - [Select](#select)
269
+ - [Slider](#slider)
270
+ - [Spinner](#spinner)
271
+ - [Switch](#switch)
272
+ - [Textarea](#textarea)
273
+
274
+ ## Accordion
275
+
276
+ An expandable/collapsible component for organizing content into sections.
277
+
278
+ ### Props
279
+
280
+ | Prop | Type | Default | Description |
281
+ |------|------|---------|-------------|
282
+ | `items` | `Array` | - | Array of accordion items with title and content |
283
+ | `modelValue` | `Number \| Array` | `null` | Currently expanded item(s) index(es) |
284
+ | `multiple` | `Boolean` | `false` | Allow multiple items to be expanded |
285
+ | `variant` | `String` | `'default'` | Visual style (default, bordered, filled, flush) |
286
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
287
+ | `disabled` | `Boolean` | `false` | Whether the accordion is disabled |
288
+
289
+ ### Events
290
+
291
+ | Event | Payload | Description |
292
+ |-------|---------|-------------|
293
+ | `update:modelValue` | `Number \| Array` | Emitted when expanded items change |
294
+ | `change` | `{ index, expanded }` | Emitted when an item is toggled |
295
+
296
+ ### Slots
297
+
298
+ | Slot | Description |
299
+ |------|-------------|
300
+ | `header-{index}` | Custom header content for specific item |
301
+ | `content-{index}` | Custom content for specific item |
302
+ | `content` | Fallback content slot |
303
+
304
+ ### Example
305
+
306
+ ```vue
307
+ <template>
308
+ <Accordion
309
+ v-model="expandedItems"
310
+ :items="accordionItems"
311
+ variant="bordered"
312
+ size="lg"
313
+ multiple
314
+ />
315
+ </template>
316
+
317
+ <script setup>
318
+ import { ref } from 'vue'
319
+ import Accordion from '@/components/Accordion.vue'
320
+
321
+ const expandedItems = ref([0])
322
+ const accordionItems = [
323
+ {
324
+ id: 'item1',
325
+ title: 'What is Vue?',
326
+ content: 'Vue is a progressive JavaScript framework for building user interfaces.'
327
+ },
328
+ {
329
+ id: 'item2',
330
+ title: 'Why use Vue?',
331
+ content: 'Vue offers a gentle learning curve, excellent performance, and great ecosystem.'
332
+ }
333
+ ]
334
+ </script>
335
+ ```
336
+
337
+ ## AccordionItem
338
+
339
+ A single expandable item for use within an accordion structure.
340
+
341
+ ### Props
342
+
343
+ | Prop | Type | Default | Description |
344
+ |------|------|---------|-------------|
345
+ | `variant` | `String` | `'default'` | Visual style (default, bordered, filled, flush) |
346
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
347
+
348
+ ### Slots
349
+
350
+ | Slot | Description |
351
+ |------|-------------|
352
+ | `header` | Header content |
353
+ | `content` | Content to show when expanded |
354
+
355
+ ### Example
356
+
357
+ ```vue
358
+ <template>
359
+ <AccordionItem variant="bordered">
360
+ <template #header>
361
+ <h3>Custom Header</h3>
362
+ </template>
363
+ <template #content>
364
+ <p>This is the content that expands.</p>
365
+ </template>
366
+ </AccordionItem>
367
+ </template>
368
+
369
+ <script setup>
370
+ import AccordionItem from '@/components/AccordionItem.vue'
371
+ </script>
372
+ ```
373
+
374
+ ## Avatar
375
+
376
+ A component for displaying user avatars with image, initials, or icon fallback.
377
+
378
+ ### Props
379
+
380
+ | Prop | Type | Default | Description |
381
+ |------|------|---------|-------------|
382
+ | `src` | `String` | - | Image source URL |
383
+ | `alt` | `String` | - | Alt text for image |
384
+ | `initials` | `String` | - | User initials to display |
385
+ | `size` | `String` | `'md'` | Size variant (xs, sm, md, lg, xl) |
386
+ | `variant` | `String` | `'default'` | Visual style (default, outline) |
387
+
388
+ ### Example
389
+
390
+ ```vue
391
+ <template>
392
+ <div class="flex space-x-4">
393
+ <Avatar src="/path/to/avatar.jpg" alt="User Avatar" />
394
+ <Avatar initials="JD" size="lg" />
395
+ <Avatar variant="outline" />
396
+ </div>
397
+ </template>
398
+
399
+ <script setup>
400
+ import Avatar from '@/components/Avatar.vue'
401
+ </script>
402
+ ```
403
+
404
+ ## Breadcrumb
405
+
406
+ A navigation component showing the current page's location in a hierarchy.
407
+
408
+ ### Props
409
+
410
+ | Prop | Type | Default | Description |
411
+ |------|------|---------|-------------|
412
+ | `items` | `Array` | - | Array of breadcrumb items with label and optional href |
413
+ | `separator` | `String` | `'chevron-right'` | Icon name for separator |
414
+ | `ariaLabel` | `String` | `'Breadcrumb navigation'` | Accessibility label |
415
+ | `variant` | `String` | `'default'` | Visual style (default, ghost) |
416
+
417
+ ### Example
418
+
419
+ ```vue
420
+ <template>
421
+ <Breadcrumb :items="breadcrumbItems" />
422
+ </template>
423
+
424
+ <script setup>
425
+ import Breadcrumb from '@/components/Breadcrumb.vue'
426
+
427
+ const breadcrumbItems = [
428
+ { label: 'Home', href: '/' },
429
+ { label: 'Products', href: '/products' },
430
+ { label: 'Electronics' }
431
+ ]
432
+ </script>
433
+ ```
434
+
435
+ ## ButtonGroup
436
+
437
+ A container component for grouping related buttons together.
438
+
439
+ ### Props
440
+
441
+ | Prop | Type | Default | Description |
442
+ |------|------|---------|-------------|
443
+ | `orientation` | `String` | `'horizontal'` | Layout direction (horizontal, vertical) |
444
+ | `size` | `String` | `'default'` | Size variant (sm, default, lg) |
445
+ | `variant` | `String` | `'default'` | Visual style (default, outline, ghost) |
446
+ | `ariaLabel` | `String` | - | Accessibility label for the group |
447
+
448
+ ### Slots
449
+
450
+ | Slot | Description |
451
+ |------|-------------|
452
+ | `default` | Button components |
453
+
454
+ ### Example
455
+
456
+ ```vue
457
+ <template>
458
+ <ButtonGroup variant="outline" aria-label="Text formatting">
459
+ <Button>Bold</Button>
460
+ <Button>Italic</Button>
461
+ <Button>Underline</Button>
462
+ </ButtonGroup>
463
+ </template>
464
+
465
+ <script setup>
466
+ import ButtonGroup from '@/components/ButtonGroup.vue'
467
+ import Button from '@/components/Button.vue'
468
+ </script>
469
+ ```
470
+
471
+ ## Calendar
472
+
473
+ A standalone calendar component for date selection with month navigation.
474
+
475
+ ### Props
476
+
477
+ | Prop | Type | Default | Description |
478
+ |------|------|---------|-------------|
479
+ | `id` | `String` | - | Custom ID |
480
+ | `modelValue` | `String \| Date` | - | Selected date |
481
+ | `disabled` | `Boolean` | `false` | Whether disabled |
482
+ | `required` | `Boolean` | `false` | Whether required |
483
+ | `min` | `String \| Date` | - | Minimum selectable date |
484
+ | `max` | `String \| Date` | - | Maximum selectable date |
485
+ | `placeholder` | `String` | `'Select date'` | Placeholder text |
486
+ | `format` | `String` | `'MM/DD/YYYY'` | Date format |
487
+ | `clearable` | `Boolean` | `true` | Show clear button |
488
+ | `showToday` | `Boolean` | `true` | Show today button |
489
+ | `calendarPosition` | `String` | `'left-0'` | Calendar dropdown position |
490
+ | `ariaDescribedby` | `String` | - | ARIA describedby attribute |
491
+
492
+ ### Events
493
+
494
+ | Event | Payload | Description |
495
+ |-------|---------|-------------|
496
+ | `update:modelValue` | `String` | Emitted when date changes |
497
+
498
+ ### Example
499
+
500
+ ```vue
501
+ <template>
502
+ <Calendar
503
+ v-model="selectedDate"
504
+ placeholder="Pick a date"
505
+ format="YYYY-MM-DD"
506
+ :min="'2023-01-01'"
507
+ :max="'2023-12-31'"
508
+ />
509
+ </template>
510
+
511
+ <script setup>
512
+ import { ref } from 'vue'
513
+ import Calendar from '@/components/Calendar.vue'
514
+
515
+ const selectedDate = ref('')
516
+ </script>
517
+ ```
518
+
519
+ ## Divider
520
+
521
+ A visual separator component for dividing content sections.
522
+
523
+ ### Props
524
+
525
+ | Prop | Type | Default | Description |
526
+ |------|------|---------|-------------|
527
+ | `orientation` | `String` | `'horizontal'` | Orientation (horizontal, vertical) |
528
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
529
+ | `color` | `String` | `'gray'` | Color variant (gray, primary, secondary) |
530
+ | `faded` | `Boolean` | `false` | Whether to apply opacity |
531
+ | `label` | `String` | - | Label text for horizontal dividers |
532
+ | `spacing` | `String` | - | Custom spacing classes |
533
+
534
+ ### Example
535
+
536
+ ```vue
537
+ <template>
538
+ <div>
539
+ <p>Content above</p>
540
+ <Divider />
541
+ <p>Content below</p>
542
+
543
+ <Divider orientation="vertical" class="h-6" />
544
+
545
+ <Divider label="Section Break" />
546
+ </div>
547
+ </template>
548
+
549
+ <script setup>
550
+ import Divider from '@/components/Divider.vue'
551
+ </script>
552
+ ```
553
+
554
+ ## Dropdown
555
+
556
+ A dropdown menu component with customizable trigger and placement.
557
+
558
+ ### Props
559
+
560
+ | Prop | Type | Default | Description |
561
+ |------|------|---------|-------------|
562
+ | `triggerText` | `String` | `'Options'` | Text for default trigger |
563
+ | `placement` | `String` | `'bottom-start'` | Dropdown position (bottom-start, bottom-end, top-start, top-end) |
564
+ | `variant` | `String` | `'default'` | Trigger button variant (default, outline, ghost) |
565
+
566
+ ### Slots
567
+
568
+ | Slot | Description |
569
+ |------|-------------|
570
+ | `trigger` | Custom trigger content |
571
+ | `default` | Dropdown menu items |
572
+
573
+ ### Example
574
+
575
+ ```vue
576
+ <template>
577
+ <Dropdown>
578
+ <template #trigger>
579
+ <Button variant="outline">Menu</Button>
580
+ </template>
581
+ <DropdownItem @click="action1">Action 1</DropdownItem>
582
+ <DropdownItem @click="action2">Action 2</DropdownItem>
583
+ <DropdownItem variant="danger" @click="delete">Delete</DropdownItem>
584
+ </Dropdown>
585
+ </template>
586
+
587
+ <script setup>
588
+ import Dropdown from '@/components/Dropdown.vue'
589
+ import DropdownItem from '@/components/DropdownItem.vue'
590
+ import Button from '@/components/Button.vue'
591
+
592
+ const action1 = () => console.log('Action 1')
593
+ const action2 = () => console.log('Action 2')
594
+ const delete = () => console.log('Delete')
595
+ </script>
596
+ ```
597
+
598
+ ## DropdownItem
599
+
600
+ An individual item within a dropdown menu.
601
+
602
+ ### Props
603
+
604
+ | Prop | Type | Default | Description |
605
+ |------|------|---------|-------------|
606
+ | `href` | `String` | - | Link URL (makes item a link) |
607
+ | `icon` | `String` | - | Icon name |
608
+ | `shortcut` | `String` | - | Keyboard shortcut text |
609
+ | `disabled` | `Boolean` | `false` | Whether disabled |
610
+ | `variant` | `String` | `'default'` | Visual variant (default, danger) |
611
+
612
+ ### Events
613
+
614
+ | Event | Payload | Description |
615
+ |-------|---------|-------------|
616
+ | `click` | `Event` | Emitted when item is clicked |
617
+
618
+ ### Slots
619
+
620
+ | Slot | Description |
621
+ |------|-------------|
622
+ | `default` | Item content |
623
+
624
+ ### Example
625
+
626
+ ```vue
627
+ <template>
628
+ <DropdownItem icon="user" shortcut="⌘U" @click="profile">
629
+ Profile
630
+ </DropdownItem>
631
+ </template>
632
+
633
+ <script setup>
634
+ import DropdownItem from '@/components/DropdownItem.vue'
635
+
636
+ const profile = () => console.log('Open profile')
637
+ </script>
638
+ ```
639
+
640
+ ## Image
641
+
642
+ An enhanced image component with loading states, aspect ratios, and error handling.
643
+
644
+ ### Props
645
+
646
+ | Prop | Type | Default | Description |
647
+ |------|------|---------|-------------|
648
+ | `src` | `String` | - | Image source URL |
649
+ | `alt` | `String` | `''` | Alt text |
650
+ | `aspectRatio` | `String` | `'auto'` | Aspect ratio (auto, square, 16/9, 4/3, 3/2) |
651
+ | `objectFit` | `String` | `'cover'` | Object fit (cover, contain, fill, none, scale-down) |
652
+ | `loading` | `String` | `'lazy'` | Loading strategy (lazy, eager) |
653
+ | `showSpinner` | `Boolean` | `true` | Show loading spinner |
654
+
655
+ ### Events
656
+
657
+ | Event | Payload | Description |
658
+ |-------|---------|-------------|
659
+ | `load` | `Event` | Emitted when image loads |
660
+ | `error` | `Event` | Emitted when image fails to load |
661
+
662
+ ### Example
663
+
664
+ ```vue
665
+ <template>
666
+ <div class="grid grid-cols-3 gap-4">
667
+ <Image
668
+ src="/path/to/image1.jpg"
669
+ alt="Image 1"
670
+ aspect-ratio="square"
671
+ />
672
+ <Image
673
+ src="/path/to/image2.jpg"
674
+ alt="Image 2"
675
+ aspect-ratio="16/9"
676
+ object-fit="contain"
677
+ />
678
+ </div>
679
+ </template>
680
+
681
+ <script setup>
682
+ import Image from '@/components/Image.vue'
683
+ </script>
684
+ ```
685
+
686
+ ## Slider
687
+
688
+ A customizable range slider component for selecting numeric values.
689
+
690
+ ### Props
691
+
692
+ | Prop | Type | Default | Description |
693
+ |------|------|---------|-------------|
694
+ | `modelValue` | `Number \| String` | `0` | The current value of the slider |
695
+ | `min` | `Number` | `0` | Minimum value |
696
+ | `max` | `Number` | `100` | Maximum value |
697
+ | `step` | `Number` | `1` | Step increment |
698
+
699
+ ### Events
700
+
701
+ | Event | Payload | Description |
702
+ |-------|---------|-------------|
703
+ | `update:modelValue` | `Number` | Emitted when the slider value changes |
704
+
705
+ ### Example
706
+
707
+ ```vue
708
+ <template>
709
+ <Slider v-model="volume" :min="0" :max="100" :step="5" />
710
+ </template>
711
+
712
+ <script setup>
713
+ import { ref } from 'vue'
714
+ import Slider from '@/components/Slider.vue'
715
+
716
+ const volume = ref(50)
717
+ </script>
718
+ ```
719
+
720
+ ## Input
721
+
722
+ A versatile input component supporting various types and features.
723
+
724
+ ### Props
725
+
726
+ | Prop | Type | Default | Description |
727
+ |------|------|---------|-------------|
728
+ | `modelValue` | `String \| Number` | `''` | The input value |
729
+ | `type` | `String` | `'text'` | Input type (text, email, password, number, tel, url, search, date, color) |
730
+ | `placeholder` | `String` | `''` | Placeholder text |
731
+ | `disabled` | `Boolean` | `false` | Whether the input is disabled |
732
+ | `readonly` | `Boolean` | `false` | Whether the input is readonly |
733
+ | `required` | `Boolean` | `false` | Whether the input is required |
734
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
735
+ | `variant` | `String` | `'default'` | Visual variant (default, error, success) |
736
+ | `iconLeft` | `String \| Object` | `null` | Icon component for left side |
737
+ | `iconRight` | `String \| Object` | `null` | Icon component for right side |
738
+ | `clearable` | `Boolean` | `false` | Show clear button when input has value |
739
+ | `clearLabel` | `String` | `'Clear input'` | Accessibility label for clear button |
740
+ | `autocomplete` | `String` | `null` | Autocomplete attribute |
741
+ | `error` | `String` | `null` | Error message |
742
+ | `id` | `String` | `null` | Custom ID for the input |
743
+
744
+ ### Events
745
+
746
+ | Event | Payload | Description |
747
+ |-------|---------|-------------|
748
+ | `update:modelValue` | `String \| Number` | Emitted when input value changes |
749
+ | `blur` | `Event` | Emitted on blur |
750
+ | `focus` | `Event` | Emitted on focus |
751
+ | `clear` | - | Emitted when clear button is clicked |
752
+ | `keydown` | `Event` | Emitted on keydown |
753
+
754
+ ### Exposed Methods
755
+
756
+ - `focus()`: Focus the input
757
+ - `blur()`: Blur the input
758
+ - `select()`: Select all text in the input
759
+
760
+ ### Example
761
+
762
+ ```vue
763
+ <template>
764
+ <Input
765
+ v-model="email"
766
+ type="email"
767
+ placeholder="Enter your email"
768
+ :iconLeft="MailIcon"
769
+ clearable
770
+ required
771
+ />
772
+ </template>
773
+
774
+ <script setup>
775
+ import { ref } from 'vue'
776
+ import Input from '@/components/Input.vue'
777
+ import MailIcon from '@/components/icons/MailIcon.vue'
778
+
779
+ const email = ref('')
780
+ </script>
781
+ ```
782
+
783
+ ## DatePicker
784
+
785
+ A date picker component with calendar dropdown.
786
+
787
+ ### Props
788
+
789
+ | Prop | Type | Default | Description |
790
+ |------|------|---------|-------------|
791
+ | `id` | `String` | - | Custom ID |
792
+ | `modelValue` | `String \| Date` | - | Selected date |
793
+ | `disabled` | `Boolean` | `false` | Whether disabled |
794
+ | `required` | `Boolean` | `false` | Whether required |
795
+ | `min` | `String \| Date` | - | Minimum selectable date |
796
+ | `max` | `String \| Date` | - | Maximum selectable date |
797
+ | `placeholder` | `String` | `'Select date'` | Placeholder text |
798
+ | `format` | `String` | `'MM/DD/YYYY'` | Date format |
799
+ | `clearable` | `Boolean` | `true` | Show clear button |
800
+ | `showToday` | `Boolean` | `true` | Show today button in calendar |
801
+ | `calendarPosition` | `String` | `'left-0 bottom-full'` | Calendar dropdown position |
802
+ | `ariaDescribedby` | `String` | - | ARIA describedby attribute |
803
+
804
+ ### Events
805
+
806
+ | Event | Payload | Description |
807
+ |-------|---------|-------------|
808
+ | `update:modelValue` | `String` | Emitted when date changes |
809
+
810
+ ### Example
811
+
812
+ ```vue
813
+ <template>
814
+ <DatePicker
815
+ v-model="selectedDate"
816
+ placeholder="Choose a date"
817
+ format="YYYY-MM-DD"
818
+ :min="minDate"
819
+ :max="maxDate"
820
+ />
821
+ </template>
822
+
823
+ <script setup>
824
+ import { ref } from 'vue'
825
+ import DatePicker from '@/components/DatePicker.vue'
826
+
827
+ const selectedDate = ref('')
828
+ const minDate = '2023-01-01'
829
+ const maxDate = '2023-12-31'
830
+ </script>
831
+ ```
832
+
833
+ ## ReusableFormModal
834
+
835
+ A reusable modal component for creating and editing forms with various field types.
836
+
837
+ ### Props
838
+
839
+ | Prop | Type | Default | Description |
840
+ |------|------|---------|-------------|
841
+ | `modelValue` | `Boolean` | `false` | Modal visibility |
842
+ | `modalType` | `String` | - | 'create' or 'edit' |
843
+ | `entityName` | `String` | - | Name of the entity being created/edited |
844
+ | `fields` | `Array` | - | Array of field configurations |
845
+ | `initialData` | `Object` | `null` | Initial form data for editing |
846
+ | `loading` | `Boolean` | `false` | Loading state |
847
+ | `customValidation` | `Function` | `null` | Custom validation function |
848
+ | `modalSize` | `String` | `'4xl'` | Modal size |
849
+ | `modalResizable` | `Boolean` | `false` | Whether modal is resizable |
850
+
851
+ ### Events
852
+
853
+ | Event | Payload | Description |
854
+ |-------|---------|-------------|
855
+ | `update:modelValue` | `Boolean` | Modal visibility changes |
856
+ | `submit` | `{ formData, modalType, originalData }` | Form submission |
857
+ | `close` | - | Modal close |
858
+
859
+ ### Field Configuration
860
+
861
+ Each field in the `fields` array should have:
862
+
863
+ ```javascript
864
+ {
865
+ name: 'fieldName', // Required
866
+ label: 'Field Label', // Required
867
+ type: 'text', // Required: text, number, password, textarea, select, checkbox, slider, date, color
868
+ placeholder: 'Placeholder',
869
+ required: false,
870
+ disabled: false,
871
+ min: 0, // For number/slider/date
872
+ max: 100, // For number/slider/date
873
+ step: 1, // For slider
874
+ rows: 3, // For textarea
875
+ options: [{ value: '1', label: 'Option 1' }], // For select
876
+ checkboxLabel: 'Check this', // For checkbox
877
+ format: 'MM/DD/YYYY', // For date
878
+ clearable: true, // For date
879
+ showToday: true, // For date
880
+ calendarPosition: 'left-0 bottom-full', // For date
881
+ validate: (value, formData) => errorMessage || null, // Custom validation
882
+ onChange: (value, formData) => {}, // Change handler
883
+ errorMessage: 'Custom error message'
884
+ }
885
+ ```
886
+
887
+ ### Example
888
+
889
+ ```vue
890
+ <template>
891
+ <ReusableFormModal
892
+ v-model="showModal"
893
+ :modalType="modalType"
894
+ entityName="User"
895
+ :fields="userFields"
896
+ :initialData="editingUser"
897
+ :loading="submitting"
898
+ @submit="handleSubmit"
899
+ />
900
+ </template>
901
+
902
+ <script setup>
903
+ import { ref } from 'vue'
904
+ import ReusableFormModal from '@/components/ReusableFormModal.vue'
905
+
906
+ const showModal = ref(false)
907
+ const modalType = ref('create')
908
+ const editingUser = ref(null)
909
+ const submitting = ref(false)
910
+
911
+ const userFields = [
912
+ {
913
+ name: 'name',
914
+ label: 'Full Name',
915
+ type: 'text',
916
+ required: true
917
+ },
918
+ {
919
+ name: 'email',
920
+ label: 'Email',
921
+ type: 'email',
922
+ required: true
923
+ },
924
+ {
925
+ name: 'age',
926
+ label: 'Age',
927
+ type: 'number',
928
+ min: 18,
929
+ max: 100
930
+ },
931
+ {
932
+ name: 'bio',
933
+ label: 'Biography',
934
+ type: 'textarea',
935
+ rows: 4
936
+ },
937
+ {
938
+ name: 'department',
939
+ label: 'Department',
940
+ type: 'select',
941
+ options: [
942
+ { value: 'engineering', label: 'Engineering' },
943
+ { value: 'design', label: 'Design' },
944
+ { value: 'marketing', label: 'Marketing' }
945
+ ]
946
+ },
947
+ {
948
+ name: 'isActive',
949
+ label: 'Active',
950
+ type: 'checkbox',
951
+ checkboxLabel: 'User is active'
952
+ },
953
+ {
954
+ name: 'rating',
955
+ label: 'Rating',
956
+ type: 'slider',
957
+ min: 1,
958
+ max: 5,
959
+ step: 1
960
+ },
961
+ {
962
+ name: 'birthDate',
963
+ label: 'Birth Date',
964
+ type: 'date',
965
+ format: 'YYYY-MM-DD'
966
+ }
967
+ ]
968
+
969
+ const handleSubmit = ({ formData, modalType }) => {
970
+ submitting.value = true
971
+ // Handle form submission
972
+ console.log('Submitted:', formData, modalType)
973
+ submitting.value = false
974
+ showModal.value = false
975
+ }
976
+ </script>
977
+ ```
978
+
979
+ ## Button
980
+
981
+ A versatile button component with multiple variants, sizes, and states.
982
+
983
+ ### Props
984
+
985
+ | Prop | Type | Default | Description |
986
+ |------|------|---------|-------------|
987
+ | `variant` | `String` | `'default'` | Visual style (default, danger, outline, secondary, ghost, link, success, warning, info, subtle, dark, light, primaryOutline, dangerOutline, successOutline, gradient) |
988
+ | `size` | `String` | `'default'` | Size variant (default, xs, sm, lg, icon) |
989
+ | `disabled` | `Boolean` | `false` | Whether the button is disabled |
990
+ | `loading` | `Boolean` | `false` | Shows loading spinner |
991
+ | `loadingText` | `String` | `null` | Text to show when loading |
992
+
993
+ ### Slots
994
+
995
+ | Slot | Description |
996
+ |------|-------------|
997
+ | `icon` | Icon content (shown before text when not loading) |
998
+ | `default` | Button text content |
999
+
1000
+ ### Example
1001
+
1002
+ ```vue
1003
+ <template>
1004
+ <div class="space-x-2">
1005
+ <Button variant="default">Default</Button>
1006
+ <Button variant="outline" size="sm">Outline</Button>
1007
+ <Button variant="danger" :loading="true" loadingText="Deleting...">
1008
+ Delete
1009
+ </Button>
1010
+ <Button variant="icon" size="icon">
1011
+ <template #icon>
1012
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1013
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
1014
+ </svg>
1015
+ </template>
1016
+ </Button>
1017
+ </div>
1018
+ </template>
1019
+
1020
+ <script setup>
1021
+ import Button from '@/components/Button.vue'
1022
+ </script>
1023
+ ```
1024
+
1025
+ ## Alert
1026
+
1027
+ A notification component for displaying messages with different variants and optional actions.
1028
+
1029
+ ### Props
1030
+
1031
+ | Prop | Type | Default | Description |
1032
+ |------|------|---------|-------------|
1033
+ | `variant` | `String` | `'info'` | Alert style (info, success, warning, error, default, danger) |
1034
+ | `title` | `String` | - | Alert title |
1035
+ | `message` | `String` | - | Alert message |
1036
+ | `dismissible` | `Boolean` | `false` | Show dismiss button |
1037
+ | `dismissLabel` | `String` | `'Dismiss alert'` | Accessibility label for dismiss button |
1038
+ | `showIcon` | `Boolean` | `true` | Show variant icon |
1039
+ | `actions` | `Array` | `[]` | Array of action buttons |
1040
+ | `autoClose` | `Boolean \| Number` | `false` | Auto-dismiss after delay (ms) or false |
1041
+
1042
+ ### Events
1043
+
1044
+ | Event | Payload | Description |
1045
+ |-------|---------|-------------|
1046
+ | `dismiss` | - | Emitted when alert is dismissed |
1047
+ | `action` | `action` | Emitted when an action button is clicked |
1048
+
1049
+ ### Slots
1050
+
1051
+ | Slot | Description |
1052
+ |------|-------------|
1053
+ | `default` | Alert content (replaces message) |
1054
+ | `actions` | Custom action buttons |
1055
+
1056
+ ### Example
1057
+
1058
+ ```vue
1059
+ <template>
1060
+ <div class="space-y-4">
1061
+ <Alert variant="success" title="Success!" message="Your changes have been saved." dismissible />
1062
+
1063
+ <Alert variant="warning" title="Warning" :autoClose="5000">
1064
+ This action cannot be undone.
1065
+ <template #actions>
1066
+ <Button variant="outline" size="sm" @click="confirmAction">Confirm</Button>
1067
+ </template>
1068
+ </Alert>
1069
+
1070
+ <Alert variant="error" title="Error" dismissible>
1071
+ <p>Something went wrong. Please try again.</p>
1072
+ </Alert>
1073
+ </div>
1074
+ </template>
1075
+
1076
+ <script setup>
1077
+ import Alert from '@/components/Alert.vue'
1078
+ import Button from '@/components/Button.vue'
1079
+
1080
+ const confirmAction = () => {
1081
+ console.log('Action confirmed')
1082
+ }
1083
+ </script>
1084
+ ```
1085
+
1086
+ ## Badge
1087
+
1088
+ A small label component for displaying status, tags, or counts with multiple variant options.
1089
+
1090
+ ### Props
1091
+
1092
+ | Prop | Type | Default | Description |
1093
+ |------|------|---------|-------------|
1094
+ | `variant` | `String` | `'default'` | Visual style (default, secondary, danger, primary, outline, success, warning, info, ghost, link, subtle, dark, light, primaryOutline, dangerOutline, successOutline, gradient) |
1095
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
1096
+ | `shape` | `String` | `'rounded'` | Shape variant (rounded, pill, square) |
1097
+ | `icon` | `String \| Object` | `null` | Icon component |
1098
+ | `dismissible` | `Boolean` | `false` | Show dismiss button |
1099
+ | `dismissLabel` | `String` | `'Dismiss'` | Accessibility label for dismiss button |
1100
+
1101
+ ### Events
1102
+
1103
+ | Event | Payload | Description |
1104
+ |-------|---------|-------------|
1105
+ | `dismiss` | - | Emitted when badge is dismissed |
1106
+
1107
+ ### Slots
1108
+
1109
+ | Slot | Description |
1110
+ |------|-------------|
1111
+ | `default` | Badge content |
1112
+
1113
+ ### Example
1114
+
1115
+ ```vue
1116
+ <template>
1117
+ <div class="space-x-2">
1118
+ <Badge variant="default">New</Badge>
1119
+ <Badge variant="primary">Primary</Badge>
1120
+ <Badge variant="secondary">Secondary</Badge>
1121
+ <Badge variant="success" size="sm">Active</Badge>
1122
+ <Badge variant="warning" shape="pill">Pending</Badge>
1123
+ <Badge variant="danger" icon="ExclamationIcon">Error</Badge>
1124
+ <Badge variant="info">Info</Badge>
1125
+ <Badge variant="ghost">Ghost</Badge>
1126
+ <Badge variant="link">Link</Badge>
1127
+ <Badge variant="subtle">Subtle</Badge>
1128
+ <Badge variant="dark">Dark</Badge>
1129
+ <Badge variant="light">Light</Badge>
1130
+ <Badge variant="primaryOutline">Primary Outline</Badge>
1131
+ <Badge variant="dangerOutline">danger Outline</Badge>
1132
+ <Badge variant="successOutline">Success Outline</Badge>
1133
+ <Badge variant="gradient">Gradient</Badge>
1134
+ <Badge variant="outline" dismissible @dismiss="handleDismiss">
1135
+ Dismissible
1136
+ </Badge>
1137
+ </div>
1138
+ </template>
1139
+
1140
+ <script setup>
1141
+ import Badge from '@/components/Badge.vue'
1142
+
1143
+ const handleDismiss = () => {
1144
+ console.log('Badge dismissed')
1145
+ }
1146
+ </script>
1147
+ ```
1148
+
1149
+ ## Card
1150
+
1151
+ A container component for grouping related content with optional header, image, and footer.
1152
+
1153
+ ### Props
1154
+
1155
+ | Prop | Type | Default | Description |
1156
+ |------|------|---------|-------------|
1157
+ | `variant` | `String` | `'default'` | Visual style (default, outlined, elevated, filled) |
1158
+ | `padding` | `String` | `'md'` | Padding size (none, sm, md, lg, xl) |
1159
+ | `title` | `String` | - | Card title |
1160
+ | `subtitle` | `String` | - | Card subtitle |
1161
+ | `image` | `String` | - | Image source URL |
1162
+ | `imageAlt` | `String` | `'Card image'` | Image alt text |
1163
+ | `hoverable` | `Boolean` | `false` | Add hover effect |
1164
+ | `clickable` | `Boolean` | `false` | Make card clickable |
1165
+ | `loading` | `Boolean` | `false` | Loading state |
1166
+
1167
+ ### Events
1168
+
1169
+ | Event | Payload | Description |
1170
+ |-------|---------|-------------|
1171
+ | `click` | `Event` | Emitted when card is clicked (if clickable) |
1172
+
1173
+ ### Slots
1174
+
1175
+ | Slot | Description |
1176
+ |------|-------------|
1177
+ | `header` | Card header content |
1178
+ | `image` | Card image |
1179
+ | `default` | Card content |
1180
+ | `footer` | Card footer |
1181
+ | `actions` | Header actions |
1182
+
1183
+ ### Example
1184
+
1185
+ ```vue
1186
+ <template>
1187
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
1188
+ <Card
1189
+ title="Card Title"
1190
+ subtitle="Card subtitle"
1191
+ image="/path/to/image.jpg"
1192
+ hoverable
1193
+ clickable
1194
+ @click="handleCardClick"
1195
+ >
1196
+ <p>This is the card content.</p>
1197
+
1198
+ <template #footer>
1199
+ <Button variant="outline" size="sm">Learn More</Button>
1200
+ </template>
1201
+ </Card>
1202
+
1203
+ <Card variant="elevated" padding="lg">
1204
+ <template #header>
1205
+ <div class="flex justify-between items-center">
1206
+ <h3 class="text-lg font-semibold">Custom Header</h3>
1207
+ <div class="space-x-2">
1208
+ <Button variant="ghost" size="sm">Edit</Button>
1209
+ <Button variant="ghost" size="sm">Delete</Button>
1210
+ </div>
1211
+ </div>
1212
+ </template>
1213
+
1214
+ <p>Card with custom header and actions.</p>
1215
+ </Card>
1216
+ </div>
1217
+ </template>
1218
+
1219
+ <script setup>
1220
+ import Card from '@/components/Card.vue'
1221
+ import Button from '@/components/Button.vue'
1222
+
1223
+ const handleCardClick = () => {
1224
+ console.log('Card clicked')
1225
+ }
1226
+ </script>
1227
+ ```
1228
+
1229
+ ## CardBody
1230
+
1231
+ A container component for card content with configurable padding.
1232
+
1233
+ ### Props
1234
+
1235
+ | Prop | Type | Default | Description |
1236
+ |------|------|---------|-------------|
1237
+ | `variant` | `String` | `'default'` | Padding variant (default, compact, spacious) |
1238
+
1239
+ ### Slots
1240
+
1241
+ | Slot | Description |
1242
+ |------|-------------|
1243
+ | `default` | Card body content |
1244
+
1245
+ ### Example
1246
+
1247
+ ```vue
1248
+ <template>
1249
+ <Card>
1250
+ <CardHeader>
1251
+ <CardTitle>Card Title</CardTitle>
1252
+ </CardHeader>
1253
+ <CardBody>
1254
+ <p>This is the main content of the card.</p>
1255
+ </CardBody>
1256
+ <CardFooter>
1257
+ <Button>Action</Button>
1258
+ </CardFooter>
1259
+ </Card>
1260
+ </template>
1261
+
1262
+ <script setup>
1263
+ import Card from '@/components/Card.vue'
1264
+ import CardHeader from '@/components/CardHeader.vue'
1265
+ import CardTitle from '@/components/CardTitle.vue'
1266
+ import CardBody from '@/components/CardBody.vue'
1267
+ import CardFooter from '@/components/CardFooter.vue'
1268
+ import Button from '@/components/Button.vue'
1269
+ </script>
1270
+ ```
1271
+
1272
+ ## CardContent
1273
+
1274
+ A container component for card content with reduced top padding.
1275
+
1276
+ ### Slots
1277
+
1278
+ | Slot | Description |
1279
+ |------|-------------|
1280
+ | `default` | Card content |
1281
+
1282
+ ### Example
1283
+
1284
+ ```vue
1285
+ <template>
1286
+ <Card>
1287
+ <CardHeader>
1288
+ <CardTitle>Card Title</CardTitle>
1289
+ </CardHeader>
1290
+ <CardContent>
1291
+ <p>This content has reduced top padding.</p>
1292
+ </CardContent>
1293
+ </Card>
1294
+ </template>
1295
+
1296
+ <script setup>
1297
+ import Card from '@/components/Card.vue'
1298
+ import CardHeader from '@/components/CardHeader.vue'
1299
+ import CardTitle from '@/components/CardTitle.vue'
1300
+ import CardContent from '@/components/CardContent.vue'
1301
+ </script>
1302
+ ```
1303
+
1304
+ ## CardFooter
1305
+
1306
+ A container component for card footer content.
1307
+
1308
+ ### Slots
1309
+
1310
+ | Slot | Description |
1311
+ |------|-------------|
1312
+ | `default` | Card footer content |
1313
+
1314
+ ### Example
1315
+
1316
+ ```vue
1317
+ <template>
1318
+ <Card>
1319
+ <CardBody>
1320
+ <p>Card content</p>
1321
+ </CardBody>
1322
+ <CardFooter>
1323
+ <div class="flex justify-end space-x-2">
1324
+ <Button variant="outline">Cancel</Button>
1325
+ <Button>Save</Button>
1326
+ </div>
1327
+ </CardFooter>
1328
+ </Card>
1329
+ </template>
1330
+
1331
+ <script setup>
1332
+ import Card from '@/components/Card.vue'
1333
+ import CardBody from '@/components/CardBody.vue'
1334
+ import CardFooter from '@/components/CardFooter.vue'
1335
+ import Button from '@/components/Button.vue'
1336
+ </script>
1337
+ ```
1338
+
1339
+ ## CardHeader
1340
+
1341
+ A container component for card header content.
1342
+
1343
+ ### Slots
1344
+
1345
+ | Slot | Description |
1346
+ |------|-------------|
1347
+ | `default` | Card header content |
1348
+
1349
+ ### Example
1350
+
1351
+ ```vue
1352
+ <template>
1353
+ <Card>
1354
+ <CardHeader>
1355
+ <CardTitle>Card Title</CardTitle>
1356
+ <p class="text-sm text-muted-foreground">Card subtitle</p>
1357
+ </CardHeader>
1358
+ <CardBody>
1359
+ <p>Card content</p>
1360
+ </CardBody>
1361
+ </Card>
1362
+ </template>
1363
+
1364
+ <script setup>
1365
+ import Card from '@/components/Card.vue'
1366
+ import CardHeader from '@/components/CardHeader.vue'
1367
+ import CardTitle from '@/components/CardTitle.vue'
1368
+ import CardBody from '@/components/CardBody.vue'
1369
+ </script>
1370
+ ```
1371
+
1372
+ ## CardTitle
1373
+
1374
+ A styled title component for card headers.
1375
+
1376
+ ### Slots
1377
+
1378
+ | Slot | Description |
1379
+ |------|-------------|
1380
+ | `default` | Title content |
1381
+
1382
+ ### Example
1383
+
1384
+ ```vue
1385
+ <template>
1386
+ <Card>
1387
+ <CardHeader>
1388
+ <CardTitle>Important Announcement</CardTitle>
1389
+ </CardHeader>
1390
+ <CardBody>
1391
+ <p>This is an important message.</p>
1392
+ </CardBody>
1393
+ </Card>
1394
+ </template>
1395
+
1396
+ <script setup>
1397
+ import Card from '@/components/Card.vue'
1398
+ import CardHeader from '@/components/CardHeader.vue'
1399
+ import CardTitle from '@/components/CardTitle.vue'
1400
+ import CardBody from '@/components/CardBody.vue'
1401
+ </script>
1402
+ ```
1403
+
1404
+ ## Checkbox
1405
+
1406
+ A customizable checkbox component with label and description support.
1407
+
1408
+ ### Props
1409
+
1410
+ | Prop | Type | Default | Description |
1411
+ |------|------|---------|-------------|
1412
+ | `modelValue` | `Boolean \| Array` | `false` | Checkbox value or array of values |
1413
+ | `value` | `String \| Number \| Boolean` | `null` | Value when used in checkbox group |
1414
+ | `label` | `String` | `null` | Checkbox label |
1415
+ | `description` | `String` | `null` | Additional description text |
1416
+ | `disabled` | `Boolean` | `false` | Whether disabled |
1417
+ | `required` | `Boolean` | `false` | Whether required |
1418
+ | `indeterminate` | `Boolean` | `false` | Indeterminate state |
1419
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
1420
+ | `variant` | `String` | `'default'` | Visual variant (default, error) |
1421
+ | `id` | `String` | `null` | Custom ID |
1422
+ | `error` | `String` | `null` | Error message |
1423
+
1424
+ ### Events
1425
+
1426
+ | Event | Payload | Description |
1427
+ |-------|---------|-------------|
1428
+ | `update:modelValue` | `Boolean \| Array` | Emitted when value changes |
1429
+ | `change` | `Boolean` | Emitted on change |
1430
+
1431
+ ### Slots
1432
+
1433
+ | Slot | Description |
1434
+ |------|-------------|
1435
+ | `default` | Label content (replaces label prop) |
1436
+
1437
+ ### Example
1438
+
1439
+ ```vue
1440
+ <template>
1441
+ <div class="space-y-4">
1442
+ <!-- Single checkbox -->
1443
+ <Checkbox v-model="agree" label="I agree to the terms" required />
1444
+
1445
+ <!-- Checkbox with description -->
1446
+ <Checkbox
1447
+ v-model="newsletter"
1448
+ label="Subscribe to newsletter"
1449
+ description="Receive weekly updates about our products"
1450
+ />
1451
+
1452
+ <!-- Checkbox group -->
1453
+ <div>
1454
+ <h4 class="font-medium mb-2">Select your interests:</h4>
1455
+ <div class="space-y-2">
1456
+ <Checkbox
1457
+ v-model="interests"
1458
+ value="tech"
1459
+ label="Technology"
1460
+ />
1461
+ <Checkbox
1462
+ v-model="interests"
1463
+ value="design"
1464
+ label="Design"
1465
+ />
1466
+ <Checkbox
1467
+ v-model="interests"
1468
+ value="business"
1469
+ label="Business"
1470
+ />
1471
+ </div>
1472
+ </div>
1473
+
1474
+ <!-- Indeterminate checkbox -->
1475
+ <Checkbox
1476
+ v-model="selectAll"
1477
+ :indeterminate="partialSelection"
1478
+ label="Select all"
1479
+ @change="handleSelectAll"
1480
+ />
1481
+ </div>
1482
+ </template>
1483
+
1484
+ <script setup>
1485
+ import { ref, computed } from 'vue'
1486
+ import Checkbox from '@/components/Checkbox.vue'
1487
+
1488
+ const agree = ref(false)
1489
+ const newsletter = ref(true)
1490
+ const interests = ref(['tech'])
1491
+ const selectAll = ref(false)
1492
+
1493
+ const partialSelection = computed(() => {
1494
+ return interests.value.length > 0 && interests.value.length < 3
1495
+ })
1496
+
1497
+ const handleSelectAll = (checked) => {
1498
+ if (checked) {
1499
+ interests.value = ['tech', 'design', 'business']
1500
+ } else {
1501
+ interests.value = []
1502
+ }
1503
+ }
1504
+ </script>
1505
+ ```
1506
+
1507
+ ## DataTable
1508
+
1509
+ A comprehensive data table component with sorting, pagination, selection, and loading states.
1510
+
1511
+ ### Props
1512
+
1513
+ | Prop | Type | Default | Description |
1514
+ |------|------|---------|-------------|
1515
+ | `data` | `Array` | - | Array of data items |
1516
+ | `columns` | `Array` | - | Column configuration array |
1517
+ | `title` | `String` | - | Table title |
1518
+ | `description` | `String` | - | Table description |
1519
+ | `selectable` | `Boolean` | `false` | Enable row selection |
1520
+ | `selectedItems` | `Array` | `[]` | Currently selected items |
1521
+ | `sortBy` | `String` | - | Initial sort column |
1522
+ | `sortOrder` | `String` | `'asc'` | Initial sort order |
1523
+ | `pageSize` | `Number` | `10` | Items per page |
1524
+ | `showPagination` | `Boolean` | `true` | Show pagination |
1525
+ | `striped` | `Boolean` | `false` | Striped rows |
1526
+ | `hoverable` | `Boolean` | `true` | Hover effects |
1527
+ | `clickableRows` | `Boolean` | `false` | Make rows clickable |
1528
+ | `emptyText` | `String` | `'No data available'` | Empty state text |
1529
+ | `rowKey` | `String` | `'id'` | Unique key for rows |
1530
+ | `variant` | `String` | `'default'` | Table variant |
1531
+ | `density` | `String` | `'normal'` | Row density |
1532
+ | `loading` | `Boolean` | `false` | Loading state |
1533
+ | `dataLoading` | `Boolean` | `false` | Data loading state |
1534
+ | `sortLoading` | `Boolean` | `false` | Sort loading state |
1535
+ | `bulkLoading` | `Boolean` | `false` | Bulk operation loading |
1536
+ | `rowLoading` | `Object` | `{}` | Row-specific loading states |
1537
+
1538
+ ### Events
1539
+
1540
+ | Event | Payload | Description |
1541
+ |-------|---------|-------------|
1542
+ | `selection-change` | `selectedItems` | Selection changed |
1543
+ | `sort-change` | `{ column, direction }` | Sort changed |
1544
+ | `row-click` | `rowData` | Row clicked |
1545
+ | `page-change` | `page` | Page changed |
1546
+ | `page-size-change` | `size` | Page size changed |
1547
+
1548
+ ### Slots
1549
+
1550
+ | Slot | Description |
1551
+ |------|-------------|
1552
+ | `header` | Table header content |
1553
+ | `filters` | Filter controls |
1554
+ | `cell-{columnKey}` | Custom cell content |
1555
+ | `actions` | Row actions |
1556
+ | `empty` | Empty state content |
1557
+ | `footer` | Table footer |
1558
+
1559
+ ### Example
1560
+
1561
+ ```vue
1562
+ <template>
1563
+ <DataTable
1564
+ :data="users"
1565
+ :columns="columns"
1566
+ title="Users"
1567
+ selectable
1568
+ :selected-items="selectedUsers"
1569
+ @selection-change="selectedUsers = $event"
1570
+ @row-click="handleRowClick"
1571
+ >
1572
+ <template #actions="{ item }">
1573
+ <Button variant="ghost" size="sm" @click="editUser(item)">Edit</Button>
1574
+ <Button variant="ghost" size="sm" @click="deleteUser(item)">Delete</Button>
1575
+ </template>
1576
+ </DataTable>
1577
+ </template>
1578
+
1579
+ <script setup>
1580
+ import { ref } from 'vue'
1581
+ import DataTable from '@/components/DataTable.vue'
1582
+ import Button from '@/components/Button.vue'
1583
+
1584
+ const selectedUsers = ref([])
1585
+ const users = ref([
1586
+ { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
1587
+ { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' }
1588
+ ])
1589
+
1590
+ const columns = [
1591
+ { key: 'name', label: 'Name', sortable: true },
1592
+ { key: 'email', label: 'Email', sortable: true },
1593
+ { key: 'role', label: 'Role' }
1594
+ ]
1595
+
1596
+ const handleRowClick = (row) => {
1597
+ console.log('Row clicked:', row)
1598
+ }
1599
+
1600
+ const editUser = (user) => {
1601
+ console.log('Edit user:', user)
1602
+ }
1603
+
1604
+ const deleteUser = (user) => {
1605
+ console.log('Delete user:', user)
1606
+ }
1607
+ </script>
1608
+ ```
1609
+
1610
+ ## Select
1611
+
1612
+ A styled select dropdown component.
1613
+
1614
+ ### Props
1615
+
1616
+ | Prop | Type | Default | Description |
1617
+ |------|------|---------|-------------|
1618
+ | `modelValue` | `String \| Number \| Boolean` | `''` | Selected value |
1619
+ | `id` | `String` | `null` | Custom ID |
1620
+ | `name` | `String` | `null` | Form name |
1621
+ | `disabled` | `Boolean` | `false` | Whether disabled |
1622
+ | `required` | `Boolean` | `false` | Whether required |
1623
+
1624
+ ### Events
1625
+
1626
+ | Event | Payload | Description |
1627
+ |-------|---------|-------------|
1628
+ | `update:modelValue` | `String \| Number \| Boolean` | Emitted when selection changes |
1629
+
1630
+ ### Slots
1631
+
1632
+ | Slot | Description |
1633
+ |------|-------------|
1634
+ | `default` | Option elements |
1635
+
1636
+ ### Example
1637
+
1638
+ ```vue
1639
+ <template>
1640
+ <Select v-model="selectedOption">
1641
+ <option value="" disabled>Select an option</option>
1642
+ <option value="option1">Option 1</option>
1643
+ <option value="option2">Option 2</option>
1644
+ <option value="option3">Option 3</option>
1645
+ </Select>
1646
+ </template>
1647
+
1648
+ <script setup>
1649
+ import { ref } from 'vue'
1650
+ import Select from '@/components/Select.vue'
1651
+
1652
+ const selectedOption = ref('')
1653
+ </script>
1654
+ ```
1655
+
1656
+ ## Textarea
1657
+
1658
+ A multi-line text input component with auto-resize and validation support.
1659
+
1660
+ ### Props
1661
+
1662
+ | Prop | Type | Default | Description |
1663
+ |------|------|---------|-------------|
1664
+ | `modelValue` | `String` | `''` | Textarea value |
1665
+ | `placeholder` | `String` | `''` | Placeholder text |
1666
+ | `disabled` | `Boolean` | `false` | Whether disabled |
1667
+ | `readonly` | `Boolean` | `false` | Whether readonly |
1668
+ | `required` | `Boolean` | `false` | Whether required |
1669
+ | `rows` | `Number` | `3` | Number of visible rows |
1670
+ | `maxlength` | `Number` | `null` | Maximum character count |
1671
+ | `resize` | `String` | `'vertical'` | Resize behavior (none, vertical, horizontal, both) |
1672
+ | `autoResize` | `Boolean` | `false` | Auto-resize to content height |
1673
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
1674
+ | `variant` | `String` | `'default'` | Visual variant (default, error, success) |
1675
+ | `error` | `String` | `null` | Error message |
1676
+ | `id` | `String` | `null` | Custom ID |
1677
+
1678
+ ### Events
1679
+
1680
+ | Event | Payload | Description |
1681
+ |-------|---------|-------------|
1682
+ | `update:modelValue` | `String` | Emitted when value changes |
1683
+ | `blur` | `Event` | Emitted on blur |
1684
+ | `focus` | `Event` | Emitted on focus |
1685
+ | `keydown` | `Event` | Emitted on keydown |
1686
+
1687
+ ### Exposed Methods
1688
+
1689
+ - `focus()`: Focus the textarea
1690
+ - `blur()`: Blur the textarea
1691
+ - `select()`: Select all text
1692
+
1693
+ ### Example
1694
+
1695
+ ```vue
1696
+ <template>
1697
+ <Textarea
1698
+ v-model="message"
1699
+ placeholder="Enter your message..."
1700
+ :rows="4"
1701
+ :autoResize="true"
1702
+ maxlength="500"
1703
+ required
1704
+ />
1705
+ </template>
1706
+
1707
+ <script setup>
1708
+ import { ref } from 'vue'
1709
+ import Textarea from '@/components/Textarea.vue'
1710
+
1711
+ const message = ref('')
1712
+ </script>
1713
+ ```
1714
+
1715
+ ## Modal
1716
+
1717
+ A modal dialog component with backdrop and keyboard support.
1718
+
1719
+ ### Props
1720
+
1721
+ | Prop | Type | Default | Description |
1722
+ |------|------|---------|-------------|
1723
+ | `modelValue` | `Boolean` | - | Modal visibility |
1724
+ | `showClose` | `Boolean` | `true` | Show close button |
1725
+ | `closeOnBackdrop` | `Boolean` | `true` | Close on backdrop click |
1726
+ | `size` | `String` | `'4xl'` | Modal size (sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl, 7xl, full) |
1727
+ | `resizable` | `Boolean` | `false` | Whether modal is resizable |
1728
+
1729
+ ### Events
1730
+
1731
+ | Event | Payload | Description |
1732
+ |-------|---------|-------------|
1733
+ | `update:modelValue` | `Boolean` | Modal visibility changes |
1734
+ | `close` | - | Emitted when modal closes |
1735
+
1736
+ ### Slots
1737
+
1738
+ | Slot | Description |
1739
+ |------|-------------|
1740
+ | `default` | Modal content |
1741
+
1742
+ ### Example
1743
+
1744
+ ```vue
1745
+ <template>
1746
+ <div>
1747
+ <Button @click="showModal = true">Open Modal</Button>
1748
+
1749
+ <Modal v-model="showModal" size="lg">
1750
+ <div class="p-6">
1751
+ <h2 class="text-lg font-semibold mb-4">Modal Title</h2>
1752
+ <p class="mb-4">Modal content goes here.</p>
1753
+ <div class="flex justify-end">
1754
+ <Button @click="showModal = false">Close</Button>
1755
+ </div>
1756
+ </div>
1757
+ </Modal>
1758
+ </div>
1759
+ </template>
1760
+
1761
+ <script setup>
1762
+ import { ref } from 'vue'
1763
+ import Modal from '@/components/Modal.vue'
1764
+ import Button from '@/components/Button.vue'
1765
+
1766
+ const showModal = ref(false)
1767
+ </script>
1768
+ ```
1769
+
1770
+ ## FormField
1771
+
1772
+ A form field wrapper component that provides labels, descriptions, and validation messages.
1773
+
1774
+ ### Props
1775
+
1776
+ | Prop | Type | Default | Description |
1777
+ |------|------|---------|-------------|
1778
+ | `label` | `String` | - | Field label |
1779
+ | `description` | `String` | - | Field description |
1780
+ | `error` | `String` | - | Error message |
1781
+ | `success` | `String` | - | Success message |
1782
+ | `helpText` | `String` | - | Help text |
1783
+ | `required` | `Boolean` | `false` | Whether field is required |
1784
+ | `type` | `String` | `'text'` | Field type (for password toggle) |
1785
+ | `modelValue` | `String \| Date` | - | Field value |
1786
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
1787
+ | `id` | `String` | - | Custom ID |
1788
+
1789
+ ### Events
1790
+
1791
+ | Event | Payload | Description |
1792
+ |-------|---------|-------------|
1793
+ | `update:modelValue` | `String \| Date` | Emitted when value changes |
1794
+
1795
+ ### Slots
1796
+
1797
+ | Slot | Description |
1798
+ |------|-------------|
1799
+ | `default` | Field input component |
1800
+
1801
+ ### Scoped Slot Props
1802
+
1803
+ The default slot receives:
1804
+
1805
+ - `fieldId`: Unique ID for the field
1806
+ - `hasError`: Boolean indicating if field has error
1807
+ - `ariaDescribedBy`: ARIA describedby attribute
1808
+ - `showPassword`: Boolean for password visibility (password fields only)
1809
+ - `togglePasswordVisibility`: Function to toggle password visibility
1810
+
1811
+ ### Example
1812
+
1813
+ ```vue
1814
+ <template>
1815
+ <FormField
1816
+ label="Email Address"
1817
+ description="We'll never share your email with anyone else."
1818
+ :error="emailError"
1819
+ required
1820
+ >
1821
+ <template #default="{ fieldId, hasError, ariaDescribedBy }">
1822
+ <Input
1823
+ :id="fieldId"
1824
+ v-model="email"
1825
+ type="email"
1826
+ placeholder="Enter your email"
1827
+ :class="hasError ? 'border-red-500' : ''"
1828
+ :aria-describedby="ariaDescribedBy"
1829
+ />
1830
+ </template>
1831
+ </FormField>
1832
+ </template>
1833
+
1834
+ <script setup>
1835
+ import { ref } from 'vue'
1836
+ import FormField from '@/components/FormField.vue'
1837
+ import Input from '@/components/Input.vue'
1838
+
1839
+ const email = ref('')
1840
+ const emailError = ref('')
1841
+ </script>
1842
+ ```
1843
+
1844
+ ## Label
1845
+
1846
+ A styled label component for form inputs.
1847
+
1848
+ ### Props
1849
+
1850
+ | Prop | Type | Default | Description |
1851
+ |------|------|---------|-------------|
1852
+ | `htmlFor` | `String` | - | ID of associated input |
1853
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
1854
+ | `required` | `Boolean` | `false` | Show required indicator |
1855
+ | `disabled` | `Boolean` | `false` | Whether associated input is disabled |
1856
+
1857
+ ### Slots
1858
+
1859
+ | Slot | Description |
1860
+ |------|-------------|
1861
+ | `default` | Label text |
1862
+
1863
+ ### Example
1864
+
1865
+ ```vue
1866
+ <template>
1867
+ <div>
1868
+ <Label htmlFor="username" required>Username</Label>
1869
+ <Input id="username" v-model="username" />
1870
+ </div>
1871
+ </template>
1872
+
1873
+ <script setup>
1874
+ import { ref } from 'vue'
1875
+ import Label from '@/components/Label.vue'
1876
+ import Input from '@/components/Input.vue'
1877
+
1878
+ const username = ref('')
1879
+ </script>
1880
+ ```
1881
+
1882
+ ## Radio
1883
+
1884
+ A radio button component for single selection in a group.
1885
+
1886
+ ### Props
1887
+
1888
+ | Prop | Type | Default | Description |
1889
+ |------|------|---------|-------------|
1890
+ | `modelValue` | `Any` | - | Selected value |
1891
+ | `value` | `Any` | - | Value of this radio button |
1892
+ | `label` | `String` | - | Radio button label |
1893
+ | `disabled` | `Boolean` | `false` | Whether disabled |
1894
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
1895
+
1896
+ ### Events
1897
+
1898
+ | Event | Payload | Description |
1899
+ |-------|---------|-------------|
1900
+ | `update:modelValue` | `Any` | Emitted when radio is selected |
1901
+
1902
+ ### Example
1903
+
1904
+ ```vue
1905
+ <template>
1906
+ <div class="space-y-2">
1907
+ <Radio v-model="selected" value="option1" label="Option 1" />
1908
+ <Radio v-model="selected" value="option2" label="Option 2" />
1909
+ <Radio v-model="selected" value="option3" label="Option 3" />
1910
+ </div>
1911
+ <p>Selected: {{ selected }}</p>
1912
+ </template>
1913
+
1914
+ <script setup>
1915
+ import { ref } from 'vue'
1916
+ import Radio from '@/components/Radio.vue'
1917
+
1918
+ const selected = ref('option1')
1919
+ </script>
1920
+ ```
1921
+
1922
+ ## Switch
1923
+
1924
+ A toggle switch component for boolean values.
1925
+
1926
+ ### Props
1927
+
1928
+ | Prop | Type | Default | Description |
1929
+ |------|------|---------|-------------|
1930
+ | `modelValue` | `Boolean` | - | Switch state |
1931
+ | `disabled` | `Boolean` | `false` | Whether disabled |
1932
+ | `size` | `String` | `'md'` | Size variant (sm, md, lg) |
1933
+
1934
+ ### Events
1935
+
1936
+ | Event | Payload | Description |
1937
+ |-------|---------|-------------|
1938
+ | `update:modelValue` | `Boolean` | Emitted when switch toggles |
1939
+
1940
+ ### Example
1941
+
1942
+ ```vue
1943
+ <template>
1944
+ <div class="flex items-center space-x-2">
1945
+ <Switch v-model="enabled" />
1946
+ <Label>Enable feature</Label>
1947
+ </div>
1948
+ <p>Feature is {{ enabled ? 'enabled' : 'disabled' }}</p>
1949
+ </template>
1950
+
1951
+ <script setup>
1952
+ import { ref } from 'vue'
1953
+ import Switch from '@/components/Switch.vue'
1954
+ import Label from '@/components/Label.vue'
1955
+
1956
+ const enabled = ref(false)
1957
+ </script>
1958
+ ```
1959
+
1960
+ ## Progress
1961
+
1962
+ A progress bar component for showing completion status.
1963
+
1964
+ ### Props
1965
+
1966
+ | Prop | Type | Default | Description |
1967
+ |------|------|---------|-------------|
1968
+ | `value` | `Number` | `0` | Current progress value |
1969
+ | `max` | `Number` | `100` | Maximum value |
1970
+ | `size` | `String` | `'default'` | Size variant (sm, default, md, lg) |
1971
+ | `variant` | `String` | `'default'` | Color variant (default, success, warning, danger) |
1972
+
1973
+ ### Example
1974
+
1975
+ ```vue
1976
+ <template>
1977
+ <div class="space-y-4">
1978
+ <Progress :value="progress" />
1979
+ <Progress :value="75" variant="success" size="sm" />
1980
+ <Progress :value="50" variant="warning" />
1981
+ <Progress :value="25" variant="danger" size="lg" />
1982
+ </div>
1983
+ </template>
1984
+
1985
+ <script setup>
1986
+ import { ref } from 'vue'
1987
+ import Progress from '@/components/Progress.vue'
1988
+
1989
+ const progress = ref(60)
1990
+ </script>
1991
+ ```
1992
+
1993
+ ## Spinner
1994
+
1995
+ A loading spinner component with various sizes and colors.
1996
+
1997
+ ### Props
1998
+
1999
+ | Prop | Type | Default | Description |
2000
+ |------|------|---------|-------------|
2001
+ | `size` | `String` | `'md'` | Size variant (xs, sm, md, lg, xl) |
2002
+ | `variant` | `String` | `'default'` | Color variant (default, primary, secondary) |
2003
+ | `label` | `String` | `'Loading...'` | Accessibility label |
2004
+
2005
+ ### Example
2006
+
2007
+ ```vue
2008
+ <template>
2009
+ <div class="space-y-4">
2010
+ <Spinner />
2011
+ <Spinner size="lg" variant="primary" />
2012
+ <Spinner size="sm" variant="secondary" label="Saving..." />
2013
+ </div>
2014
+ </template>
2015
+
2016
+ <script setup>
2017
+ import Spinner from '@/components/Spinner.vue'
2018
+ </script>
2019
+ ```
2020
+
2021
+ ## Icon
2022
+
2023
+ A FontAwesome icon component with size and color options.
2024
+
2025
+ ### Props
2026
+
2027
+ | Prop | Type | Default | Description |
2028
+ |------|------|---------|-------------|
2029
+ | `icon` | `String` | - | FontAwesome icon name |
2030
+ | `prefix` | `String` | `'fas'` | FontAwesome prefix (fas, far, fab, etc.) |
2031
+ | `size` | `String` | `'md'` | Size variant (xs, sm, md, lg, xl, xxl) |
2032
+ | `color` | `String` | - | Text color class |
2033
+ | `ariaLabel` | `String` | - | Accessibility label |
2034
+
2035
+ ### Example
2036
+
2037
+ ```vue
2038
+ <template>
2039
+ <div class="space-x-4">
2040
+ <Icon icon="user" />
2041
+ <Icon icon="heart" prefix="far" color="red-500" />
2042
+ <Icon icon="github" prefix="fab" size="lg" ariaLabel="GitHub" />
2043
+ </div>
2044
+ </template>
2045
+
2046
+ <script setup>
2047
+ import Icon from '@/components/Icon.vue'
2048
+ </script>
2049
+ ```
2050
+
2051
+ <!-- Additional components (DataTableCell, DataTableFilters, DataTableHeader, DataTablePagination, DataTableRow, DataTableToolBar, FileUpload, Footer, Header, InputGroup, Link, ListItem, Logo, MainNavigation, MenuItem, ModalBody, ModalFooter, ModalHeader, Notification, Option, ProgressBar, RiskModal, Search, Sidebar, Stepper, StepperItem, Loader, Tab, TabPanel, Text, Timeline, TimelineItem, Toast, Tooltip, Typography) follow the same pattern. For these components, refer to their source code for props, events, and slots. -->
2052
+
2053
+ ## Testing
2054
+
2055
+ This library includes comprehensive testing with both unit and integration tests to ensure reliability and maintainability.
2056
+
2057
+ ### Test Structure
2058
+
2059
+ ```
2060
+ src/__tests__/
2061
+ ├── *.spec.js # Unit tests for individual components
2062
+ └── integration/ # Integration tests for component combinations
2063
+ ├── FormIntegration.spec.js
2064
+ ├── ModalIntegration.spec.js
2065
+ ├── CardIntegration.spec.js
2066
+ └── NavigationIntegration.spec.js
2067
+ ```
2068
+
2069
+ ### Testing Types
2070
+
2071
+ #### Unit Tests
2072
+ - Individual component functionality
2073
+ - Props, events, and styling validation
2074
+ - Accessibility testing
2075
+ - Error handling
2076
+
2077
+ #### Integration Tests
2078
+ - **Form Integration**: Complete form workflows with Input, Button, Select, Checkbox
2079
+ - **Modal Integration**: Modal with form submission and alert interactions
2080
+ - **Card Integration**: Cards with headers, content, footers, and actions
2081
+ - **Navigation Integration**: Dropdown menus and breadcrumb navigation
2082
+
2083
+ ### CI/CD Pipeline
2084
+
2085
+ The project uses GitHub Actions for automated testing:
2086
+
2087
+ - **Triggers**: Push/PR to `main` and `develop` branches
2088
+ - **Node.js versions**: 18.x, 20.x, 22.x
2089
+ - **Checks**: Linting, unit tests, integration tests, build verification
2090
+ - **Coverage**: Uploaded to Codecov with 70% threshold requirements
2091
+ - **Release**: Automatic NPM publishing on main branch pushes
2092
+
2093
+ ### Coverage Requirements
2094
+
2095
+ - Branches: 70%
2096
+ - Functions: 70%
2097
+ - Lines: 70%
2098
+ - Statements: 70%
2099
+
2100
+ ### Running Tests Locally
2101
+
2102
+ ```bash
2103
+ # Run all tests
2104
+ npm run test:unit
2105
+
2106
+ # Run tests once (CI mode)
2107
+ npm run test:unit:run
2108
+
2109
+ # Run with coverage
2110
+ npm run test:coverage
2111
+
2112
+ # Run only integration tests
2113
+ npm run test:unit -- --testPathPattern=integration
2114
+
2115
+ # Run specific test file
2116
+ npm run test:unit -- Button.spec.js
2117
+ ```
2118
+
2119
+ ### Test Configuration
2120
+
2121
+ - **Framework**: Vitest with jsdom environment
2122
+ - **Coverage**: V8 provider with HTML, JSON, and text reporters
2123
+ - **Mocking**: FontAwesome icons and other external dependencies
2124
+ - **Assertions**: Built-in Vitest matchers
2125
+
2126
+ ### Writing Tests
2127
+
2128
+ When adding new components, follow these patterns:
2129
+
2130
+ 1. **Unit Tests**: Test component props, events, slots, and styling
2131
+ 2. **Integration Tests**: Test component combinations and workflows
2132
+ 3. **Accessibility**: Include ARIA attributes and keyboard navigation tests
2133
+ 4. **Edge Cases**: Test disabled states, loading states, and error conditions
2134
+
2135
+ Example test structure:
2136
+ ```javascript
2137
+ import { describe, it, expect } from 'vitest'
2138
+ import { mount } from '@vue/test-utils'
2139
+ import Component from '../components/Component.vue'
2140
+
2141
+ describe('Component', () => {
2142
+ it('renders with default props', () => {
2143
+ const wrapper = mount(Component)
2144
+ expect(wrapper.exists()).toBe(true)
2145
+ })
2146
+
2147
+ it('handles user interactions', async () => {
2148
+ const wrapper = mount(Component)
2149
+ await wrapper.find('button').trigger('click')
2150
+ expect(wrapper.emitted('click')).toHaveLength(1)
2151
+ })
2152
+ })
2153
+ ```