@velkymx/vibeui 0.8.2 → 1.0.2
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.
- package/AGENTS.md +44 -0
- package/README.md +245 -58
- package/dist/purify.es-1D-VntFD.mjs +679 -0
- package/dist/src/App.vue.d.ts +3 -0
- package/dist/src/components/HelloWorld.vue.d.ts +6 -0
- package/dist/src/components/VibeAccordion.vue.d.ts +89 -0
- package/dist/{components → src/components}/VibeAlert.vue.d.ts +24 -30
- package/dist/src/components/VibeAutocomplete.vue.d.ts +74 -0
- package/dist/{components → src/components}/VibeBadge.vue.d.ts +10 -18
- package/dist/src/components/VibeBreadcrumb.vue.d.ts +51 -0
- package/dist/{components → src/components}/VibeButton.vue.d.ts +16 -20
- package/dist/{components → src/components}/VibeButtonGroup.vue.d.ts +10 -18
- package/dist/{components → src/components}/VibeCard.vue.d.ts +51 -24
- package/dist/{components → src/components}/VibeCarousel.vue.d.ts +27 -49
- package/dist/src/components/VibeChartBar.vue.d.ts +61 -0
- package/dist/src/components/VibeChartLine.vue.d.ts +70 -0
- package/dist/src/components/VibeChartPie.vue.d.ts +34 -0
- package/dist/{components → src/components}/VibeCloseButton.vue.d.ts +9 -7
- package/dist/{components → src/components}/VibeCol.vue.d.ts +9 -17
- package/dist/src/components/VibeCollapse.vue.d.ts +76 -0
- package/dist/src/components/VibeContainer.vue.d.ts +36 -0
- package/dist/src/components/VibeDataTable.vue.d.ts +131 -0
- package/dist/src/components/VibeDatePicker.vue.d.ts +120 -0
- package/dist/src/components/VibeDraggable.vue.d.ts +77 -0
- package/dist/{components → src/components}/VibeDropdown.vue.d.ts +46 -43
- package/dist/src/components/VibeDroppable.vue.d.ts +70 -0
- package/dist/src/components/VibeFileInput.vue.d.ts +127 -0
- package/dist/{components → src/components}/VibeFormCheckbox.vue.d.ts +30 -22
- package/dist/{components → src/components}/VibeFormDatepicker.vue.d.ts +27 -30
- package/dist/{components → src/components}/VibeFormGroup.vue.d.ts +11 -14
- package/dist/{components → src/components}/VibeFormInput.vue.d.ts +22 -23
- package/dist/{components → src/components}/VibeFormRadio.vue.d.ts +23 -24
- package/dist/{components → src/components}/VibeFormSelect.vue.d.ts +28 -34
- package/dist/{components → src/components}/VibeFormSpinbutton.vue.d.ts +31 -34
- package/dist/{components → src/components}/VibeFormSwitch.vue.d.ts +22 -23
- package/dist/{components → src/components}/VibeFormTextarea.vue.d.ts +24 -25
- package/dist/{components → src/components}/VibeFormWysiwyg.vue.d.ts +24 -23
- package/dist/src/components/VibeHero.vue.d.ts +108 -0
- package/dist/{components → src/components}/VibeIcon.vue.d.ts +27 -7
- package/dist/{components → src/components}/VibeInputGroup.vue.d.ts +11 -13
- package/dist/{components → src/components}/VibeLink.vue.d.ts +14 -18
- package/dist/{components → src/components}/VibeListGroup.vue.d.ts +26 -22
- package/dist/{components → src/components}/VibeModal.vue.d.ts +29 -45
- package/dist/{components → src/components}/VibeNav.vue.d.ts +40 -20
- package/dist/{components → src/components}/VibeNavbar.vue.d.ts +12 -19
- package/dist/src/components/VibeNavbarBrand.vue.d.ts +34 -0
- package/dist/src/components/VibeNavbarNav.vue.d.ts +80 -0
- package/dist/{components → src/components}/VibeNavbarToggle.vue.d.ts +7 -5
- package/dist/{components → src/components}/VibeOffcanvas.vue.d.ts +28 -43
- package/dist/{components → src/components}/VibePagination.vue.d.ts +38 -29
- package/dist/{components → src/components}/VibePlaceholder.vue.d.ts +9 -17
- package/dist/src/components/VibePopover.vue.d.ts +72 -0
- package/dist/src/components/VibeProgress.vue.d.ts +37 -0
- package/dist/src/components/VibeResizable.vue.d.ts +140 -0
- package/dist/{components → src/components}/VibeRow.vue.d.ts +9 -17
- package/dist/src/components/VibeScrollspy.vue.d.ts +89 -0
- package/dist/src/components/VibeSkeleton.vue.d.ts +54 -0
- package/dist/src/components/VibeSlider.vue.d.ts +77 -0
- package/dist/src/components/VibeSortable.vue.d.ts +59 -0
- package/dist/{components → src/components}/VibeSpinner.vue.d.ts +4 -7
- package/dist/src/components/VibeStepper.vue.d.ts +133 -0
- package/dist/src/components/VibeTab.vue.d.ts +41 -0
- package/dist/src/components/VibeTabContent.vue.d.ts +56 -0
- package/dist/src/components/VibeTabs.vue.d.ts +78 -0
- package/dist/{components → src/components}/VibeToast.vue.d.ts +40 -42
- package/dist/src/components/VibeToastHost.vue.d.ts +16 -0
- package/dist/src/components/VibeTooltip.vue.d.ts +63 -0
- package/dist/src/components/chart/chartColors.d.ts +3 -0
- package/dist/src/components/chart/chartResize.d.ts +2 -0
- package/dist/src/components/chart/chartTooltip.d.ts +2 -0
- package/dist/src/components/chart/chartTypes.d.ts +6 -0
- package/dist/src/components/chart/drawBar.d.ts +5 -0
- package/dist/src/components/chart/drawLine.d.ts +18 -0
- package/dist/src/components/chart/drawPie.d.ts +4 -0
- package/dist/src/components/dndStore.d.ts +7 -0
- package/dist/{components → src/components}/index.d.ts +18 -1
- package/dist/{composables → src/composables}/useBreakpoints.d.ts +1 -0
- package/dist/{composables → src/composables}/useColorMode.d.ts +1 -1
- package/dist/src/composables/useForm.d.ts +22 -0
- package/dist/src/composables/useId.d.ts +2 -0
- package/dist/src/composables/usePosition.d.ts +20 -0
- package/dist/src/composables/useToast.d.ts +52 -0
- package/dist/src/directives/vTooltip.d.ts +24 -0
- package/dist/{index.d.ts → src/index.d.ts} +6 -0
- package/dist/src/injectionKeys.d.ts +28 -0
- package/dist/{types.d.ts → src/types.d.ts} +32 -6
- package/dist/src/utils/safeCss.d.ts +16 -0
- package/dist/src/utils/safeHref.d.ts +7 -0
- package/dist/src/utils/sanitizeHtml.d.ts +13 -0
- package/dist/vibeui.css +2 -1
- package/dist/vibeui.es.js +8351 -3508
- package/dist/vibeui.umd.js +3 -1
- package/docs/README.md +85 -13
- package/docs/components/advanced/popover.md +27 -52
- package/docs/components/advanced/scrollspy.md +57 -15
- package/docs/components/advanced/tooltip.md +26 -47
- package/docs/components/card/card.md +9 -1
- package/docs/components/charts/chart-bar.md +129 -0
- package/docs/components/charts/chart-line.md +136 -0
- package/docs/components/charts/chart-pie.md +102 -0
- package/docs/components/core/alert.md +27 -5
- package/docs/components/core/badge.md +0 -6
- package/docs/components/core/button-group.md +0 -6
- package/docs/components/core/button.md +1 -1
- package/docs/components/core/close-button.md +5 -5
- package/docs/components/core/link.md +60 -17
- package/docs/components/core/placeholder.md +0 -6
- package/docs/components/core/skeleton.md +40 -0
- package/docs/components/core/spinner.md +0 -6
- package/docs/components/data/datatable.md +29 -10
- package/docs/components/hero/hero.md +64 -0
- package/docs/components/interactive/accordion.md +29 -0
- package/docs/components/interactive/carousel.md +19 -4
- package/docs/components/interactive/collapse.md +3 -2
- package/docs/components/interactive/date-picker.md +78 -0
- package/docs/components/interactive/draggable.md +91 -0
- package/docs/components/interactive/dropdown.md +54 -18
- package/docs/components/interactive/modal.md +15 -20
- package/docs/components/interactive/offcanvas.md +4 -1
- package/docs/components/interactive/resizable.md +73 -0
- package/docs/components/interactive/slider.md +57 -0
- package/docs/components/interactive/sortable.md +52 -0
- package/docs/components/interactive/stepper.md +83 -0
- package/docs/components/interactive/tabs.md +66 -0
- package/docs/components/interactive/toast.md +93 -30
- package/docs/components/layout/col.md +0 -6
- package/docs/components/layout/container.md +0 -6
- package/docs/components/layout/row.md +0 -6
- package/docs/components/list/list-group.md +4 -0
- package/docs/components/navigation/breadcrumb.md +4 -0
- package/docs/components/navigation/nav.md +64 -1
- package/docs/components/navigation/navbar.md +2 -0
- package/docs/components/navigation/pagination.md +16 -0
- package/docs/components/progress/progress.md +7 -1
- package/docs/composables/color-mode.md +44 -6
- package/docs/composables/use-form.md +78 -0
- package/docs/composables/use-position.md +68 -0
- package/docs/composables/use-toast.md +91 -0
- package/docs/directives/v-tooltip.md +58 -0
- package/docs/forms/README.md +60 -61
- package/docs/forms/autocomplete.md +96 -0
- package/docs/forms/file-input.md +97 -0
- package/docs/forms/form-checkbox.md +75 -25
- package/docs/forms/form-datepicker.md +58 -28
- package/docs/forms/form-group.md +79 -44
- package/docs/forms/form-input.md +88 -31
- package/docs/forms/form-radio.md +60 -36
- package/docs/forms/form-select.md +75 -31
- package/docs/forms/form-spinbutton.md +72 -33
- package/docs/forms/form-switch.md +53 -25
- package/docs/forms/form-textarea.md +60 -29
- package/docs/forms/form-wysiwyg.md +73 -38
- package/docs/forms/input-group.md +53 -34
- package/docs/forms/validation.md +135 -521
- package/docs/getting-started/starter-template.md +136 -0
- package/docs/superpowers/plans/2026-05-12-vibe-charts.md +1999 -0
- package/docs/superpowers/plans/2026-05-29-e2e-browser-testing.md +615 -0
- package/docs/superpowers/specs/2026-05-12-charting-design.md +185 -0
- package/docs/superpowers/specs/2026-05-29-e2e-browser-testing-design.md +168 -0
- package/docs/utilities/position.md +82 -0
- package/docs/versioning.md +57 -0
- package/examples/README.md +201 -0
- package/examples/album.html +262 -0
- package/examples/blog.html +166 -0
- package/examples/carousel.html +114 -0
- package/examples/checkout.html +275 -0
- package/examples/cover.html +89 -0
- package/examples/dashboard.html +156 -0
- package/examples/index.html +129 -0
- package/examples/jumbotron.html +56 -0
- package/examples/mobile-dashboard.html +138 -0
- package/examples/pricing.html +172 -0
- package/examples/product.html +145 -0
- package/examples/sidebars.html +166 -0
- package/examples/sign-in.html +119 -0
- package/examples/starter.html +314 -0
- package/examples/sticky-footer-navbar.html +70 -0
- package/examples/sticky-footer.html +60 -0
- package/examples/test-simple.html +91 -0
- package/llms.txt +407 -47
- package/package.json +42 -13
- package/dist/App.vue.d.ts +0 -2
- package/dist/components/HelloWorld.vue.d.ts +0 -5
- package/dist/components/VibeAccordion.vue.d.ts +0 -90
- package/dist/components/VibeBreadcrumb.vue.d.ts +0 -47
- package/dist/components/VibeCollapse.vue.d.ts +0 -84
- package/dist/components/VibeContainer.vue.d.ts +0 -44
- package/dist/components/VibeDataTable.vue.d.ts +0 -76
- package/dist/components/VibeNavbarBrand.vue.d.ts +0 -42
- package/dist/components/VibeNavbarNav.vue.d.ts +0 -61
- package/dist/components/VibePopover.vue.d.ts +0 -95
- package/dist/components/VibeProgress.vue.d.ts +0 -45
- package/dist/components/VibeScrollspy.vue.d.ts +0 -77
- package/dist/components/VibeTabContent.vue.d.ts +0 -74
- package/dist/components/VibeTooltip.vue.d.ts +0 -86
- package/dist/composables/useId.d.ts +0 -5
- package/dist/types/index.d.ts +0 -6
- /package/dist/{composables → src/composables}/useBackButton.d.ts +0 -0
- /package/dist/{composables → src/composables}/useFormValidation.d.ts +0 -0
- /package/dist/{main.d.ts → src/main.d.ts} +0 -0
|
@@ -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.
|