From ac255c8553a7c9147322543c1b0c026d51be1253 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Mon, 19 Jan 2026 17:16:00 +0100 Subject: [PATCH] feat: transitions, spacing --- .../src/components/dialog-select-model.tsx | 2 +- packages/app/src/components/prompt-input.tsx | 2 +- packages/ui/src/components/button.css | 3 ++ packages/ui/src/components/icon.tsx | 6 +-- packages/ui/src/components/message-nav.css | 12 +++-- packages/ui/src/components/select.css | 45 +++++++++++-------- packages/ui/src/components/select.tsx | 3 +- 7 files changed, 41 insertions(+), 32 deletions(-) diff --git a/packages/app/src/components/dialog-select-model.tsx b/packages/app/src/components/dialog-select-model.tsx index d54f9369a..72c9cec63 100644 --- a/packages/app/src/components/dialog-select-model.tsx +++ b/packages/app/src/components/dialog-select-model.tsx @@ -73,7 +73,7 @@ export const ModelSelectorPopover: Component<{ const [open, setOpen] = createSignal(false) return ( - + {props.children} diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 2f85652a9..e4476bdca 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -784,7 +784,7 @@ export const PromptInput: Component = (props) => { .abort({ sessionID: params.id!, }) - .catch(() => {}) + .catch(() => { }) const addToHistory = (prompt: Prompt, mode: "normal" | "shell") => { const text = prompt diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index c25b89af9..69b5058f8 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -10,6 +10,9 @@ cursor: default; outline: none; white-space: nowrap; + transition-property: background-color, border-color, color, box-shadow; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.25, 0, 0.5, 1); &[data-variant="primary"] { background-color: var(--icon-strong-base); diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index 2d680b28b..b59497b6f 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -8,7 +8,7 @@ const icons = { "bubble-5": ``, brain: ``, "bullet-list": ``, - "check-small": ``, + "check-small": ``, "chevron-down": ``, "chevron-right": ``, "chevron-grabber-vertical": ``, @@ -33,7 +33,7 @@ const icons = { mcp: ``, glasses: ``, "magnifying-glass-menu": ``, - "window-cursor": ``, + "window-cursor": ``, task: ``, stop: ``, "layout-left": ``, @@ -53,7 +53,7 @@ const icons = { "dot-grid": ``, "circle-check": ``, copy: ``, - check: ``, + check: ``, photo: ``, share: ``, download: ``, diff --git a/packages/ui/src/components/message-nav.css b/packages/ui/src/components/message-nav.css index 41fa2b779..7bd605fbd 100644 --- a/packages/ui/src/components/message-nav.css +++ b/packages/ui/src/components/message-nav.css @@ -26,13 +26,10 @@ grid-template-rows: repeat(var(--message-nav-items), var(--message-nav-item-height)); border-radius: var(--radius-md); transition-property: background-color, box-shadow, width, grid-template-rows, padding; - transition-duration: 200ms, 200ms, 200ms, 300ms, 300ms, 200ms; + transition-duration: 150ms; + transition-delay: 100ms, 100ms, 0ms, 0ms, 0ms, 0ms; transition-timing-function: cubic-bezier(0.25, 0, 0.5, 1); - &:not(:hover) { - transition-delay: 200ms, 200ms, 0ms, 0ms, 0ms, 0ms; - } - &:hover { --message-nav-line-opacity: 0; --message-nav-item-height: 23px; @@ -43,6 +40,7 @@ --message-nav-title-transition-duration: 300ms; --message-nav-title-transition-delay: 100ms; + transition-duration: 200ms, 200ms, 200ms, 300ms, 300ms, 200ms; background-color: var(--surface-raised-stronger-non-alpha); box-shadow: 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), @@ -85,7 +83,7 @@ left: 4px; top: 50%; opacity: var(--message-nav-line-opacity, 1); - transform: scaleX(var(--message-nav-line-scale, 0.66)) translateY(-50%); + transform: scaleX(var(--message-nav-line-scale, 0.66)) scaleY(.66) translateY(-50%); transform-origin: 0% 50%; background-color: var(--icon-weak-base); transition-property: opacity, background-color, transform; @@ -128,7 +126,7 @@ [data-slot="message-nav-item-title-inner"] { font-size: 12px; line-height: 23px; - padding-right: 4px; + padding-left: 4px; color: var(--text-base); white-space: nowrap; display: inline-flex; diff --git a/packages/ui/src/components/select.css b/packages/ui/src/components/select.css index 49b644db0..1ba5ec968 100644 --- a/packages/ui/src/components/select.css +++ b/packages/ui/src/components/select.css @@ -2,6 +2,7 @@ [data-slot="select-select-trigger"] { padding: 0 4px 0 8px; box-shadow: none; + transition: background-color 200ms cubic-bezier(0.25, 0, 0.5, 1); [data-slot="select-select-trigger-value"] { overflow: hidden; @@ -16,9 +17,10 @@ justify-content: center; flex-shrink: 0; color: var(--text-weak); - transition: transform 0.1s ease-in-out; + transition: transform 200ms cubic-bezier(0.25, 0, 0.5, 1); } + &:hover, &[data-expanded] { &[data-variant="secondary"] { background-color: var(--button-secondary-hover); @@ -46,21 +48,26 @@ } [data-component="select-content"] { - min-width: 4rem; + min-width: 8rem; max-width: 23rem; overflow: hidden; border-radius: var(--radius-md); background-color: var(--surface-raised-stronger-non-alpha); - padding: 2px; + padding: 4px; box-shadow: var(--shadow-xs-border); z-index: 50; + transform-origin: var(--kb-popper-content-transform-origin); + pointer-events: none; - &[data-closed] { - animation: select-close 0.15s ease-out; + animation: selectContentHide 200ms cubic-bezier(0.25, 0, 0.5, 1) forwards; + + @starting-style { + animation: none; } &[data-expanded] { - animation: select-open 0.15s ease-out; + pointer-events: auto; + animation: selectContentShow 200ms cubic-bezier(0.25, 0, 0.5, 1) forwards; } [data-slot="select-select-content-list"] { @@ -87,13 +94,13 @@ position: relative; display: flex; align-items: center; - padding: 0 6px 0 6px; + padding: 4px 8px; gap: 12px; border-radius: var(--radius-sm); /* text-12-medium */ font-family: var(--font-family-sans); - font-size: var(--font-size-small); + font-size: var(--font-size-base); font-style: normal; font-weight: var(--font-weight-medium); line-height: var(--line-height-large); /* 166.667% */ @@ -102,13 +109,13 @@ color: var(--text-strong); transition: - background-color 0.2s ease-in-out, - color 0.2s ease-in-out; + background-color 200ms cubic-bezier(0.25, 0, 0.5, 1), + color 200ms cubic-bezier(0.25, 0, 0.5, 1); outline: none; user-select: none; - &[data-highlighted] { - background: var(--surface-raised-base-hover); + &:hover { + background-color: var(--surface-raised-base-hover); } &[data-disabled] { background-color: var(--surface-raised-base); @@ -131,24 +138,24 @@ } } -@keyframes select-open { +@keyframes selectContentShow { from { opacity: 0; - transform: scale(0.95); + transform: scaleY(0.9); } to { opacity: 1; - transform: scale(1); + transform: scaleY(1); } } -@keyframes select-close { +@keyframes selectContentHide { from { opacity: 1; - transform: scale(1); + transform: scaleY(1); } to { opacity: 0; - transform: scale(0.95); + transform: scaleY(0.9); } -} +} \ No newline at end of file diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index e60fcbee1..5be00b4e9 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -49,6 +49,7 @@ export function Select(props: SelectProps & ButtonProps) { placement="bottom-start" value={local.current} options={grouped()} + gutter={12} optionValue={(x) => (local.value ? local.value(x) : (x as string))} optionTextValue={(x) => (local.label ? local.label(x) : (x as string))} optionGroupChildren="options" @@ -73,7 +74,7 @@ export function Select(props: SelectProps & ButtonProps) { : (itemProps.item.rawValue as string)} - + )}