@meistrari/tela-build 1.47.3 → 1.48.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 (32) hide show
  1. package/components/tela/button/button.vue +6 -6
  2. package/components/tela/card/card.mdx +10 -8
  3. package/components/tela/card/card.stories.ts +19 -19
  4. package/components/tela/card/card.vue +7 -5
  5. package/components/tela/chart/chart-bar.vue +2 -2
  6. package/components/tela/create-card/create-card.mdx +84 -0
  7. package/components/tela/create-card/create-card.stories.ts +133 -0
  8. package/components/tela/create-card/create-card.vue +108 -0
  9. package/components/tela/filter/filter-trigger.vue +1 -1
  10. package/components/tela/home/home-body.vue +5 -0
  11. package/components/tela/home/home-content.vue +5 -0
  12. package/components/tela/home/home-section.vue +5 -0
  13. package/components/tela/home/home-title.vue +5 -0
  14. package/components/tela/home/home-toolbar.vue +10 -0
  15. package/components/tela/home/home.mdx +285 -0
  16. package/components/tela/home/home.vue +5 -0
  17. package/components/tela/home/metrics/metrics-card.vue +23 -0
  18. package/components/tela/home/metrics/metrics-group.vue +5 -0
  19. package/components/tela/home/metrics/metrics-stat.vue +23 -0
  20. package/components/tela/home/metrics/metrics.vue +18 -0
  21. package/components/tela/icon/custom.vue +9 -6
  22. package/components/tela/input/input.vue +1 -1
  23. package/components/tela/progress-bar/progress-bar.mdx +117 -0
  24. package/components/tela/progress-bar/progress-bar.stories.ts +148 -0
  25. package/components/tela/progress-bar/progress-bar.vue +88 -0
  26. package/components/tela/sidebar/sidebar-footer.vue +1 -1
  27. package/components/tela/sidebar/sidebar-item.vue +2 -1
  28. package/components/tela/sidebar/sidebar.mdx +2 -2
  29. package/components/tela/table/table-head.vue +1 -1
  30. package/components/tela/table/table-header.vue +1 -1
  31. package/components/tela/table/table-row.vue +1 -1
  32. package/package.json +1 -1
@@ -33,16 +33,16 @@ const sizeStyle = computed(() => (({
33
33
 
34
34
  const variantStyle = computed(() => (({
35
35
  'primary': fold`
36
- bg-gray-900 text-white
37
- hover:bg-gray-800
38
- active:bg-gray-700
36
+ bg-neutral-900 text-white
37
+ hover:bg-neutral-800
38
+ active:bg-neutral-700
39
39
  focus-visible:ring-0.5px focus-visible:ring-cyan-600
40
40
  `,
41
41
  'secondary': fold`
42
- bg-white text-gray-900 border border-0.5px
42
+ bg-white text-neutral-900 border border-0.5px
43
43
  [box-shadow:0_1px_6px_0_rgba(103,127,148,0.05)]
44
- hover:bg-subtle hover:border-gray-300
45
- active:bg-muted active:border-gray-400/60
44
+ hover:bg-subtle hover:border-strong
45
+ active:bg-muted active:border-neutral-400/60
46
46
  focus-visible:ring-0.5px focus-visible:ring-cyan-600
47
47
  `,
48
48
  'ghost': fold`
@@ -14,16 +14,18 @@ A surface container component used to group related content with consistent visu
14
14
 
15
15
  Always use the `size` prop to control card padding — it maps directly to the standardized values. Never apply padding manually to `<TelaCard>` or its inner elements.
16
16
 
17
+ Only `xs` and `sm` are available. Both share `rounded-12px`.
18
+
17
19
  | `size` | Applied classes | Use for |
18
20
  |--------|------------------|---------|
19
- | `md` *(default)* | `p-32px sm:p-48px rounded-24px` | Standard and large cards |
20
- | `sm` | `p-24px rounded-12px` | Small cards, inner containers |
21
+ | `xs` | `p-20px` | Compact cards, dense inner containers |
22
+ | `sm` *(default)* | `p-24px` | Standard cards |
21
23
 
22
24
  ```vue
23
- <!-- Correct — use size prop -->
24
- <TelaCard size="md">...</TelaCard>
25
+ <!-- Correct — use xs or sm -->
26
+ <TelaCard size="xs">...</TelaCard>
25
27
  <TelaCard size="sm">...</TelaCard>
26
- <TelaCard>...</TelaCard> <!-- md is the default -->
28
+ <TelaCard>...</TelaCard> <!-- sm is the default -->
27
29
 
28
30
  <!-- Incorrect — never apply padding manually -->
29
31
  <TelaCard class="p-20px">...</TelaCard>
@@ -43,10 +45,10 @@ Always use the `size` prop to control card padding — it maps directly to the s
43
45
  </TelaCard>
44
46
  ```
45
47
 
46
- ### Minor / Inner Card
48
+ ### Compact / Inner Card
47
49
 
48
50
  ```vue
49
- <TelaCard size="sm">
51
+ <TelaCard size="xs">
50
52
  <span class="body-12-medium text-secondary">Compact content</span>
51
53
  </TelaCard>
52
54
  ```
@@ -85,7 +87,7 @@ Cards in grids must use `h-full` for consistent heights.
85
87
 
86
88
  | Prop | Type | Default | Description |
87
89
  |------|------|---------|-------------|
88
- | `size` | `'sm' \| 'md'` | `'md'` | `md` = `p-32px sm:p-48px rounded-24px`, `sm` = `p-24px rounded-12px` |
90
+ | `size` | `'xs' \| 'sm'` | `'sm'` | `xs` = `p-20px`, `sm` = `p-24px`. Both use `rounded-12px` |
89
91
 
90
92
  ## Slots
91
93
 
@@ -8,15 +8,15 @@ const meta: Meta<typeof Card> = {
8
8
  layout: 'centered',
9
9
  docs: {
10
10
  description: {
11
- component: 'A surface container that groups related content with consistent visual boundaries. Use the `size` prop to control padding — `md` for standard cards, `sm` for minor or inner containers.',
11
+ component: 'A surface container that groups related content with consistent visual boundaries. Use the `size` prop to control padding — `sm` for standard cards, `xs` for compact or inner containers.',
12
12
  },
13
13
  },
14
14
  },
15
15
  argTypes: {
16
16
  size: {
17
17
  control: 'select',
18
- options: ['md', 'sm'],
19
- description: '`md` applies standard card padding. `sm` applies minor/inner container padding.',
18
+ options: ['xs', 'sm'],
19
+ description: '`sm` applies standard card padding. `xs` applies compact/inner container padding.',
20
20
  },
21
21
  },
22
22
  }
@@ -41,7 +41,7 @@ export const Default: Story = {
41
41
  `,
42
42
  }),
43
43
  args: {
44
- size: 'md',
44
+ size: 'sm',
45
45
  },
46
46
  }
47
47
 
@@ -49,10 +49,10 @@ export const Standard: Story = {
49
49
  render: () => ({
50
50
  components: { Card },
51
51
  template: `
52
- <Card size="md">
52
+ <Card size="sm">
53
53
  <div style="display: flex; flex-direction: column; gap: 8px; min-width: 280px;">
54
54
  <p class="heading-h4-semibold text-contrast">Standard Card</p>
55
- <p class="body-14-regular text-secondary">Used for large, standard, and medium cards.</p>
55
+ <p class="body-14-regular text-secondary">Used for standard content surfaces.</p>
56
56
  </div>
57
57
  </Card>
58
58
  `,
@@ -60,7 +60,7 @@ export const Standard: Story = {
60
60
  parameters: {
61
61
  docs: {
62
62
  description: {
63
- story: 'Default size (`md`). Use for primary content surfaces.',
63
+ story: 'Default size (`sm`). Use for primary content surfaces.',
64
64
  },
65
65
  },
66
66
  },
@@ -70,10 +70,10 @@ export const Minor: Story = {
70
70
  render: () => ({
71
71
  components: { Card },
72
72
  template: `
73
- <Card size="sm">
73
+ <Card size="xs">
74
74
  <div style="display: flex; flex-direction: column; gap: 8px; min-width: 240px;">
75
- <p class="heading-h5-semibold text-contrast">Minor Card</p>
76
- <p class="body-12-regular text-secondary">Used for small cards and inner containers.</p>
75
+ <p class="heading-h5-semibold text-contrast">Compact Card</p>
76
+ <p class="body-12-regular text-secondary">Used for compact cards and inner containers.</p>
77
77
  </div>
78
78
  </Card>
79
79
  `,
@@ -81,7 +81,7 @@ export const Minor: Story = {
81
81
  parameters: {
82
82
  docs: {
83
83
  description: {
84
- story: 'Small size (`sm`). Use for compact cards or nested inner containers.',
84
+ story: 'Compact size (`xs`). Use for compact cards or nested inner containers.',
85
85
  },
86
86
  },
87
87
  },
@@ -92,18 +92,18 @@ export const SizeComparison: Story = {
92
92
  components: { Card },
93
93
  template: `
94
94
  <div style="display: flex; gap: 16px; align-items: flex-start;">
95
- <Card size="md">
95
+ <Card size="sm">
96
96
  <div style="display: flex; flex-direction: column; gap: 6px; min-width: 200px;">
97
- <p class="body-12-medium text-secondary">size="md"</p>
97
+ <p class="body-12-medium text-secondary">size="sm"</p>
98
98
  <p class="heading-h4-semibold text-contrast">Standard</p>
99
- <p class="body-14-regular text-tertiary">p-32px sm:p-48px padding</p>
99
+ <p class="body-14-regular text-tertiary">p-24px padding</p>
100
100
  </div>
101
101
  </Card>
102
- <Card size="sm">
102
+ <Card size="xs">
103
103
  <div style="display: flex; flex-direction: column; gap: 6px; min-width: 200px;">
104
- <p class="body-12-medium text-secondary">size="sm"</p>
105
- <p class="heading-h4-semibold text-contrast">Minor</p>
106
- <p class="body-14-regular text-tertiary">p-24px padding</p>
104
+ <p class="body-12-medium text-secondary">size="xs"</p>
105
+ <p class="heading-h4-semibold text-contrast">Compact</p>
106
+ <p class="body-14-regular text-tertiary">p-20px padding</p>
107
107
  </div>
108
108
  </Card>
109
109
  </div>
@@ -136,7 +136,7 @@ export const Grid: Story = {
136
136
  layout: 'padded',
137
137
  docs: {
138
138
  description: {
139
- story: 'Cards used in a grid layout. No padding override needed — `size="md"` is the default.',
139
+ story: 'Cards used in a grid layout. No padding override needed — `size="sm"` is the default.',
140
140
  },
141
141
  },
142
142
  },
@@ -1,21 +1,23 @@
1
1
  <script setup lang="ts">
2
2
  import type { HTMLAttributes } from 'vue'
3
3
 
4
- const props = withDefaults(defineProps<{
5
- size?: 'sm' | 'md'
4
+ const props = withDefaults(defineProps <{
5
+ size?: 'xs' | 'sm'
6
6
  class?: HTMLAttributes['class']
7
7
  /** @deprecated Use `class` instead */
8
8
  contentPadding?: HTMLAttributes['class']
9
9
  /** @deprecated Use `class` instead */
10
10
  borderRadius?: HTMLAttributes['class']
11
11
  }>(), {
12
- size: 'md',
12
+ size: 'sm',
13
13
  })
14
14
 
15
15
  const sizeStyles = computed(() => (({
16
+ xs: { padding: 'p-20px' },
16
17
  sm: { padding: 'p-24px' },
18
+ /** @deprecated: Use 'xs' or 'sm' instead */
17
19
  md: { padding: 'p-32px' },
18
- }) as Record<string, { padding: string }>)[props.size ?? 'md'] ?? { padding: '' })
20
+ }) as Record<string, { padding: string }>)[props.size ?? 'sm'] ?? { padding: '' })
19
21
 
20
22
  const paddingClass = computed(() => props.contentPadding ?? sizeStyles.value.padding)
21
23
  const rootEl = ref<HTMLElement | null>(null)
@@ -26,7 +28,7 @@ defineExpose({
26
28
  </script>
27
29
 
28
30
  <template>
29
- <div ref="rootEl" :class="cn('rounded-16px bg border-0.5px border', paddingClass, props.class)">
31
+ <div ref="rootEl" :class="cn('rounded-12px bg border-0.5px border', paddingClass, props.class)">
30
32
  <slot />
31
33
  </div>
32
34
  </template>
@@ -8,7 +8,7 @@ const props = withDefaults(defineProps<{
8
8
  }>(), {
9
9
  height: '12px',
10
10
  gap: '2px',
11
- duration: 1000,
11
+ duration: 400,
12
12
  })
13
13
 
14
14
  const animatedFilled = ref(0)
@@ -52,7 +52,7 @@ watch(() => props.filled, (newValue) => {
52
52
  :style="{ height }"
53
53
  w-1px
54
54
  rounded-1px
55
- :bg="bar.isFilled ? '#5DC16B' : '#DFE3E7'"
55
+ :bg="bar.isFilled ? 'green-500' : 'neutral-200'"
56
56
  />
57
57
  </div>
58
58
  </template>
@@ -0,0 +1,84 @@
1
+ # TelaCreateCard
2
+
3
+ A fixed-size entry point card for creating something new from files. Click it to open the native file picker, or drag files directly onto it. It emits a `change` event with the native input event so the parent owns the upload logic.
4
+
5
+ ## Rules
6
+
7
+ - **Always** handle the `change` event — the component only surfaces files, it does not upload them.
8
+ - The card has a **fixed footprint** (`w-221px h-128px`). Lay it out in a grid or flex row alongside other cards; do not stretch it.
9
+ - Use it as the **first cell** in a list of existing items (the "add new" affordance), not as a standalone hero.
10
+ - Set `multiple={false}` when the flow only accepts a single file.
11
+ - Pass `name` when the input participates in a native `<form>` submission.
12
+ - Use `disabled` while an upload is in flight — it blocks both click and drag-and-drop.
13
+
14
+ ## Examples
15
+
16
+ ### Default
17
+
18
+ ```vue
19
+ <TelaCreateCard @change="handleChange" />
20
+ ```
21
+
22
+ ```ts
23
+ function handleChange(event: Event) {
24
+ const input = event.target as HTMLInputElement
25
+ const files = input.files
26
+ // upload files...
27
+ }
28
+ ```
29
+
30
+ ### Custom Labels
31
+
32
+ ```vue
33
+ <TelaCreateCard
34
+ title="Upload dataset"
35
+ description="Drop a CSV or"
36
+ browse-label="choose a file"
37
+ :multiple="false"
38
+ @change="handleChange"
39
+ />
40
+ ```
41
+
42
+ ### Without Browse Label
43
+
44
+ ```vue
45
+ <!-- Empty browse-label hides the underlined call-to-action -->
46
+ <TelaCreateCard
47
+ title="New canvas"
48
+ description="Drag files here"
49
+ browse-label=""
50
+ @change="handleChange"
51
+ />
52
+ ```
53
+
54
+ ### Disabled (e.g. while uploading)
55
+
56
+ ```vue
57
+ <TelaCreateCard :disabled="isUploading" @change="handleChange" />
58
+ ```
59
+
60
+ ### In a Grid
61
+
62
+ ```vue
63
+ <div class="grid grid-cols-3 gap-4">
64
+ <TelaCreateCard @change="handleChange" />
65
+ <TelaCard v-for="item in items" :key="item.id" h-full>...</TelaCard>
66
+ </div>
67
+ ```
68
+
69
+ ## Props
70
+
71
+ | Prop | Type | Default | Description |
72
+ |------|------|---------|-------------|
73
+ | `title` | `string` | `'New analysis'` | Heading shown inside the card |
74
+ | `description` | `string` | `'Drag files or'` | Leading helper text before the browse label |
75
+ | `browseLabel` | `string` | `'browse your computer'` | Underlined call-to-action appended after the description. Empty string hides it |
76
+ | `multiple` | `boolean` | `true` | Whether the file input accepts multiple files |
77
+ | `name` | `string` | — | `name` attribute forwarded to the underlying file input |
78
+ | `disabled` | `boolean` | `false` | Disables clicking and drag-and-drop, and dims the card |
79
+
80
+ ## Events
81
+
82
+ | Event | Payload | Description |
83
+ |-------|---------|-------------|
84
+ | `change` | `Event` | Native input change event, fired on file selection and on drop. Read files from `(event.target as HTMLInputElement).files` |
@@ -0,0 +1,133 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import CreateCard from './create-card.vue'
3
+
4
+ const meta: Meta<typeof CreateCard> = {
5
+ title: 'Core/CreateCard',
6
+ component: CreateCard,
7
+ parameters: {
8
+ layout: 'centered',
9
+ docs: {
10
+ description: {
11
+ component: 'A fixed-size entry point card for creating something new from files. Click to open the file picker, or drag files onto it. Emits `change` with the native input event.',
12
+ },
13
+ },
14
+ },
15
+ argTypes: {
16
+ title: {
17
+ control: 'text',
18
+ description: 'Heading shown inside the card.',
19
+ },
20
+ description: {
21
+ control: 'text',
22
+ description: 'Leading helper text before the browse label.',
23
+ },
24
+ browseLabel: {
25
+ control: 'text',
26
+ description: 'Underlined call-to-action appended after the description.',
27
+ },
28
+ multiple: {
29
+ control: 'boolean',
30
+ description: 'Whether the file input accepts multiple files.',
31
+ },
32
+ name: {
33
+ control: 'text',
34
+ description: 'Name attribute forwarded to the underlying file input.',
35
+ },
36
+ disabled: {
37
+ control: 'boolean',
38
+ description: 'Disables clicking and drag-and-drop.',
39
+ },
40
+ },
41
+ args: {
42
+ onChange: (event: Event) => {
43
+ const input = event.target as HTMLInputElement
44
+ // eslint-disable-next-line no-console
45
+ console.log('change', input.files)
46
+ },
47
+ },
48
+ }
49
+
50
+ export default meta
51
+
52
+ type Story = StoryObj<typeof meta>
53
+
54
+ export const Default: Story = {
55
+ render: args => ({
56
+ components: { CreateCard },
57
+ setup() {
58
+ return { args }
59
+ },
60
+ template: '<CreateCard v-bind="args" @change="args.onChange" />',
61
+ }),
62
+ args: {
63
+ title: 'New analysis',
64
+ description: 'Drag files or',
65
+ browseLabel: 'browse your computer',
66
+ multiple: true,
67
+ },
68
+ }
69
+
70
+ export const Disabled: Story = {
71
+ render: args => ({
72
+ components: { CreateCard },
73
+ setup() {
74
+ return { args }
75
+ },
76
+ template: '<CreateCard v-bind="args" @change="args.onChange" />',
77
+ }),
78
+ args: {
79
+ disabled: true,
80
+ },
81
+ parameters: {
82
+ docs: {
83
+ description: {
84
+ story: 'Disabled state — clicking and drag-and-drop are inert and the card is dimmed.',
85
+ },
86
+ },
87
+ },
88
+ }
89
+
90
+ export const CustomLabels: Story = {
91
+ render: args => ({
92
+ components: { CreateCard },
93
+ setup() {
94
+ return { args }
95
+ },
96
+ template: '<CreateCard v-bind="args" @change="args.onChange" />',
97
+ }),
98
+ args: {
99
+ title: 'Upload dataset',
100
+ description: 'Drop a CSV or',
101
+ browseLabel: 'choose a file',
102
+ multiple: false,
103
+ },
104
+ parameters: {
105
+ docs: {
106
+ description: {
107
+ story: 'Custom title, description, and browse label. Set `multiple: false` to accept a single file.',
108
+ },
109
+ },
110
+ },
111
+ }
112
+
113
+ export const NoBrowseLabel: Story = {
114
+ render: args => ({
115
+ components: { CreateCard },
116
+ setup() {
117
+ return { args }
118
+ },
119
+ template: '<CreateCard v-bind="args" @change="args.onChange" />',
120
+ }),
121
+ args: {
122
+ title: 'New canvas',
123
+ description: 'Drag files here',
124
+ browseLabel: '',
125
+ },
126
+ parameters: {
127
+ docs: {
128
+ description: {
129
+ story: 'Omitting `browseLabel` (empty string) hides the underlined call-to-action.',
130
+ },
131
+ },
132
+ },
133
+ }
@@ -0,0 +1,108 @@
1
+ <script setup lang="ts">
2
+ const props = withDefaults(defineProps<{
3
+ disabled?: boolean
4
+ title?: string
5
+ description?: string
6
+ browseLabel?: string
7
+ multiple?: boolean
8
+ name?: string
9
+ }>(), {
10
+ title: 'New analysis',
11
+ description: 'Drag files or',
12
+ browseLabel: 'browse your computer',
13
+ multiple: true,
14
+ })
15
+
16
+ const emit = defineEmits<{
17
+ (e: 'change', event: Event): void
18
+ }>()
19
+
20
+ const fileInputRef = ref<HTMLInputElement | null>(null)
21
+
22
+ const dragDepth = ref(0)
23
+ const isDragging = computed(() => dragDepth.value > 0)
24
+
25
+ function openFilePicker() {
26
+ if (props.disabled)
27
+ return
28
+
29
+ fileInputRef.value?.click()
30
+ }
31
+
32
+ function handleFileChange(event: Event) {
33
+ emit('change', event)
34
+ }
35
+
36
+ function onDragEnter() {
37
+ if (props.disabled)
38
+ return
39
+
40
+ dragDepth.value++
41
+ }
42
+
43
+ function onDragLeave() {
44
+ if (props.disabled)
45
+ return
46
+
47
+ dragDepth.value = Math.max(0, dragDepth.value - 1)
48
+ }
49
+
50
+ function onDrop(event: DragEvent) {
51
+ dragDepth.value = 0
52
+
53
+ if (props.disabled)
54
+ return
55
+
56
+ const files = event.dataTransfer?.files
57
+
58
+ if (files?.length && fileInputRef.value) {
59
+ const dataTransfer = new DataTransfer()
60
+ const droppedFiles = props.multiple ? Array.from(files) : Array.from(files).slice(0, 1)
61
+
62
+ for (const file of droppedFiles)
63
+ dataTransfer.items.add(file)
64
+
65
+ fileInputRef.value.files = dataTransfer.files
66
+ fileInputRef.value.dispatchEvent(new Event('change', { bubbles: true }))
67
+ }
68
+ }
69
+ </script>
70
+
71
+ <template>
72
+ <button
73
+ type="button"
74
+ :disabled="disabled"
75
+ relative w-221px h-128px rounded-12px p-20px
76
+ bg border-0.5px border
77
+ flex="~ col" items-start justify-end text-start
78
+ hover:bg-subtle hover:border-strong active:bg-muted disabled:opacity-50 disabled:cursor-not-allowed
79
+ :class="isDragging ? 'border-dashed border-neutral-400 bg-subtle' : 'active:border-neutral-400/60'"
80
+ @click="openFilePicker"
81
+ @dragenter.prevent="onDragEnter"
82
+ @dragover.prevent
83
+ @dragleave.prevent="onDragLeave"
84
+ @drop.prevent="onDrop"
85
+ >
86
+ <TelaIcon name="i-ph-plus" size="20px" color="icon" absolute top-16px right-16px />
87
+ <div flex="~ col" items-start justify-end gap-4px>
88
+ <h5 heading-h5-semibold text-primary>
89
+ {{ title }}
90
+ </h5>
91
+ <div leading-none>
92
+ <span body-12-regular text-secondary>
93
+ {{ description }}
94
+ </span>
95
+ <span v-if="browseLabel" block body-12-regular leading-none text-secondary underline underline-offset-3>{{ browseLabel }}</span>
96
+ </div>
97
+ </div>
98
+ </button>
99
+
100
+ <input
101
+ ref="fileInputRef"
102
+ type="file"
103
+ :multiple="multiple"
104
+ :name="name"
105
+ hidden
106
+ @change="handleFileChange"
107
+ >
108
+ </template>
@@ -48,7 +48,7 @@ defineEmits<{
48
48
  name="i-ph-caret-down-bold"
49
49
  size="12px"
50
50
  color="icon-secondary"
51
- class="shrink-0 transition-all ease-out duration-120 group-data-[active]:rotate-180"
51
+ class="shrink-0 transition-all ease-out duration-150 group-data-[active]:rotate-180"
52
52
  />
53
53
  </button>
54
54
  </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div flex="~ col" gap-46px>
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <main flex="~ col" w-full max-w-1600px mx-auto px-48px py-32px gap-24px>
3
+ <slot />
4
+ </main>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <section flex="~ col" gap-24px>
3
+ <slot />
4
+ </section>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <h1 heading-h4-semibold text-primary>
3
+ <slot />
4
+ </h1>
5
+ </template>
@@ -0,0 +1,10 @@
1
+ <template>
2
+ <div flex items-center justify-between gap-12px flex-wrap>
3
+ <div flex items-center gap-8px flex-wrap>
4
+ <slot />
5
+ </div>
6
+ <div v-if="$slots.actions" flex items-center gap-8px flex-wrap>
7
+ <slot name="actions" />
8
+ </div>
9
+ </div>
10
+ </template>