@meistrari/tela-build 1.56.1 → 1.57.1
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/components/tela/breadcrumbs/breadcrumbs-item.vue +34 -0
- package/components/tela/breadcrumbs/breadcrumbs-separator.vue +5 -0
- package/components/tela/breadcrumbs/breadcrumbs.mdx +49 -0
- package/components/tela/breadcrumbs/breadcrumbs.vue +7 -0
- package/components/tela/button/button.mdx +4 -4
- package/components/tela/checkbox/checkbox-card.vue +4 -4
- package/components/tela/checkbox/checkbox.mdx +9 -8
- package/components/tela/code-block/code-block.mdx +0 -2
- package/components/tela/code-block/code-block.vue +22 -16
- package/components/tela/collapsible-group/collapsible-group.mdx +5 -5
- package/components/tela/copy-button.vue +5 -5
- package/components/tela/create-card/create-card.mdx +9 -19
- package/components/tela/create-card/create-card.vue +1 -1
- package/components/tela/details/details.mdx +3 -3
- package/components/tela/dropdown-menu/DropdownMenu.vue +0 -6
- package/components/tela/expandable-input.vue +2 -1
- package/components/tela/header/header.mdx +20 -20
- package/components/tela/home/home.mdx +3 -3
- package/components/tela/hover-card/hover-card.mdx +1 -4
- package/components/tela/icon-button/icon-button.vue +2 -2
- package/components/tela/icon.vue +1 -1
- package/components/tela/input/input.vue +0 -1
- package/components/tela/sidebar/sidebar.mdx +7 -7
- package/components/tela/switch/switch.vue +1 -1
- package/components/tela/tabs/tabs.vue +2 -1
- package/components/tela/tags/tags-select.vue +3 -11
- package/components/tela/tags/tags.vue +2 -2
- package/components/tela/textarea/textarea.mdx +1 -0
- package/components/tela/tooltip-group/tooltip-group-trigger.vue +5 -0
- package/docs/typography.md +30 -20
- package/lib/__tests__/doc-generator.test.ts +141 -1
- package/lib/doc-generator.ts +169 -17
- package/nuxt.config.ts +2 -6
- package/package.json +2 -13
- package/utils/citations.ts +12 -1
- package/utils/design-tokens.ts +124 -60
- package/components/tela/animated/animated-number.stories.ts +0 -52
- package/components/tela/avatar/avatar.stories.ts +0 -62
- package/components/tela/avatar/group/avatar-group.stories.ts +0 -78
- package/components/tela/avatar/label/avatar-label.stories.ts +0 -74
- package/components/tela/badge/badge.stories.ts +0 -82
- package/components/tela/button/button.stories.ts +0 -202
- package/components/tela/card/card.stories.ts +0 -143
- package/components/tela/chat/chat.stories.ts +0 -253
- package/components/tela/chat/text-input/chat-text-input.stories.ts +0 -128
- package/components/tela/chat/text-message/chat-text-message.stories.ts +0 -138
- package/components/tela/checkbox/checkbox.stories.ts +0 -104
- package/components/tela/code-block/code-block.stories.ts +0 -226
- package/components/tela/collapsible-group/collapsible-group.stories.ts +0 -134
- package/components/tela/collapsible-section/collapsible-section.stories.ts +0 -53
- package/components/tela/combobox/combobox.stories.ts +0 -237
- package/components/tela/complex-table/complex-table-cell.stories.ts +0 -144
- package/components/tela/complex-table/complex-table-header-cell.stories.ts +0 -102
- package/components/tela/complex-table/complex-table-header.stories.ts +0 -88
- package/components/tela/complex-table/complex-table.stories.ts +0 -353
- package/components/tela/create-card/create-card.stories.ts +0 -133
- package/components/tela/disclaimer/disclaimer.stories.ts +0 -196
- package/components/tela/dropdown-menu/dropdown-menu.stories.ts +0 -163
- package/components/tela/file-upload/file-upload.stories.ts +0 -48
- package/components/tela/filter/filter.stories.ts +0 -596
- package/components/tela/filters/checkbox-filter.stories.ts +0 -218
- package/components/tela/filters/date-filter.stories.ts +0 -258
- package/components/tela/filters/user-filter.stories.ts +0 -344
- package/components/tela/header/header.stories.ts +0 -222
- package/components/tela/heading-tabs/heading-tabs.stories.ts +0 -111
- package/components/tela/hover-card/hover-card.stories.ts +0 -87
- package/components/tela/input/input.stories.ts +0 -148
- package/components/tela/input-otp/input-otp.stories.ts +0 -138
- package/components/tela/label/label.stories.ts +0 -37
- package/components/tela/multiple-select/multiple-select.stories.ts +0 -325
- package/components/tela/playback-timeline/playback-timeline.stories.ts +0 -66
- package/components/tela/popover/popover.stories.ts +0 -150
- package/components/tela/popover-list/popover-list.stories.ts +0 -330
- package/components/tela/preview/preview.stories.ts +0 -217
- package/components/tela/progress-bar/progress-bar.stories.ts +0 -148
- package/components/tela/radio-group/radio-group.stories.ts +0 -106
- package/components/tela/range-calendar.stories.ts +0 -110
- package/components/tela/scroll-area/scroll-area.stories.ts +0 -129
- package/components/tela/segment-bar/segment-bar.stories.ts +0 -115
- package/components/tela/segment-toggle/segment-toggle.stories.ts +0 -113
- package/components/tela/select-menu/select-menu.stories.ts +0 -91
- package/components/tela/sheet/sheet.stories.ts +0 -201
- package/components/tela/side-sheet/side-sheet.stories.ts +0 -134
- package/components/tela/sidebar/sidebar.stories.ts +0 -250
- package/components/tela/skeleton/skeleton.stories.ts +0 -35
- package/components/tela/status/status.stories.ts +0 -212
- package/components/tela/status-bar/status-bar.stories.ts +0 -64
- package/components/tela/switch/switch.stories.ts +0 -80
- package/components/tela/table/table.stories.ts +0 -384
- package/components/tela/tabs/tabs.stories.ts +0 -72
- package/components/tela/tags/tags-select.stories.ts +0 -47
- package/components/tela/tags/tags.stories.ts +0 -161
- package/components/tela/textarea/textarea.stories.ts +0 -50
- package/components/tela/timeline-waterfall/timeline-waterfall.stories.ts +0 -151
- package/components/tela/tooltip/tooltip.stories.ts +0 -200
- package/components/tela/tooltip-group/tooltip-group.stories.ts +0 -465
- package/components/tela/uploader/uploader.stories.ts +0 -416
- package/composables/optimistic-async-data/stories/optimistic-async-data-collection.stories.ts +0 -47
- 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,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`).
|
|
@@ -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
|
-
<!--
|
|
19
|
+
<!-- Correct — icon on the leading side -->
|
|
20
20
|
<TelaButton icon="i-ph-export" leading>Export</TelaButton>
|
|
21
21
|
|
|
22
|
-
<!--
|
|
22
|
+
<!-- Correct — icon on the trailing side (default) -->
|
|
23
23
|
<TelaButton icon="i-ph-arrow-right">Next</TelaButton>
|
|
24
24
|
|
|
25
|
-
<!--
|
|
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
|
-
<!--
|
|
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
|
|
16
|
-
'has-[[aria-checked=false]]:hover:bg-
|
|
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-
|
|
22
|
+
<h4 class="body-12-medium text-primary">
|
|
23
23
|
{{ label }}
|
|
24
24
|
</h4>
|
|
25
|
-
<p class="body-12-regular text-
|
|
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
|
-
<
|
|
54
|
+
<TelaLabel for="terms" class="cursor-pointer">
|
|
55
55
|
I accept the terms and conditions
|
|
56
|
-
</
|
|
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
|
|
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="
|
|
83
|
+
v-model="notifications"
|
|
83
84
|
value="notifications"
|
|
84
85
|
name="preferences"
|
|
85
86
|
/>
|
|
86
|
-
<
|
|
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="
|
|
93
|
+
v-model="newsletter"
|
|
93
94
|
value="newsletter"
|
|
94
95
|
name="preferences"
|
|
95
96
|
/>
|
|
96
|
-
<
|
|
97
|
+
<TelaLabel for="newsletter" class="cursor-pointer">Subscribe to newsletter</TelaLabel>
|
|
97
98
|
</div>
|
|
98
99
|
</form>
|
|
99
100
|
</template>
|
|
@@ -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
|
|
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
|
|
67
|
-
:class="!props.truncate
|
|
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
|
|
72
|
+
v-for="i in lineCount"
|
|
72
73
|
:key="i"
|
|
73
|
-
class="flex items-center
|
|
74
|
-
:class="props.hideLineNumbers ? '
|
|
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
|
-
<
|
|
77
|
+
<span
|
|
77
78
|
v-if="!props.hideLineNumbers"
|
|
78
|
-
class="w-2.75rem
|
|
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-
|
|
84
|
-
:class="i % 3 === 0 ? 'w-
|
|
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
|
|
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
|
|
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-
|
|
22
|
-
ghost: 'text-
|
|
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
|
-
<
|
|
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
|
|
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
|
-
###
|
|
223
|
+
### TelaDetailsLeft
|
|
224
224
|
|
|
225
225
|
```typescript
|
|
226
226
|
type DetailsLeftProps = {
|
|
@@ -228,7 +228,7 @@ type DetailsLeftProps = {
|
|
|
228
228
|
}
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
-
###
|
|
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 —
|
|
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
|
|
@@ -7,7 +7,7 @@ const props = defineProps<{
|
|
|
7
7
|
|
|
8
8
|
const internalValue = defineModel<string>()
|
|
9
9
|
|
|
10
|
-
const isEditing =
|
|
10
|
+
const isEditing = defineModel<boolean>('editing', { default: false })
|
|
11
11
|
const containerEl = ref<HTMLDivElement | null>()
|
|
12
12
|
const inputEl = ref<HTMLTextAreaElement | null>()
|
|
13
13
|
|
|
@@ -84,6 +84,7 @@ function onStopEditing() {
|
|
|
84
84
|
font-inherit
|
|
85
85
|
tabindex="0"
|
|
86
86
|
border-0.5px border
|
|
87
|
+
shadow-flying
|
|
87
88
|
:spellcheck="false"
|
|
88
89
|
v-bind="$attrs"
|
|
89
90
|
@keydown.enter="onStopEditing"
|
|
@@ -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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
187
|
+
### TelaHeaderLeadingSummarySeparator
|
|
188
188
|
|
|
189
189
|
Small circular dot separator (3px) for summary content. Has `aria-hidden="true"`.
|
|
190
190
|
|
|
191
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
219
|
+
### TelaHeaderCenterStepsSeparator
|
|
220
220
|
|
|
221
221
|
Horizontal line separator (16px wide, 1px height) between steps. Has `aria-hidden="true"`.
|
|
222
222
|
|
|
223
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
###
|
|
261
|
+
### TelaHeaderTrailingActions
|
|
262
262
|
|
|
263
263
|
Three-dot dropdown menu for contextual actions.
|
|
264
264
|
|