@meistrari/tela-build 1.74.3 → 1.75.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/CHANGELOG.md +14 -0
- package/components/tela/chat/chat-empty-state.vue +3 -3
- package/components/tela/chat/chat-model-selector.vue +1 -1
- package/components/tela/chat/chat-shell-context.ts +6 -0
- package/components/tela/chat/chat.mdx +93 -128
- package/components/tela/chat/floating/floating-window.vue +2 -0
- package/components/tela/chat/prompt-input/prompt-input-action-menu.vue +7 -1
- package/components/tela/chat/prompt-input/prompt-input-textarea.vue +0 -1
- package/components/tela/chat/prompt-input/prompt-input.vue +6 -1
- package/components/tela/chat/sidepanel/sidepanel-window.vue +6 -0
- package/components/tela/combobox/combobox-trigger.vue +1 -1
- package/components/tela/icon-button/icon-button.vue +1 -1
- package/components/tela/select-menu/select-menu-content.vue +2 -2
- package/components/tela/select-menu/select-menu-trigger.vue +1 -1
- package/package.json +1 -1
- package/utils/design-tokens.ts +27 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Latest updates and announcements.
|
|
4
4
|
|
|
5
|
+
## September 22, 2026
|
|
6
|
+
|
|
7
|
+
- [Prompt Input](/templates/chat#prompt-input) adapts to its shell: inside `TelaChatFloatingWindow` and `TelaChatSidepanelWindow` it uses a 12px radius and 8px right padding, and the action menu trigger stays inline. On full-page chats it keeps the 16px radius and pulls the trigger flush with the editor.
|
|
8
|
+
|
|
9
|
+
- [Empty State](/templates/chat#empty-state) uses the `heading-h3` and `body-14` type scale instead of custom sizes, with 4px between title and description.
|
|
10
|
+
|
|
11
|
+
- [Model Selector](/templates/chat#model-selector) trigger uses `body-14-medium` with 7px vertical padding, and its caret is now `icon-tertiary`, matching the select menu.
|
|
12
|
+
|
|
13
|
+
- [Icon Button](/components/icon-button) `sm` padding is 7px so the button lands on 32px with its 18px (`md`) icon.
|
|
14
|
+
|
|
15
|
+
- [Select Menu](/components/select-menu) and [Combobox](/components/combobox) caret uses `icon-tertiary`.
|
|
16
|
+
|
|
17
|
+
- [Colors](/colors) adds `taupe` and `stone` palettes: warm and cool neutral scales available as `bg-`, `text-`, and `border-` utilities.
|
|
18
|
+
|
|
5
19
|
## September 18, 2026
|
|
6
20
|
|
|
7
21
|
- [Floating chat](/templates/chat#floating) docs now show `TelaChatAnswer` docked above the prompt input inside the window.
|
|
@@ -15,16 +15,16 @@ defineProps<{
|
|
|
15
15
|
:class="compact ? 'gap-24px px-12px pt-16px' : 'gap-40px px-24px'"
|
|
16
16
|
>
|
|
17
17
|
<div flex="~ col" gap-32px :class="compact ? 'mt-auto' : ''">
|
|
18
|
-
<div v-if="title || description" flex="~ col" items-center gap-
|
|
18
|
+
<div v-if="title || description" flex="~ col" items-center gap-4px text-center>
|
|
19
19
|
<component
|
|
20
20
|
:is="compact ? 'h5' : 'h1'"
|
|
21
21
|
v-if="title"
|
|
22
22
|
text-primary
|
|
23
|
-
:class="compact ? 'heading-h4-semibold' : '
|
|
23
|
+
:class="compact ? 'heading-h4-semibold' : 'heading-h3-semibold'"
|
|
24
24
|
>
|
|
25
25
|
{{ title }}
|
|
26
26
|
</component>
|
|
27
|
-
<p v-if="description" text-secondary
|
|
27
|
+
<p v-if="description" text-secondary body-14-regular>
|
|
28
28
|
{{ description }}
|
|
29
29
|
</p>
|
|
30
30
|
</div>
|
|
@@ -58,7 +58,7 @@ function getTabLabel(tab: string) {
|
|
|
58
58
|
:get-tab-label="getTabLabel"
|
|
59
59
|
icon-class="scale-90"
|
|
60
60
|
content-class="w-[min(440px,calc(100vw-32px))]"
|
|
61
|
-
trigger-class="rounded-8px! gap-6px! bg-transparent! border-none! hover:bg-muted! shadow-none! duration-80 pl-10px! pr-8px! data-[state=open]:bg-muted!"
|
|
61
|
+
trigger-class="rounded-8px! gap-6px! bg-transparent! body-14-medium! py-7px! border-none! hover:bg-muted! shadow-none! duration-80 pl-10px! pr-8px! data-[state=open]:bg-muted!"
|
|
62
62
|
@update:model-value="model = $event ?? null"
|
|
63
63
|
/>
|
|
64
64
|
</template>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { InjectionKey } from 'vue'
|
|
2
|
+
|
|
3
|
+
export type ChatShell = 'floating' | 'sidepanel'
|
|
4
|
+
|
|
5
|
+
/** Provided by `TelaChatFloatingWindow` and `TelaChatSidepanelWindow` so nested primitives can adapt to the shell. */
|
|
6
|
+
export const chatShellContextKey: InjectionKey<ChatShell> = Symbol('tela-chat-shell')
|
|
@@ -149,11 +149,8 @@ The window opens over its own launcher: the surface springs out of the launcher'
|
|
|
149
149
|
|
|
150
150
|
The widget header inside the window gets two extra actions automatically: **expand** grows the window until 8px from the top of the viewport (and back), and **minimize** closes it. See [Widget Header & History](#widget-header--history).
|
|
151
151
|
|
|
152
|
-
When the assistant needs a decision, dock a [`TelaChatAnswer`](#answer) above the prompt input: wrap both in one `[data-chat-composer]` element with a 12px gap so `TelaChatBody` pins and measures them together.
|
|
153
|
-
|
|
154
152
|
```vue
|
|
155
153
|
<script setup lang="ts">
|
|
156
|
-
import type { TelaChatAnswerQuestion } from '@meistrari/tela-build/types'
|
|
157
154
|
import { getMimeTypeIcon } from '@meistrari/tela-build/utils/files'
|
|
158
155
|
|
|
159
156
|
const isOpen = ref(false)
|
|
@@ -176,61 +173,6 @@ const conversations = [
|
|
|
176
173
|
{ id: 'c2', title: 'Sidepanel layout questions' },
|
|
177
174
|
{ id: 'c3', title: 'Model selector options' },
|
|
178
175
|
]
|
|
179
|
-
|
|
180
|
-
// The assistant needs a decision before it continues. The host owns the
|
|
181
|
-
// question sequence and the selection; the card only emits intent.
|
|
182
|
-
const questions: TelaChatAnswerQuestion[] = [
|
|
183
|
-
{
|
|
184
|
-
id: 'tone',
|
|
185
|
-
title: 'Which tone should the announcement use?',
|
|
186
|
-
type: 'single',
|
|
187
|
-
recommendFirst: true,
|
|
188
|
-
options: [
|
|
189
|
-
{ id: 'concise', label: 'Concise', description: 'Short and factual, for the changelog.' },
|
|
190
|
-
{ id: 'friendly', label: 'Friendly', description: 'Warmer copy, for the newsletter.' },
|
|
191
|
-
{ id: 'formal', label: 'Formal', description: 'For enterprise customers.' },
|
|
192
|
-
],
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
id: 'sections',
|
|
196
|
-
title: 'Which sections should it include?',
|
|
197
|
-
type: 'multiple',
|
|
198
|
-
options: [
|
|
199
|
-
{ id: 'highlights', label: 'Highlights' },
|
|
200
|
-
{ id: 'breaking', label: 'Breaking changes' },
|
|
201
|
-
{ id: 'upgrade', label: 'Upgrade guide' },
|
|
202
|
-
],
|
|
203
|
-
},
|
|
204
|
-
]
|
|
205
|
-
const index = ref(0)
|
|
206
|
-
const expanded = ref(true)
|
|
207
|
-
const answering = ref(true)
|
|
208
|
-
const answers = ref<Record<string, string[]>>({})
|
|
209
|
-
const question = computed(() => questions[index.value]!)
|
|
210
|
-
const selected = computed(() => answers.value[question.value.id] ?? [])
|
|
211
|
-
|
|
212
|
-
function select(id: string) {
|
|
213
|
-
answers.value[question.value.id] = [id]
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function toggle(id: string, checked: boolean) {
|
|
217
|
-
answers.value[question.value.id] = checked
|
|
218
|
-
? [...selected.value, id]
|
|
219
|
-
: selected.value.filter(value => value !== id)
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function advance() {
|
|
223
|
-
if (index.value < questions.length - 1) {
|
|
224
|
-
index.value++
|
|
225
|
-
return
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const summary = questions
|
|
229
|
-
.map(item => `${item.title} ${(answers.value[item.id] ?? []).join(', ') || 'skipped'}`)
|
|
230
|
-
.join(' ')
|
|
231
|
-
messages.value.push({ id: `${Date.now()}`, role: 'user', text: summary })
|
|
232
|
-
answering.value = false
|
|
233
|
-
}
|
|
234
176
|
</script>
|
|
235
177
|
|
|
236
178
|
<template>
|
|
@@ -255,76 +197,53 @@ function advance() {
|
|
|
255
197
|
</TelaChatConversationContent>
|
|
256
198
|
</TelaChatConversation>
|
|
257
199
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
<
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
<
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
<TelaChatPromptInputActionMenuSub>
|
|
306
|
-
<TelaChatPromptInputActionMenuSubTrigger icon="i-ph-notepad" icon-size="16px">
|
|
307
|
-
Skills
|
|
308
|
-
</TelaChatPromptInputActionMenuSubTrigger>
|
|
309
|
-
<TelaChatPromptInputActionMenuSubContent>
|
|
310
|
-
<TelaChatPromptInputActionMenuItem
|
|
311
|
-
v-for="skill in skills"
|
|
312
|
-
:key="skill.id"
|
|
313
|
-
@click="draft = skill.label"
|
|
314
|
-
>
|
|
315
|
-
<span class="min-w-0 max-w-200px truncate">{{ skill.label }}</span>
|
|
316
|
-
</TelaChatPromptInputActionMenuItem>
|
|
317
|
-
</TelaChatPromptInputActionMenuSubContent>
|
|
318
|
-
</TelaChatPromptInputActionMenuSub>
|
|
319
|
-
</TelaChatPromptInputActionMenuContent>
|
|
320
|
-
</TelaChatPromptInputActionMenu>
|
|
321
|
-
</TelaChatPromptInputTools>
|
|
322
|
-
<TelaChatPromptInputActions>
|
|
323
|
-
<TelaChatPromptSubmitButton status="ready" :disabled="!draft.trim()" />
|
|
324
|
-
</TelaChatPromptInputActions>
|
|
325
|
-
</TelaChatPromptInputToolbar>
|
|
326
|
-
</TelaChatPromptInput>
|
|
327
|
-
</div>
|
|
200
|
+
<TelaChatPromptInput>
|
|
201
|
+
<TelaChatPromptInputTextarea placeholder="Ask anything" :empty="!draft" />
|
|
202
|
+
<TelaChatPromptInputToolbar>
|
|
203
|
+
<TelaChatPromptInputTools>
|
|
204
|
+
<TelaChatPromptInputActionMenu>
|
|
205
|
+
<TelaChatPromptInputActionMenuTrigger />
|
|
206
|
+
<TelaChatPromptInputActionMenuContent>
|
|
207
|
+
<TelaChatPromptInputActionMenuItem icon="i-ph-paperclip">
|
|
208
|
+
Add files or photos
|
|
209
|
+
</TelaChatPromptInputActionMenuItem>
|
|
210
|
+
<TelaChatPromptInputActionMenuSub>
|
|
211
|
+
<TelaChatPromptInputActionMenuSubTrigger icon="i-ph-clock-counter-clockwise">
|
|
212
|
+
Recent files
|
|
213
|
+
</TelaChatPromptInputActionMenuSubTrigger>
|
|
214
|
+
<TelaChatPromptInputActionMenuSubContent>
|
|
215
|
+
<TelaChatPromptInputActionMenuItem
|
|
216
|
+
v-for="file in recentFiles"
|
|
217
|
+
:key="file.id"
|
|
218
|
+
>
|
|
219
|
+
<img :src="getMimeTypeIcon(file.type)" class="w-16px h-16px mr-8px shrink-0" alt="">
|
|
220
|
+
<span class="min-w-0 max-w-200px truncate">{{ file.label }}</span>
|
|
221
|
+
</TelaChatPromptInputActionMenuItem>
|
|
222
|
+
</TelaChatPromptInputActionMenuSubContent>
|
|
223
|
+
</TelaChatPromptInputActionMenuSub>
|
|
224
|
+
<TelaMenubarSeparator />
|
|
225
|
+
<TelaChatPromptInputActionMenuSub>
|
|
226
|
+
<TelaChatPromptInputActionMenuSubTrigger icon="i-ph-notepad" icon-size="16px">
|
|
227
|
+
Skills
|
|
228
|
+
</TelaChatPromptInputActionMenuSubTrigger>
|
|
229
|
+
<TelaChatPromptInputActionMenuSubContent>
|
|
230
|
+
<TelaChatPromptInputActionMenuItem
|
|
231
|
+
v-for="skill in skills"
|
|
232
|
+
:key="skill.id"
|
|
233
|
+
@click="draft = skill.label"
|
|
234
|
+
>
|
|
235
|
+
<span class="min-w-0 max-w-200px truncate">{{ skill.label }}</span>
|
|
236
|
+
</TelaChatPromptInputActionMenuItem>
|
|
237
|
+
</TelaChatPromptInputActionMenuSubContent>
|
|
238
|
+
</TelaChatPromptInputActionMenuSub>
|
|
239
|
+
</TelaChatPromptInputActionMenuContent>
|
|
240
|
+
</TelaChatPromptInputActionMenu>
|
|
241
|
+
</TelaChatPromptInputTools>
|
|
242
|
+
<TelaChatPromptInputActions>
|
|
243
|
+
<TelaChatPromptSubmitButton status="ready" :disabled="!draft.trim()" />
|
|
244
|
+
</TelaChatPromptInputActions>
|
|
245
|
+
</TelaChatPromptInputToolbar>
|
|
246
|
+
</TelaChatPromptInput>
|
|
328
247
|
</TelaChatBody>
|
|
329
248
|
</TelaChatFloatingWindow>
|
|
330
249
|
</div>
|
|
@@ -1740,3 +1659,49 @@ type TextShimmerProps = {
|
|
|
1740
1659
|
<TelaChatConversation />
|
|
1741
1660
|
</div>
|
|
1742
1661
|
```
|
|
1662
|
+
|
|
1663
|
+
## Folder Map
|
|
1664
|
+
|
|
1665
|
+
Where each primitive lives in `components/tela/chat/`. Component names come from the file path
|
|
1666
|
+
(`chat/chat-widget-header.vue` → `TelaChatWidgetHeader`).
|
|
1667
|
+
|
|
1668
|
+
### Shells
|
|
1669
|
+
|
|
1670
|
+
| Folder / file | What it is |
|
|
1671
|
+
| --- | --- |
|
|
1672
|
+
| `floating/` | `TelaChatFloatingWindow` popover shell, its launcher `TelaChatFloatingWindowTrigger`, escape-layer tracking, and the window context (expand, close). |
|
|
1673
|
+
| `sidepanel/` | `TelaChatSidepanelWindow`, the in-flow docked shell. |
|
|
1674
|
+
| `chat-shell-context.ts` | Injection key both shells provide (`floating` or `sidepanel`) so nested primitives can adapt. |
|
|
1675
|
+
| `chat-widget-*.vue` | Chrome shared by the shells: `TelaChatWidgetHeader`, `TelaChatWidgetCard`, `TelaChatWidgetHistoryList`, `TelaChatWidgetSources` / `Source`. |
|
|
1676
|
+
|
|
1677
|
+
### Body and conversation
|
|
1678
|
+
|
|
1679
|
+
| Folder / file | What it is |
|
|
1680
|
+
| --- | --- |
|
|
1681
|
+
| `chat-body.vue` | `TelaChatBody`, the scroll region that docks the prompt input and pads the conversation for it. `variant="widget"` or `"page"`. |
|
|
1682
|
+
| `conversation/` | `TelaChatConversation` and `TelaChatConversationContent`, the message list. |
|
|
1683
|
+
| `message/` | `TelaChatMessage` with avatar, content, and feedback controls. |
|
|
1684
|
+
| `answer/` | `TelaChatAnswer`, choice questions the assistant asks inline. |
|
|
1685
|
+
| `chat-empty-state.vue` | `TelaChatEmptyState`, shown before the first message. |
|
|
1686
|
+
| `chat-suggestions.vue`, `chat-suggestion.vue` | Suggested prompts. |
|
|
1687
|
+
| `chat-reasoning-step.vue` | `TelaChatReasoningStep`, collapsible tool or reasoning entry. |
|
|
1688
|
+
| `chat-text-shimmer.vue` | `TelaChatTextShimmer`, streaming placeholder text. |
|
|
1689
|
+
|
|
1690
|
+
### Composer and run state
|
|
1691
|
+
|
|
1692
|
+
| Folder / file | What it is |
|
|
1693
|
+
| --- | --- |
|
|
1694
|
+
| `prompt-input/` | `TelaChatPromptInput` and its parts: textarea, toolbar, tools, action menu, attachments, hints. |
|
|
1695
|
+
| `chat-prompt-submit-button.vue` | `TelaChatPromptSubmitButton`, the send control. |
|
|
1696
|
+
| `chat-model-selector.vue` | `TelaChatModelSelector`, model picker for the toolbar. |
|
|
1697
|
+
| `chat-working-indicator.vue` | `TelaChatWorkingIndicator`, running-turn row with elapsed time. |
|
|
1698
|
+
| `chat-stop-run-button.vue` | `TelaChatStopRunButton`, replaces the prompt input while a turn runs. |
|
|
1699
|
+
| `chat-animate-enter.vue` | `TelaChatAnimateEnter`, enter/exit preset for swapping the input and stop button. |
|
|
1700
|
+
| `chat-powered-by-tela.vue` | `TelaChatPoweredByTela` footer. |
|
|
1701
|
+
| `icons/` | Provider marks (`TelaChatIconsAnthropic`, `Openai`, `Gemini`) and the Tela wordmark. |
|
|
1702
|
+
|
|
1703
|
+
### Legacy thread chat
|
|
1704
|
+
|
|
1705
|
+
`index.vue` (`TelaChat`), `text-message/`, `text-input/`, `pure-text-input/`, `command/`,
|
|
1706
|
+
and `types.ts` are the older comment-thread chat used by the application. They are kept
|
|
1707
|
+
as is; new work should compose the primitives above.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { hasOpenEscapeLayer } from './escape-layer'
|
|
3
|
+
import { chatShellContextKey } from '../chat-shell-context'
|
|
3
4
|
import { floatingWindowContextKey } from './floating-window-context'
|
|
4
5
|
|
|
5
6
|
const props = withDefaults(defineProps<{
|
|
@@ -90,6 +91,7 @@ onMounted(() => {
|
|
|
90
91
|
measureLauncher()
|
|
91
92
|
})
|
|
92
93
|
|
|
94
|
+
provide(chatShellContextKey, 'floating')
|
|
93
95
|
provide(floatingWindowContextKey, {
|
|
94
96
|
expanded,
|
|
95
97
|
toggleExpanded: () => {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { chatShellContextKey } from '../chat-shell-context'
|
|
3
|
+
|
|
4
|
+
const isWidgetShell = Boolean(inject(chatShellContextKey, null))
|
|
5
|
+
</script>
|
|
6
|
+
|
|
1
7
|
<template>
|
|
2
|
-
<div ml--8px>
|
|
8
|
+
<div :class="cn(isWidgetShell ? 'ml--8px' : 'ml--10px')">
|
|
3
9
|
<TelaMenubarRoot>
|
|
4
10
|
<TelaMenubarMenu>
|
|
5
11
|
<slot />
|
|
@@ -28,7 +28,6 @@ const EDITOR_MAX_HEIGHT = 228
|
|
|
28
28
|
const COMPACT_EDITOR_MAX_HEIGHT = 140
|
|
29
29
|
|
|
30
30
|
const editorRef = ref<HTMLElement | null>(null)
|
|
31
|
-
// Widget-variant bodies get the lower editor cap; full-page bodies the taller one.
|
|
32
31
|
const isCompact = ref(false)
|
|
33
32
|
|
|
34
33
|
const maxHeight = computed(() => isCompact.value ? COMPACT_EDITOR_MAX_HEIGHT : EDITOR_MAX_HEIGHT)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { chatShellContextKey } from '../chat-shell-context'
|
|
3
|
+
|
|
2
4
|
const props = defineProps<{
|
|
3
5
|
/** Locked inputs render muted and non-interactive. */
|
|
4
6
|
locked?: boolean
|
|
@@ -6,6 +8,8 @@ const props = defineProps<{
|
|
|
6
8
|
|
|
7
9
|
const rootRef = ref<HTMLElement | null>(null)
|
|
8
10
|
|
|
11
|
+
const isWidgetShell = Boolean(inject(chatShellContextKey, null))
|
|
12
|
+
|
|
9
13
|
const INTERACTIVE = '[data-prompt-editor], button, a, input, select, textarea, [contenteditable], [role="button"], [role="combobox"], [role="menuitem"], [role="option"]'
|
|
10
14
|
|
|
11
15
|
function focusEditor(event: MouseEvent) {
|
|
@@ -42,7 +46,8 @@ function focusEditor(event: MouseEvent) {
|
|
|
42
46
|
ref="rootRef"
|
|
43
47
|
data-chat-prompt-input
|
|
44
48
|
:class="cn(
|
|
45
|
-
'flex flex-col
|
|
49
|
+
'flex flex-col bg border-[0.5px] border-strong overflow-hidden relative [box-shadow:0_4px_16px_0_rgba(85,91,98,0.14)]',
|
|
50
|
+
isWidgetShell ? 'rounded-12px gap-12px pl-16px pr-8px pb-8px' : 'rounded-16px gap-10px pl-20px pr-10px pb-10px',
|
|
46
51
|
locked ? 'bg-muted cursor-not-allowed' : 'cursor-text',
|
|
47
52
|
)"
|
|
48
53
|
@mousedown="focusEditor"
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { chatShellContextKey } from '../chat-shell-context'
|
|
3
|
+
|
|
4
|
+
provide(chatShellContextKey, 'sidepanel')
|
|
5
|
+
</script>
|
|
6
|
+
|
|
1
7
|
<template>
|
|
2
8
|
<aside class="sticky top-0 w-[min(440px,100vw)] flex flex-col h-100dvh overflow-hidden shrink-0 border-l-0.5px border bg-muted p-8px">
|
|
3
9
|
<div data-widget-frame class="flex-1 min-h-0 flex flex-col border-0.5px rounded-12px overflow-hidden bg">
|
|
@@ -26,7 +26,7 @@ const delegatedProps = reactiveOmit(props, 'class')
|
|
|
26
26
|
v-if="!props.asChild"
|
|
27
27
|
name="i-ph-caret-down-bold"
|
|
28
28
|
size="15px"
|
|
29
|
-
color="icon-
|
|
29
|
+
color="icon-tertiary"
|
|
30
30
|
class="shrink-0 transition-transform ease-out duration-150 group-data-[state=open]:rotate-180"
|
|
31
31
|
/>
|
|
32
32
|
</ComboboxTrigger>
|
|
@@ -34,7 +34,7 @@ const style = computed(() => {
|
|
|
34
34
|
'3xs': 'text-6px p-1 rounded-6px',
|
|
35
35
|
'2xs': 'text-8px p-4px rounded-4px', // 16px
|
|
36
36
|
'xs': 'text-12px p-6px rounded-8px', // 26px
|
|
37
|
-
'sm': 'text-16px p-
|
|
37
|
+
'sm': 'text-16px p-7px rounded-10px', // 32px
|
|
38
38
|
'md': 'text-20px p-6.4px rounded-10px', // 44px
|
|
39
39
|
} as Record<typeof props.size, string>)[props.size]
|
|
40
40
|
|
|
@@ -33,7 +33,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
|
33
33
|
<SelectContent
|
|
34
34
|
v-bind="{ ...forwarded, ...$attrs }"
|
|
35
35
|
:class="cn(
|
|
36
|
-
'SelectContent popover-enter-exit relative z-999 max-h-80 overflow-hidden rounded-[10px] border-
|
|
36
|
+
'SelectContent popover-enter-exit relative z-999 max-h-80 overflow-hidden rounded-[10px] border-0.5px border bg',
|
|
37
37
|
props.class,
|
|
38
38
|
)"
|
|
39
39
|
:side-offset="4"
|
|
@@ -49,7 +49,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
|
49
49
|
v-else
|
|
50
50
|
v-bind="{ ...forwarded, ...$attrs }"
|
|
51
51
|
:class="cn(
|
|
52
|
-
'SelectContent popover-enter-exit relative z-999 max-h-80 overflow-hidden rounded-[16px] border-
|
|
52
|
+
'SelectContent popover-enter-exit relative z-999 max-h-80 overflow-hidden rounded-[16px] border-0.5px border bg',
|
|
53
53
|
props.class,
|
|
54
54
|
)"
|
|
55
55
|
:side-offset="4"
|
|
@@ -29,7 +29,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
|
|
29
29
|
>
|
|
30
30
|
<slot />
|
|
31
31
|
<SelectIcon as-child>
|
|
32
|
-
<TelaIcon name="i-ph-caret-down-bold" :size="props.triggerIconSize" color="icon-
|
|
32
|
+
<TelaIcon name="i-ph-caret-down-bold" :size="props.triggerIconSize" color="icon-tertiary" class="shrink-0 transition-all ease-out duration-150 group-data-[state=open]:rotate-180" />
|
|
33
33
|
</SelectIcon>
|
|
34
34
|
</SelectTrigger>
|
|
35
35
|
</template>
|
package/package.json
CHANGED
package/utils/design-tokens.ts
CHANGED
|
@@ -43,6 +43,32 @@ const BASE_COLORS = {
|
|
|
43
43
|
900: '#171717',
|
|
44
44
|
950: '#0A0A0A',
|
|
45
45
|
},
|
|
46
|
+
taupe: {
|
|
47
|
+
50: '#F9F9F9',
|
|
48
|
+
100: '#F5F1EB',
|
|
49
|
+
200: '#E8E4DE',
|
|
50
|
+
300: '#D1CABE',
|
|
51
|
+
400: '#A89D8C',
|
|
52
|
+
500: '#837969',
|
|
53
|
+
600: '#695F50',
|
|
54
|
+
700: '#554C3D',
|
|
55
|
+
800: '#3D372E',
|
|
56
|
+
900: '#2E281F',
|
|
57
|
+
950: '#16130F',
|
|
58
|
+
},
|
|
59
|
+
stone: {
|
|
60
|
+
50: '#F9F9F9',
|
|
61
|
+
100: '#F5F5F5',
|
|
62
|
+
200: '#E5E5E5',
|
|
63
|
+
300: '#D4D4D4',
|
|
64
|
+
400: '#A9A49F',
|
|
65
|
+
500: '#75716D',
|
|
66
|
+
600: '#55524D',
|
|
67
|
+
700: '#433F3B',
|
|
68
|
+
800: '#2A2524',
|
|
69
|
+
900: '#1E1A16',
|
|
70
|
+
950: '#0B0B0B',
|
|
71
|
+
},
|
|
46
72
|
orange: {
|
|
47
73
|
50: '#FFF7ED',
|
|
48
74
|
100: '#FFEDD5',
|
|
@@ -478,7 +504,7 @@ const PALETTE_STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950] as
|
|
|
478
504
|
type PaletteStep = (typeof PALETTE_STEPS)[number]
|
|
479
505
|
|
|
480
506
|
/** Display order for palette hues; hues missing from this list are appended at the end rather than dropped. */
|
|
481
|
-
const PALETTE_HUE_ORDER: readonly string[] = ['gray', 'neutral', 'red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo', 'purple', 'pink', 'rose']
|
|
507
|
+
const PALETTE_HUE_ORDER: readonly string[] = ['gray', 'neutral', 'taupe', 'stone', 'red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo', 'purple', 'pink', 'rose']
|
|
482
508
|
|
|
483
509
|
function isPaletteScale(scale: unknown): scale is Record<PaletteStep, string> {
|
|
484
510
|
return typeof scale === 'object' && scale !== null && PALETTE_STEPS.every(step => step in scale)
|