@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.
- package/AGENTS.md +44 -0
- package/CLAUDE.md +48 -0
- package/README.md +222 -197
- package/dist/App.vue.d.ts +2 -1
- package/dist/components/HelloWorld.vue.d.ts +2 -1
- package/dist/components/VibeAccordion.vue.d.ts +39 -40
- package/dist/components/VibeAlert.vue.d.ts +21 -37
- package/dist/components/VibeAutocomplete.vue.d.ts +59 -31
- package/dist/components/VibeBadge.vue.d.ts +10 -18
- package/dist/components/VibeBreadcrumb.vue.d.ts +25 -21
- package/dist/components/VibeButton.vue.d.ts +13 -17
- package/dist/components/VibeButtonGroup.vue.d.ts +11 -19
- package/dist/components/VibeCard.vue.d.ts +51 -24
- package/dist/components/VibeCarousel.vue.d.ts +27 -49
- package/dist/components/VibeChartBar.vue.d.ts +61 -0
- package/dist/components/VibeChartLine.vue.d.ts +70 -0
- package/dist/components/VibeChartPie.vue.d.ts +34 -0
- package/dist/components/VibeCloseButton.vue.d.ts +9 -7
- package/dist/components/VibeCol.vue.d.ts +9 -17
- package/dist/components/VibeCollapse.vue.d.ts +24 -32
- package/dist/components/VibeContainer.vue.d.ts +9 -17
- package/dist/components/VibeDataTable.vue.d.ts +122 -63
- package/dist/components/VibeDatePicker.vue.d.ts +4 -6
- package/dist/components/VibeDraggable.vue.d.ts +9 -13
- package/dist/components/VibeDropdown.vue.d.ts +46 -43
- package/dist/components/VibeDroppable.vue.d.ts +9 -13
- package/dist/components/VibeFileInput.vue.d.ts +14 -20
- package/dist/components/VibeFormCheckbox.vue.d.ts +30 -22
- package/dist/components/VibeFormDatepicker.vue.d.ts +27 -30
- package/dist/components/VibeFormErrorSummary.vue.d.ts +17 -0
- package/dist/components/VibeFormGroup.vue.d.ts +10 -13
- package/dist/components/VibeFormInput.vue.d.ts +60 -25
- package/dist/components/VibeFormRadio.vue.d.ts +23 -24
- package/dist/components/VibeFormSelect.vue.d.ts +28 -34
- package/dist/components/VibeFormSpinbutton.vue.d.ts +31 -34
- package/dist/components/VibeFormSwitch.vue.d.ts +22 -23
- package/dist/components/VibeFormTextarea.vue.d.ts +24 -25
- package/dist/components/VibeFormWysiwyg.vue.d.ts +23 -22
- package/dist/components/VibeHero.vue.d.ts +117 -0
- package/dist/components/VibeIcon.vue.d.ts +27 -7
- package/dist/components/VibeInputGroup.vue.d.ts +12 -14
- package/dist/components/VibeLink.vue.d.ts +14 -18
- package/dist/components/VibeListGroup.vue.d.ts +26 -22
- package/dist/components/VibeModal.vue.d.ts +47 -45
- package/dist/components/VibeNav.vue.d.ts +40 -20
- package/dist/components/VibeNavbar.vue.d.ts +12 -19
- package/dist/components/VibeNavbarBrand.vue.d.ts +9 -17
- package/dist/components/VibeNavbarNav.vue.d.ts +52 -33
- package/dist/components/VibeNavbarToggle.vue.d.ts +7 -5
- package/dist/components/VibeOffcanvas.vue.d.ts +28 -43
- package/dist/components/VibePagination.vue.d.ts +38 -29
- package/dist/components/VibePlaceholder.vue.d.ts +9 -17
- package/dist/components/VibePopover.vue.d.ts +17 -40
- package/dist/components/VibeProgress.vue.d.ts +13 -21
- package/dist/components/VibeResizable.vue.d.ts +10 -14
- package/dist/components/VibeRow.vue.d.ts +9 -17
- package/dist/components/VibeScrollspy.vue.d.ts +37 -25
- package/dist/components/VibeSkeleton.vue.d.ts +2 -1
- package/dist/components/VibeSlider.vue.d.ts +4 -5
- package/dist/components/VibeSortable.vue.d.ts +37 -18
- package/dist/components/VibeSpinner.vue.d.ts +4 -7
- package/dist/components/VibeStepper.vue.d.ts +32 -31
- package/dist/components/VibeTab.vue.d.ts +7 -11
- package/dist/components/VibeTabContent.vue.d.ts +13 -31
- package/dist/components/VibeTabs.vue.d.ts +9 -13
- package/dist/components/VibeToast.vue.d.ts +31 -44
- package/dist/components/VibeToastHost.vue.d.ts +2 -1
- package/dist/components/VibeTooltip.vue.d.ts +16 -39
- package/dist/components/chart/chartColors.d.ts +3 -0
- package/dist/components/chart/chartResize.d.ts +2 -0
- package/dist/components/chart/chartTooltip.d.ts +2 -0
- package/dist/components/chart/chartTypes.d.ts +6 -0
- package/dist/components/chart/drawBar.d.ts +5 -0
- package/dist/components/chart/drawLine.d.ts +18 -0
- package/dist/components/chart/drawPie.d.ts +4 -0
- package/dist/components/dndStore.d.ts +1 -0
- package/dist/components/index.d.ts +6 -1
- package/dist/composables/useBreakpoints.d.ts +1 -0
- package/dist/composables/useColorMode.d.ts +1 -1
- package/dist/composables/useId.d.ts +1 -4
- package/dist/directives/vTooltip.d.ts +2 -3
- package/dist/injectionKeys.d.ts +34 -0
- package/dist/purify.es-eYghtX9j.mjs +735 -0
- package/dist/types.d.ts +23 -2
- package/dist/utils/routeKey.d.ts +11 -0
- package/dist/utils/safeCss.d.ts +16 -0
- package/dist/utils/safeHref.d.ts +7 -0
- package/dist/utils/sanitizeHtml.d.ts +13 -0
- package/dist/vibeui.css +2 -1
- package/dist/vibeui.es.js +8527 -5855
- package/dist/vibeui.umd.js +3 -1
- package/docs/README.md +225 -0
- package/docs/components/advanced/popover.md +125 -0
- package/docs/components/advanced/scrollspy.md +106 -0
- package/docs/components/advanced/tooltip.md +90 -0
- package/docs/components/card/card.md +223 -0
- 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 +94 -0
- package/docs/components/core/badge.md +75 -0
- package/docs/components/core/button-group.md +99 -0
- package/docs/components/core/button.md +145 -0
- package/docs/components/core/close-button.md +82 -0
- package/docs/components/core/link.md +79 -0
- package/docs/components/core/placeholder.md +129 -0
- package/docs/components/core/skeleton.md +40 -0
- package/docs/components/core/spinner.md +103 -0
- package/docs/components/data/datatable.md +437 -0
- package/docs/components/hero/hero.md +65 -0
- package/docs/components/interactive/accordion.md +121 -0
- package/docs/components/interactive/carousel.md +112 -0
- package/docs/components/interactive/collapse.md +106 -0
- package/docs/components/interactive/date-picker.md +78 -0
- package/docs/components/interactive/draggable.md +91 -0
- package/docs/components/interactive/dropdown.md +129 -0
- package/docs/components/interactive/modal.md +151 -0
- package/docs/components/interactive/offcanvas.md +92 -0
- 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 +177 -0
- package/docs/components/layout/col.md +117 -0
- package/docs/components/layout/container.md +53 -0
- package/docs/components/layout/row.md +107 -0
- package/docs/components/list/list-group.md +225 -0
- package/docs/components/navigation/breadcrumb.md +120 -0
- package/docs/components/navigation/nav.md +151 -0
- package/docs/components/navigation/navbar.md +114 -0
- package/docs/components/navigation/pagination.md +163 -0
- package/docs/components/progress/progress.md +188 -0
- package/docs/composables/back-button.md +28 -0
- package/docs/composables/breakpoints.md +54 -0
- package/docs/composables/color-mode.md +179 -0
- 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 +87 -0
- package/docs/forms/autocomplete.md +96 -0
- package/docs/forms/file-input.md +97 -0
- package/docs/forms/form-checkbox.md +100 -0
- package/docs/forms/form-datepicker.md +80 -0
- package/docs/forms/form-error-summary.md +96 -0
- package/docs/forms/form-group.md +118 -0
- package/docs/forms/form-input.md +140 -0
- package/docs/forms/form-radio.md +82 -0
- package/docs/forms/form-select.md +98 -0
- package/docs/forms/form-spinbutton.md +94 -0
- package/docs/forms/form-switch.md +75 -0
- package/docs/forms/form-textarea.md +82 -0
- package/docs/forms/form-wysiwyg.md +99 -0
- package/docs/forms/input-group.md +70 -0
- package/docs/forms/validation.md +213 -0
- 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 +801 -0
- package/package.json +44 -14
- package/dist/types/index.d.ts +0 -6
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# VibeToast
|
|
2
|
+
|
|
3
|
+
Push notifications for lightweight alerts.
|
|
4
|
+
|
|
5
|
+
The recommended way to show toasts is the **`useToast()` service** with a single `<VibeToastHost />` mounted once near your app root. The `<VibeToast>` component is the lower-level primitive for when you need a toast bound directly to local component state.
|
|
6
|
+
|
|
7
|
+
## Toast Service (recommended)
|
|
8
|
+
|
|
9
|
+
Mount `<VibeToastHost />` once (typically in `App.vue`), then call `useToast()` anywhere to enqueue toasts. The host manages containers, positioning, and dismissal for you.
|
|
10
|
+
|
|
11
|
+
```vue
|
|
12
|
+
<!-- App.vue -->
|
|
13
|
+
<template>
|
|
14
|
+
<RouterView />
|
|
15
|
+
<VibeToastHost />
|
|
16
|
+
</template>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```vue
|
|
20
|
+
<!-- AnyComponent.vue -->
|
|
21
|
+
<template>
|
|
22
|
+
<VibeButton @click="save">Save</VibeButton>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup>
|
|
26
|
+
import { useToast } from '@velkymx/vibeui'
|
|
27
|
+
|
|
28
|
+
const toast = useToast()
|
|
29
|
+
|
|
30
|
+
function save() {
|
|
31
|
+
// ...persist...
|
|
32
|
+
toast.success('Saved successfully')
|
|
33
|
+
toast.error('Something went wrong', { title: 'Error' })
|
|
34
|
+
toast.info('Heads up', { delay: 8000 })
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### `useToast()` API
|
|
40
|
+
|
|
41
|
+
| Method | Signature | Description |
|
|
42
|
+
|--------|-----------|-------------|
|
|
43
|
+
| `show` | `(body, options?) => ToastSpec` | Enqueue a toast with explicit options |
|
|
44
|
+
| `success` | `(body, options?) => ToastSpec` | Shorthand for `variant: 'success'` |
|
|
45
|
+
| `error` | `(body, options?) => ToastSpec` | Shorthand for `variant: 'danger'` |
|
|
46
|
+
| `warn` | `(body, options?) => ToastSpec` | Shorthand for `variant: 'warning'` |
|
|
47
|
+
| `info` | `(body, options?) => ToastSpec` | Shorthand for `variant: 'info'` |
|
|
48
|
+
| `dismiss` | `(id) => boolean` | Remove a toast by id; returns `true` if found |
|
|
49
|
+
| `clear` | `() => void` | Remove all queued toasts |
|
|
50
|
+
| `toasts` | `readonly ToastSpec[]` | Reactive readonly snapshot of the queue |
|
|
51
|
+
|
|
52
|
+
`ToastShowOptions`: `{ id?, title?, variant?, placement?, autohide?, delay? }`. Passing an existing `id` updates that toast in place instead of adding a new one. The variant shorthands (`success`, `error`, `warn`, `info`) accept the same options minus `variant`.
|
|
53
|
+
|
|
54
|
+
### `<VibeToastHost />` Props
|
|
55
|
+
|
|
56
|
+
| Prop | Type | Default | Description |
|
|
57
|
+
|------|------|---------|-------------|
|
|
58
|
+
| `defaultPlacement` | `ToastPlacement` | `'top-end'` | Placement used for toasts that don't specify one |
|
|
59
|
+
|
|
60
|
+
Toasts are grouped into one fixed container per placement, so toasts with different `placement` values render in the correct corner automatically.
|
|
61
|
+
|
|
62
|
+
## VibeToast Component (primitive)
|
|
63
|
+
|
|
64
|
+
Use the component directly when you want a toast tied to a local `v-model`.
|
|
65
|
+
|
|
66
|
+
### Props
|
|
67
|
+
|
|
68
|
+
| Prop | Type | Default | Description |
|
|
69
|
+
|------|------|---------|-------------|
|
|
70
|
+
| `id` | `String` | `Auto-generated` | Unique identifier |
|
|
71
|
+
| `modelValue` | `Boolean` | `false` | Control visibility (v-model) |
|
|
72
|
+
| `title` | `String` | `''` | Toast title |
|
|
73
|
+
| `variant` | `Variant` | `undefined` | Color variant |
|
|
74
|
+
| `autohide` | `Boolean` | `true` | Auto hide after delay |
|
|
75
|
+
| `delay` | `Number` | `5000` | Delay in milliseconds |
|
|
76
|
+
| `teleport` | `Boolean\|String` | `'body'` | Destination for Vue Teleport |
|
|
77
|
+
| `placement` | `ToastPlacement` | `'top-end'` | Position of the toast |
|
|
78
|
+
| `noContainer` | `Boolean` | `false` | Render only the `.toast` element (no Teleport/container). Used internally by `VibeToastHost` to group toasts |
|
|
79
|
+
|
|
80
|
+
### Events
|
|
81
|
+
|
|
82
|
+
| Event | Payload | Description |
|
|
83
|
+
|-------|---------|-------------|
|
|
84
|
+
| `update:modelValue` | `Boolean` | Emitted when visibility changes |
|
|
85
|
+
| `show` | - | Emitted when toast starts showing |
|
|
86
|
+
| `shown` | - | Emitted when toast is fully shown |
|
|
87
|
+
| `hide` | - | Emitted when toast starts hiding |
|
|
88
|
+
| `hidden` | - | Emitted when toast is fully hidden |
|
|
89
|
+
| `component-error` | `ComponentError` | Emitted if Bootstrap JS fails to load |
|
|
90
|
+
|
|
91
|
+
### Slots
|
|
92
|
+
|
|
93
|
+
| Slot | Description |
|
|
94
|
+
|------|-------------|
|
|
95
|
+
| `default` | Toast body content |
|
|
96
|
+
| `header` | Custom header content |
|
|
97
|
+
|
|
98
|
+
### Usage
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<template>
|
|
102
|
+
<div>
|
|
103
|
+
<VibeButton @click="showToast = true">Show Toast</VibeButton>
|
|
104
|
+
|
|
105
|
+
<VibeToast v-model="showToast" title="Notification" variant="primary">
|
|
106
|
+
This toast is controlled via Vue state.
|
|
107
|
+
</VibeToast>
|
|
108
|
+
</div>
|
|
109
|
+
</template>
|
|
110
|
+
|
|
111
|
+
<script setup>
|
|
112
|
+
import { ref } from 'vue'
|
|
113
|
+
const showToast = ref(false)
|
|
114
|
+
</script>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Placed Toasts
|
|
118
|
+
|
|
119
|
+
```vue
|
|
120
|
+
<template>
|
|
121
|
+
<div>
|
|
122
|
+
<VibeToast
|
|
123
|
+
v-model="showSuccess"
|
|
124
|
+
title="Success"
|
|
125
|
+
variant="success"
|
|
126
|
+
placement="bottom-end"
|
|
127
|
+
>
|
|
128
|
+
Operation completed successfully!
|
|
129
|
+
</VibeToast>
|
|
130
|
+
|
|
131
|
+
<VibeToast v-model="showInfo" title="Center" variant="info" placement="middle-center">
|
|
132
|
+
I am in the middle of the screen
|
|
133
|
+
</VibeToast>
|
|
134
|
+
</div>
|
|
135
|
+
</template>
|
|
136
|
+
|
|
137
|
+
<script setup>
|
|
138
|
+
import { ref } from 'vue'
|
|
139
|
+
const showSuccess = ref(false)
|
|
140
|
+
const showInfo = ref(false)
|
|
141
|
+
</script>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### Custom Delay
|
|
145
|
+
|
|
146
|
+
```vue
|
|
147
|
+
<template>
|
|
148
|
+
<VibeToast v-model="show" title="Quick Toast" :delay="2000">
|
|
149
|
+
This will auto-hide after 2 seconds
|
|
150
|
+
</VibeToast>
|
|
151
|
+
</template>
|
|
152
|
+
|
|
153
|
+
<script setup>
|
|
154
|
+
import { ref } from 'vue'
|
|
155
|
+
const show = ref(true)
|
|
156
|
+
</script>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Important Notes
|
|
160
|
+
|
|
161
|
+
**Prefer the service:** Use `useToast()` + `<VibeToastHost />` for most cases. It dedupes/updates by `id`, queues multiple toasts, and handles container placement. Reach for `<VibeToast>` only when you need a toast bound to a single local boolean.
|
|
162
|
+
|
|
163
|
+
**Automatic Container:** Unlike raw Bootstrap, `<VibeToast>` automatically manages its own `toast-container` and positioning based on the `placement` prop (unless `noContainer` is set).
|
|
164
|
+
|
|
165
|
+
**Teleportation:** By default, the component teleports to the `<body>` so it is always visible on top of other elements.
|
|
166
|
+
|
|
167
|
+
**SSR:** The toast queue is a module singleton. In SSR runtimes call `resetToastStoreForSSR()` in your per-request reset hook to avoid leaking one request's pending toasts into another's render.
|
|
168
|
+
|
|
169
|
+
**Escape Hatch:** `<VibeToast>` exposes `_unsafe_bsInstance` (raw Bootstrap Toast instance) via template ref. It is **not** part of the stable API — calling `dispose()` or other lifecycle methods on it directly **will** break the component. Prefer `v-model` and the exposed `show()` / `hide()` methods.
|
|
170
|
+
|
|
171
|
+
## Bootstrap CSS Classes
|
|
172
|
+
|
|
173
|
+
- `.toast`
|
|
174
|
+
- `.toast-header`
|
|
175
|
+
- `.toast-body`
|
|
176
|
+
- `.text-bg-{variant}`
|
|
177
|
+
- `.toast-container`
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# VibeCol
|
|
2
|
+
|
|
3
|
+
Column component for Bootstrap's grid system. Supports responsive sizing, offsets, ordering, and alignment.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Default | Description |
|
|
8
|
+
|------|------|---------|-------------|
|
|
9
|
+
| `tag` | `Tag` | `'div'` | HTML element to render |
|
|
10
|
+
| `cols` | `ColSize \| Boolean` | `undefined` | Base column width (`1`-`12`, `'auto'`, or `true` for equal-width) |
|
|
11
|
+
| `sm` | `ColSize \| Boolean` | `undefined` | Column width at `sm` breakpoint |
|
|
12
|
+
| `md` | `ColSize \| Boolean` | `undefined` | Column width at `md` breakpoint |
|
|
13
|
+
| `lg` | `ColSize \| Boolean` | `undefined` | Column width at `lg` breakpoint |
|
|
14
|
+
| `xl` | `ColSize \| Boolean` | `undefined` | Column width at `xl` breakpoint |
|
|
15
|
+
| `xxl` | `ColSize \| Boolean` | `undefined` | Column width at `xxl` breakpoint |
|
|
16
|
+
| `offset` | `Number` | `undefined` | Base offset (`0`-`11`) |
|
|
17
|
+
| `offsetSm` | `Number` | `undefined` | Offset at `sm` breakpoint |
|
|
18
|
+
| `offsetMd` | `Number` | `undefined` | Offset at `md` breakpoint |
|
|
19
|
+
| `offsetLg` | `Number` | `undefined` | Offset at `lg` breakpoint |
|
|
20
|
+
| `offsetXl` | `Number` | `undefined` | Offset at `xl` breakpoint |
|
|
21
|
+
| `offsetXxl` | `Number` | `undefined` | Offset at `xxl` breakpoint |
|
|
22
|
+
| `order` | `OrderValue` | `undefined` | Base visual order |
|
|
23
|
+
| `orderSm` | `OrderValue` | `undefined` | Order at `sm` breakpoint |
|
|
24
|
+
| `orderMd` | `OrderValue` | `undefined` | Order at `md` breakpoint |
|
|
25
|
+
| `orderLg` | `OrderValue` | `undefined` | Order at `lg` breakpoint |
|
|
26
|
+
| `orderXl` | `OrderValue` | `undefined` | Order at `xl` breakpoint |
|
|
27
|
+
| `orderXxl` | `OrderValue` | `undefined` | Order at `xxl` breakpoint |
|
|
28
|
+
| `alignSelf` | `AlignItems` | `undefined` | Individual column vertical alignment |
|
|
29
|
+
|
|
30
|
+
### Type Reference
|
|
31
|
+
|
|
32
|
+
- **ColSize:** `1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'auto'`
|
|
33
|
+
- **OrderValue:** `0 | 1 | 2 | 3 | 4 | 5 | 'first' | 'last'`
|
|
34
|
+
- **AlignItems:** `'start' | 'center' | 'end' | 'baseline' | 'stretch'`
|
|
35
|
+
|
|
36
|
+
## Slots
|
|
37
|
+
|
|
38
|
+
| Slot | Description |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| `default` | Column content |
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Equal-width Columns
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
<template>
|
|
48
|
+
<VibeRow>
|
|
49
|
+
<!-- No sizing props = equal-width (col class) -->
|
|
50
|
+
<VibeCol>1 of 3</VibeCol>
|
|
51
|
+
<VibeCol>2 of 3</VibeCol>
|
|
52
|
+
<VibeCol>3 of 3</VibeCol>
|
|
53
|
+
</VibeRow>
|
|
54
|
+
</template>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Specific Widths
|
|
58
|
+
|
|
59
|
+
```vue
|
|
60
|
+
<template>
|
|
61
|
+
<VibeRow>
|
|
62
|
+
<VibeCol :cols="8">Main content</VibeCol>
|
|
63
|
+
<VibeCol :cols="4">Sidebar</VibeCol>
|
|
64
|
+
</VibeRow>
|
|
65
|
+
</template>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Responsive Columns
|
|
69
|
+
|
|
70
|
+
```vue
|
|
71
|
+
<template>
|
|
72
|
+
<VibeRow>
|
|
73
|
+
<!-- Full width on mobile, half on medium, third on large -->
|
|
74
|
+
<VibeCol :cols="12" :md="6" :lg="4">Responsive</VibeCol>
|
|
75
|
+
<VibeCol :cols="12" :md="6" :lg="4">Responsive</VibeCol>
|
|
76
|
+
<VibeCol :cols="12" :md="12" :lg="4">Responsive</VibeCol>
|
|
77
|
+
</VibeRow>
|
|
78
|
+
</template>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Auto-width Column
|
|
82
|
+
|
|
83
|
+
```vue
|
|
84
|
+
<template>
|
|
85
|
+
<VibeRow>
|
|
86
|
+
<VibeCol :cols="2">Fixed</VibeCol>
|
|
87
|
+
<VibeCol cols="auto">Sized to content</VibeCol>
|
|
88
|
+
<VibeCol :cols="2">Fixed</VibeCol>
|
|
89
|
+
</VibeRow>
|
|
90
|
+
</template>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Offsets and Ordering
|
|
94
|
+
|
|
95
|
+
```vue
|
|
96
|
+
<template>
|
|
97
|
+
<VibeRow>
|
|
98
|
+
<VibeCol :cols="4" :offset="4">Centered column</VibeCol>
|
|
99
|
+
</VibeRow>
|
|
100
|
+
|
|
101
|
+
<VibeRow>
|
|
102
|
+
<VibeCol :cols="6" order="last">Appears second</VibeCol>
|
|
103
|
+
<VibeCol :cols="6" order="first">Appears first</VibeCol>
|
|
104
|
+
</VibeRow>
|
|
105
|
+
</template>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Vertical Alignment
|
|
109
|
+
|
|
110
|
+
```vue
|
|
111
|
+
<template>
|
|
112
|
+
<VibeRow align-items="start" style="height: 200px;">
|
|
113
|
+
<VibeCol>Top-aligned</VibeCol>
|
|
114
|
+
<VibeCol align-self="end">Bottom-aligned</VibeCol>
|
|
115
|
+
</VibeRow>
|
|
116
|
+
</template>
|
|
117
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# VibeContainer
|
|
2
|
+
|
|
3
|
+
Responsive container component wrapping Bootstrap's `.container`, `.container-fluid`, and `.container-{breakpoint}` classes.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Default | Description |
|
|
8
|
+
|------|------|---------|-------------|
|
|
9
|
+
| `fluid` | `Boolean \| ContainerType` | `false` | `false` = `.container`, `true` = `.container-fluid`, or a breakpoint (`'sm'`, `'md'`, `'lg'`, `'xl'`, `'xxl'`) for `.container-{breakpoint}` |
|
|
10
|
+
| `tag` | `Tag` | `'div'` | HTML element to render |
|
|
11
|
+
|
|
12
|
+
### ContainerType
|
|
13
|
+
|
|
14
|
+
`'sm' | 'md' | 'lg' | 'xl' | 'xxl'`
|
|
15
|
+
|
|
16
|
+
## Slots
|
|
17
|
+
|
|
18
|
+
| Slot | Description |
|
|
19
|
+
|------|-------------|
|
|
20
|
+
| `default` | Container content |
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Fixed-width Container
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<template>
|
|
28
|
+
<VibeContainer>
|
|
29
|
+
<p>Responsive fixed-width container</p>
|
|
30
|
+
</VibeContainer>
|
|
31
|
+
</template>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Fluid Container
|
|
35
|
+
|
|
36
|
+
```vue
|
|
37
|
+
<template>
|
|
38
|
+
<VibeContainer fluid>
|
|
39
|
+
<p>Full-width container spanning the entire viewport</p>
|
|
40
|
+
</VibeContainer>
|
|
41
|
+
</template>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Responsive Breakpoint Container
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
<template>
|
|
48
|
+
<!-- 100% wide until the md breakpoint, then fixed-width -->
|
|
49
|
+
<VibeContainer fluid="md">
|
|
50
|
+
<p>Fluid until medium breakpoint</p>
|
|
51
|
+
</VibeContainer>
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# VibeRow
|
|
2
|
+
|
|
3
|
+
Row component for Bootstrap's grid system. Provides gutters, row columns, and alignment props.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Default | Description |
|
|
8
|
+
|------|------|---------|-------------|
|
|
9
|
+
| `tag` | `Tag` | `'div'` | HTML element to render |
|
|
10
|
+
| `gutters` | `GutterSize` | `undefined` | Base gutter size (both axes) |
|
|
11
|
+
| `guttersX` | `GutterSize` | `undefined` | Horizontal gutter size |
|
|
12
|
+
| `guttersY` | `GutterSize` | `undefined` | Vertical gutter size |
|
|
13
|
+
| `guttersSm` | `GutterSize` | `undefined` | Gutter size at `sm` breakpoint |
|
|
14
|
+
| `guttersMd` | `GutterSize` | `undefined` | Gutter size at `md` breakpoint |
|
|
15
|
+
| `guttersLg` | `GutterSize` | `undefined` | Gutter size at `lg` breakpoint |
|
|
16
|
+
| `guttersXl` | `GutterSize` | `undefined` | Gutter size at `xl` breakpoint |
|
|
17
|
+
| `guttersXxl` | `GutterSize` | `undefined` | Gutter size at `xxl` breakpoint |
|
|
18
|
+
| `guttersXSm` | `GutterSize` | `undefined` | Horizontal gutter at `sm` breakpoint |
|
|
19
|
+
| `guttersXMd` | `GutterSize` | `undefined` | Horizontal gutter at `md` breakpoint |
|
|
20
|
+
| `guttersXLg` | `GutterSize` | `undefined` | Horizontal gutter at `lg` breakpoint |
|
|
21
|
+
| `guttersXXl` | `GutterSize` | `undefined` | Horizontal gutter at `xl` breakpoint |
|
|
22
|
+
| `guttersXXxl` | `GutterSize` | `undefined` | Horizontal gutter at `xxl` breakpoint |
|
|
23
|
+
| `guttersYSm` | `GutterSize` | `undefined` | Vertical gutter at `sm` breakpoint |
|
|
24
|
+
| `guttersYMd` | `GutterSize` | `undefined` | Vertical gutter at `md` breakpoint |
|
|
25
|
+
| `guttersYLg` | `GutterSize` | `undefined` | Vertical gutter at `lg` breakpoint |
|
|
26
|
+
| `guttersYXl` | `GutterSize` | `undefined` | Vertical gutter at `xl` breakpoint |
|
|
27
|
+
| `guttersYXxl` | `GutterSize` | `undefined` | Vertical gutter at `xxl` breakpoint |
|
|
28
|
+
| `rowCols` | `RowColsSize` | `undefined` | Number of columns per row |
|
|
29
|
+
| `rowColsSm` | `RowColsSize` | `undefined` | Columns per row at `sm` breakpoint |
|
|
30
|
+
| `rowColsMd` | `RowColsSize` | `undefined` | Columns per row at `md` breakpoint |
|
|
31
|
+
| `rowColsLg` | `RowColsSize` | `undefined` | Columns per row at `lg` breakpoint |
|
|
32
|
+
| `rowColsXl` | `RowColsSize` | `undefined` | Columns per row at `xl` breakpoint |
|
|
33
|
+
| `rowColsXxl` | `RowColsSize` | `undefined` | Columns per row at `xxl` breakpoint |
|
|
34
|
+
| `alignItems` | `AlignItems` | `undefined` | Vertical alignment of columns |
|
|
35
|
+
| `justifyContent` | `JustifyContent` | `undefined` | Horizontal distribution of columns |
|
|
36
|
+
|
|
37
|
+
### Type Reference
|
|
38
|
+
|
|
39
|
+
- **GutterSize:** `0 | 1 | 2 | 3 | 4 | 5`
|
|
40
|
+
- **RowColsSize:** `1 | 2 | 3 | 4 | 5 | 6`
|
|
41
|
+
- **AlignItems:** `'start' | 'center' | 'end' | 'baseline' | 'stretch'`
|
|
42
|
+
- **JustifyContent:** `'start' | 'center' | 'end' | 'around' | 'between' | 'evenly'`
|
|
43
|
+
|
|
44
|
+
## Slots
|
|
45
|
+
|
|
46
|
+
| Slot | Description |
|
|
47
|
+
|------|-------------|
|
|
48
|
+
| `default` | Row content (typically `VibeCol` components) |
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
### Basic Grid
|
|
53
|
+
|
|
54
|
+
```vue
|
|
55
|
+
<template>
|
|
56
|
+
<VibeContainer>
|
|
57
|
+
<VibeRow>
|
|
58
|
+
<VibeCol>Column 1</VibeCol>
|
|
59
|
+
<VibeCol>Column 2</VibeCol>
|
|
60
|
+
<VibeCol>Column 3</VibeCol>
|
|
61
|
+
</VibeRow>
|
|
62
|
+
</VibeContainer>
|
|
63
|
+
</template>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### With Gutters
|
|
67
|
+
|
|
68
|
+
```vue
|
|
69
|
+
<template>
|
|
70
|
+
<VibeContainer>
|
|
71
|
+
<VibeRow :gutters="3" :guttersY="4">
|
|
72
|
+
<VibeCol :cols="6">Col 1</VibeCol>
|
|
73
|
+
<VibeCol :cols="6">Col 2</VibeCol>
|
|
74
|
+
<VibeCol :cols="6">Col 3</VibeCol>
|
|
75
|
+
<VibeCol :cols="6">Col 4</VibeCol>
|
|
76
|
+
</VibeRow>
|
|
77
|
+
</VibeContainer>
|
|
78
|
+
</template>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Row Columns
|
|
82
|
+
|
|
83
|
+
```vue
|
|
84
|
+
<template>
|
|
85
|
+
<VibeContainer>
|
|
86
|
+
<!-- Automatically size each child to 1/3 width -->
|
|
87
|
+
<VibeRow :row-cols="3">
|
|
88
|
+
<VibeCol>Item 1</VibeCol>
|
|
89
|
+
<VibeCol>Item 2</VibeCol>
|
|
90
|
+
<VibeCol>Item 3</VibeCol>
|
|
91
|
+
</VibeRow>
|
|
92
|
+
</VibeContainer>
|
|
93
|
+
</template>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Alignment
|
|
97
|
+
|
|
98
|
+
```vue
|
|
99
|
+
<template>
|
|
100
|
+
<VibeContainer>
|
|
101
|
+
<VibeRow align-items="center" justify-content="between">
|
|
102
|
+
<VibeCol :cols="4">Left</VibeCol>
|
|
103
|
+
<VibeCol :cols="4">Right</VibeCol>
|
|
104
|
+
</VibeRow>
|
|
105
|
+
</VibeContainer>
|
|
106
|
+
</template>
|
|
107
|
+
```
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# VibeListGroup
|
|
2
|
+
|
|
3
|
+
Data-driven component for displaying flexible lists of content.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Default | Description |
|
|
8
|
+
|------|------|---------|-------------|
|
|
9
|
+
| `flush` | `Boolean` | `false` | Remove borders and rounded corners |
|
|
10
|
+
| `horizontal` | `Boolean\|String` | `false` | Horizontal layout: `true` or breakpoint (`'sm'`, `'md'`, `'lg'`, `'xl'`) |
|
|
11
|
+
| `numbered` | `Boolean` | `false` | Numbered list items |
|
|
12
|
+
| `tag` | `String` | `'ul'` | HTML tag: `'ul'`, `'ol'`, or `'div'` |
|
|
13
|
+
| `items` | `ListGroupItem[]` | Required | Array of list group items |
|
|
14
|
+
|
|
15
|
+
### ListGroupItem Interface
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
interface ListGroupItem {
|
|
19
|
+
text: string
|
|
20
|
+
href?: string
|
|
21
|
+
to?: string | object
|
|
22
|
+
active?: boolean
|
|
23
|
+
disabled?: boolean
|
|
24
|
+
variant?: Variant
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Events
|
|
29
|
+
|
|
30
|
+
| Event | Payload | Description |
|
|
31
|
+
|-------|---------|-------------|
|
|
32
|
+
| `item-click` | `{ item, index, event }` | Emitted when an item is clicked (unless disabled) |
|
|
33
|
+
|
|
34
|
+
## Slots
|
|
35
|
+
|
|
36
|
+
| Slot | Scope | Description |
|
|
37
|
+
|------|-------|-------------|
|
|
38
|
+
| `item` | `{ item, index }` | Custom item rendering |
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
### Basic List
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<template>
|
|
46
|
+
<VibeListGroup :items="listItems" />
|
|
47
|
+
</template>
|
|
48
|
+
|
|
49
|
+
<script setup>
|
|
50
|
+
const listItems = [
|
|
51
|
+
{ text: 'An item' },
|
|
52
|
+
{ text: 'A second item' },
|
|
53
|
+
{ text: 'A third item' }
|
|
54
|
+
]
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Active and Disabled Items
|
|
59
|
+
|
|
60
|
+
```vue
|
|
61
|
+
<template>
|
|
62
|
+
<VibeListGroup :items="listItems" />
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<script setup>
|
|
66
|
+
const listItems = [
|
|
67
|
+
{ text: 'An item' },
|
|
68
|
+
{ text: 'A second item', active: true },
|
|
69
|
+
{ text: 'A third item' },
|
|
70
|
+
{ text: 'A disabled item', disabled: true }
|
|
71
|
+
]
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### With Links
|
|
76
|
+
|
|
77
|
+
```vue
|
|
78
|
+
<template>
|
|
79
|
+
<VibeListGroup :items="listItems" />
|
|
80
|
+
</template>
|
|
81
|
+
|
|
82
|
+
<script setup>
|
|
83
|
+
const listItems = [
|
|
84
|
+
{ text: 'Link 1', href: '#', active: true },
|
|
85
|
+
{ text: 'Link 2', href: '#' },
|
|
86
|
+
{ text: 'Link 3', href: '#' }
|
|
87
|
+
]
|
|
88
|
+
</script>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### With Router Links
|
|
92
|
+
|
|
93
|
+
```vue
|
|
94
|
+
<template>
|
|
95
|
+
<VibeListGroup :items="listItems" />
|
|
96
|
+
</template>
|
|
97
|
+
|
|
98
|
+
<script setup>
|
|
99
|
+
const listItems = [
|
|
100
|
+
{ text: 'Home', to: { name: 'home' } },
|
|
101
|
+
{ text: 'About', to: { name: 'about' } },
|
|
102
|
+
{ text: 'Contact', to: { name: 'contact' } }
|
|
103
|
+
]
|
|
104
|
+
</script>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Colored Items
|
|
108
|
+
|
|
109
|
+
```vue
|
|
110
|
+
<template>
|
|
111
|
+
<VibeListGroup :items="listItems" />
|
|
112
|
+
</template>
|
|
113
|
+
|
|
114
|
+
<script setup>
|
|
115
|
+
const listItems = [
|
|
116
|
+
{ text: 'Primary item', variant: 'primary' },
|
|
117
|
+
{ text: 'Success item', variant: 'success' },
|
|
118
|
+
{ text: 'Danger item', variant: 'danger' },
|
|
119
|
+
{ text: 'Warning item', variant: 'warning' },
|
|
120
|
+
{ text: 'Info item', variant: 'info' }
|
|
121
|
+
]
|
|
122
|
+
</script>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Flush List
|
|
126
|
+
|
|
127
|
+
Remove borders and rounded corners:
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<template>
|
|
131
|
+
<VibeListGroup flush :items="listItems" />
|
|
132
|
+
</template>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Horizontal List
|
|
136
|
+
|
|
137
|
+
```vue
|
|
138
|
+
<template>
|
|
139
|
+
<!-- Always horizontal -->
|
|
140
|
+
<VibeListGroup horizontal :items="listItems" />
|
|
141
|
+
|
|
142
|
+
<!-- Horizontal on md and up -->
|
|
143
|
+
<VibeListGroup horizontal="md" :items="listItems" />
|
|
144
|
+
</template>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Numbered List
|
|
148
|
+
|
|
149
|
+
```vue
|
|
150
|
+
<template>
|
|
151
|
+
<VibeListGroup numbered tag="ol" :items="listItems" />
|
|
152
|
+
</template>
|
|
153
|
+
|
|
154
|
+
<script setup>
|
|
155
|
+
const listItems = [
|
|
156
|
+
{ text: 'First item' },
|
|
157
|
+
{ text: 'Second item' },
|
|
158
|
+
{ text: 'Third item' }
|
|
159
|
+
]
|
|
160
|
+
</script>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Custom Item Rendering
|
|
164
|
+
|
|
165
|
+
Use the `item` scoped slot for complex content:
|
|
166
|
+
|
|
167
|
+
```vue
|
|
168
|
+
<template>
|
|
169
|
+
<VibeListGroup :items="listItems">
|
|
170
|
+
<template #item="{ item }">
|
|
171
|
+
<div class="d-flex justify-content-between align-items-center">
|
|
172
|
+
<div>
|
|
173
|
+
<h5 class="mb-1">{{ item.text }}</h5>
|
|
174
|
+
<p class="mb-1">{{ item.description }}</p>
|
|
175
|
+
</div>
|
|
176
|
+
<VibeBadge variant="primary">{{ item.count }}</VibeBadge>
|
|
177
|
+
</div>
|
|
178
|
+
</template>
|
|
179
|
+
</VibeListGroup>
|
|
180
|
+
</template>
|
|
181
|
+
|
|
182
|
+
<script setup>
|
|
183
|
+
const listItems = [
|
|
184
|
+
{ text: 'Inbox', description: 'Unread messages', count: 14 },
|
|
185
|
+
{ text: 'Starred', description: 'Important items', count: 3 },
|
|
186
|
+
{ text: 'Sent', description: 'Outgoing mail', count: 25 }
|
|
187
|
+
]
|
|
188
|
+
</script>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### With Event Handling
|
|
192
|
+
|
|
193
|
+
```vue
|
|
194
|
+
<template>
|
|
195
|
+
<VibeListGroup :items="listItems" @item-click="handleClick" />
|
|
196
|
+
</template>
|
|
197
|
+
|
|
198
|
+
<script setup>
|
|
199
|
+
const listItems = [
|
|
200
|
+
{ text: 'Item 1' },
|
|
201
|
+
{ text: 'Item 2' },
|
|
202
|
+
{ text: 'Item 3' }
|
|
203
|
+
]
|
|
204
|
+
|
|
205
|
+
const handleClick = ({ item, index }) => {
|
|
206
|
+
console.log(`Clicked: ${item.text} at index ${index}`)
|
|
207
|
+
}
|
|
208
|
+
</script>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Important Notes
|
|
212
|
+
|
|
213
|
+
**`href` sanitization:** Each item's `href` is sanitized. Only `https://`/`http://` URLs, absolute paths (`/path`), relative paths (`./`, `../`), and anchors (`#section`) are allowed. Dangerous values such as `javascript:`, `data:`, `vbscript:`, and protocol-relative `//host` URLs are stripped — the item renders without an `href` (falling back to a non-link element). Use `to` for in-app navigation via Vue Router.
|
|
214
|
+
|
|
215
|
+
## Bootstrap CSS Classes
|
|
216
|
+
|
|
217
|
+
- `.list-group`
|
|
218
|
+
- `.list-group-flush`
|
|
219
|
+
- `.list-group-horizontal`, `.list-group-horizontal-{breakpoint}`
|
|
220
|
+
- `.list-group-numbered`
|
|
221
|
+
- `.list-group-item`
|
|
222
|
+
- `.list-group-item-{variant}`
|
|
223
|
+
- `.list-group-item-action`
|
|
224
|
+
- `.active`
|
|
225
|
+
- `.disabled`
|