@velkymx/vibeui 0.9.0 → 1.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 (184) hide show
  1. package/AGENTS.md +44 -0
  2. package/CLAUDE.md +48 -0
  3. package/README.md +222 -197
  4. package/dist/App.vue.d.ts +2 -1
  5. package/dist/components/HelloWorld.vue.d.ts +2 -1
  6. package/dist/components/VibeAccordion.vue.d.ts +39 -40
  7. package/dist/components/VibeAlert.vue.d.ts +21 -37
  8. package/dist/components/VibeAutocomplete.vue.d.ts +59 -31
  9. package/dist/components/VibeBadge.vue.d.ts +10 -18
  10. package/dist/components/VibeBreadcrumb.vue.d.ts +25 -21
  11. package/dist/components/VibeButton.vue.d.ts +13 -17
  12. package/dist/components/VibeButtonGroup.vue.d.ts +11 -19
  13. package/dist/components/VibeCard.vue.d.ts +51 -24
  14. package/dist/components/VibeCarousel.vue.d.ts +27 -49
  15. package/dist/components/VibeChartBar.vue.d.ts +61 -0
  16. package/dist/components/VibeChartLine.vue.d.ts +70 -0
  17. package/dist/components/VibeChartPie.vue.d.ts +34 -0
  18. package/dist/components/VibeCloseButton.vue.d.ts +9 -7
  19. package/dist/components/VibeCol.vue.d.ts +9 -17
  20. package/dist/components/VibeCollapse.vue.d.ts +24 -32
  21. package/dist/components/VibeContainer.vue.d.ts +9 -17
  22. package/dist/components/VibeDataTable.vue.d.ts +122 -63
  23. package/dist/components/VibeDatePicker.vue.d.ts +4 -6
  24. package/dist/components/VibeDraggable.vue.d.ts +9 -13
  25. package/dist/components/VibeDropdown.vue.d.ts +46 -43
  26. package/dist/components/VibeDroppable.vue.d.ts +9 -13
  27. package/dist/components/VibeFileInput.vue.d.ts +14 -20
  28. package/dist/components/VibeFormCheckbox.vue.d.ts +30 -22
  29. package/dist/components/VibeFormDatepicker.vue.d.ts +27 -30
  30. package/dist/components/VibeFormErrorSummary.vue.d.ts +17 -0
  31. package/dist/components/VibeFormGroup.vue.d.ts +10 -13
  32. package/dist/components/VibeFormInput.vue.d.ts +60 -25
  33. package/dist/components/VibeFormRadio.vue.d.ts +23 -24
  34. package/dist/components/VibeFormSelect.vue.d.ts +28 -34
  35. package/dist/components/VibeFormSpinbutton.vue.d.ts +31 -34
  36. package/dist/components/VibeFormSwitch.vue.d.ts +22 -23
  37. package/dist/components/VibeFormTextarea.vue.d.ts +24 -25
  38. package/dist/components/VibeFormWysiwyg.vue.d.ts +23 -22
  39. package/dist/components/VibeHero.vue.d.ts +117 -0
  40. package/dist/components/VibeIcon.vue.d.ts +27 -7
  41. package/dist/components/VibeInputGroup.vue.d.ts +12 -14
  42. package/dist/components/VibeLink.vue.d.ts +14 -18
  43. package/dist/components/VibeListGroup.vue.d.ts +26 -22
  44. package/dist/components/VibeModal.vue.d.ts +47 -45
  45. package/dist/components/VibeNav.vue.d.ts +40 -20
  46. package/dist/components/VibeNavbar.vue.d.ts +12 -19
  47. package/dist/components/VibeNavbarBrand.vue.d.ts +9 -17
  48. package/dist/components/VibeNavbarNav.vue.d.ts +52 -33
  49. package/dist/components/VibeNavbarToggle.vue.d.ts +7 -5
  50. package/dist/components/VibeOffcanvas.vue.d.ts +28 -43
  51. package/dist/components/VibePagination.vue.d.ts +38 -29
  52. package/dist/components/VibePlaceholder.vue.d.ts +9 -17
  53. package/dist/components/VibePopover.vue.d.ts +17 -40
  54. package/dist/components/VibeProgress.vue.d.ts +13 -21
  55. package/dist/components/VibeResizable.vue.d.ts +10 -14
  56. package/dist/components/VibeRow.vue.d.ts +9 -17
  57. package/dist/components/VibeScrollspy.vue.d.ts +37 -25
  58. package/dist/components/VibeSkeleton.vue.d.ts +2 -1
  59. package/dist/components/VibeSlider.vue.d.ts +4 -5
  60. package/dist/components/VibeSortable.vue.d.ts +37 -18
  61. package/dist/components/VibeSpinner.vue.d.ts +4 -7
  62. package/dist/components/VibeStepper.vue.d.ts +32 -31
  63. package/dist/components/VibeTab.vue.d.ts +7 -11
  64. package/dist/components/VibeTabContent.vue.d.ts +13 -31
  65. package/dist/components/VibeTabs.vue.d.ts +9 -13
  66. package/dist/components/VibeToast.vue.d.ts +31 -44
  67. package/dist/components/VibeToastHost.vue.d.ts +2 -1
  68. package/dist/components/VibeTooltip.vue.d.ts +16 -39
  69. package/dist/components/chart/chartColors.d.ts +3 -0
  70. package/dist/components/chart/chartResize.d.ts +2 -0
  71. package/dist/components/chart/chartTooltip.d.ts +2 -0
  72. package/dist/components/chart/chartTypes.d.ts +6 -0
  73. package/dist/components/chart/drawBar.d.ts +5 -0
  74. package/dist/components/chart/drawLine.d.ts +18 -0
  75. package/dist/components/chart/drawPie.d.ts +4 -0
  76. package/dist/components/dndStore.d.ts +1 -0
  77. package/dist/components/index.d.ts +6 -1
  78. package/dist/composables/useBreakpoints.d.ts +1 -0
  79. package/dist/composables/useColorMode.d.ts +1 -1
  80. package/dist/composables/useId.d.ts +1 -4
  81. package/dist/directives/vTooltip.d.ts +2 -3
  82. package/dist/injectionKeys.d.ts +34 -0
  83. package/dist/purify.es-eYghtX9j.mjs +735 -0
  84. package/dist/types.d.ts +23 -2
  85. package/dist/utils/routeKey.d.ts +11 -0
  86. package/dist/utils/safeCss.d.ts +16 -0
  87. package/dist/utils/safeHref.d.ts +7 -0
  88. package/dist/utils/sanitizeHtml.d.ts +13 -0
  89. package/dist/vibeui.css +2 -1
  90. package/dist/vibeui.es.js +8527 -5855
  91. package/dist/vibeui.umd.js +3 -1
  92. package/docs/README.md +225 -0
  93. package/docs/components/advanced/popover.md +125 -0
  94. package/docs/components/advanced/scrollspy.md +106 -0
  95. package/docs/components/advanced/tooltip.md +90 -0
  96. package/docs/components/card/card.md +223 -0
  97. package/docs/components/charts/chart-bar.md +129 -0
  98. package/docs/components/charts/chart-line.md +136 -0
  99. package/docs/components/charts/chart-pie.md +102 -0
  100. package/docs/components/core/alert.md +94 -0
  101. package/docs/components/core/badge.md +75 -0
  102. package/docs/components/core/button-group.md +99 -0
  103. package/docs/components/core/button.md +145 -0
  104. package/docs/components/core/close-button.md +82 -0
  105. package/docs/components/core/link.md +79 -0
  106. package/docs/components/core/placeholder.md +129 -0
  107. package/docs/components/core/skeleton.md +40 -0
  108. package/docs/components/core/spinner.md +103 -0
  109. package/docs/components/data/datatable.md +437 -0
  110. package/docs/components/hero/hero.md +65 -0
  111. package/docs/components/interactive/accordion.md +121 -0
  112. package/docs/components/interactive/carousel.md +112 -0
  113. package/docs/components/interactive/collapse.md +106 -0
  114. package/docs/components/interactive/date-picker.md +78 -0
  115. package/docs/components/interactive/draggable.md +91 -0
  116. package/docs/components/interactive/dropdown.md +129 -0
  117. package/docs/components/interactive/modal.md +151 -0
  118. package/docs/components/interactive/offcanvas.md +92 -0
  119. package/docs/components/interactive/resizable.md +73 -0
  120. package/docs/components/interactive/slider.md +57 -0
  121. package/docs/components/interactive/sortable.md +52 -0
  122. package/docs/components/interactive/stepper.md +83 -0
  123. package/docs/components/interactive/tabs.md +66 -0
  124. package/docs/components/interactive/toast.md +177 -0
  125. package/docs/components/layout/col.md +117 -0
  126. package/docs/components/layout/container.md +53 -0
  127. package/docs/components/layout/row.md +107 -0
  128. package/docs/components/list/list-group.md +225 -0
  129. package/docs/components/navigation/breadcrumb.md +120 -0
  130. package/docs/components/navigation/nav.md +151 -0
  131. package/docs/components/navigation/navbar.md +114 -0
  132. package/docs/components/navigation/pagination.md +163 -0
  133. package/docs/components/progress/progress.md +188 -0
  134. package/docs/composables/back-button.md +28 -0
  135. package/docs/composables/breakpoints.md +54 -0
  136. package/docs/composables/color-mode.md +179 -0
  137. package/docs/composables/use-form.md +78 -0
  138. package/docs/composables/use-position.md +68 -0
  139. package/docs/composables/use-toast.md +91 -0
  140. package/docs/directives/v-tooltip.md +58 -0
  141. package/docs/forms/README.md +87 -0
  142. package/docs/forms/autocomplete.md +96 -0
  143. package/docs/forms/file-input.md +97 -0
  144. package/docs/forms/form-checkbox.md +100 -0
  145. package/docs/forms/form-datepicker.md +80 -0
  146. package/docs/forms/form-error-summary.md +96 -0
  147. package/docs/forms/form-group.md +118 -0
  148. package/docs/forms/form-input.md +140 -0
  149. package/docs/forms/form-radio.md +82 -0
  150. package/docs/forms/form-select.md +98 -0
  151. package/docs/forms/form-spinbutton.md +94 -0
  152. package/docs/forms/form-switch.md +75 -0
  153. package/docs/forms/form-textarea.md +82 -0
  154. package/docs/forms/form-wysiwyg.md +99 -0
  155. package/docs/forms/input-group.md +70 -0
  156. package/docs/forms/validation.md +213 -0
  157. package/docs/getting-started/starter-template.md +136 -0
  158. package/docs/superpowers/plans/2026-05-12-vibe-charts.md +1999 -0
  159. package/docs/superpowers/plans/2026-05-29-e2e-browser-testing.md +615 -0
  160. package/docs/superpowers/specs/2026-05-12-charting-design.md +185 -0
  161. package/docs/superpowers/specs/2026-05-29-e2e-browser-testing-design.md +168 -0
  162. package/docs/utilities/position.md +82 -0
  163. package/docs/versioning.md +57 -0
  164. package/examples/README.md +201 -0
  165. package/examples/album.html +262 -0
  166. package/examples/blog.html +166 -0
  167. package/examples/carousel.html +114 -0
  168. package/examples/checkout.html +275 -0
  169. package/examples/cover.html +89 -0
  170. package/examples/dashboard.html +156 -0
  171. package/examples/index.html +129 -0
  172. package/examples/jumbotron.html +56 -0
  173. package/examples/mobile-dashboard.html +138 -0
  174. package/examples/pricing.html +172 -0
  175. package/examples/product.html +145 -0
  176. package/examples/sidebars.html +166 -0
  177. package/examples/sign-in.html +119 -0
  178. package/examples/starter.html +314 -0
  179. package/examples/sticky-footer-navbar.html +70 -0
  180. package/examples/sticky-footer.html +60 -0
  181. package/examples/test-simple.html +91 -0
  182. package/llms.txt +801 -0
  183. package/package.json +44 -14
  184. package/dist/types/index.d.ts +0 -6
@@ -0,0 +1,185 @@
1
+ # VibeChart Components — Design Spec
2
+ **Date:** 2026-05-12
3
+ **Status:** Approved
4
+
5
+ ## Overview
6
+
7
+ Three canvas-based chart components for VibeUI: `VibeChartLine`, `VibeChartBar`, `VibeChartPie`. ES2022+, no external dependencies, Bootstrap CSS var color integration, `ResizeObserver`-driven responsiveness.
8
+
9
+ ## Architecture
10
+
11
+ ### File Structure
12
+
13
+ ```
14
+ src/components/
15
+ VibeChartLine.vue
16
+ VibeChartBar.vue
17
+ VibeChartPie.vue
18
+
19
+ src/components/chart/ ← internal only, not exported
20
+ chartColors.ts ← Bootstrap var resolver + cycler
21
+ chartTooltip.ts ← canvas tooltip hit-test + render
22
+ chartResize.ts ← ResizeObserver setup/teardown
23
+ chartTypes.ts ← shared internal types
24
+ ```
25
+
26
+ Three public components consume `chart/` internals directly. Nothing in `chart/` appears in `src/index.ts`. Each component owns its own `draw()` canvas function.
27
+
28
+ ### Approach
29
+
30
+ - Approach B: three separate components with shared internal utilities
31
+ - No exported composable — `chart/` is private infrastructure
32
+ - No fallbacks, no defensive wrapping — trust the data
33
+ - No animation, snap render only
34
+
35
+ ## Data Shape
36
+
37
+ ```ts
38
+ // src/types.ts additions
39
+ export interface ChartDataset {
40
+ label: string
41
+ data: number[]
42
+ color?: string // overrides auto color for this series
43
+ }
44
+
45
+ export interface ChartData {
46
+ labels: string[]
47
+ datasets: ChartDataset[]
48
+ }
49
+
50
+ export type ChartLegendPosition = 'top' | 'bottom' | 'none'
51
+ ```
52
+
53
+ ## Props API
54
+
55
+ ### All three components
56
+
57
+ | Prop | Type | Default |
58
+ |------|------|---------|
59
+ | `data` | `ChartData` | required |
60
+ | `legend` | `ChartLegendPosition` | `'bottom'` |
61
+ | `height` | `number \| string` | `'auto'` (16:9 ratio) |
62
+
63
+ ### VibeChartLine + VibeChartBar only
64
+
65
+ | Prop | Type | Default |
66
+ |------|------|---------|
67
+ | `show-axes` | `boolean` | `true` |
68
+ | `show-grid` | `boolean` | `true` |
69
+
70
+ ### VibeChartLine only
71
+
72
+ | Prop | Type | Default |
73
+ |------|------|---------|
74
+ | `smooth` | `boolean` | `false` |
75
+ | `fill` | `boolean` | `false` |
76
+
77
+ ### VibeChartBar only
78
+
79
+ | Prop | Type | Default |
80
+ |------|------|---------|
81
+ | `stacked` | `boolean` | `false` |
82
+
83
+ ## Canvas Rendering
84
+
85
+ ### Resize
86
+
87
+ ```ts
88
+ // chartResize.ts
89
+ export function useChartResize(
90
+ container: Ref<HTMLElement | null>,
91
+ canvas: Ref<HTMLCanvasElement | null>,
92
+ onResize: (w: number, h: number) => void
93
+ ): void
94
+ ```
95
+
96
+ - `ResizeObserver` on container div
97
+ - Canvas pixel dims: `canvas.width = dpr * w`, `ctx.scale(dpr, dpr)` for HiDPI
98
+ - Container: `width: 100%`, height auto = `w * (9/16)` or `height` prop
99
+ - Set up in `onMounted`, torn down in `onUnmounted`
100
+
101
+ ### Draw cycle
102
+
103
+ - `draw(ctx, data, w, h, props)` — pure function per component
104
+ - `watch(() => props.data, redraw, { deep: true })` triggers on data change
105
+ - Every resize calls `redraw()`
106
+ - ES2022+: `Array.at()`, `Object.hasOwn()`, etc.
107
+
108
+ ## Color System
109
+
110
+ ```ts
111
+ // chartColors.ts
112
+ const BS_VARS = [
113
+ '--bs-primary', '--bs-success', '--bs-danger',
114
+ '--bs-warning', '--bs-info', '--bs-secondary',
115
+ '--bs-dark', '--bs-light'
116
+ ]
117
+
118
+ export function resolveColors(
119
+ datasets: ChartDataset[],
120
+ el: HTMLElement
121
+ ): string[]
122
+ ```
123
+
124
+ - Per-dataset `color` prop wins
125
+ - Otherwise cycles `--bs-*` vars via `getComputedStyle(el)` at draw time
126
+ - Dark mode automatic — reads current computed value each redraw
127
+ - Cycles with `i % BS_VARS.length` for unlimited datasets
128
+
129
+ ## Tooltip
130
+
131
+ ```ts
132
+ // chartTooltip.ts
133
+ export interface TooltipHit {
134
+ datasetIndex: number
135
+ pointIndex: number
136
+ value: number
137
+ label: string
138
+ }
139
+
140
+ export function bindTooltip(
141
+ canvas: HTMLCanvasElement,
142
+ hitTest: (x: number, y: number) => TooltipHit | null,
143
+ redraw: () => void
144
+ ): () => void // returns cleanup fn
145
+ ```
146
+
147
+ - `mousemove` listener on canvas
148
+ - Each component provides its own `hitTest(x, y)` fn
149
+ - On hit: redraws base chart then draws rounded-rect overlay at cursor
150
+ - `mouseleave`: clears tooltip (redraw base only)
151
+ - Single canvas — no overlay element
152
+
153
+ ## Legend
154
+
155
+ HTML, not canvas. Order in DOM determines visual position.
156
+
157
+ ```html
158
+ <div v-if="legend !== 'none'" :class="['vibe-chart-legend', `vibe-chart-legend--${legend}`]">
159
+ <span v-for="(ds, i) in data.datasets" :key="i" class="vibe-chart-legend-item">
160
+ <span class="vibe-chart-legend-swatch" :style="{ background: resolvedColors[i] }"></span>
161
+ {{ ds.label }}
162
+ </span>
163
+ </div>
164
+ <canvas ref="canvasEl" />
165
+ ```
166
+
167
+ - `legend="top"`: div before canvas
168
+ - `legend="bottom"`: div after canvas
169
+ - `legend="none"`: v-if removes it
170
+
171
+ ## Exports
172
+
173
+ `src/types.ts`: add `ChartDataset`, `ChartData`, `ChartLegendPosition`
174
+
175
+ `src/index.ts`:
176
+ ```ts
177
+ export { default as VibeChartLine } from './components/VibeChartLine.vue'
178
+ export { default as VibeChartBar } from './components/VibeChartBar.vue'
179
+ export { default as VibeChartPie } from './components/VibeChartPie.vue'
180
+ export type { ChartData, ChartDataset, ChartLegendPosition } from './types'
181
+ ```
182
+
183
+ `src/components/index.ts`: register all three in plugin.
184
+
185
+ No new peer dependencies. Zero external imports in chart code.
@@ -0,0 +1,168 @@
1
+ # E2E Browser Testing — Design
2
+
3
+ **Date:** 2026-05-29
4
+ **Status:** Approved (design)
5
+ **Topic:** Real-browser test coverage for the Bootstrap-JS + Quill integration paths the happy-dom unit suite cannot reach.
6
+
7
+ ## Problem
8
+
9
+ The 925-test unit suite runs in happy-dom with Bootstrap JS mocked (`tests/mocks/bootstrap.ts`) and Quill unable to initialize. The integration layer that is hardest to get right — real Popper positioning, Bootstrap show/hide lifecycles and animations, and Quill editor behavior + DOMPurify sanitization — is therefore **unverified**. This is the top risk for a 1.0 commercial launch.
10
+
11
+ Goal: add a real-browser test layer that executes the actual Bootstrap JS and Quill code paths, covering every interactive component, without slowing the existing unit inner loop.
12
+
13
+ ## Decisions
14
+
15
+ | Decision | Choice | Rationale |
16
+ |---|---|---|
17
+ | Scope | All interactive paths: Overlays, Popper-positioned, Motion, Quill | "It all needs to work." |
18
+ | Test framework | Vitest 4 browser mode | Already installed; same API as the 925 unit tests; bundles with our real Vite 8 — no second bundler, no version mismatch, nothing experimental in the framework layer. |
19
+ | Browser driver | Playwright (provider) | Battle-tested headless Chromium driver. |
20
+ | Mount helper | `vitest-browser-vue` (`render` + `expect.element`) | Vitest-native Vue mounting in the browser. |
21
+ | Browsers | Chromium only | Integration bugs (Popper/Bootstrap/Quill) are engine-agnostic; keeps CI lean. Add WebKit later if needed. |
22
+ | CI | Separate required `e2e` job | Blocks merge on failure; parallel to unit job. |
23
+
24
+ Playwright Component Testing (`@playwright/experimental-ct-vue`) was rejected: it bundles with its own pinned Vite (≠ our Vite 8), and the framework layer is experimental. Vitest browser mode keeps our real Vite 8 pipeline and is stable in Vitest 4.
25
+
26
+ ## Architecture
27
+
28
+ Two Vitest projects share one Vite 8 pipeline (`extends: true` inherits root `plugins: [vue()]`):
29
+
30
+ - **`unit`** — happy-dom, `bootstrap → tests/mocks/bootstrap.ts` alias. Today's 925 tests, unchanged. The mock alias is scoped to this project only.
31
+ - **`browser`** — real headless Chromium via the Playwright provider. **No bootstrap alias**, so components' own `import('bootstrap')` resolves the real package and the real Bootstrap JS executes for the first time. Real Quill (`new Quill()`) runs against a real contenteditable.
32
+
33
+ ```ts
34
+ // vite.config.ts — test block
35
+ test: {
36
+ projects: [
37
+ {
38
+ extends: true,
39
+ test: {
40
+ name: 'unit',
41
+ environment: 'happy-dom',
42
+ include: ['tests/**/*.test.ts'],
43
+ exclude: ['tests/browser/**'],
44
+ alias: { bootstrap: path.resolve(__dirname, 'tests/mocks/bootstrap.ts') }
45
+ }
46
+ },
47
+ {
48
+ extends: true,
49
+ test: {
50
+ name: 'browser',
51
+ include: ['tests/browser/**/*.browser.test.ts'],
52
+ setupFiles: ['tests/browser/setup.ts'],
53
+ browser: {
54
+ enabled: true,
55
+ provider: 'playwright',
56
+ headless: true,
57
+ instances: [{ browser: 'chromium' }]
58
+ }
59
+ }
60
+ }
61
+ ]
62
+ }
63
+ ```
64
+
65
+ New dev dependencies: `@vitest/browser`, `playwright`, `vitest-browser-vue`.
66
+
67
+ Real dependency loading in the browser project:
68
+ - Bootstrap CSS + Quill CSS imported once in `tests/browser/setup.ts`.
69
+ - Bootstrap JS: never imported globally — pulled by components via their own dynamic `import('bootstrap')`, exercising the production path.
70
+ - Quill: real package, real editor instance.
71
+
72
+ ## File Layout
73
+
74
+ ```
75
+ tests/
76
+ browser/
77
+ setup.ts # imports bootstrap + quill CSS; per-test cleanup
78
+ helpers.ts # openModal(), waitForBsEvent(), getQuill()
79
+ overlays.browser.test.ts # Modal, Offcanvas, Toast
80
+ popper.browser.test.ts # Tooltip, Popover, Dropdown
81
+ motion.browser.test.ts # Collapse, Accordion, Carousel, Tabs, Scrollspy
82
+ wysiwyg.browser.test.ts # VibeFormWysiwyg / Quill
83
+ ```
84
+
85
+ Mount pattern:
86
+ ```ts
87
+ import { render } from 'vitest-browser-vue'
88
+ import { expect, test } from 'vitest'
89
+ import VibeModal from '../../src/components/VibeModal.vue'
90
+
91
+ test('opens, traps focus, returns focus on close', async () => {
92
+ const screen = render(VibeModal, { props: { modelValue: true, title: 'Hi' } })
93
+ await expect.element(screen.getByRole('dialog')).toBeVisible()
94
+ })
95
+ ```
96
+
97
+ ## Scripts (`package.json`)
98
+
99
+ ```jsonc
100
+ "test": "vitest --project unit", // fast inner loop, unchanged default
101
+ "test:run": "vitest run --project unit", // CI unit (name kept)
102
+ "test:browser": "vitest run --project browser",
103
+ "test:all": "vitest run" // both projects
104
+ ```
105
+
106
+ `test` / `test:run` stay pinned to `unit` so the inner loop never pays browser-launch cost.
107
+
108
+ ## Coverage Matrix
109
+
110
+ Only behavior happy-dom cannot reach (real Bootstrap JS / Popper / Quill). No re-testing prop/class logic the unit suite already covers.
111
+
112
+ **overlays — Modal / Offcanvas / Toast**
113
+ - Modal: `v-model=true` → `.modal.show` + `.modal-backdrop` present; ESC closes → `v-model=false`; focus returns to trigger on close; backdrop click closes; body scroll lock.
114
+ - Offcanvas: open/close lifecycle, backdrop, ESC, focus return.
115
+ - Toast: autohide timer fires → hidden; `v-model` sync.
116
+
117
+ **popper — Tooltip / Popover / Dropdown**
118
+ - Tooltip: hover → real Popper positions `.tooltip` with computed `transform`; leave → removed.
119
+ - Popover: click → `.popover` shown + positioned; outside-click dismiss.
120
+ - Dropdown: toggle → `.dropdown-menu.show` + Popper placement; ESC/outside close; keyboard arrow nav.
121
+
122
+ **motion — Collapse / Accordion / Carousel / Tabs / Scrollspy**
123
+ - Collapse: toggle → `.collapsing` transition → `.collapse.show`.
124
+ - Accordion: opening one closes siblings (real Bootstrap).
125
+ - Carousel: `next()` advances active item; indicators sync.
126
+ - Tabs: click tab → pane `.active` swap, `.fade` handled.
127
+ - Scrollspy: scroll container → active nav link tracks.
128
+
129
+ **wysiwyg — VibeFormWysiwyg (our glue only; Quill's own behavior is not our project to test)**
130
+ - Real `new Quill()` mounts the editor — proves our dynamic-import + init glue runs (path happy-dom cannot run).
131
+ - Set HTML containing `<script>` / `onerror` → our `sanitizeHtml.ts` (DOMPurify) strips it. This is our security layer, exercised end-to-end in a real browser for the only time.
132
+
133
+ Explicitly **not** tested (Quill's behavior, not ours): typing → v-model round-trip, toolbar formatting output, disabled/readonly editability.
134
+
135
+ ## CI Wiring
136
+
137
+ New `e2e` job in `.github/workflows/ci.yml`, parallel to the unit job, required for merge:
138
+
139
+ ```yaml
140
+ e2e:
141
+ runs-on: ubuntu-latest
142
+ steps:
143
+ - uses: actions/checkout@v5
144
+ - uses: actions/setup-node@v5
145
+ with:
146
+ node-version: 24
147
+ cache: npm
148
+ - run: npm ci
149
+ - run: npx playwright install --with-deps chromium
150
+ - run: npm run test:browser
151
+ ```
152
+
153
+ Existing unit job untouched (`npm run test:run` stays the `unit` project). Chromium-only install keeps the job lean.
154
+
155
+ ## Risks & Verification (resolved in a smoke phase before the full suite)
156
+
157
+ - **`vitest-browser-vue` API shape** — verify `render` + `expect.element` against the installed version with a smoke spec (mount `VibeButton`, assert visible) before writing the four real specs. If the mount API differs, adjust the helper, not the architecture.
158
+ - **Real Bootstrap JS resolution** — confirm the browser project resolves the real `bootstrap` (no mock-alias leak from root) by mounting `VibeModal` and asserting a real `.modal-backdrop` appears (the mock never creates one). Proves real Bootstrap JS executing.
159
+ - **Animation timing** — real CSS transitions are async. Use `expect.element(...).toBeVisible()` polling and Bootstrap `shown.bs.*` events via a `waitForBsEvent` helper; never fixed `setTimeout`.
160
+ - **Quill in CI** — real Quill needs real layout, which headless Chromium provides. This is the exact gap that motivated the work.
161
+
162
+ No fallback path: each uncertainty resolves to a concrete smoke-phase check before the full suite is authored.
163
+
164
+ ## Out of Scope
165
+
166
+ - Firefox / WebKit browsers (Chromium only for 1.0).
167
+ - Visual regression / screenshot diffing.
168
+ - Re-testing prop/class/validation logic already covered by the unit suite.
@@ -0,0 +1,82 @@
1
+ # Positioning Utilities
2
+
3
+ VibeUI exposes Bootstrap 5.3's position utility classes directly through a Bootstrap CSS import. These are static, declarative classes — pair them with `usePosition` (see `docs/composables/use-position.md`) when you need JS-driven anchoring.
4
+
5
+ ## position-{value}
6
+
7
+ | Class | Effect |
8
+ |------|--------|
9
+ | `.position-static` | Default flow positioning |
10
+ | `.position-relative` | Relative to its normal position |
11
+ | `.position-absolute` | Relative to nearest positioned ancestor |
12
+ | `.position-fixed` | Relative to the viewport |
13
+ | `.position-sticky` | Switches to fixed when scroll threshold passed |
14
+
15
+ ## top / start / bottom / end
16
+
17
+ For `.position-absolute`, `.position-fixed`, `.position-sticky`: place the element along a side of the containing box.
18
+
19
+ | Class | Position |
20
+ |------|----------|
21
+ | `.top-0` / `.top-50` / `.top-100` | 0%, 50%, 100% from top |
22
+ | `.start-0` / `.start-50` / `.start-100` | 0%, 50%, 100% from inline-start |
23
+ | `.bottom-0` / `.bottom-50` / `.bottom-100` | from bottom |
24
+ | `.end-0` / `.end-50` / `.end-100` | from inline-end |
25
+
26
+ ## translate-middle
27
+
28
+ Shifts the element by –50% on one or both axes — useful for centering relative to its anchor coordinate.
29
+
30
+ | Class | Effect |
31
+ |------|--------|
32
+ | `.translate-middle` | `translate(-50%, -50%)` |
33
+ | `.translate-middle-x` | `translate(-50%, 0)` |
34
+ | `.translate-middle-y` | `translate(0, -50%)` |
35
+
36
+ ## Common patterns
37
+
38
+ **Centering a card in its container:**
39
+
40
+ ```html
41
+ <div class="position-relative" style="height: 200px;">
42
+ <div class="position-absolute top-50 start-50 translate-middle">
43
+ Centered
44
+ </div>
45
+ </div>
46
+ ```
47
+
48
+ **Sticky page header:**
49
+
50
+ ```html
51
+ <header class="position-sticky top-0 bg-body z-3">
52
+ <!-- ... -->
53
+ </header>
54
+ ```
55
+
56
+ **Fixed FAB (floating action button):**
57
+
58
+ ```html
59
+ <VibeButton variant="primary" class="position-fixed bottom-0 end-0 m-3 rounded-circle">
60
+ +
61
+ </VibeButton>
62
+ ```
63
+
64
+ **Notification badge offset on an avatar:**
65
+
66
+ ```html
67
+ <div class="position-relative d-inline-block">
68
+ <img src="avatar.png" class="rounded-circle" />
69
+ <VibeBadge variant="danger" pill class="position-absolute top-0 start-100 translate-middle">
70
+ 3
71
+ </VibeBadge>
72
+ </div>
73
+ ```
74
+
75
+ ## When to reach for `usePosition` instead
76
+
77
+ - The anchor is dynamic (not a parent in the DOM).
78
+ - You need viewport collision handling (flip / shift).
79
+ - You need to reposition on scroll, resize, or anchor mutation.
80
+ - The placement is computed at runtime (e.g. picker calendars, autocomplete menus).
81
+
82
+ For those cases, see [`usePosition`](../composables/use-position.md).
@@ -0,0 +1,57 @@
1
+ # Versioning & Stability Policy
2
+
3
+ VibeUI follows [Semantic Versioning](https://semver.org/). This page defines what is covered by that promise so you can embed VibeUI in a long-lived project with confidence.
4
+
5
+ ## The promise
6
+
7
+ Within a major version (e.g. all of `1.x`), the **public API does not break**. You can upgrade minor and patch releases without code changes.
8
+
9
+ - **MAJOR** (`2.0.0`) — breaking changes to the public API.
10
+ - **MINOR** (`1.1.0`) — new components, props, events, or composables, backwards-compatible.
11
+ - **PATCH** (`1.0.1`) — bug fixes, internal changes, no API change.
12
+
13
+ ## What counts as public API
14
+
15
+ Covered by the SemVer promise:
16
+
17
+ - **Component names** and their registration (global plugin install + named exports).
18
+ - **Props** — names, types, and documented default behavior.
19
+ - **Events** (`emits`) — names and payload shapes.
20
+ - **Slots** — names and slot-prop shapes.
21
+ - **Composables** exported from the package entry (`useColorMode`, `useToast`, `useForm`, `useFormValidation`, `useBreakpoints`, `useId`, `usePosition`, `useBackButton`, etc.) — their call signatures and return shapes.
22
+ - **Directives** exported from the entry (e.g. `vTooltip`).
23
+ - **Published TypeScript types** for all of the above.
24
+
25
+ ## What is explicitly NOT covered
26
+
27
+ These may change in any release, including patches:
28
+
29
+ - **Escape hatches prefixed `_unsafe_`** (e.g. `_unsafe_bsInstance`). They expose the underlying Bootstrap/Quill instance and are not a stable interface — using them couples you to third-party internals at your own risk.
30
+ - **Internal modules** not exported from the package entry (anything under `src/utils`, `src/injectionKeys`, internal composables, etc.).
31
+ - **Generated DOM structure / CSS class composition** beyond what Bootstrap itself defines. We target Bootstrap 5.3 markup; we don't promise the exact wrapper nesting.
32
+ - **Console warnings** (dev-only deprecation/validation messages).
33
+
34
+ ## Deprecation policy
35
+
36
+ When a public API needs to change:
37
+
38
+ 1. The old form keeps working and emits a **dev-only deprecation warning** for at least one **minor** release.
39
+ 2. The replacement is documented alongside the deprecation.
40
+ 3. Removal happens only in the next **major**.
41
+
42
+ (Example already in the codebase: the tooltip/popover `content` prop is deprecated in favor of `text` and still functions.)
43
+
44
+ ## Peer dependency policy
45
+
46
+ VibeUI declares its framework requirements as peer dependencies:
47
+
48
+ - **`vue` (required, `^3.5`)** and **`bootstrap` (required, `^5.3`)** — supported ranges. Raising the **minimum** supported version of either is a **major** change.
49
+ - **`quill`, `dompurify`, `bootstrap-icons` (optional)** — needed only for `VibeFormWysiwyg` (quill + dompurify) and `VibeIcon` (bootstrap-icons). Absent unless you use those features.
50
+
51
+ A new major of an upstream peer (Bootstrap 6, Quill 3, Vue 4) is adopted in a **major** VibeUI release, never a minor.
52
+
53
+ ## Recommendations for long-lived projects
54
+
55
+ - **Pin a version** (`"@velkymx/vibeui": "1.4.2"`) or a tilde range (`~1.4.0`) rather than a wide caret, and upgrade deliberately.
56
+ - Read `CHANGELOG.md` before upgrading minors.
57
+ - The full test suite ships with the source — if you ever need to fork and patch, you inherit the regression safety net (unit + real-browser tests).
@@ -0,0 +1,201 @@
1
+ # VibeUI Examples
2
+
3
+ This directory contains standalone HTML examples demonstrating how to use VibeUI components, similar to [Bootstrap's examples](https://getbootstrap.com/docs/5.3/examples/).
4
+
5
+ ## 🚀 Quick Start
6
+
7
+ ### Option 1: Open Directly in Browser
8
+ Simply open any `.html` file in your browser:
9
+ 1. Build VibeUI first: `cd .. && npm run build`
10
+ 2. Open `examples/index.html` in your browser
11
+
12
+ ### Option 2: Use a Local Server
13
+ For the best experience (especially with routing), serve the files:
14
+
15
+ ```bash
16
+ # Using Python
17
+ python -m http.server 8000
18
+
19
+ # Using Node.js
20
+ npx serve .
21
+
22
+ # Using PHP
23
+ php -S localhost:8000
24
+ ```
25
+
26
+ Then open http://localhost:8000 in your browser.
27
+
28
+ ### Option 3: GitHub Pages
29
+ The examples work perfectly on GitHub Pages! Just push to a repository and enable GitHub Pages.
30
+
31
+ ## 📁 Examples
32
+
33
+ - **[index.html](index.html)** - Examples gallery homepage
34
+ - **[starter.html](starter.html)** - Starter template with common components
35
+ - **[album.html](album.html)** - Photo gallery with card grid
36
+ - **[pricing.html](pricing.html)** - Pricing tables with comparison
37
+ - **[dashboard.html](dashboard.html)** - Admin dashboard with sidebar
38
+
39
+ ## 🎯 How They Work
40
+
41
+ Each example is a **standalone HTML file** that uses:
42
+
43
+ 1. **Vue 3** from CDN (`vue.global.prod.js`)
44
+ 2. **Bootstrap 5.3** from CDN
45
+ 3. **Bootstrap Icons** from CDN
46
+ 4. **VibeUI** from the local `dist/vibeui.umd.js` build
47
+
48
+ ### Example Structure
49
+
50
+ ```html
51
+ <!DOCTYPE html>
52
+ <html>
53
+ <head>
54
+ <!-- Bootstrap CSS -->
55
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
56
+ <!-- Bootstrap Icons -->
57
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
58
+ <!-- VibeUI CSS -->
59
+ <link rel="stylesheet" href="../dist/vibeui.css">
60
+ </head>
61
+ <body>
62
+ <div id="app">
63
+ <!-- Use VibeUI components here -->
64
+ <vibe-button variant="primary">Click me!</vibe-button>
65
+ </div>
66
+
67
+ <!-- Vue 3 -->
68
+ <script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
69
+ <!-- Bootstrap JS -->
70
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
71
+ <!-- VibeUI -->
72
+ <script src="../dist/vibeui.umd.js"></script>
73
+ <script>
74
+ const { createApp } = Vue;
75
+ createApp({
76
+ data() {
77
+ return {
78
+ // Your data here
79
+ }
80
+ }
81
+ }).use(VibeUI.default).mount('#app');
82
+ </script>
83
+ </body>
84
+ </html>
85
+ ```
86
+
87
+ ## 🔧 Using with NPM Package
88
+
89
+ To use the published VibeUI package from npm instead of the local build:
90
+
91
+ 1. Install VibeUI: `npm install @velkymx/vibeui`
92
+ 2. Copy examples to your project
93
+ 3. Update the script src to point to your node_modules:
94
+ ```html
95
+ <script src="/node_modules/@velkymx/vibeui/dist/vibeui.umd.js"></script>
96
+ ```
97
+
98
+ Or use a CDN once VibeUI is published to npm:
99
+ ```html
100
+ <script src="https://cdn.jsdelivr.net/npm/@velkymx/vibeui"></script>
101
+ ```
102
+
103
+ ## 📦 Components Used
104
+
105
+ ### Starter Example
106
+ - `vibe-navbar`, `vibe-navbar-brand`, `vibe-navbar-toggle`
107
+ - `vibe-container`, `vibe-row`, `vibe-col`
108
+ - `vibe-button`, `vibe-badge`, `vibe-alert`
109
+ - `vibe-card`, `vibe-card-body`
110
+ - `vibe-dropdown`, `vibe-dropdown-item`
111
+ - `vibe-icon`
112
+
113
+ ### Album Example
114
+ - `vibe-navbar`
115
+ - `vibe-container`, `vibe-row`, `vibe-col`
116
+ - `vibe-card`, `vibe-card-body`
117
+ - `vibe-button`, `vibe-button-group`
118
+ - `vibe-icon`
119
+
120
+ ### Pricing Example
121
+ - `vibe-container`, `vibe-row`, `vibe-col`
122
+ - `vibe-card`, `vibe-card-header`, `vibe-card-body`
123
+ - `vibe-button`, `vibe-badge`
124
+ - `vibe-nav`
125
+ - `vibe-icon`
126
+
127
+ ### Dashboard Example
128
+ - `vibe-container`, `vibe-row`, `vibe-col`
129
+ - `vibe-card`, `vibe-card-body`
130
+ - `vibe-list-group`, `vibe-list-group-item`
131
+ - `vibe-button`, `vibe-button-group`, `vibe-badge`
132
+ - `vibe-icon`
133
+
134
+ ## 🎨 Customization
135
+
136
+ You can customize these examples by:
137
+
138
+ 1. **Modifying the data**: Change the `data()` function in the Vue app
139
+ 2. **Adding new components**: Use any VibeUI component from the library
140
+ 3. **Styling**: Add your own CSS or modify Bootstrap variables
141
+ 4. **Adding features**: Extend the Vue app with methods, computed properties, etc.
142
+
143
+ ## 📝 Example: Adding Your Own Data
144
+
145
+ ```html
146
+ <script>
147
+ const { createApp } = Vue;
148
+ createApp({
149
+ data() {
150
+ return {
151
+ // Your custom data
152
+ products: [
153
+ { id: 1, name: 'Product 1', price: 29.99 },
154
+ { id: 2, name: 'Product 2', price: 39.99 }
155
+ ]
156
+ }
157
+ },
158
+ methods: {
159
+ addToCart(product) {
160
+ console.log('Added to cart:', product);
161
+ }
162
+ }
163
+ }).use(VibeUI.default).mount('#app');
164
+ </script>
165
+ ```
166
+
167
+ ## 🌐 Deployment
168
+
169
+ These examples can be deployed anywhere:
170
+
171
+ - **GitHub Pages**: Push to repo, enable Pages
172
+ - **Netlify**: Drag & drop the folder
173
+ - **Vercel**: Deploy as static site
174
+ - **Any web server**: Upload the files
175
+
176
+ Just make sure VibeUI is built first (`npm run build` in the root directory).
177
+
178
+ ## 🛠️ Development Workflow
179
+
180
+ 1. Make changes to VibeUI source code
181
+ 2. Build VibeUI: `cd .. && npm run build`
182
+ 3. Refresh the example in your browser
183
+ 4. Changes will be reflected immediately
184
+
185
+ ## ❓ Troubleshooting
186
+
187
+ **Q: Examples don't load when opened directly**
188
+ A: Make sure you've built VibeUI first: `cd .. && npm run build`
189
+
190
+ **Q: Components aren't rendering**
191
+ A: Check the browser console for errors. Make sure all script tags are loading correctly.
192
+
193
+ **Q: Icons not showing**
194
+ A: Verify the Bootstrap Icons CSS is loading from the CDN.
195
+
196
+ **Q: Getting CORS errors**
197
+ A: Use a local server instead of opening files directly (see Quick Start above).
198
+
199
+ ## 📄 License
200
+
201
+ These examples are part of VibeUI and are licensed under the MIT License.