@meistrari/tela-build 1.56.1 → 1.57.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 (98) hide show
  1. package/components/tela/breadcrumbs/breadcrumbs-item.vue +34 -0
  2. package/components/tela/breadcrumbs/breadcrumbs-separator.vue +5 -0
  3. package/components/tela/breadcrumbs/breadcrumbs.mdx +49 -0
  4. package/components/tela/breadcrumbs/breadcrumbs.vue +7 -0
  5. package/components/tela/button/button.mdx +4 -4
  6. package/components/tela/checkbox/checkbox-card.vue +4 -4
  7. package/components/tela/checkbox/checkbox.mdx +9 -8
  8. package/components/tela/code-block/code-block.mdx +0 -2
  9. package/components/tela/code-block/code-block.vue +22 -16
  10. package/components/tela/collapsible-group/collapsible-group.mdx +5 -5
  11. package/components/tela/copy-button.vue +5 -5
  12. package/components/tela/create-card/create-card.mdx +9 -19
  13. package/components/tela/create-card/create-card.vue +1 -1
  14. package/components/tela/details/details.mdx +3 -3
  15. package/components/tela/dropdown-menu/DropdownMenu.vue +0 -6
  16. package/components/tela/header/header.mdx +20 -20
  17. package/components/tela/home/home.mdx +3 -3
  18. package/components/tela/hover-card/hover-card.mdx +1 -4
  19. package/components/tela/icon-button/icon-button.vue +2 -2
  20. package/components/tela/icon.vue +1 -1
  21. package/components/tela/input/input.vue +0 -1
  22. package/components/tela/sidebar/sidebar.mdx +7 -7
  23. package/components/tela/switch/switch.vue +1 -1
  24. package/components/tela/tabs/tabs.vue +2 -1
  25. package/components/tela/tags/tags-select.vue +3 -11
  26. package/components/tela/tags/tags.vue +2 -2
  27. package/components/tela/textarea/textarea.mdx +1 -0
  28. package/components/tela/tooltip-group/tooltip-group-trigger.vue +5 -0
  29. package/docs/typography.md +30 -20
  30. package/lib/__tests__/doc-generator.test.ts +141 -1
  31. package/lib/doc-generator.ts +169 -17
  32. package/nuxt.config.ts +2 -6
  33. package/package.json +2 -13
  34. package/utils/citations.ts +12 -1
  35. package/utils/design-tokens.ts +124 -60
  36. package/components/tela/animated/animated-number.stories.ts +0 -52
  37. package/components/tela/avatar/avatar.stories.ts +0 -62
  38. package/components/tela/avatar/group/avatar-group.stories.ts +0 -78
  39. package/components/tela/avatar/label/avatar-label.stories.ts +0 -74
  40. package/components/tela/badge/badge.stories.ts +0 -82
  41. package/components/tela/button/button.stories.ts +0 -202
  42. package/components/tela/card/card.stories.ts +0 -143
  43. package/components/tela/chat/chat.stories.ts +0 -253
  44. package/components/tela/chat/text-input/chat-text-input.stories.ts +0 -128
  45. package/components/tela/chat/text-message/chat-text-message.stories.ts +0 -138
  46. package/components/tela/checkbox/checkbox.stories.ts +0 -104
  47. package/components/tela/code-block/code-block.stories.ts +0 -226
  48. package/components/tela/collapsible-group/collapsible-group.stories.ts +0 -134
  49. package/components/tela/collapsible-section/collapsible-section.stories.ts +0 -53
  50. package/components/tela/combobox/combobox.stories.ts +0 -237
  51. package/components/tela/complex-table/complex-table-cell.stories.ts +0 -144
  52. package/components/tela/complex-table/complex-table-header-cell.stories.ts +0 -102
  53. package/components/tela/complex-table/complex-table-header.stories.ts +0 -88
  54. package/components/tela/complex-table/complex-table.stories.ts +0 -353
  55. package/components/tela/create-card/create-card.stories.ts +0 -133
  56. package/components/tela/disclaimer/disclaimer.stories.ts +0 -196
  57. package/components/tela/dropdown-menu/dropdown-menu.stories.ts +0 -163
  58. package/components/tela/file-upload/file-upload.stories.ts +0 -48
  59. package/components/tela/filter/filter.stories.ts +0 -596
  60. package/components/tela/filters/checkbox-filter.stories.ts +0 -218
  61. package/components/tela/filters/date-filter.stories.ts +0 -258
  62. package/components/tela/filters/user-filter.stories.ts +0 -344
  63. package/components/tela/header/header.stories.ts +0 -222
  64. package/components/tela/heading-tabs/heading-tabs.stories.ts +0 -111
  65. package/components/tela/hover-card/hover-card.stories.ts +0 -87
  66. package/components/tela/input/input.stories.ts +0 -148
  67. package/components/tela/input-otp/input-otp.stories.ts +0 -138
  68. package/components/tela/label/label.stories.ts +0 -37
  69. package/components/tela/multiple-select/multiple-select.stories.ts +0 -325
  70. package/components/tela/playback-timeline/playback-timeline.stories.ts +0 -66
  71. package/components/tela/popover/popover.stories.ts +0 -150
  72. package/components/tela/popover-list/popover-list.stories.ts +0 -330
  73. package/components/tela/preview/preview.stories.ts +0 -217
  74. package/components/tela/progress-bar/progress-bar.stories.ts +0 -148
  75. package/components/tela/radio-group/radio-group.stories.ts +0 -106
  76. package/components/tela/range-calendar.stories.ts +0 -110
  77. package/components/tela/scroll-area/scroll-area.stories.ts +0 -129
  78. package/components/tela/segment-bar/segment-bar.stories.ts +0 -115
  79. package/components/tela/segment-toggle/segment-toggle.stories.ts +0 -113
  80. package/components/tela/select-menu/select-menu.stories.ts +0 -91
  81. package/components/tela/sheet/sheet.stories.ts +0 -201
  82. package/components/tela/side-sheet/side-sheet.stories.ts +0 -134
  83. package/components/tela/sidebar/sidebar.stories.ts +0 -250
  84. package/components/tela/skeleton/skeleton.stories.ts +0 -35
  85. package/components/tela/status/status.stories.ts +0 -212
  86. package/components/tela/status-bar/status-bar.stories.ts +0 -64
  87. package/components/tela/switch/switch.stories.ts +0 -80
  88. package/components/tela/table/table.stories.ts +0 -384
  89. package/components/tela/tabs/tabs.stories.ts +0 -72
  90. package/components/tela/tags/tags-select.stories.ts +0 -47
  91. package/components/tela/tags/tags.stories.ts +0 -161
  92. package/components/tela/textarea/textarea.stories.ts +0 -50
  93. package/components/tela/timeline-waterfall/timeline-waterfall.stories.ts +0 -151
  94. package/components/tela/tooltip/tooltip.stories.ts +0 -200
  95. package/components/tela/tooltip-group/tooltip-group.stories.ts +0 -465
  96. package/components/tela/uploader/uploader.stories.ts +0 -416
  97. package/composables/optimistic-async-data/stories/optimistic-async-data-collection.stories.ts +0 -47
  98. package/composables/optimistic-async-data/stories/optimistic-async-data.stories.ts +0 -104
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ import { NuxtLink } from '#components'
3
+ import { Primitive } from 'reka-ui'
4
+
5
+ const props = defineProps<{
6
+ to?: string
7
+ current?: boolean
8
+ }>()
9
+
10
+ const isLink = computed(() => props.to !== undefined)
11
+
12
+ const style = computed(() => {
13
+ if (isLink.value)
14
+ return 'body-12-regular text-tertiary hover:text-secondary transition-colors duration-150'
15
+
16
+ if (props.current)
17
+ return 'body-12-medium text-primary'
18
+
19
+ return 'body-12-regular text-tertiary'
20
+ })
21
+ </script>
22
+
23
+ <template>
24
+ <li class="flex items-center select-none">
25
+ <Primitive
26
+ :as="isLink ? NuxtLink : 'span'"
27
+ :to="to"
28
+ :aria-current="current ? 'page' : undefined"
29
+ :class="style"
30
+ >
31
+ <slot />
32
+ </Primitive>
33
+ </li>
34
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <li aria-hidden="true" class="flex items-center">
3
+ <TelaIcon name="i-ph-caret-right-bold" size="10px" color="icon-tertiary" />
4
+ </li>
5
+ </template>
@@ -0,0 +1,49 @@
1
+ import { Meta, Canvas } from '@storybook/blocks';
2
+ import * as BreadcrumbsStories from './breadcrumbs.stories';
3
+
4
+ <Meta of={BreadcrumbsStories} />
5
+
6
+ # TelaBreadcrumbs
7
+
8
+ A navigation trail showing where the current page sits in the hierarchy — e.g. **Components › Button** or **Layouts › Home**. Built on Reka UI's `Primitive`, so items render as `NuxtLink`s when given a `to` and as the plain current-page label when not.
9
+
10
+ ## Example
11
+
12
+ ```vue
13
+ <TelaBreadcrumbs>
14
+ <TelaBreadcrumbsItem to="/components">Components</TelaBreadcrumbsItem>
15
+ <TelaBreadcrumbsSeparator />
16
+ <TelaBreadcrumbsItem current>Button</TelaBreadcrumbsItem>
17
+ </TelaBreadcrumbs>
18
+ ```
19
+
20
+ <Canvas of={BreadcrumbsStories.Default} />
21
+
22
+ ## Rules
23
+
24
+ - The last item is the current page: set `current` (and no `to`) so it renders emphasized (`text-primary`) with `aria-current="page"`, never as a link.
25
+ - An item with neither `to` nor `current` is a plain, non-interactive step (`text-tertiary`) — use it for sections that have no landing page of their own.
26
+ - Put a `TelaBreadcrumbsSeparator` between every pair of items — never at the ends.
27
+ - Ancestor items get a `to` and render as links in `text-tertiary`, brightening on hover.
28
+ - Keep labels short — section and page names, not full titles.
29
+
30
+ ## Components
31
+
32
+ ### TelaBreadcrumbs
33
+
34
+ Root wrapper. Renders a `<nav aria-label="Breadcrumb">` with a horizontal `<ol>` — place items and separators as direct children.
35
+
36
+ ### TelaBreadcrumbsItem
37
+
38
+ One step in the trail, rendered as an `<li>`. With `to` it renders a `NuxtLink`; without it, the current page label.
39
+
40
+ ```typescript
41
+ interface BreadcrumbsItemProps {
42
+ to?: string // route path — renders as a NuxtLink when provided
43
+ current?: boolean // marks the current page (aria-current="page", emphasized)
44
+ }
45
+ ```
46
+
47
+ ### TelaBreadcrumbsSeparator
48
+
49
+ A small caret between items, hidden from assistive tech (`aria-hidden`).
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <nav aria-label="Breadcrumb">
3
+ <ol class="flex items-center gap-4px">
4
+ <slot />
5
+ </ol>
6
+ </nav>
7
+ </template>
@@ -16,16 +16,16 @@ A versatile button component with multiple variants, sizes, and states. Supports
16
16
  - **Icon API — two separate props, never one.** The icon **name** goes on `icon`; its **position** is toggled with the boolean `leading`. Default position is trailing. `leading` never takes a value.
17
17
 
18
18
  ```vue
19
- <!-- Correct — icon on the leading side -->
19
+ <!-- Correct — icon on the leading side -->
20
20
  <TelaButton icon="i-ph-export" leading>Export</TelaButton>
21
21
 
22
- <!-- Correct — icon on the trailing side (default) -->
22
+ <!-- Correct — icon on the trailing side (default) -->
23
23
  <TelaButton icon="i-ph-arrow-right">Next</TelaButton>
24
24
 
25
- <!-- Wrong — `leading` is a boolean, not a slot for the icon name -->
25
+ <!-- Wrong — `leading` is a boolean, not a slot for the icon name -->
26
26
  <TelaButton leading="i-ph-export">Export</TelaButton>
27
27
 
28
- <!-- Wrong — no `icon` prop means no icon renders -->
28
+ <!-- Wrong — no `icon` prop means no icon renders -->
29
29
  <TelaButton leading>Export</TelaButton>
30
30
  ```
31
31
 
@@ -12,17 +12,17 @@ const forwarded = useForwardPropsEmits(props, emits)
12
12
  <template>
13
13
  <Label
14
14
  :class="cn(
15
- 'w-[380px] p-[12px] flex items-center gap-[12px] rounded-[8px] bg-white-1000 cursor-pointer border-[0.5px] border-gray-200 transition-colors disabled:cursor-not-allowed disabled:bg-gray-100 disabled:border-gray-200',
16
- 'has-[[aria-checked=false]]:hover:bg-gray-50 has-[[aria-checked=false]]:hover:border-gray-300 has-[[aria-checked=true]]:bg-blue-100/60 has-[[aria-checked=true]]:border-blue-700',
15
+ 'w-[380px] p-[12px] flex items-center gap-[12px] rounded-[8px] bg cursor-pointer border-0.5px border transition-colors disabled:cursor-not-allowed disabled:bg-muted disabled:border',
16
+ 'has-[[aria-checked=false]]:hover:bg-subtle has-[[aria-checked=false]]:hover:border-strong has-[[aria-checked=true]]:bg-blue-100/60 has-[[aria-checked=true]]:border-blue-700',
17
17
  props.class,
18
18
  )"
19
19
  >
20
20
  <TelaCheckbox v-bind="forwarded" />
21
21
  <div>
22
- <h4 class="body-12-medium text-gray-900">
22
+ <h4 class="body-12-medium text-primary">
23
23
  {{ label }}
24
24
  </h4>
25
- <p class="body-12-regular text-gray-500">
25
+ <p class="body-12-regular text-secondary">
26
26
  {{ description }}
27
27
  </p>
28
28
  </div>
@@ -51,9 +51,9 @@ const accepted = ref(false)
51
51
  <template>
52
52
  <div class="flex items-center gap-2">
53
53
  <TelaCheckbox id="terms" v-model="accepted" />
54
- <label for="terms" class="cursor-pointer">
54
+ <TelaLabel for="terms" class="cursor-pointer">
55
55
  I accept the terms and conditions
56
- </label>
56
+ </TelaLabel>
57
57
  </div>
58
58
  </template>
59
59
  ```
@@ -71,29 +71,30 @@ const accepted = ref(false)
71
71
  <script setup>
72
72
  import { ref } from 'vue'
73
73
 
74
- const preferences = ref([])
74
+ const notifications = ref(false)
75
+ const newsletter = ref(false)
75
76
  </script>
76
77
 
77
78
  <template>
78
- <form>
79
+ <form class="flex flex-col gap-2">
79
80
  <div class="flex items-center gap-2">
80
81
  <TelaCheckbox
81
82
  id="notifications"
82
- v-model="preferences"
83
+ v-model="notifications"
83
84
  value="notifications"
84
85
  name="preferences"
85
86
  />
86
- <label for="notifications">Enable notifications</label>
87
+ <TelaLabel for="notifications" class="cursor-pointer">Enable notifications</TelaLabel>
87
88
  </div>
88
89
 
89
90
  <div class="flex items-center gap-2">
90
91
  <TelaCheckbox
91
92
  id="newsletter"
92
- v-model="preferences"
93
+ v-model="newsletter"
93
94
  value="newsletter"
94
95
  name="preferences"
95
96
  />
96
- <label for="newsletter">Subscribe to newsletter</label>
97
+ <TelaLabel for="newsletter" class="cursor-pointer">Subscribe to newsletter</TelaLabel>
97
98
  </div>
98
99
  </form>
99
100
  </template>
@@ -42,9 +42,7 @@ const code = `function greet(name: string) {
42
42
  language="bash"
43
43
  :code="'pnpm install'"
44
44
  hide-line-numbers
45
- without-border
46
45
  copy-button-variant="ghost"
47
- class="bg-neutral-50 rounded-12px"
48
46
  />
49
47
  ```
50
48
 
@@ -30,7 +30,8 @@ const props = withDefaults(defineProps<{
30
30
  const highlighted = ref('')
31
31
  const isLoading = ref(true)
32
32
  const theme = computed(() => TelaTheme(props.background ?? 'transparent'))
33
- const skeletonLineCount = computed(() => props.code?.split('\n').length || 1)
33
+ const lineCount = computed(() => props.code?.split('\n').length || 1)
34
+ const isSingleLine = computed(() => lineCount.value === 1)
34
35
 
35
36
  watchEffect(() => {
36
37
  if (props.code && props.language) {
@@ -54,7 +55,7 @@ watchEffect(() => {
54
55
  </script>
55
56
 
56
57
  <template>
57
- <div relative>
58
+ <div class="relative">
58
59
  <TelaScrollArea
59
60
  :orientation="props.truncate ? 'vertical' : 'both'"
60
61
  :scroll-hide-delay="0"
@@ -63,32 +64,30 @@ watchEffect(() => {
63
64
  >
64
65
  <div
65
66
  v-if="isLoading"
66
- class="block w-full py-9px text-[13px] leading-[1.5] overflow-visible border-0"
67
- :class="!props.truncate ? 'pt-0.65rem' : ''"
67
+ class="block w-full text-[13px] leading-[1.5] overflow-visible border-0"
68
+ :class="props.hideLineNumbers ? 'py-9px' : [!props.truncate && 'pt-0.65rem', isSingleLine && !props.truncate ? 'pb-0.6rem' : 'pb-0.4rem']"
68
69
  :style="props.hideLineNumbers ? undefined : { backgroundColor: '#fff' }"
69
70
  >
70
71
  <div
71
- v-for="i in skeletonLineCount"
72
+ v-for="i in lineCount"
72
73
  :key="i"
73
- class="flex items-center gap-4px min-h-1.5em"
74
- :class="props.hideLineNumbers ? 'px-16px' : 'bg-white'"
74
+ class="flex items-center"
75
+ :class="props.hideLineNumbers ? 'min-h-18px pl-14px pr-48px' : 'min-h-1.5em bg-white'"
75
76
  >
76
- <pre
77
+ <span
77
78
  v-if="!props.hideLineNumbers"
78
- class="w-2.75rem text-right pr-1rem text-neutral-400 text-13px"
79
- >
80
- {{ i }}
81
- </pre>
79
+ class="w-2.75rem shrink-0 pr-1rem text-right font-mono text-neutral-400 text-13px"
80
+ >{{ i }}</span>
82
81
  <TelaSkeleton
83
- class="h-16px rounded-2px bg-neutral-200"
84
- :class="i % 3 === 0 ? 'w-full' : i % 3 === 1 ? 'w-4/5' : 'w-3/5'"
82
+ class="h-14px rounded-2px bg-neutral-200"
83
+ :class="i % 3 === 0 ? 'w-90%' : i % 3 === 1 ? 'w-4/5' : 'w-3/5'"
85
84
  />
86
85
  </div>
87
86
  </div>
88
87
  <div
89
88
  v-else
90
89
  class="block w-full text-13px leading-[1.5] overflow-visible border-0"
91
- :class="!props.truncate ? 'pt-0.65rem' : ''"
90
+ :class="[!props.truncate && 'pt-0.65rem', isSingleLine && !props.truncate && 'pb-0.2rem']"
92
91
  v-html="highlighted"
93
92
  />
94
93
  </TelaScrollArea>
@@ -97,7 +96,7 @@ watchEffect(() => {
97
96
  :content="code"
98
97
  :variant="copyButtonVariant"
99
98
  :size="copyButtonSize"
100
- :class="cn('absolute top-10px right-10px z-10', props.copyButtonClass)"
99
+ :class="cn('absolute right-8px z-10', isSingleLine ? 'top-1/2 -translate-y-1/2' : 'top-8px', props.copyButtonClass)"
101
100
  />
102
101
  </div>
103
102
  </template>
@@ -122,11 +121,18 @@ pre.shiki {
122
121
  width: fit-content;
123
122
  min-width: 100%;
124
123
  counter-reset: line;
124
+ /* collapse the \n text nodes shiki emits between .line spans — each
125
+ block .line below already breaks the line, and Nuxt Content's
126
+ ProsePre leaks a global `pre code .line { display: block }` that
127
+ would otherwise double every line break */
128
+ white-space: normal;
125
129
  }
126
130
 
127
131
  code .line {
128
132
  --line-background-color: var(--pre-background-color);
129
133
  --line-border-color: #404040;
134
+ display: block;
135
+ white-space: pre;
130
136
  width: 100%;
131
137
  counter-increment: line;
132
138
  background-color: var(--line-background-color);
@@ -12,7 +12,7 @@ A grouped collapsible component for stacking multiple expandable items in a sing
12
12
  ### Basic Usage
13
13
 
14
14
  ```vue
15
- <TelaCollapsibleGroup>
15
+ <TelaCollapsibleGroup class="w-full">
16
16
  <TelaCollapsibleGroupItem title="Item 1" :items-length="4">
17
17
  <p>Lorem ipsum dolor sit amet.</p>
18
18
  </TelaCollapsibleGroupItem>
@@ -30,7 +30,7 @@ A grouped collapsible component for stacking multiple expandable items in a sing
30
30
  Omit `itemsLength` to hide the count badge entirely.
31
31
 
32
32
  ```vue
33
- <TelaCollapsibleGroup>
33
+ <TelaCollapsibleGroup class="w-full">
34
34
  <TelaCollapsibleGroupItem title="Overview">
35
35
  <p>Just a title and content.</p>
36
36
  </TelaCollapsibleGroupItem>
@@ -45,7 +45,7 @@ Omit `itemsLength` to hide the count badge entirely.
45
45
  The count text defaults to `item` / `items`. Pass `singularLabel` and `pluralLabel` to localize or customize.
46
46
 
47
47
  ```vue
48
- <TelaCollapsibleGroup>
48
+ <TelaCollapsibleGroup class="w-full">
49
49
  <TelaCollapsibleGroupItem
50
50
  title="Documents"
51
51
  :items-length="1"
@@ -75,7 +75,7 @@ const isOpen = ref(true)
75
75
  </script>
76
76
 
77
77
  <template>
78
- <TelaCollapsibleGroup>
78
+ <TelaCollapsibleGroup class="w-full">
79
79
  <TelaCollapsibleGroupItem
80
80
  v-model:open="isOpen"
81
81
  title="Controlled Item"
@@ -92,7 +92,7 @@ const isOpen = ref(true)
92
92
  The `trigger-trailing` slot lets you place arbitrary content (badges, actions) next to the item count.
93
93
 
94
94
  ```vue
95
- <TelaCollapsibleGroup>
95
+ <TelaCollapsibleGroup class="w-full">
96
96
  <TelaCollapsibleGroupItem title="With Action" :items-length="2">
97
97
  <template #trigger-trailing>
98
98
  <TelaBadge variant="warning">Pending</TelaBadge>
@@ -18,8 +18,8 @@ const props = withDefaults(defineProps<{
18
18
  const showConfirmationIcon = ref(false)
19
19
 
20
20
  const variantStyles = computed(() => ({
21
- default: 'bg-white text-gray-400 border-0.5px border hover:bg-gray-50 hover:border-strong',
22
- ghost: 'text-gray-900 hover:bg-gray-100',
21
+ default: 'bg-white text-icon-tertiary border-0.5px border hover:bg-subtle hover:border-strong',
22
+ ghost: 'text-contrast hover:bg-muted',
23
23
  } as Record<'default' | 'ghost', string>)[props.variant])
24
24
 
25
25
  const sizeStyles = computed(() => {
@@ -70,7 +70,7 @@ const transition = {
70
70
  <button
71
71
  flex="~ " items-center justify-center
72
72
  ease will-change-transform active:scale-94
73
- class="group transition-[background-color,border-color,color,transform]"
73
+ class="group duration-80 transition-[background-color,border-color,color,transform]"
74
74
  :class="cn(isHovered === false && 'opacity-0', sizeStyles, variantStyles, props.class)"
75
75
  @click="onClick(copy)"
76
76
  >
@@ -84,7 +84,7 @@ const transition = {
84
84
  <TelaIcon
85
85
  :size="size"
86
86
  name="i-ph-copy"
87
- op-80
87
+ op-80 duration-80
88
88
  group-hover:op-100
89
89
  />
90
90
  </Motion>
@@ -97,7 +97,7 @@ const transition = {
97
97
  <TelaIcon
98
98
  :size="size"
99
99
  name="i-ph-check"
100
- op-80
100
+ op-80 duration-80
101
101
  group-hover:op-100
102
102
  />
103
103
  </Motion>
@@ -16,15 +16,16 @@ A fixed-size entry point card for creating something new from files. Click it to
16
16
  ### Default
17
17
 
18
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
19
+ <script setup>
20
+ function handleChange(event) {
21
+ const files = event.target.files
26
22
  // upload files...
27
23
  }
24
+ </script>
25
+
26
+ <template>
27
+ <TelaCreateCard @change="handleChange" />
28
+ </template>
28
29
  ```
29
30
 
30
31
  ### Custom Labels
@@ -35,7 +36,6 @@ function handleChange(event: Event) {
35
36
  description="Drop a CSV or"
36
37
  browse-label="choose a file"
37
38
  :multiple="false"
38
- @change="handleChange"
39
39
  />
40
40
  ```
41
41
 
@@ -47,23 +47,13 @@ function handleChange(event: Event) {
47
47
  title="New canvas"
48
48
  description="Drag files here"
49
49
  browse-label=""
50
- @change="handleChange"
51
50
  />
52
51
  ```
53
52
 
54
53
  ### Disabled (e.g. while uploading)
55
54
 
56
55
  ```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>
56
+ <TelaCreateCard disabled />
67
57
  ```
68
58
 
69
59
  ## Props
@@ -75,7 +75,7 @@ function onDrop(event: DragEvent) {
75
75
  relative w-221px h-128px rounded-12px p-20px
76
76
  bg border-0.5px border
77
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
78
+ not-disabled:hover:bg-subtle not-disabled:hover:border-strong active:bg-muted disabled:opacity-50 disabled:cursor-not-allowed
79
79
  :class="isDragging ? 'border-dashed border-neutral-400 bg-subtle' : 'active:border-neutral-400/60'"
80
80
  @click="openFilePicker"
81
81
  @dragenter.prevent="onDragEnter"
@@ -220,7 +220,7 @@ const handleConfirm = () => {}
220
220
 
221
221
  ## Props
222
222
 
223
- ### `TelaDetailsLeft`
223
+ ### TelaDetailsLeft
224
224
 
225
225
  ```typescript
226
226
  type DetailsLeftProps = {
@@ -228,7 +228,7 @@ type DetailsLeftProps = {
228
228
  }
229
229
  ```
230
230
 
231
- ### `TelaDetailsReviewConfirm`
231
+ ### TelaDetailsReviewConfirm
232
232
 
233
233
  ```typescript
234
234
  type ReviewConfirmProps = {
@@ -259,7 +259,7 @@ All other shell components are slot-only.
259
259
  9. **Left is the detail, right is the context — keep them asymmetric.** `TelaDetailsLeft` carries the dense, primary content (sectioned body, tables, forms, long copy); `TelaDetailsRight` stays lighter and more scannable. `TelaPreview` is the principal right-column content — a file or artifact preview alongside the primary column — but the right side can also hold simpler supporting pieces: cards, an accordion (`TelaCollapsibleGroup`), or a bit of metadata. Don't push primary detail into the right column; if it grows as complex as the left, reconsider the split.
260
260
  10. **When the page has a `TelaDetailsFooter`, close off the right column on scroll-bottom.** The sticky right column otherwise butts flush against the footer's top border with a square, open corner. Use `useDetailsScroll` to drive an `isAtBottom` flag and bind `border-b-0.5px rounded-bl-12px` to `TelaDetailsRight` so its bottom edge matches the footer when the user reaches the end. Pages **without** a footer don't need this.
261
261
 
262
- ## Scroll state — `useDetailsScroll`
262
+ ## Scroll state — useDetailsScroll
263
263
 
264
264
  > **`useDetailsScroll` gives you two independent signals — use each only when it applies:**
265
265
  >
@@ -2,8 +2,6 @@
2
2
  import type { HTMLAttributes } from 'vue'
3
3
  import type { TooltipProps } from '../tooltip/tooltip.vue'
4
4
 
5
- import { VisuallyHidden } from 'radix-vue'
6
-
7
5
  import DropdownMenuRoot from './DropdownMenuRoot.vue'
8
6
  import DropdownMenuContent from './DropdownMenuContent.vue'
9
7
  import DropdownMenuGroup from './DropdownMenuGroup.vue'
@@ -47,7 +45,6 @@ defineEmits(['click'])
47
45
 
48
46
  const search = ref('')
49
47
  const searchInputEl = ref<HTMLInputElement>()
50
- const isStorybook = Boolean(import.meta.env.STORYBOOK)
51
48
 
52
49
  const filteredItems = computed(() => search.value ? props.items.filter(item => item.label.toLowerCase().includes(search.value.toLowerCase())) : props.items)
53
50
  const groups = computed(() => filteredItems.value.reduce((acc, item) => {
@@ -77,9 +74,6 @@ function onToggle(open: boolean) {
77
74
  <DropdownMenuRoot :modal="shouldBeModal" :default-open="defaultOpen" @update:open="onToggle">
78
75
  <DropdownMenuTrigger as-child :class="cn('data-[state=open]:bg-muted', triggerClass)" @click.prevent.stop>
79
76
  <slot />
80
- <VisuallyHidden v-if="isStorybook" as-child>
81
- <button />
82
- </VisuallyHidden>
83
77
  </DropdownMenuTrigger>
84
78
 
85
79
  <DropdownMenuContent
@@ -130,25 +130,25 @@ A composable header component for fullscreen views. Provides a sticky top bar wi
130
130
 
131
131
  ## Components
132
132
 
133
- ### `TelaHeader`
133
+ ### TelaHeader
134
134
 
135
135
  Root header container. Sticky-positioned at the top with 64px height, bottom border, and full width.
136
136
 
137
137
  - **Slots:** `default` - accepts `TelaHeaderLeading`, `TelaHeaderCenter`, and `TelaHeaderTrailing`
138
138
 
139
- ### `TelaHeaderLeading`
139
+ ### TelaHeaderLeading
140
140
 
141
141
  Left-side container with 12px gap between children.
142
142
 
143
143
  - **Slots:** `default` - accepts `TelaHeaderLeadingTrigger`, `TelaHeaderLeadingContent`
144
144
 
145
- ### `TelaHeaderLeadingTrigger`
145
+ ### TelaHeaderLeadingTrigger
146
146
 
147
147
  Close button (X icon) for the leading section.
148
148
 
149
149
  - **Events:** `click` - emitted when the button is clicked
150
150
 
151
- ### `TelaHeaderLeadingContent`
151
+ ### TelaHeaderLeadingContent
152
152
 
153
153
  Layout wrapper for leading content (title + summary).
154
154
 
@@ -156,19 +156,19 @@ Layout wrapper for leading content (title + summary).
156
156
  |------|------|---------|-------------|
157
157
  | `direction` | `'vertical' \| 'horizontal'` | `'vertical'` | Layout direction for child elements |
158
158
 
159
- ### `TelaHeaderLeadingTitle`
159
+ ### TelaHeaderLeadingTitle
160
160
 
161
161
  H5 heading element with semibold weight and primary text color.
162
162
 
163
163
  - **Slots:** `default` - heading text
164
164
 
165
- ### `TelaHeaderLeadingSummary`
165
+ ### TelaHeaderLeadingSummary
166
166
 
167
167
  Horizontal container (8px gap) for status and metadata items.
168
168
 
169
169
  - **Slots:** `default` - accepts status, content, and separators
170
170
 
171
- ### `TelaHeaderLeadingSummaryStatus`
171
+ ### TelaHeaderLeadingSummaryStatus
172
172
 
173
173
  Status indicator using `TelaStatus` with 12px medium body text.
174
174
 
@@ -178,35 +178,35 @@ Status indicator using `TelaStatus` with 12px medium body text.
178
178
  | `label` | `string` | - | Status label text |
179
179
  | `labelClass` | `HTMLAttributes['class']` | - | Additional CSS class for the label |
180
180
 
181
- ### `TelaHeaderLeadingSummaryContent`
181
+ ### TelaHeaderLeadingSummaryContent
182
182
 
183
183
  Inner wrapper for summary items with 6px gap.
184
184
 
185
185
  - **Slots:** `default` - accepts `TelaHeaderLabel` and `TelaHeaderLeadingSummarySeparator`
186
186
 
187
- ### `TelaHeaderLeadingSummarySeparator`
187
+ ### TelaHeaderLeadingSummarySeparator
188
188
 
189
189
  Small circular dot separator (3px) for summary content. Has `aria-hidden="true"`.
190
190
 
191
- ### `TelaHeaderLabel`
191
+ ### TelaHeaderLabel
192
192
 
193
193
  12px regular body text with secondary color. Use for metadata labels (counts, timestamps, pagination indicators).
194
194
 
195
195
  - **Slots:** `default` - label text
196
196
 
197
- ### `TelaHeaderCenter`
197
+ ### TelaHeaderCenter
198
198
 
199
199
  Absolutely positioned center section (horizontally centered via `left: 50%; transform: translateX(-50%)`).
200
200
 
201
201
  - **Slots:** `default` - accepts `TelaHeaderCenterSteps`
202
202
 
203
- ### `TelaHeaderCenterSteps`
203
+ ### TelaHeaderCenterSteps
204
204
 
205
205
  Container for step indicators with muted background and 12px gap.
206
206
 
207
207
  - **Slots:** `default` - accepts `TelaHeaderCenterStepsItem` and `TelaHeaderCenterStepsSeparator`
208
208
 
209
- ### `TelaHeaderCenterStepsItem`
209
+ ### TelaHeaderCenterStepsItem
210
210
 
211
211
  Individual step with a numbered circle indicator and label.
212
212
 
@@ -216,29 +216,29 @@ Individual step with a numbered circle indicator and label.
216
216
  | `label` | `string` | - | Step label text |
217
217
  | `disabled` | `boolean` | `false` | Dims the step with tertiary colors |
218
218
 
219
- ### `TelaHeaderCenterStepsSeparator`
219
+ ### TelaHeaderCenterStepsSeparator
220
220
 
221
221
  Horizontal line separator (16px wide, 1px height) between steps. Has `aria-hidden="true"`.
222
222
 
223
- ### `TelaHeaderTrailing`
223
+ ### TelaHeaderTrailing
224
224
 
225
225
  Right-side container with 16px gap between children.
226
226
 
227
227
  - **Slots:** `default` - accepts `TelaHeaderTrailingContent` and `TelaHeaderTrailingActions`
228
228
 
229
- ### `TelaHeaderTrailingContent`
229
+ ### TelaHeaderTrailingContent
230
230
 
231
231
  Wrapper for trailing items with 12px gap.
232
232
 
233
233
  - **Slots:** `default` - accepts labels, pagination, buttons
234
234
 
235
- ### `TelaHeaderTrailingPagination`
235
+ ### TelaHeaderTrailingPagination
236
236
 
237
237
  Tight container (2px gap) for prev/next navigation buttons.
238
238
 
239
239
  - **Slots:** `default` - accepts `TelaHeaderTrailingPaginationPrevButton` and `TelaHeaderTrailingPaginationNextButton`
240
240
 
241
- ### `TelaHeaderTrailingPaginationPrevButton`
241
+ ### TelaHeaderTrailingPaginationPrevButton
242
242
 
243
243
  Previous navigation button with left caret icon.
244
244
 
@@ -248,7 +248,7 @@ Previous navigation button with left caret icon.
248
248
 
249
249
  - **Events:** `click` - emitted when the button is clicked
250
250
 
251
- ### `TelaHeaderTrailingPaginationNextButton`
251
+ ### TelaHeaderTrailingPaginationNextButton
252
252
 
253
253
  Next navigation button with right caret icon.
254
254
 
@@ -258,7 +258,7 @@ Next navigation button with right caret icon.
258
258
 
259
259
  - **Events:** `click` - emitted when the button is clicked
260
260
 
261
- ### `TelaHeaderTrailingActions`
261
+ ### TelaHeaderTrailingActions
262
262
 
263
263
  Three-dot dropdown menu for contextual actions.
264
264