@paraxe/vue 1.0.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 (107) hide show
  1. package/dist/.loba-build.json +5 -0
  2. package/dist/composites/Accordion.d.ts +22 -0
  3. package/dist/composites/AccordionItem.d.ts +21 -0
  4. package/dist/composites/ButtonGroup.d.ts +21 -0
  5. package/dist/composites/SectionHeader.d.ts +20 -0
  6. package/dist/data/EmptyState.d.ts +22 -0
  7. package/dist/data/List.d.ts +35 -0
  8. package/dist/data/ListItem.d.ts +19 -0
  9. package/dist/data/Pagination.d.ts +17 -0
  10. package/dist/data/Table.d.ts +51 -0
  11. package/dist/elements/Badge.d.ts +19 -0
  12. package/dist/elements/Button.d.ts +33 -0
  13. package/dist/elements/Card.d.ts +21 -0
  14. package/dist/elements/Image.d.ts +13 -0
  15. package/dist/elements/Tag.d.ts +13 -0
  16. package/dist/feedback/Alert.d.ts +27 -0
  17. package/dist/feedback/Progress.d.ts +29 -0
  18. package/dist/feedback/Skeleton.d.ts +13 -0
  19. package/dist/feedback/Toast.d.ts +33 -0
  20. package/dist/forms/Checkbox.d.ts +27 -0
  21. package/dist/forms/Choice.d.ts +19 -0
  22. package/dist/forms/ChoiceGroup.d.ts +32 -0
  23. package/dist/forms/FormField.d.ts +29 -0
  24. package/dist/forms/Input.d.ts +29 -0
  25. package/dist/forms/Radio.d.ts +26 -0
  26. package/dist/forms/Select.d.ts +28 -0
  27. package/dist/forms/Switch.d.ts +24 -0
  28. package/dist/forms/Textarea.d.ts +24 -0
  29. package/dist/index.d.ts +47 -0
  30. package/dist/index.js +1888 -0
  31. package/dist/navigation/Breadcrumb.d.ts +22 -0
  32. package/dist/navigation/Breadcrumbs.d.ts +18 -0
  33. package/dist/navigation/Sidebar.d.ts +22 -0
  34. package/dist/navigation/SidebarGroup.d.ts +18 -0
  35. package/dist/navigation/SidebarItem.d.ts +28 -0
  36. package/dist/navigation/Tab.d.ts +19 -0
  37. package/dist/navigation/Tabs.d.ts +22 -0
  38. package/dist/overlays/Dialog.d.ts +26 -0
  39. package/dist/overlays/Drawer.d.ts +28 -0
  40. package/dist/overlays/Popover.d.ts +20 -0
  41. package/dist/overlays/Tooltip.d.ts +21 -0
  42. package/dist/primitives/Container.d.ts +19 -0
  43. package/dist/primitives/Divider.d.ts +3 -0
  44. package/dist/primitives/Grid.d.ts +25 -0
  45. package/dist/primitives/Section.d.ts +13 -0
  46. package/dist/primitives/Stack.d.ts +21 -0
  47. package/dist/typography/Eyebrow.d.ts +13 -0
  48. package/dist/typography/Heading.d.ts +19 -0
  49. package/dist/typography/Label.d.ts +24 -0
  50. package/dist/typography/Text.d.ts +22 -0
  51. package/doc.md +527 -0
  52. package/package.json +29 -0
  53. package/src/composites/Accordion.vue +60 -0
  54. package/src/composites/AccordionItem.vue +66 -0
  55. package/src/composites/ButtonGroup.vue +27 -0
  56. package/src/composites/SectionHeader.vue +23 -0
  57. package/src/data/EmptyState.vue +40 -0
  58. package/src/data/List.vue +125 -0
  59. package/src/data/ListItem.vue +97 -0
  60. package/src/data/Pagination.vue +254 -0
  61. package/src/data/Table.vue +382 -0
  62. package/src/elements/Avatar.vue +0 -0
  63. package/src/elements/Badge.vue +30 -0
  64. package/src/elements/Button.vue +56 -0
  65. package/src/elements/Card.vue +34 -0
  66. package/src/elements/Icon.vue +0 -0
  67. package/src/elements/Image.vue +36 -0
  68. package/src/elements/Tag.vue +10 -0
  69. package/src/env.d.ts +8 -0
  70. package/src/feedback/Alert.vue +63 -0
  71. package/src/feedback/Progress.vue +95 -0
  72. package/src/feedback/Skeleton.vue +43 -0
  73. package/src/feedback/Toast.vue +141 -0
  74. package/src/forms/Checkbox.vue +54 -0
  75. package/src/forms/Choice.vue +82 -0
  76. package/src/forms/ChoiceGroup.vue +130 -0
  77. package/src/forms/FormField.vue +55 -0
  78. package/src/forms/Input.vue +54 -0
  79. package/src/forms/Radio.vue +64 -0
  80. package/src/forms/Select.vue +43 -0
  81. package/src/forms/Switch.vue +57 -0
  82. package/src/forms/Textarea.vue +54 -0
  83. package/src/index.ts +47 -0
  84. package/src/navigation/Breadcrumb.vue +59 -0
  85. package/src/navigation/Breadcrumbs.vue +30 -0
  86. package/src/navigation/Menu.vue +0 -0
  87. package/src/navigation/Sidebar.vue +35 -0
  88. package/src/navigation/SidebarGroup.vue +34 -0
  89. package/src/navigation/SidebarItem.vue +137 -0
  90. package/src/navigation/Tab.vue +78 -0
  91. package/src/navigation/Tabs.vue +68 -0
  92. package/src/overlays/Dialog.vue +193 -0
  93. package/src/overlays/Drawer.vue +200 -0
  94. package/src/overlays/Popover.vue +106 -0
  95. package/src/overlays/Tooltip.vue +69 -0
  96. package/src/primitives/Container.vue +24 -0
  97. package/src/primitives/Divider.vue +6 -0
  98. package/src/primitives/Grid.vue +36 -0
  99. package/src/primitives/Section.vue +8 -0
  100. package/src/primitives/Stack.vue +28 -0
  101. package/src/typography/Eyebrow.vue +9 -0
  102. package/src/typography/Heading.vue +27 -0
  103. package/src/typography/Label.vue +34 -0
  104. package/src/typography/Text.vue +38 -0
  105. package/tsconfig.json +17 -0
  106. package/tsconfig.tsbuildinfo +1 -0
  107. package/vite.config.ts +30 -0
package/doc.md ADDED
@@ -0,0 +1,527 @@
1
+ # Loba UI Vue
2
+
3
+ Loba UI Vue is the Vue implementation of the Loba Design System. It provides reusable application UI so projects can focus on product logic, data, and behaviour instead of rebuilding common interface patterns.
4
+
5
+ ## Installation
6
+
7
+ Import the components you need from `@paraxe/vue`.
8
+
9
+ ```ts
10
+ import {
11
+ Button,
12
+ Card,
13
+ Stack,
14
+ Grid,
15
+ Table,
16
+ Sidebar,
17
+ } from "@paraxe/vue";
18
+ ```
19
+
20
+ Loba Design tokens and component styles must also be available to the project.
21
+
22
+ ## Core Principle
23
+
24
+ Use Loba UI components for repeated UI responsibilities.
25
+
26
+ ```text
27
+ Loba UI
28
+ → components
29
+ → behaviour
30
+ → states
31
+ → accessibility
32
+ → design consistency
33
+
34
+ Application
35
+ → data
36
+ → business logic
37
+ → routing
38
+ → API calls
39
+ → page-specific composition
40
+ ```
41
+
42
+ Do not recreate a Loba component with custom HTML/CSS when the existing component already owns that responsibility.
43
+
44
+ ## Layout
45
+
46
+ ### Stack
47
+
48
+ Use `Stack` for vertical composition.
49
+
50
+ ```vue
51
+ <Stack size="large" fullWidth>
52
+ <Heading level="h1">Prospects</Heading>
53
+ <Text>Manage your sales pipeline.</Text>
54
+ </Stack>
55
+ ```
56
+
57
+ `Stack` is intentionally composition-focused. Avoid adding unnecessary page-level wrappers just to reproduce its spacing.
58
+
59
+ ### Grid
60
+
61
+ Use `Grid` for structured columns.
62
+
63
+ ```vue
64
+ <Grid columns="3" size="medium">
65
+ <Card>...</Card>
66
+ <Card>...</Card>
67
+ <Card>...</Card>
68
+ </Grid>
69
+ ```
70
+
71
+ ### Container
72
+
73
+ Use `Container` for page content boundaries.
74
+
75
+ ```vue
76
+ <Section>
77
+ <Container>
78
+ ...
79
+ </Container>
80
+ </Section>
81
+ ```
82
+
83
+ ## Card and Surfaces
84
+
85
+ `Card` is the standard bounded content container.
86
+
87
+ ```vue
88
+ <Card>
89
+ ...
90
+ </Card>
91
+ ```
92
+
93
+ Card variants control containment and depth:
94
+
95
+ ```vue
96
+ <Card variant="outlined">
97
+ ...
98
+ </Card>
99
+
100
+ <Card variant="elevated">
101
+ ...
102
+ </Card>
103
+ ```
104
+
105
+ Surface classes modify the visual layer independently:
106
+
107
+ ```vue
108
+ <Card class="surface-raised">
109
+ ...
110
+ </Card>
111
+ ```
112
+
113
+ The important distinction is:
114
+
115
+ ```text
116
+ Card
117
+ → container / border / radius / elevation / interaction
118
+
119
+ surface-*
120
+ → background visual layer
121
+ ```
122
+
123
+ Do not create a `<Surface>` wrapper around a Card.
124
+
125
+ ## Forms
126
+
127
+ Loba UI provides:
128
+
129
+ ```text
130
+ Input
131
+ Textarea
132
+ Select
133
+ FormField
134
+ Checkbox
135
+ Radio
136
+ Switch
137
+ ChoiceGroup
138
+ Choice
139
+ ```
140
+
141
+ Use existing controls rather than recreating browser controls with application CSS.
142
+
143
+ `ChoiceGroup` is intended for prominent visual choices:
144
+
145
+ ```vue
146
+ <ChoiceGroup
147
+ v-model="projectType"
148
+ class="choice-group--grid-2"
149
+ >
150
+ <Choice value="renovation">
151
+ Renovation
152
+ </Choice>
153
+
154
+ <Choice value="new-build">
155
+ New build
156
+ </Choice>
157
+ </ChoiceGroup>
158
+ ```
159
+
160
+ ## Data
161
+
162
+ Use the Data components for application records:
163
+
164
+ ```text
165
+ List
166
+ ListItem
167
+ Table
168
+ Pagination
169
+ EmptyState
170
+ ```
171
+
172
+ For example:
173
+
174
+ ```vue
175
+ <Table
176
+ :columns="columns"
177
+ :rows="rows"
178
+ sortable
179
+ selectable
180
+ multiple
181
+ />
182
+ ```
183
+
184
+ Let the component own its behaviour. Avoid wrapping a component in custom layout CSS when the component already provides that responsibility.
185
+
186
+ For example, Pagination should normally be used directly:
187
+
188
+ ```vue
189
+ <Pagination
190
+ :current-page="page"
191
+ :total-items="totalItems"
192
+ :page-size="pageSize"
193
+ @update:current-page="page = $event"
194
+ />
195
+ ```
196
+
197
+ ## Navigation
198
+
199
+ ### Sidebar
200
+
201
+ Sidebar is the persistent application shell.
202
+
203
+ ```text
204
+ Sidebar
205
+ ├── header
206
+ ├── navigation
207
+ │ ├── SidebarGroup
208
+ │ │ └── SidebarItem
209
+ │ └── ...
210
+ └── footer
211
+ ```
212
+
213
+ Example:
214
+
215
+ ```vue
216
+ <Sidebar :collapsed="collapsed">
217
+ <template #header>
218
+ ...
219
+ </template>
220
+
221
+ <SidebarGroup label="Workspace">
222
+ <SidebarItem active href="/dashboard">
223
+ Dashboard
224
+ </SidebarItem>
225
+
226
+ <SidebarItem>
227
+ Sales
228
+
229
+ <template #children>
230
+ <SidebarItem href="/calls">
231
+ Calls
232
+ </SidebarItem>
233
+
234
+ <SidebarItem href="/follow-ups">
235
+ Follow-ups
236
+ </SidebarItem>
237
+ </template>
238
+ </SidebarItem>
239
+ </SidebarGroup>
240
+
241
+ <template #footer>
242
+ ...
243
+ </template>
244
+ </Sidebar>
245
+ ```
246
+
247
+ Sidebar is router-agnostic. The application controls navigation and active state.
248
+
249
+ ### Tabs
250
+
251
+ Tabs switch between views of the same context.
252
+
253
+ ```vue
254
+ <Tabs v-model="activeTab">
255
+ <Tab value="overview">
256
+ Overview
257
+ </Tab>
258
+
259
+ <Tab value="activity">
260
+ Activity
261
+ </Tab>
262
+
263
+ <Tab value="documents">
264
+ Documents
265
+ </Tab>
266
+ </Tabs>
267
+ ```
268
+
269
+ The application owns the content:
270
+
271
+ ```vue
272
+ <Card v-if="activeTab === 'overview'">
273
+ ...
274
+ </Card>
275
+
276
+ <Card v-else-if="activeTab === 'activity'">
277
+ ...
278
+ </Card>
279
+ ```
280
+
281
+ Loba UI does not provide a separate `TabPanel` component.
282
+
283
+ ### Breadcrumbs
284
+
285
+ Breadcrumbs communicate hierarchical location.
286
+
287
+ ```vue
288
+ <Breadcrumbs separator="›">
289
+ <Breadcrumb href="/dashboard">
290
+ Dashboard
291
+ </Breadcrumb>
292
+
293
+ <Breadcrumb href="/prospects">
294
+ Prospects
295
+ </Breadcrumb>
296
+
297
+ <Breadcrumb current>
298
+ James Wilson
299
+ </Breadcrumb>
300
+ </Breadcrumbs>
301
+ ```
302
+
303
+ ## Overlays
304
+
305
+ Loba UI provides four overlay patterns:
306
+
307
+ ```text
308
+ Dialog
309
+ → focused task or decision
310
+
311
+ Drawer
312
+ → larger contextual workspace
313
+
314
+ Popover
315
+ → contextual interactive content
316
+
317
+ Tooltip
318
+ → short non-interactive explanation
319
+ ```
320
+
321
+ ### Dialog
322
+
323
+ Use for focused tasks:
324
+
325
+ ```vue
326
+ <Dialog v-model="showDialog">
327
+ <Stack size="large">
328
+ ...
329
+ </Stack>
330
+ </Dialog>
331
+ ```
332
+
333
+ ### Drawer
334
+
335
+ Use for larger contextual workspaces:
336
+
337
+ ```vue
338
+ <Drawer v-model="showDrawer">
339
+ <Stack size="large">
340
+ ...
341
+ </Stack>
342
+ </Drawer>
343
+ ```
344
+
345
+ ### Popover
346
+
347
+ Use for interactive contextual UI:
348
+
349
+ ```vue
350
+ <Popover>
351
+ <template #trigger>
352
+ <Button variant="secondary">
353
+ Filters
354
+ </Button>
355
+ </template>
356
+
357
+ ...
358
+ </Popover>
359
+ ```
360
+
361
+ ### Tooltip
362
+
363
+ Use for short explanations:
364
+
365
+ ```vue
366
+ <Tooltip text="Delete prospect">
367
+ <Button variant="ghost">
368
+ Delete
369
+ </Button>
370
+ </Tooltip>
371
+ ```
372
+
373
+ ## Feedback
374
+
375
+ Loba UI provides:
376
+
377
+ ```text
378
+ Alert
379
+ → persistent in-flow message
380
+
381
+ Progress
382
+ → operation completion
383
+
384
+ Skeleton
385
+ → loading placeholder
386
+
387
+ Toast
388
+ → temporary floating notification
389
+ ```
390
+
391
+ These should not overlap in purpose.
392
+
393
+ ## Composition Rules
394
+
395
+ Prefer:
396
+
397
+ ```vue
398
+ <Card class="surface-raised">
399
+ <Stack size="large" fullWidth>
400
+ <Heading level="h2">
401
+ Pipeline
402
+ </Heading>
403
+
404
+ <Table ... />
405
+ </Stack>
406
+ </Card>
407
+ ```
408
+
409
+ over creating custom page-specific UI components for every repeated visual pattern.
410
+
411
+ Create a new component only when a pattern has a **real reusable responsibility**.
412
+
413
+ Avoid:
414
+
415
+ ```text
416
+ ProspectCard
417
+ DashboardPanel
418
+ ToolbarWrapper
419
+ TableContainer
420
+ SectionBox
421
+ ```
422
+
423
+ unless repeated application work proves that they deserve to exist.
424
+
425
+ ## Custom CSS
426
+
427
+ Custom CSS is allowed.
428
+
429
+ Loba UI is not intended to prevent application-specific styling. It is intended to remove unnecessary repetition.
430
+
431
+ Use custom CSS for:
432
+
433
+ ```text
434
+ page-specific layout
435
+ brand-specific compositions
436
+ unique visual treatments
437
+ application-specific responsive behaviour
438
+ ```
439
+
440
+ Do not use custom CSS to recreate:
441
+
442
+ ```text
443
+ buttons
444
+ cards
445
+ forms
446
+ tables
447
+ navigation
448
+ dialogs
449
+ drawers
450
+ feedback
451
+ ```
452
+
453
+ when Loba UI already provides them.
454
+
455
+ ## Design Tokens
456
+
457
+ Loba Design separates:
458
+
459
+ ```text
460
+ tokens.css
461
+ → structural values
462
+
463
+ themes/*.css
464
+ → colours / semantic theme values
465
+
466
+ components.css
467
+ → component implementation styles
468
+ ```
469
+
470
+ Components should consume existing tokens instead of inventing duplicate values.
471
+
472
+ For example:
473
+
474
+ ```css
475
+ background: var(--surface-raised);
476
+ border-color: var(--border-default);
477
+ color: var(--text-primary);
478
+ ```
479
+
480
+ ## Framework Responsibility
481
+
482
+ Loba UI Vue provides Vue-specific implementations.
483
+
484
+ The design language remains in Loba Design so the same system can eventually support other frameworks.
485
+
486
+ The Vue layer should therefore focus on:
487
+
488
+ ```text
489
+ props
490
+ events
491
+ slots
492
+ state
493
+ Vue behaviour
494
+ ```
495
+
496
+ while shared visual decisions remain in Loba Design.
497
+
498
+ ## Building an Application
499
+
500
+ A typical Loba application can be structured around:
501
+
502
+ ```text
503
+ App Shell
504
+ ├── Sidebar
505
+
506
+ └── Main
507
+ ├── Breadcrumbs
508
+ ├── SectionHeader
509
+ ├── Cards
510
+ ├── Forms
511
+ ├── Data
512
+ ├── Tabs
513
+ ├── Dialog / Drawer
514
+ └── Feedback
515
+ ```
516
+
517
+ The intended workflow is:
518
+
519
+ ```text
520
+ Choose the Loba component
521
+ → compose it
522
+ → connect application state
523
+ → add business logic
524
+ → add custom CSS only when genuinely necessary
525
+ ```
526
+
527
+ Loba UI exists to make application building faster without replacing the developer's understanding of HTML, CSS, JavaScript, Vue, or TypeScript.
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@paraxe/vue",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "dev": "vite",
16
+ "build": "vite build",
17
+ "typecheck": "vue-tsc --noEmit"
18
+ },
19
+ "dependencies": {
20
+ "@paraxe/core": "workspace:*",
21
+ "vue": "^3.5.13"
22
+ },
23
+ "devDependencies": {
24
+ "@vitejs/plugin-vue": "^6.0.1",
25
+ "vite": "^7.1.2",
26
+ "vue-tsc": "^3.0.5",
27
+ "typescript": "^5.9.2"
28
+ }
29
+ }
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ import { provide, ref, computed } from "vue";
3
+
4
+ type AccordionContext = {
5
+ openItems: Readonly<ReturnType<typeof ref<string[]>>>;
6
+ isOpen: (id: string) => boolean;
7
+ toggleItem: (id: string) => void;
8
+ };
9
+
10
+ const props = withDefaults(
11
+ defineProps<{
12
+ multiple?: boolean;
13
+ collapsible?: boolean;
14
+ defaultOpen?: string[];
15
+ }>(),
16
+ {
17
+ multiple: false,
18
+ collapsible: true,
19
+ defaultOpen: () => [],
20
+ },
21
+ );
22
+
23
+ const openItems = ref<string[]>([...props.defaultOpen]);
24
+
25
+ function isOpen(id: string) {
26
+ return openItems.value.includes(id);
27
+ }
28
+
29
+ function toggleItem(id: string) {
30
+ const currentlyOpen = isOpen(id);
31
+
32
+ if (currentlyOpen) {
33
+ if (!props.collapsible) {
34
+ return;
35
+ }
36
+
37
+ openItems.value = openItems.value.filter((item) => item !== id);
38
+ return;
39
+ }
40
+
41
+ if (props.multiple) {
42
+ openItems.value = [...openItems.value, id];
43
+ return;
44
+ }
45
+
46
+ openItems.value = [id];
47
+ }
48
+
49
+ provide("loba-accordion", {
50
+ openItems,
51
+ isOpen,
52
+ toggleItem,
53
+ } satisfies AccordionContext);
54
+ </script>
55
+
56
+ <template>
57
+ <div class="accordion">
58
+ <slot />
59
+ </div>
60
+ </template>
@@ -0,0 +1,66 @@
1
+ <script setup lang="ts">
2
+ import { computed, inject } from "vue";
3
+
4
+ interface Props {
5
+ id: string;
6
+ disabled?: boolean;
7
+ }
8
+
9
+ const props = withDefaults(defineProps<Props>(), {
10
+ disabled: false,
11
+ });
12
+
13
+ type AccordionContext = {
14
+ isOpen: (id: string) => boolean;
15
+ toggleItem: (id: string) => void;
16
+ };
17
+ const injectedAccordion = inject<AccordionContext>("loba-accordion");
18
+
19
+ if (!injectedAccordion) {
20
+ throw new Error(
21
+ "AccordionItem must be used inside an Accordion.",
22
+ );
23
+ }
24
+
25
+ const accordion = injectedAccordion;
26
+
27
+ if (!accordion) {
28
+ throw new Error(
29
+ "AccordionItem must be used inside an Accordion.",
30
+ );
31
+ }
32
+
33
+ const isOpen = computed(() => accordion.isOpen(props.id));
34
+
35
+ function toggle() {
36
+ if (!props.disabled) {
37
+ accordion.toggleItem(props.id);
38
+ }
39
+ }
40
+ </script>
41
+
42
+ <template>
43
+ <div
44
+ class="accordion-item"
45
+ :class="{ 'accordion-item--open': isOpen }"
46
+ >
47
+ <button
48
+ type="button"
49
+ class="accordion-trigger"
50
+ :disabled="props.disabled"
51
+ :aria-expanded="isOpen"
52
+ :aria-controls="`accordion-${props.id}`"
53
+ @click="toggle"
54
+ >
55
+ <slot name="trigger" />
56
+ </button>
57
+
58
+ <div
59
+ v-show="isOpen"
60
+ :id="`accordion-${props.id}`"
61
+ class="accordion-content"
62
+ >
63
+ <slot />
64
+ </div>
65
+ </div>
66
+ </template>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+
4
+ type ButtonGroupAlign = "start" | "center" | "end";
5
+
6
+ interface Props {
7
+ align?: ButtonGroupAlign;
8
+ stack?: boolean;
9
+ }
10
+
11
+ const props = withDefaults(defineProps<Props>(), {
12
+ align: "start",
13
+ stack: false,
14
+ });
15
+
16
+ const buttonGroupClasses = computed(() => ({
17
+ "button-group--center": props.align === "center",
18
+ "button-group--end": props.align === "end",
19
+ "button-group--stack": props.stack,
20
+ }));
21
+ </script>
22
+
23
+ <template>
24
+ <div class="button-group" :class="buttonGroupClasses">
25
+ <slot />
26
+ </div>
27
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ interface Props {
3
+ width?: "default" | "wide";
4
+ align?: "left" | "center";
5
+ }
6
+
7
+ const props = withDefaults(defineProps<Props>(), {
8
+ width: "default",
9
+ align: "left",
10
+ });
11
+ </script>
12
+
13
+ <template>
14
+ <header
15
+ class="section-header"
16
+ :class="{
17
+ 'section-header--wide': props.width === 'wide',
18
+ 'section-header--center': props.align === 'center',
19
+ }"
20
+ >
21
+ <slot />
22
+ </header>
23
+ </template>