From 81f4c7a8d596decd623e7b122b5bf66a84d0d7b1 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Mon, 26 Jan 2026 03:42:29 +0100 Subject: [PATCH 01/26] feat: scroll helper components --- packages/ui/src/components/scroll-fade.css | 122 +++++++++++++ packages/ui/src/components/scroll-fade.tsx | 183 +++++++++++++++++++ packages/ui/src/components/scroll-reveal.tsx | 141 ++++++++++++++ 3 files changed, 446 insertions(+) create mode 100644 packages/ui/src/components/scroll-fade.css create mode 100644 packages/ui/src/components/scroll-fade.tsx create mode 100644 packages/ui/src/components/scroll-reveal.tsx diff --git a/packages/ui/src/components/scroll-fade.css b/packages/ui/src/components/scroll-fade.css new file mode 100644 index 000000000000..afb82eb5eecd --- /dev/null +++ b/packages/ui/src/components/scroll-fade.css @@ -0,0 +1,122 @@ +[data-component="scroll-fade"] { + overflow: auto; + overscroll-behavior: contain; + scrollbar-width: none; + box-sizing: border-box; + color: inherit; + font: inherit; + -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } + + &[data-direction="horizontal"] { + overflow-x: auto; + overflow-y: hidden; + + /* Both fades */ + &[data-fade-start][data-fade-end] { + mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + + /* Only start fade */ + &[data-fade-start]:not([data-fade-end]) { + mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black 100% + ); + -webkit-mask-image: linear-gradient( + to right, + transparent, + black var(--scroll-fade-start), + black 100% + ); + } + + /* Only end fade */ + &:not([data-fade-start])[data-fade-end] { + mask-image: linear-gradient( + to right, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to right, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + } + + &[data-direction="vertical"] { + overflow-y: auto; + overflow-x: hidden; + + &[data-fade-start][data-fade-end] { + mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + + /* Only start fade */ + &[data-fade-start]:not([data-fade-end]) { + mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black 100% + ); + -webkit-mask-image: linear-gradient( + to bottom, + transparent, + black var(--scroll-fade-start), + black 100% + ); + } + + /* Only end fade */ + &:not([data-fade-start])[data-fade-end] { + mask-image: linear-gradient( + to bottom, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + -webkit-mask-image: linear-gradient( + to bottom, + black 0%, + black calc(100% - var(--scroll-fade-end)), + transparent + ); + } + } +} \ No newline at end of file diff --git a/packages/ui/src/components/scroll-fade.tsx b/packages/ui/src/components/scroll-fade.tsx new file mode 100644 index 000000000000..dc98ae6ab5a3 --- /dev/null +++ b/packages/ui/src/components/scroll-fade.tsx @@ -0,0 +1,183 @@ +import { + type JSX, + createEffect, + createSignal, + onCleanup, + onMount, + splitProps, +} from "solid-js" +import "./scroll-fade.css" + +export interface ScrollFadeProps extends JSX.HTMLAttributes { + direction?: "horizontal" | "vertical" + fadeStartSize?: number + fadeEndSize?: number + trackTransformSelector?: string + ref?: (el: HTMLDivElement) => void +} + +export function ScrollFade(props: ScrollFadeProps) { + const [local, others] = splitProps(props, [ + "children", + "direction", + "fadeStartSize", + "fadeEndSize", + "trackTransformSelector", + "class", + "style", + "ref", + ]) + + const direction = () => local.direction ?? "vertical" + const fadeStartSize = () => local.fadeStartSize ?? 20 + const fadeEndSize = () => local.fadeEndSize ?? 20 + + const getTransformOffset = (element: Element): number => { + const style = getComputedStyle(element) + const transform = style.transform + if (!transform || transform === "none") return 0 + + const match = transform.match(/matrix(?:3d)?\(([^)]+)\)/) + if (!match) return 0 + + const values = match[1].split(",").map((v) => parseFloat(v.trim())) + const isHorizontal = direction() === "horizontal" + + if (transform.startsWith("matrix3d")) { + return isHorizontal ? -(values[12] || 0) : -(values[13] || 0) + } else { + return isHorizontal ? -(values[4] || 0) : -(values[5] || 0) + } + } + + let containerRef: HTMLDivElement | undefined + + const [fadeStart, setFadeStart] = createSignal(0) + const [fadeEnd, setFadeEnd] = createSignal(0) + const [isScrollable, setIsScrollable] = createSignal(false) + + let lastScrollPos = 0 + let lastTransformPos = 0 + let lastScrollSize = 0 + let lastClientSize = 0 + + const updateFade = () => { + if (!containerRef) return + + const isHorizontal = direction() === "horizontal" + const scrollPos = isHorizontal ? containerRef.scrollLeft : containerRef.scrollTop + const scrollSize = isHorizontal ? containerRef.scrollWidth : containerRef.scrollHeight + const clientSize = isHorizontal ? containerRef.clientWidth : containerRef.clientHeight + + let transformPos = 0 + if (local.trackTransformSelector) { + const transformElement = containerRef.querySelector(local.trackTransformSelector) + if (transformElement) { + transformPos = getTransformOffset(transformElement) + } + } + + const effectiveScrollPos = Math.max(scrollPos, transformPos) + + if ( + effectiveScrollPos === lastScrollPos && + transformPos === lastTransformPos && + scrollSize === lastScrollSize && + clientSize === lastClientSize + ) { + return + } + + lastScrollPos = effectiveScrollPos + lastTransformPos = transformPos + lastScrollSize = scrollSize + lastClientSize = clientSize + + const maxScroll = scrollSize - clientSize + const canScroll = maxScroll > 1 + + setIsScrollable(canScroll) + + if (!canScroll) { + setFadeStart(0) + setFadeEnd(0) + return + } + + const progress = maxScroll > 0 ? effectiveScrollPos / maxScroll : 0 + + const startProgress = Math.min(progress / 0.1, 1) + setFadeStart(startProgress * fadeStartSize()) + + const endProgress = progress > 0.9 ? (1 - progress) / 0.1 : 1 + setFadeEnd(Math.max(0, endProgress) * fadeEndSize()) + } + + onMount(() => { + if (!containerRef) return + + updateFade() + + containerRef.addEventListener("scroll", updateFade, { passive: true }) + + const resizeObserver = new ResizeObserver(() => { + lastScrollSize = 0 + lastClientSize = 0 + updateFade() + }) + resizeObserver.observe(containerRef) + + const mutationObserver = new MutationObserver(() => { + lastScrollSize = 0 + lastClientSize = 0 + requestAnimationFrame(updateFade) + }) + mutationObserver.observe(containerRef, { + childList: true, + subtree: true, + characterData: true, + }) + + let rafId: number + const pollScroll = () => { + updateFade() + rafId = requestAnimationFrame(pollScroll) + } + rafId = requestAnimationFrame(pollScroll) + + onCleanup(() => { + containerRef?.removeEventListener("scroll", updateFade) + resizeObserver.disconnect() + mutationObserver.disconnect() + cancelAnimationFrame(rafId) + }) + }) + + createEffect(() => { + local.children + requestAnimationFrame(updateFade) + }) + + return ( +
{ + containerRef = el + local.ref?.(el) + }} + data-component="scroll-fade" + data-direction={direction()} + data-scrollable={isScrollable() || undefined} + data-fade-start={fadeStart() > 0 || undefined} + data-fade-end={fadeEnd() > 0 || undefined} + class={local.class} + style={{ + ...(typeof local.style === "object" ? local.style : {}), + "--scroll-fade-start": `${fadeStart()}px`, + "--scroll-fade-end": `${fadeEnd()}px`, + }} + {...others} + > + {local.children} +
+ ) +} \ No newline at end of file diff --git a/packages/ui/src/components/scroll-reveal.tsx b/packages/ui/src/components/scroll-reveal.tsx new file mode 100644 index 000000000000..3e9c8b362bbe --- /dev/null +++ b/packages/ui/src/components/scroll-reveal.tsx @@ -0,0 +1,141 @@ +import { type JSX, onCleanup, splitProps } from "solid-js" +import { ScrollFade, type ScrollFadeProps } from './scroll-fade' + +const SCROLL_SPEED = 60 +const PAUSE_DURATION = 800 + +type ScrollAnimationState = { + rafId: number | null + startTime: number + running: boolean +} + +const startScrollAnimation = (containerEl: HTMLElement): ScrollAnimationState | null => { + containerEl.offsetHeight + + const extraWidth = containerEl.scrollWidth - containerEl.clientWidth + + if (extraWidth <= 0) { + return null + } + + const scrollDuration = (extraWidth / SCROLL_SPEED) * 1000 + const totalDuration = PAUSE_DURATION + scrollDuration + PAUSE_DURATION + scrollDuration + PAUSE_DURATION + + const state: ScrollAnimationState = { + rafId: null, + startTime: performance.now(), + running: true, + } + + const animate = (currentTime: number) => { + if (!state.running) return + + const elapsed = currentTime - state.startTime + const progress = (elapsed % totalDuration) / totalDuration + + const pausePercent = PAUSE_DURATION / totalDuration + const scrollPercent = scrollDuration / totalDuration + + const pauseEnd1 = pausePercent + const scrollEnd1 = pauseEnd1 + scrollPercent + const pauseEnd2 = scrollEnd1 + pausePercent + const scrollEnd2 = pauseEnd2 + scrollPercent + + let scrollPos = 0 + + if (progress < pauseEnd1) { + scrollPos = 0 + } else if (progress < scrollEnd1) { + const scrollProgress = (progress - pauseEnd1) / scrollPercent + scrollPos = scrollProgress * extraWidth + } else if (progress < pauseEnd2) { + scrollPos = extraWidth + } else if (progress < scrollEnd2) { + const scrollProgress = (progress - pauseEnd2) / scrollPercent + scrollPos = extraWidth * (1 - scrollProgress) + } else { + scrollPos = 0 + } + + containerEl.scrollLeft = scrollPos + state.rafId = requestAnimationFrame(animate) + } + + state.rafId = requestAnimationFrame(animate) + return state +} + +const stopScrollAnimation = (state: ScrollAnimationState | null, containerEl?: HTMLElement) => { + if (state) { + state.running = false + if (state.rafId !== null) { + cancelAnimationFrame(state.rafId) + } + } + if (containerEl) { + containerEl.scrollLeft = 0 + } +} + +export interface ScrollRevealProps extends Omit { + hoverDelay?: number +} + +export function ScrollReveal(props: ScrollRevealProps) { + const [local, others] = splitProps(props, ["children", "hoverDelay", "ref"]) + + const hoverDelay = () => local.hoverDelay ?? 300 + + let containerRef: HTMLDivElement | undefined + let hoverTimeout: ReturnType | undefined + let scrollAnimationState: ScrollAnimationState | null = null + + const handleMouseEnter: JSX.EventHandler = () => { + hoverTimeout = setTimeout(() => { + if (!containerRef) return + + containerRef.offsetHeight + + const isScrollable = containerRef.scrollWidth > containerRef.clientWidth + 1 + + if (isScrollable) { + stopScrollAnimation(scrollAnimationState, containerRef) + scrollAnimationState = startScrollAnimation(containerRef) + } + }, hoverDelay()) + } + + const handleMouseLeave: JSX.EventHandler = () => { + if (hoverTimeout) { + clearTimeout(hoverTimeout) + hoverTimeout = undefined + } + stopScrollAnimation(scrollAnimationState, containerRef) + scrollAnimationState = null + } + + onCleanup(() => { + if (hoverTimeout) { + clearTimeout(hoverTimeout) + } + stopScrollAnimation(scrollAnimationState, containerRef) + }) + + return ( + { + containerRef = el + local.ref?.(el) + }} + fadeStartSize={8} + fadeEndSize={8} + direction="horizontal" + onMouseEnter={handleMouseEnter} + onMouseLeave={handleMouseLeave} + {...others} + > + {local.children} + + ) +} From 116646807738df94a1e7248d2dee88a4c55baf47 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Mon, 26 Jan 2026 03:43:09 +0100 Subject: [PATCH 02/26] feat: scroll settings --- packages/app/src/components/settings-general.tsx | 10 ++++++++-- packages/app/src/components/settings-keybinds.tsx | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx index 75acf4f74215..d9a27ecce6c0 100644 --- a/packages/app/src/components/settings-general.tsx +++ b/packages/app/src/components/settings-general.tsx @@ -6,6 +6,7 @@ import { useLanguage } from "@/context/language" import { useSettings, monoFontFamily } from "@/context/settings" import { playSound, SOUND_OPTIONS } from "@/utils/sound" import { Link } from "./link" +import { ScrollFade } from "@opencode-ai/ui/scroll-fade" export const SettingsGeneral: Component = () => { const theme = useTheme() @@ -48,7 +49,12 @@ export const SettingsGeneral: Component = () => { const soundOptions = [...SOUND_OPTIONS] return ( -
+
{
- + ) } diff --git a/packages/app/src/components/settings-keybinds.tsx b/packages/app/src/components/settings-keybinds.tsx index 4dc39714955b..e8c642f50ec3 100644 --- a/packages/app/src/components/settings-keybinds.tsx +++ b/packages/app/src/components/settings-keybinds.tsx @@ -8,6 +8,7 @@ import fuzzysort from "fuzzysort" import { formatKeybind, parseKeybind, useCommand } from "@/context/command" import { useLanguage } from "@/context/language" import { useSettings } from "@/context/settings" +import { ScrollFade } from "@opencode-ai/ui/scroll-fade" const IS_MAC = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) const PALETTE_ID = "command.palette" @@ -349,7 +350,12 @@ export const SettingsKeybinds: Component = () => { }) return ( -
+
{
- + ) } From a7fade7ab9b2420e200aacc28845947aaa143c69 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Mon, 26 Jan 2026 03:43:29 +0100 Subject: [PATCH 03/26] feat: list scrolling --- packages/ui/src/components/list.css | 16 ++++++---------- packages/ui/src/components/list.tsx | 11 +++++++++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/ui/src/components/list.css b/packages/ui/src/components/list.css index 95641bb202ec..dab5b2fca24d 100644 --- a/packages/ui/src/components/list.css +++ b/packages/ui/src/components/list.css @@ -19,7 +19,7 @@ [data-component="list"] { display: flex; flex-direction: column; - gap: 12px; + gap: 8px; overflow: hidden; padding: 0 12px; @@ -114,15 +114,6 @@ gap: 12px; overflow-y: auto; overscroll-behavior: contain; - mask: linear-gradient(to bottom, #ffff calc(100% - var(--bottom-fade)), #0000); - animation: scroll; - animation-timeline: --scroll; - scroll-timeline: --scroll y; - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } [data-slot="list-empty-state"] { display: flex; @@ -238,6 +229,11 @@ color: var(--icon-strong-base); } } + + [name="check"] { + color: var(--icon-strong-base); + } + [data-slot="list-item-active-icon"] { display: none; align-items: center; diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx index 6a7f3a029f40..b084b441b235 100644 --- a/packages/ui/src/components/list.tsx +++ b/packages/ui/src/components/list.tsx @@ -5,6 +5,7 @@ import { useI18n } from "../context/i18n" import { Icon, type IconProps } from "./icon" import { IconButton } from "./icon-button" import { TextField } from "./text-field" +import { ScrollFade } from "./scroll-fade" function findByKey(container: HTMLElement, key: string) { const nodes = container.querySelectorAll('[data-slot="list-item"][data-key]') @@ -241,7 +242,13 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void }) {searchAction()} -
+ 0} fallback={ @@ -301,7 +308,7 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void }) )} -
+ ) } From ab07c9451d9c0b12d919ecabd7a6cf961baf9bec Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:47:39 +0100 Subject: [PATCH 04/26] feat: animated chevron --- packages/ui/src/components/collapsible.css | 44 +++++++-------- packages/ui/src/components/collapsible.tsx | 42 +++++++++----- packages/ui/src/components/message-part.css | 1 + packages/ui/src/components/message-part.tsx | 3 +- packages/ui/src/components/morph-chevron.css | 10 ++++ packages/ui/src/components/morph-chevron.tsx | 55 +++++++++++++++++++ packages/ui/src/components/session-review.tsx | 2 +- 7 files changed, 118 insertions(+), 39 deletions(-) create mode 100644 packages/ui/src/components/morph-chevron.css create mode 100644 packages/ui/src/components/morph-chevron.tsx diff --git a/packages/ui/src/components/collapsible.css b/packages/ui/src/components/collapsible.css index c2b09f761822..44fdfe53cc56 100644 --- a/packages/ui/src/components/collapsible.css +++ b/packages/ui/src/components/collapsible.css @@ -4,7 +4,9 @@ flex-direction: column; background-color: var(--surface-inset-base); border: 1px solid var(--border-weaker-base); - transition: background-color 0.15s ease; + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); border-radius: var(--radius-md); overflow: clip; @@ -44,16 +46,28 @@ display: flex; align-items: center; justify-content: center; + color: var(--text-weak); } } [data-slot="collapsible-content"] { - overflow: hidden; - /* animation: slideUp 250ms ease-out; */ + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - /* &[data-expanded] { */ - /* animation: slideDown 250ms ease-out; */ - /* } */ + > * { + overflow: hidden; + } + + &[data-expanded] { + grid-template-rows: 1fr; + } + + &[data-closed] { + grid-template-rows: 0fr; + } } &[data-variant="ghost"] { @@ -77,21 +91,3 @@ } } } - -@keyframes slideDown { - from { - height: 0; - } - to { - height: var(--kb-collapsible-content-height); - } -} - -@keyframes slideUp { - from { - height: var(--kb-collapsible-content-height); - } - to { - height: 0; - } -} diff --git a/packages/ui/src/components/collapsible.tsx b/packages/ui/src/components/collapsible.tsx index 903afc3085ee..55b7b60333c9 100644 --- a/packages/ui/src/components/collapsible.tsx +++ b/packages/ui/src/components/collapsible.tsx @@ -1,6 +1,8 @@ import { Collapsible as Kobalte, CollapsibleRootProps } from "@kobalte/core/collapsible" -import { ComponentProps, ParentProps, splitProps } from "solid-js" -import { Icon } from "./icon" +import { Accessor, ComponentProps, createContext, createSignal, ParentProps, splitProps, useContext } from "solid-js" +import { MorphChevron } from "./morph-chevron" + +const CollapsibleContext = createContext>() export interface CollapsibleProps extends ParentProps { class?: string @@ -9,17 +11,30 @@ export interface CollapsibleProps extends ParentProps { } function CollapsibleRoot(props: CollapsibleProps) { - const [local, others] = splitProps(props, ["class", "classList", "variant"]) + const [local, others] = splitProps(props, ["class", "classList", "variant", "open", "onOpenChange", "children"]) + const [internalOpen, setInternalOpen] = createSignal(local.open ?? false) + + const handleOpenChange = (open: boolean) => { + setInternalOpen(open) + local.onOpenChange?.(open) + } + return ( - + + + {local.children} + + ) } @@ -32,9 +47,10 @@ function CollapsibleContent(props: ComponentProps) { } function CollapsibleArrow(props?: ComponentProps<"div">) { + const isOpen = useContext(CollapsibleContext) return (
- +
) } diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css index d47a3a79b56f..ea11ca3e57a0 100644 --- a/packages/ui/src/components/message-part.css +++ b/packages/ui/src/components/message-part.css @@ -103,6 +103,7 @@ } } + [data-component="text-part"] { width: 100%; diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index d5d844161474..b344fe0f5d52 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -48,6 +48,7 @@ import { Tooltip } from "./tooltip" import { IconButton } from "./icon-button" import { createAutoScroll } from "../hooks" import { createResizeObserver } from "@solid-primitives/resize-observer" +import { MorphChevron } from "./morph-chevron" interface Diagnostic { range: { @@ -414,7 +415,7 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp toggleExpanded() }} > - +
props.expanded, + (expanded, prev) => { + if (prev === undefined) return + if (expanded) { + expandAnim?.beginElement() + } else { + collapseAnim?.beginElement() + } + }, + ), + ) + + return ( + + + + + + + ) +} diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index 2b6d93e2d3fe..8872a8001641 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -480,7 +480,7 @@ export const SessionReview = (props: SessionReviewProps) => { } return ( - +
From bc77e15a11b2f78a43594051075712d511eac454 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:47:53 +0100 Subject: [PATCH 05/26] feat: reasoning icon --- packages/ui/src/components/reasoning-icon.css | 8 +++++ packages/ui/src/components/reasoning-icon.tsx | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 packages/ui/src/components/reasoning-icon.css create mode 100644 packages/ui/src/components/reasoning-icon.tsx diff --git a/packages/ui/src/components/reasoning-icon.css b/packages/ui/src/components/reasoning-icon.css new file mode 100644 index 000000000000..b03f69a931ae --- /dev/null +++ b/packages/ui/src/components/reasoning-icon.css @@ -0,0 +1,8 @@ +[data-component="reasoning-icon"] { + color: var(--icon-strong-base); + + [data-slot="reasoning-icon-percentage"] { + transition: clip-path 200ms cubic-bezier(0.25, 0, 0.5, 1); + clip-path: inset(calc(100% - var(--reasoning-icon-percentage) * 100%) 0 0 0); + } +} diff --git a/packages/ui/src/components/reasoning-icon.tsx b/packages/ui/src/components/reasoning-icon.tsx new file mode 100644 index 000000000000..0ad60e9640f0 --- /dev/null +++ b/packages/ui/src/components/reasoning-icon.tsx @@ -0,0 +1,32 @@ +import { type ComponentProps, splitProps } from "solid-js" + +export interface ReasoningIconProps extends Pick, "class" | "classList"> { + percentage: number + size?: number + strokeWidth?: number +} + +export function ReasoningIcon(props: ReasoningIconProps) { + const [split, rest] = splitProps(props, ["percentage", "size", "strokeWidth", "class", "classList"]) + + const size = () => split.size || 16 + const strokeWidth = () => split.strokeWidth || 1.25 + + return ( + + + + + ) +} From e3312f1c3ff3171655950a6c2224e3ab0cca1e1f Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:48:16 +0100 Subject: [PATCH 06/26] feat: transition select, dropdown --- packages/ui/src/components/dropdown-menu.css | 44 +++--- packages/ui/src/components/select.css | 134 +++++++------------ packages/ui/src/components/select.tsx | 18 ++- 3 files changed, 85 insertions(+), 111 deletions(-) diff --git a/packages/ui/src/components/dropdown-menu.css b/packages/ui/src/components/dropdown-menu.css index cba041613eab..2e00505a8fee 100644 --- a/packages/ui/src/components/dropdown-menu.css +++ b/packages/ui/src/components/dropdown-menu.css @@ -2,26 +2,24 @@ [data-component="dropdown-menu-sub-content"] { min-width: 8rem; overflow: hidden; + border: none; border-radius: var(--radius-md); - border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); + box-shadow: var(--shadow-xs-border); background-clip: padding-box; background-color: var(--surface-raised-stronger-non-alpha); padding: 4px; - box-shadow: var(--shadow-md); - z-index: 50; + z-index: 100; transform-origin: var(--kb-menu-content-transform-origin); - &:focus, - &:focus-visible { - outline: none; - } + animation: dropdownMenuContentHide var(--transition-duration) var(--transition-easing) forwards; - &[data-closed] { - animation: dropdown-menu-close 0.15s ease-out; + @starting-style { + animation: none; } &[data-expanded] { - animation: dropdown-menu-open 0.15s ease-out; + pointer-events: auto; + animation: dropdownMenuContentShow var(--transition-duration) var(--transition-easing) forwards; } } @@ -38,18 +36,22 @@ padding: 4px 8px; border-radius: var(--radius-sm); cursor: default; - user-select: none; outline: none; font-family: var(--font-family-sans); - font-size: var(--font-size-small); + font-size: var(--font-size-base); font-weight: var(--font-weight-medium); line-height: var(--line-height-large); letter-spacing: var(--letter-spacing-normal); color: var(--text-strong); - &[data-highlighted] { - background: var(--surface-raised-base-hover); + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + user-select: none; + + &:hover { + background-color: var(--surface-raised-base-hover); } &[data-disabled] { @@ -61,6 +63,8 @@ [data-slot="dropdown-menu-sub-trigger"] { &[data-expanded] { background: var(--surface-raised-base-hover); + outline: none; + border: none; } } @@ -102,24 +106,24 @@ } } -@keyframes dropdown-menu-open { +@keyframes dropdownMenuContentShow { from { opacity: 0; - transform: scale(0.96); + transform: scaleY(0.95); } to { opacity: 1; - transform: scale(1); + transform: scaleY(1); } } -@keyframes dropdown-menu-close { +@keyframes dropdownMenuContentHide { from { opacity: 1; - transform: scale(1); + transform: scaleY(1); } to { opacity: 0; - transform: scale(0.96); + transform: scaleY(0.95); } } diff --git a/packages/ui/src/components/select.css b/packages/ui/src/components/select.css index 3e175855bef5..0698c5c387d7 100644 --- a/packages/ui/src/components/select.css +++ b/packages/ui/src/components/select.css @@ -1,7 +1,13 @@ [data-component="select"] { [data-slot="select-select-trigger"] { - padding: 0 4px 0 8px; + display: flex; + padding: 4px 8px !important; + align-items: center; + justify-content: space-between; box-shadow: none; + transition-property: background-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); [data-slot="select-select-trigger-value"] { overflow: hidden; @@ -15,10 +21,10 @@ align-items: center; justify-content: center; flex-shrink: 0; - color: var(--text-weak); - transition: transform 0.1s ease-in-out; + color: var(--icon-base); } + &:hover, &[data-expanded] { &[data-variant="secondary"] { background-color: var(--button-secondary-hover); @@ -30,78 +36,41 @@ background-color: var(--icon-strong-active); } } - &:not([data-expanded]):focus { &[data-variant="secondary"] { background-color: var(--button-secondary-base); } &[data-variant="ghost"] { - background-color: var(--surface-raised-base-hover); + background-color: transparent; } &[data-variant="primary"] { background-color: var(--icon-strong-base); } } } - - &[data-trigger-style="settings"] { - [data-slot="select-select-trigger"] { - padding: 6px 6px 6px 12px; - box-shadow: none; - border-radius: 6px; - min-width: 160px; - height: 32px; - justify-content: flex-end; - gap: 12px; - background-color: transparent; - - [data-slot="select-select-trigger-value"] { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-size: var(--font-size-base); - font-weight: var(--font-weight-regular); - } - [data-slot="select-select-trigger-icon"] { - width: 16px; - height: 20px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - color: var(--text-weak); - background-color: var(--surface-raised-base); - border-radius: 4px; - transition: transform 0.1s ease-in-out; - } - - &[data-slot="select-select-trigger"]:hover:not(:disabled), - &[data-slot="select-select-trigger"][data-expanded], - &[data-slot="select-select-trigger"][data-expanded]:hover:not(:disabled) { - background-color: var(--input-base); - box-shadow: var(--shadow-xs-border-base); - } - - &:not([data-expanded]):focus { - background-color: transparent; - box-shadow: none; - } - } - } } [data-component="select-content"] { - min-width: 104px; + min-width: 8rem; max-width: 23rem; overflow: hidden; border-radius: var(--radius-md); background-color: var(--surface-raised-stronger-non-alpha); padding: 4px; box-shadow: var(--shadow-xs-border); - z-index: 60; + z-index: 50; + transform-origin: var(--kb-popper-content-transform-origin); + pointer-events: none; + + animation: selectContentHide var(--transition-duration) var(--transition-easing) forwards; + + @starting-style { + animation: none; + } &[data-expanded] { - animation: select-open 0.15s ease-out; + pointer-events: auto; + animation: selectContentShow var(--transition-duration) var(--transition-easing) forwards; } [data-slot="select-select-content-list"] { @@ -111,43 +80,38 @@ overflow-x: hidden; display: flex; flex-direction: column; - &:focus { outline: none; } - > *:not([role="presentation"]) + *:not([role="presentation"]) { margin-top: 2px; } } - [data-slot="select-select-item"] { position: relative; display: flex; align-items: center; - padding: 2px 8px; + padding: 4px 8px; gap: 12px; - border-radius: 4px; - cursor: default; + 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% */ letter-spacing: var(--letter-spacing-normal); - color: var(--text-strong); - transition: - background-color 0.2s ease-in-out, - color 0.2s ease-in-out; + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); 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); @@ -160,6 +124,11 @@ margin-left: auto; width: 16px; height: 16px; + color: var(--icon-strong-base); + + svg { + color: var(--icon-strong-base); + } } &:focus { outline: none; @@ -170,33 +139,24 @@ } } -[data-component="select-content"][data-trigger-style="settings"] { - min-width: 160px; - border-radius: 8px; - padding: 0; - - [data-slot="select-select-content-list"] { - padding: 4px; +@keyframes selectContentShow { + from { + opacity: 0; + transform: scaleY(0.95); } - - [data-slot="select-select-item"] { - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); + to { + opacity: 1; + transform: scaleY(1); } } -@keyframes select-open { +@keyframes selectContentHide { from { - opacity: 0; - transform: scale(0.95); + opacity: 1; + transform: scaleY(1); } to { - opacity: 1; - transform: scale(1); + opacity: 0; + transform: scaleY(0.95); } } diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index b83f5f4630aa..092b486b22c7 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -1,8 +1,10 @@ import { Select as Kobalte } from "@kobalte/core/select" -import { createMemo, onCleanup, splitProps, type ComponentProps, type JSX } from "solid-js" +import { createMemo, createSignal, onCleanup, splitProps, type ComponentProps, type JSX } from "solid-js" import { pipe, groupBy, entries, map } from "remeda" +import { Show } from "solid-js" import { Button, ButtonProps } from "./button" import { Icon } from "./icon" +import { MorphChevron } from "./morph-chevron" export type SelectProps = Omit>, "value" | "onSelect" | "children"> & { placeholder?: string @@ -38,6 +40,8 @@ export function Select(props: SelectProps & Omit) "triggerVariant", ]) + const [isOpen, setIsOpen] = createSignal(false) + const state = { key: undefined as string | undefined, cleanup: undefined as (() => void) | void, @@ -85,7 +89,7 @@ export function Select(props: SelectProps & Omit) data-component="select" data-trigger-style={local.triggerVariant} placement={local.triggerVariant === "settings" ? "bottom-end" : "bottom-start"} - gutter={4} + gutter={8} value={local.current} options={grouped()} optionValue={(x) => (local.value ? local.value(x) : (x as string))} @@ -114,7 +118,7 @@ export function Select(props: SelectProps & Omit) : (itemProps.item.rawValue as string)} - + )} @@ -123,6 +127,7 @@ export function Select(props: SelectProps & Omit) stop() }} onOpenChange={(open) => { + setIsOpen(open) local.onOpenChange?.(open) if (!open) stop() }} @@ -148,7 +153,12 @@ export function Select(props: SelectProps & Omit) }} - + + + + + + From d6beccf938cfb3a88b01437c9bfd01fbfe29db1f Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:50:00 +0100 Subject: [PATCH 07/26] feat: animate accordion, user message --- packages/ui/src/components/accordion.css | 49 +++++++++++++-------- packages/ui/src/components/accordion.tsx | 43 +++++++++++++----- packages/ui/src/components/session-turn.css | 15 ++----- packages/ui/src/components/session-turn.tsx | 2 +- packages/ui/src/styles/index.css | 2 + 5 files changed, 68 insertions(+), 43 deletions(-) diff --git a/packages/ui/src/components/accordion.css b/packages/ui/src/components/accordion.css index 7bf287fe549c..97632989810a 100644 --- a/packages/ui/src/components/accordion.css +++ b/packages/ui/src/components/accordion.css @@ -36,7 +36,9 @@ border-radius: var(--radius-md); overflow: clip; color: var(--text-strong); - transition: background-color 0.15s ease; + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); /* text-12-regular */ font-family: var(--font-family-sans); @@ -58,6 +60,16 @@ } } + [data-slot="accordion-arrow"] { + flex-shrink: 0; + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weak); + } + &[data-expanded] { [data-slot="accordion-trigger"] { border-bottom-left-radius: 0; @@ -69,30 +81,29 @@ border-top: none; border-bottom-left-radius: var(--radius-md); border-bottom-right-radius: var(--radius-md); + height: auto; } } [data-slot="accordion-content"] { - overflow: hidden; + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); width: 100%; - } - } -} -@keyframes slideDown { - from { - height: 0; - } - to { - height: var(--kb-accordion-content-height); - } -} + > * { + overflow: hidden; + } -@keyframes slideUp { - from { - height: var(--kb-accordion-content-height); - } - to { - height: 0; + &[data-expanded] { + grid-template-rows: 1fr; + } + + &[data-closed] { + grid-template-rows: 0fr; + } + } } } diff --git a/packages/ui/src/components/accordion.tsx b/packages/ui/src/components/accordion.tsx index 535d38e3d076..e30be95e056e 100644 --- a/packages/ui/src/components/accordion.tsx +++ b/packages/ui/src/components/accordion.tsx @@ -1,6 +1,7 @@ import { Accordion as Kobalte } from "@kobalte/core/accordion" -import { splitProps } from "solid-js" +import { Accessor, createContext, splitProps, useContext } from "solid-js" import type { ComponentProps, ParentProps } from "solid-js" +import { MorphChevron } from "./morph-chevron" export interface AccordionProps extends ComponentProps {} export interface AccordionItemProps extends ComponentProps {} @@ -8,6 +9,8 @@ export interface AccordionHeaderProps extends ComponentProps {} export interface AccordionContentProps extends ComponentProps {} +const AccordionItemContext = createContext>() + function AccordionRoot(props: AccordionProps) { const [split, rest] = splitProps(props, ["class", "classList"]) return ( @@ -22,17 +25,19 @@ function AccordionRoot(props: AccordionProps) { ) } -function AccordionItem(props: AccordionItemProps) { - const [split, rest] = splitProps(props, ["class", "classList"]) +function AccordionItem(props: AccordionItemProps & { expanded?: boolean }) { + const [split, rest] = splitProps(props, ["class", "classList", "expanded"]) return ( - + split.expanded ?? false}> + + ) } @@ -84,9 +89,25 @@ function AccordionContent(props: ParentProps) { ) } +export interface AccordionArrowProps extends ComponentProps<"div"> { + expanded?: boolean +} + +function AccordionArrow(props: AccordionArrowProps = {}) { + const [local, rest] = splitProps(props, ["expanded"]) + const contextExpanded = useContext(AccordionItemContext) + const isExpanded = () => local.expanded ?? contextExpanded?.() ?? false + return ( +
+ +
+ ) +} + export const Accordion = Object.assign(AccordionRoot, { Item: AccordionItem, Header: AccordionHeader, Trigger: AccordionTrigger, Content: AccordionContent, + Arrow: AccordionArrow, }) diff --git a/packages/ui/src/components/session-turn.css b/packages/ui/src/components/session-turn.css index bf143cd4fd85..c8372d32e8d3 100644 --- a/packages/ui/src/components/session-turn.css +++ b/packages/ui/src/components/session-turn.css @@ -106,10 +106,11 @@ [data-component="user-message"] [data-slot="user-message-text"] { max-height: var(--user-message-collapsed-height, 64px); + transition: max-height 200ms cubic-bezier(0.25, 0, 0.5, 1); } [data-component="user-message"][data-expanded="true"] [data-slot="user-message-text"] { - max-height: none; + max-height: 2000px; } [data-component="user-message"][data-can-expand="true"] [data-slot="user-message-text"] { @@ -141,17 +142,6 @@ background: transparent; cursor: pointer; color: var(--text-weak); - - [data-slot="icon-svg"] { - transition: transform 0.15s ease; - } - } - - [data-component="user-message"][data-expanded="true"] - [data-slot="user-message-text"] - [data-slot="user-message-expand"] - [data-slot="icon-svg"] { - transform: rotate(180deg); } [data-component="user-message"] [data-slot="user-message-text"] [data-slot="user-message-expand"]:hover { @@ -457,6 +447,7 @@ gap: 16px; align-items: center; justify-content: flex-end; + color: var(--icon-base); } [data-slot="session-turn-accordion-content"] { diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index fe53c0939c1c..fc0a9f7192b5 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -548,7 +548,7 @@ export function SessionTurn( data-slot="session-turn-collapsible-trigger-content" variant="ghost" size="small" - onClick={props.onStepsExpandedToggle ?? (() => {})} + onClick={props.onStepsExpandedToggle ?? (() => { })} aria-expanded={props.stepsExpanded} > diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css index 3ed0310ef2b6..7c8548734d82 100644 --- a/packages/ui/src/styles/index.css +++ b/packages/ui/src/styles/index.css @@ -33,8 +33,10 @@ @import "../components/markdown.css" layer(components); @import "../components/message-part.css" layer(components); @import "../components/message-nav.css" layer(components); +@import "../components/morph-chevron.css" layer(components); @import "../components/popover.css" layer(components); @import "../components/progress-circle.css" layer(components); +@import "../components/reasoning-icon.css" layer(components); @import "../components/radio-group.css" layer(components); @import "../components/resize-handle.css" layer(components); @import "../components/select.css" layer(components); From f2ca48f1572c726b6e39a6375279c5f508e9e186 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:50:11 +0100 Subject: [PATCH 08/26] feat: cycle label --- packages/ui/src/components/cycle-label.css | 51 ++++++++ packages/ui/src/components/cycle-label.tsx | 132 +++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 packages/ui/src/components/cycle-label.css create mode 100644 packages/ui/src/components/cycle-label.tsx diff --git a/packages/ui/src/components/cycle-label.css b/packages/ui/src/components/cycle-label.css new file mode 100644 index 000000000000..a67471fe5192 --- /dev/null +++ b/packages/ui/src/components/cycle-label.css @@ -0,0 +1,51 @@ +.cycle-label { + --c-dur: 200ms; + --c-stag: 30ms; + --c-ease: cubic-bezier(0.25, 0, 0.5, 1); + --c-opacity-start: 0; + --c-opacity-end: 1; + --c-blur-start: 0px; + --c-blur-end: 0px; + --c-skew: 10deg; + + display: inline-flex; + position: relative; + + transform-style: preserve-3d; + perspective: 500px; + transition: width 200ms var(--c-ease); + will-change: width; + overflow: hidden; + + .cycle-char { + display: inline-block; + transform-style: preserve-3d; + min-width: 0.25em; + backface-visibility: hidden; + + transition: + transform var(--c-dur) var(--c-ease), + opacity var(--c-dur) var(--c-ease), + filter var(--c-dur) var(--c-ease); + transition-delay: calc(var(--i, 0) * var(--c-stag)); + + &.enter { + opacity: var(--c-opacity-end); + filter: blur(var(--c-blur-end)); + transform: translateY(0) rotateX(0) skewX(0); + } + + &.exit { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transform: translateY(50%) rotateX(90deg) skewX(var(--c-skew)); + } + + &.pre { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transition: none; + transform: translateY(-50%) rotateX(-90deg) skewX(calc(var(--c-skew) * -1)); + } + } +} diff --git a/packages/ui/src/components/cycle-label.tsx b/packages/ui/src/components/cycle-label.tsx new file mode 100644 index 000000000000..e34385a2c2f8 --- /dev/null +++ b/packages/ui/src/components/cycle-label.tsx @@ -0,0 +1,132 @@ +import "./cycle-label.css" +import { createEffect, createSignal, JSX, on } from "solid-js" + +export interface CycleLabelProps extends JSX.HTMLAttributes { + value: string + onValueChange?: (value: string) => void + duration?: number | ((value: string) => number) + stagger?: number + opacity?: [number, number] + blur?: [number, number] + skewX?: number + onAnimationStart?: () => void + onAnimationEnd?: () => void +} + +const segmenter = + typeof Intl !== "undefined" && Intl.Segmenter ? new Intl.Segmenter("en", { granularity: "grapheme" }) : null + +const getChars = (text: string): string[] => + segmenter ? Array.from(segmenter.segment(text), (s) => s.segment) : text.split("") + +const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) + +export function CycleLabel(props: CycleLabelProps) { + const getDuration = (text: string) => { + const d = props?.duration ?? 200 + return typeof d === "function" ? d(text) : d + } + const stagger = () => props?.stagger ?? 20 + const opacity = () => props?.opacity ?? [0, 1] + const blur = () => props?.blur ?? [0, 0] + const skewX = () => props?.skewX ?? 10 + + let containerRef: HTMLSpanElement | undefined + let isAnimating = false + const [currentText, setCurrentText] = createSignal(props.value) + + const setChars = (el: HTMLElement, text: string, state: "enter" | "exit" | "pre" = "enter") => { + el.innerHTML = "" + const chars = getChars(text) + chars.forEach((char, i) => { + const span = document.createElement("span") + span.textContent = char === " " ? "\u00A0" : char + span.className = `cycle-char ${state}` + span.style.setProperty("--i", String(i)) + el.appendChild(span) + }) + } + + const animateToText = async (newText: string) => { + if (!containerRef || isAnimating) return + if (newText === currentText()) return + + isAnimating = true + props.onAnimationStart?.() + + const dur = getDuration(newText) + const stag = stagger() + + containerRef.style.width = containerRef.offsetWidth + "px" + + const oldChars = containerRef.querySelectorAll(".cycle-char") + oldChars.forEach((c) => c.classList.replace("enter", "exit")) + + const clone = containerRef.cloneNode(false) as HTMLElement + Object.assign(clone.style, { + position: "absolute", + visibility: "hidden", + width: "auto", + transition: "none", + }) + setChars(clone, newText) + document.body.appendChild(clone) + const nextWidth = clone.offsetWidth + clone.remove() + + const exitTime = oldChars.length * stag + dur + await wait(exitTime * 0.3) + + containerRef.style.width = nextWidth + "px" + + const widthDur = 200 + await wait(widthDur * 0.3) + + setChars(containerRef, newText, "pre") + containerRef.offsetWidth + + Array.from(containerRef.children).forEach((c) => (c.className = "cycle-char enter")) + setCurrentText(newText) + props.onValueChange?.(newText) + + const enterTime = getChars(newText).length * stag + dur + await wait(enterTime) + + containerRef.style.width = "" + isAnimating = false + props.onAnimationEnd?.() + } + + createEffect( + on( + () => props.value, + (newValue) => { + if (newValue !== currentText()) { + animateToText(newValue) + } + }, + ), + ) + + const initRef = (el: HTMLSpanElement) => { + containerRef = el + setChars(el, props.value) + } + + return ( + + ) +} From f39ff9c4ae809f9fb3703f12d8d9c9e90c7394ff Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:50:48 +0100 Subject: [PATCH 09/26] feat: multiple transitions --- packages/ui/src/components/card.css | 4 ++- packages/ui/src/components/checkbox.css | 12 +++++++ packages/ui/src/components/dialog.css | 41 ++++++++++++------------ packages/ui/src/components/switch.css | 12 +++---- packages/ui/src/components/tabs.css | 3 ++ packages/ui/src/components/tag.css | 3 ++ packages/ui/src/styles/utilities.css | 42 +++++++++++++++++++++++++ 7 files changed, 89 insertions(+), 28 deletions(-) diff --git a/packages/ui/src/components/card.css b/packages/ui/src/components/card.css index 6dae47223d67..809fbdacde37 100644 --- a/packages/ui/src/components/card.css +++ b/packages/ui/src/components/card.css @@ -4,7 +4,9 @@ flex-direction: column; background-color: var(--surface-inset-base); border: 1px solid var(--border-weaker-base); - transition: background-color 0.15s ease; + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); border-radius: var(--radius-md); padding: 6px 12px; overflow: clip; diff --git a/packages/ui/src/components/checkbox.css b/packages/ui/src/components/checkbox.css index b10ebbbd197b..cad0dd2dd6bd 100644 --- a/packages/ui/src/components/checkbox.css +++ b/packages/ui/src/components/checkbox.css @@ -4,6 +4,18 @@ gap: 12px; cursor: default; + [data-slot="checkbox-checkbox-control"] { + transition-property: border-color, background-color, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } + + [data-slot="checkbox-checkbox-indicator"] { + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } + [data-slot="checkbox-checkbox-input"] { position: absolute; width: 1px; diff --git a/packages/ui/src/components/dialog.css b/packages/ui/src/components/dialog.css index a0e7e111fd0f..e0e06c24145e 100644 --- a/packages/ui/src/components/dialog.css +++ b/packages/ui/src/components/dialog.css @@ -6,11 +6,15 @@ z-index: 50; background-color: hsl(from var(--background-base) h s l / 0.2); - /* animation: overlayHide 250ms ease 100ms forwards; */ - /**/ - /* &[data-expanded] { */ - /* animation: overlayShow 250ms ease; */ - /* } */ + animation: overlayHide var(--transition-duration) var(--transition-easing) forwards; + + &[data-expanded] { + animation: overlayShow var(--transition-duration) var(--transition-easing) forwards; + } + + @starting-style { + animation: none; + } } [data-component="dialog"] { @@ -31,7 +35,6 @@ flex-direction: column; align-items: center; justify-items: start; - overflow: visible; [data-slot="dialog-content"] { display: flex; @@ -41,16 +44,8 @@ width: 100%; max-height: 100%; min-height: 280px; - overflow: auto; pointer-events: auto; - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } - /* padding: 8px; */ /* padding: 8px 8px 0 8px; */ border-radius: var(--radius-xl); @@ -58,11 +53,15 @@ background-clip: padding-box; box-shadow: var(--shadow-lg-border-base); - /* animation: contentHide 300ms ease-in forwards; */ - /**/ - /* &[data-expanded] { */ - /* animation: contentShow 300ms ease-out; */ - /* } */ + animation: contentHide var(--transition-duration) var(--transition-easing) forwards; + + &[data-expanded] { + animation: contentShow var(--transition-duration) var(--transition-easing) forwards; + } + + @starting-style { + animation: none; + } [data-slot="dialog-header"] { display: flex; @@ -166,7 +165,7 @@ @keyframes contentShow { from { opacity: 0; - transform: scale(0.96); + transform: translateY(2.5%) scale(0.975); } to { opacity: 1; @@ -180,6 +179,6 @@ } to { opacity: 0; - transform: scale(0.96); + transform: translateY(-2.5%) scale(0.975); } } diff --git a/packages/ui/src/components/switch.css b/packages/ui/src/components/switch.css index 89e844732201..9ea722760a2d 100644 --- a/packages/ui/src/components/switch.css +++ b/packages/ui/src/components/switch.css @@ -26,9 +26,9 @@ border-radius: 3px; border: 1px solid var(--border-weak-base); background: var(--surface-base); - transition: - background-color 150ms, - border-color 150ms; + transition-property: background-color, border-color, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } [data-slot="switch-thumb"] { @@ -47,9 +47,9 @@ 0 1px 3px 0 rgba(19, 16, 16, 0.08); transform: translateX(-1px); - transition: - transform 150ms, - background-color 150ms; + transition-property: transform, background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } [data-slot="switch-label"] { diff --git a/packages/ui/src/components/tabs.css b/packages/ui/src/components/tabs.css index 9af141306b65..5a8507564dfb 100644 --- a/packages/ui/src/components/tabs.css +++ b/packages/ui/src/components/tabs.css @@ -57,6 +57,9 @@ border-bottom: 1px solid var(--border-weak-base); border-right: 1px solid var(--border-weak-base); background-color: var(--background-base); + transition-property: background-color, border-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); [data-slot="tabs-trigger"] { display: flex; diff --git a/packages/ui/src/components/tag.css b/packages/ui/src/components/tag.css index 0e8b7b9f1047..5ffd2b91155b 100644 --- a/packages/ui/src/components/tag.css +++ b/packages/ui/src/components/tag.css @@ -8,6 +8,9 @@ border: 0.5px solid var(--border-weak-base); background: var(--surface-raised-base); color: var(--text-base); + transition-property: background-color, border-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); &[data-size="normal"] { height: 18px; diff --git a/packages/ui/src/styles/utilities.css b/packages/ui/src/styles/utilities.css index 8c954f1fe4e7..82a913c8830c 100644 --- a/packages/ui/src/styles/utilities.css +++ b/packages/ui/src/styles/utilities.css @@ -1,6 +1,17 @@ :root { interpolate-size: allow-keywords; + /* Transition tokens */ + --transition-duration: 200ms; + --transition-easing: cubic-bezier(0.25, 0, 0.5, 1); + --transition-fast: 150ms; + --transition-slow: 300ms; + + /* Allow height transitions from 0 to auto */ + @supports (interpolate-size: allow-keywords) { + interpolate-size: allow-keywords; + } + [data-popper-positioner] { pointer-events: none; } @@ -129,3 +140,34 @@ line-height: var(--line-height-x-large); /* 120% */ letter-spacing: var(--letter-spacing-tightest); } + +/* Transition utility classes */ +.transition-colors { + transition-property: background-color, border-color, color, fill, stroke; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-opacity { + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-transform { + transition-property: transform; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-shadow { + transition-property: box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} + +.transition-interactive { + transition-property: background-color, border-color, color, box-shadow, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); +} From 32d29ecbb1776076397c7d6785395c30dded4987 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:51:31 +0100 Subject: [PATCH 10/26] feat: transitions, review, dialog --- .../src/components/dialog-select-model.tsx | 39 +++++++++++++++++-- .../src/components/session-context-usage.tsx | 6 +-- packages/ui/src/components/hover-card.css | 4 +- packages/ui/src/components/icon-button.css | 5 ++- packages/ui/src/components/radio-group.css | 17 ++++---- packages/ui/src/components/resize-handle.css | 4 +- packages/ui/src/components/session-review.css | 12 +++--- packages/ui/src/context/dialog.tsx | 28 +++++++++++++ 8 files changed, 88 insertions(+), 27 deletions(-) diff --git a/packages/app/src/components/dialog-select-model.tsx b/packages/app/src/components/dialog-select-model.tsx index 5569d7780fe9..15c3aeb1bb49 100644 --- a/packages/app/src/components/dialog-select-model.tsx +++ b/packages/app/src/components/dialog-select-model.tsx @@ -88,7 +88,7 @@ const ModelList: Component<{ export function ModelSelectorPopover(props: { provider?: string - children?: JSX.Element + children?: JSX.Element | ((open: boolean) => JSX.Element) triggerAs?: T triggerProps?: ComponentProps }) { @@ -101,13 +101,44 @@ export function ModelSelectorPopover(props: { } const language = useLanguage() + // Handle ESC key to close + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === "Escape") { + e.preventDefault() + e.stopPropagation() + setOpen(false) + } + } + + const renderChildren = () => { + if (typeof props.children === "function") { + return props.children(open()) + } + return props.children + } + return ( - - {props.children} + + {renderChildren()} - + +
setOpen(false)} + onKeyDown={handleKeyDown} + /> + + {language.t("dialog.model.select.title")} ( -
- +
+
) @@ -99,7 +99,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) { } @@ -1899,11 +1920,15 @@ export const PromptInput: Component = (props) => { keybind={command.keybind("model.choose")} > - - - - {local.model.current()?.name ?? language.t("dialog.model.select.title")} - + {(open) => ( + <> + + + + {local.model.current()?.name ?? language.t("dialog.model.select.title")} + + + )} @@ -1915,10 +1940,13 @@ export const PromptInput: Component = (props) => { > @@ -1932,7 +1960,7 @@ export const PromptInput: Component = (props) => { variant="ghost" onClick={() => permission.toggleAutoAccept(params.id!, sdk.directory)} classList={{ - "_hidden group-hover/prompt-input:flex size-6 items-center justify-center": true, + "_hidden group-hover/prompt-input:flex items-center justify-center": true, "text-text-base": !permission.isAutoAccepting(params.id!, sdk.directory), "hover:bg-surface-success-base": permission.isAutoAccepting(params.id!, sdk.directory), }} @@ -1954,7 +1982,7 @@ export const PromptInput: Component = (props) => {
-
+
= (props) => { onClick={() => fileInputRef.click()} aria-label={language.t("prompt.action.attachFile")} > - + @@ -1996,7 +2024,7 @@ export const PromptInput: Component = (props) => {
{language.t("prompt.action.send")} - +
@@ -2007,7 +2035,7 @@ export const PromptInput: Component = (props) => { disabled={!prompt.dirty() && !working()} icon={working() ? "stop" : "arrow-up"} variant="primary" - class="h-6 w-4.5" + class="h-6 w-5" aria-label={working() ? language.t("prompt.action.stop") : language.t("prompt.action.send")} /> diff --git a/packages/ui/src/components/progress-circle.css b/packages/ui/src/components/progress-circle.css index afaf72af61ee..75329a2c5c98 100644 --- a/packages/ui/src/components/progress-circle.css +++ b/packages/ui/src/components/progress-circle.css @@ -1,12 +1,10 @@ [data-component="progress-circle"] { - transform: rotate(-90deg); + color: inherit; [data-slot="progress-circle-background"] { - stroke: var(--border-weak-base); - } - - [data-slot="progress-circle-progress"] { - stroke: var(--border-active); + transform-origin: 50% 50%; + transform: rotate(270deg); + stroke-opacity: 0.35; transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1); } } diff --git a/packages/ui/src/components/progress-circle.tsx b/packages/ui/src/components/progress-circle.tsx index 02bd36bb7105..bf7676476fdd 100644 --- a/packages/ui/src/components/progress-circle.tsx +++ b/packages/ui/src/components/progress-circle.tsx @@ -1,4 +1,4 @@ -import { type ComponentProps, createMemo, splitProps } from "solid-js" +import { type ComponentProps, splitProps } from "solid-js" export interface ProgressCircleProps extends Pick, "class" | "classList"> { percentage: number @@ -10,25 +10,13 @@ export function ProgressCircle(props: ProgressCircleProps) { const [split, rest] = splitProps(props, ["percentage", "size", "strokeWidth", "class", "classList"]) const size = () => split.size || 16 - const strokeWidth = () => split.strokeWidth || 3 - - const viewBoxSize = 16 - const center = viewBoxSize / 2 - const radius = () => center - strokeWidth() / 2 - const circumference = createMemo(() => 2 * Math.PI * radius()) - - const offset = createMemo(() => { - const clampedPercentage = Math.max(0, Math.min(100, split.percentage || 0)) - const progress = clampedPercentage / 100 - return circumference() * (1 - progress) - }) return ( - - + + + + + + + ) -} +} \ No newline at end of file From 50f10ed7c035abead1182f08169761f1cee2fdf7 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:52:00 +0100 Subject: [PATCH 12/26] feat: button transition --- packages/ui/src/components/button.css | 29 +++++++++++---------------- packages/ui/src/components/button.tsx | 2 +- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index 6922d996f136..1822b34a73d4 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -8,8 +8,13 @@ text-decoration: none; user-select: none; cursor: default; - outline: none; + padding: 4px 8px; white-space: nowrap; + transition-property: background-color, border-color, color, box-shadow, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + outline: none; + line-height: 20px; &[data-variant="primary"] { background-color: var(--button-primary-base); @@ -87,7 +92,6 @@ &:active:not(:disabled) { background-color: var(--button-secondary-base); scale: 0.99; - transition: all 150ms ease-out; } &:disabled { border-color: var(--border-disabled); @@ -102,34 +106,27 @@ } &[data-size="small"] { - height: 22px; - padding: 0 8px; + padding: 2px 8px; &[data-icon] { - padding: 0 12px 0 4px; + padding: 2px 12px 2px 4px; } - font-size: var(--font-size-small); - line-height: var(--line-height-large); gap: 4px; /* 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% */ letter-spacing: var(--letter-spacing-normal); } &[data-size="normal"] { - height: 24px; - line-height: 24px; - padding: 0 6px; + padding: 4px 6px; &[data-icon] { - padding: 0 12px 0 4px; + padding: 4px 12px 4px 4px; } - font-size: var(--font-size-small); gap: 6px; /* text-12-medium */ @@ -141,11 +138,10 @@ } &[data-size="large"] { - height: 32px; padding: 6px 12px; &[data-icon] { - padding: 0 12px 0 8px; + padding: 6px 12px 6px 8px; } gap: 8px; @@ -155,7 +151,6 @@ font-size: 14px; font-style: normal; font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ letter-spacing: var(--letter-spacing-normal); } diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx index 7f974b2f76e7..b2d2004d3c8c 100644 --- a/packages/ui/src/components/button.tsx +++ b/packages/ui/src/components/button.tsx @@ -4,7 +4,7 @@ import { Icon, IconProps } from "./icon" export interface ButtonProps extends ComponentProps, - Pick, "class" | "classList" | "children"> { + Pick, "class" | "classList" | "children" | "style"> { size?: "small" | "normal" | "large" variant?: "primary" | "secondary" | "ghost" icon?: IconProps["name"] From ce89c2d1b82d46ffdf24c38abc6f421b4891c9fa Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 17:52:07 +0100 Subject: [PATCH 13/26] feat: popover & list --- packages/ui/src/components/list.css | 12 ++++-- packages/ui/src/components/popover.css | 58 ++++++++++++++++++++------ 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/packages/ui/src/components/list.css b/packages/ui/src/components/list.css index dab5b2fca24d..f24e9ec1328b 100644 --- a/packages/ui/src/components/list.css +++ b/packages/ui/src/components/list.css @@ -38,7 +38,9 @@ flex-shrink: 0; background-color: transparent; opacity: 0.5; - transition: opacity 0.15s ease; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); &:hover:not(:disabled), &:focus:not(:disabled), @@ -89,7 +91,9 @@ height: 20px; background-color: transparent; opacity: 0.5; - transition: opacity 0.15s ease; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); &:hover:not(:disabled), &:focus:not(:disabled), @@ -189,7 +193,9 @@ background: linear-gradient(to bottom, var(--surface-raised-stronger-non-alpha), transparent); pointer-events: none; opacity: 0; - transition: opacity 0.15s ease; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); } &[data-stuck="true"]::after { diff --git a/packages/ui/src/components/popover.css b/packages/ui/src/components/popover.css index b49542afd9b8..d200fe8b2476 100644 --- a/packages/ui/src/components/popover.css +++ b/packages/ui/src/components/popover.css @@ -15,16 +15,35 @@ transform-origin: var(--kb-popover-content-transform-origin); - &:focus-within { - outline: none; - } + animation: popoverContentHide var(--transition-duration) var(--transition-easing) forwards; - &[data-closed] { - animation: popover-close 0.15s ease-out; + @starting-style { + animation: none; } &[data-expanded] { - animation: popover-open 0.15s ease-out; + pointer-events: auto; + animation: popoverContentShow var(--transition-duration) var(--transition-easing) forwards; + } + + [data-origin-top-right] { + transform-origin: top right; + } + + [data-origin-top-left] { + transform-origin: top left; + } + + [data-origin-bottom-right] { + transform-origin: bottom right; + } + + [data-origin-bottom-left] { + transform-origin: bottom left; + } + + &:focus-within { + outline: none; } [data-slot="popover-header"] { @@ -75,24 +94,39 @@ } } -@keyframes popover-open { +@keyframes popoverContentShow { from { opacity: 0; - transform: scale(0.96); + transform: scaleY(0.95); } to { opacity: 1; - transform: scale(1); + transform: scaleY(1); } } -@keyframes popover-close { +@keyframes popoverContentHide { from { opacity: 1; - transform: scale(1); + transform: scaleY(1); } to { opacity: 0; - transform: scale(0.96); + transform: scaleY(0.95); + } +} + +[data-component="model-popover-content"] { + transform-origin: var(--kb-popper-content-transform-origin); + pointer-events: none; + animation: popoverContentHide var(--transition-duration) var(--transition-easing) forwards; + + @starting-style { + animation: none; + } + + &[data-expanded] { + pointer-events: auto; + animation: popoverContentShow var(--transition-duration) var(--transition-easing) forwards; } } From b788d52a212b8975b3a155b91368d989b5806d6e Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 29 Jan 2026 18:30:03 +0100 Subject: [PATCH 14/26] format --- packages/ui/src/components/accordion.css | 186 +-- packages/ui/src/components/avatar.css | 64 +- packages/ui/src/components/basic-tool.css | 168 +- packages/ui/src/components/button.css | 331 ++-- packages/ui/src/components/card.css | 52 +- packages/ui/src/components/checkbox.css | 265 +-- packages/ui/src/components/code.css | 4 +- packages/ui/src/components/collapsible.css | 170 +- packages/ui/src/components/cycle-label.css | 87 +- packages/ui/src/components/dialog.css | 348 ++-- packages/ui/src/components/diff-changes.css | 66 +- packages/ui/src/components/diff.css | 60 +- packages/ui/src/components/dropdown-menu.css | 234 +-- packages/ui/src/components/file-icon.css | 6 +- packages/ui/src/components/hover-card.css | 102 +- packages/ui/src/components/icon-button.css | 282 ++-- packages/ui/src/components/icon.css | 54 +- packages/ui/src/components/image-preview.css | 110 +- packages/ui/src/components/inline-input.css | 28 +- packages/ui/src/components/keybind.css | 30 +- packages/ui/src/components/line-comment.css | 140 +- packages/ui/src/components/list.css | 654 ++++---- packages/ui/src/components/logo.css | 4 +- packages/ui/src/components/markdown.css | 416 ++--- packages/ui/src/components/message-nav.css | 179 +- packages/ui/src/components/message-part.css | 1483 ++++++++--------- packages/ui/src/components/morph-chevron.css | 16 +- packages/ui/src/components/morph-chevron.tsx | 12 +- packages/ui/src/components/popover.css | 240 +-- .../ui/src/components/progress-circle.css | 14 +- packages/ui/src/components/provider-icon.css | 6 +- packages/ui/src/components/radio-group.css | 321 ++-- packages/ui/src/components/reasoning-icon.css | 12 +- packages/ui/src/components/resize-handle.css | 116 +- packages/ui/src/components/scroll-fade.css | 226 +-- packages/ui/src/components/select.css | 286 ++-- packages/ui/src/components/session-review.css | 427 ++--- packages/ui/src/components/session-turn.css | 1139 ++++++------- packages/ui/src/components/spinner.css | 8 +- .../components/sticky-accordion-header.css | 24 +- packages/ui/src/components/switch.css | 261 +-- packages/ui/src/components/tabs.css | 904 +++++----- packages/ui/src/components/tag.css | 66 +- packages/ui/src/components/text-field.css | 264 +-- packages/ui/src/components/toast.css | 382 ++--- packages/ui/src/components/tooltip.css | 116 +- packages/ui/src/components/typewriter.css | 18 +- packages/ui/src/styles/utilities.css | 231 +-- 48 files changed, 5339 insertions(+), 5273 deletions(-) diff --git a/packages/ui/src/components/accordion.css b/packages/ui/src/components/accordion.css index 97632989810a..441bd0542f2f 100644 --- a/packages/ui/src/components/accordion.css +++ b/packages/ui/src/components/accordion.css @@ -1,109 +1,107 @@ [data-component="accordion"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - align-self: stretch; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + align-self: stretch; - [data-slot="accordion-item"] { - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - overflow: clip; + [data-slot="accordion-item"] { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + overflow: clip; - [data-slot="accordion-header"] { - width: 100%; - display: flex; - align-items: center; - margin: 0; - padding: 0; + [data-slot="accordion-header"] { + width: 100%; + display: flex; + align-items: center; + margin: 0; + padding: 0; - [data-slot="accordion-trigger"] { - width: 100%; - display: flex; - height: 32px; - padding: 8px 12px; - justify-content: space-between; - align-items: center; - align-self: stretch; - cursor: default; - user-select: none; + [data-slot="accordion-trigger"] { + width: 100%; + display: flex; + height: 32px; + padding: 8px 12px; + justify-content: space-between; + align-items: center; + align-self: stretch; + cursor: default; + user-select: none; - background-color: var(--surface-base); - border: 1px solid var(--border-weak-base); - border-radius: var(--radius-md); - overflow: clip; - color: var(--text-strong); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + background-color: var(--surface-base); + border: 1px solid var(--border-weak-base); + border-radius: var(--radius-md); + overflow: clip; + color: var(--text-strong); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &:hover { - background-color: var(--surface-base); - } - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } - } - } + &:hover { + background-color: var(--surface-base); + } + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } + } + } - [data-slot="accordion-arrow"] { - flex-shrink: 0; - width: 16px; - height: 16px; - display: flex; - align-items: center; - justify-content: center; - color: var(--text-weak); - } + [data-slot="accordion-arrow"] { + flex-shrink: 0; + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weak); + } - &[data-expanded] { - [data-slot="accordion-trigger"] { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } + [data-slot="accordion-content"] { + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + width: 100%; - [data-slot="accordion-content"] { - border: 1px solid var(--border-weak-base); - border-top: none; - border-bottom-left-radius: var(--radius-md); - border-bottom-right-radius: var(--radius-md); - height: auto; - } - } + > * { + overflow: hidden; + } + } - [data-slot="accordion-content"] { - display: grid; - grid-template-rows: 0fr; - transition-property: grid-template-rows, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - width: 100%; + [data-slot="accordion-content"][data-expanded] { + grid-template-rows: 1fr; + } - > * { - overflow: hidden; - } + [data-slot="accordion-content"][data-closed] { + grid-template-rows: 0fr; + } - &[data-expanded] { - grid-template-rows: 1fr; - } + &[data-expanded] [data-slot="accordion-trigger"] { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } - &[data-closed] { - grid-template-rows: 0fr; - } - } - } + &[data-expanded] [data-slot="accordion-content"] { + border: 1px solid var(--border-weak-base); + border-top: none; + border-bottom-left-radius: var(--radius-md); + border-bottom-right-radius: var(--radius-md); + height: auto; + } + } } diff --git a/packages/ui/src/components/avatar.css b/packages/ui/src/components/avatar.css index 5872160771ce..dff6bb7b89f4 100644 --- a/packages/ui/src/components/avatar.css +++ b/packages/ui/src/components/avatar.css @@ -1,49 +1,49 @@ [data-component="avatar"] { - --avatar-bg: var(--color-surface-info-base); - --avatar-fg: var(--color-text-base); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - border-radius: var(--radius-sm); - border: 1px solid var(--color-border-weak-base); - font-family: var(--font-mono); - font-weight: 500; - text-transform: uppercase; - background-color: var(--avatar-bg); - color: var(--avatar-fg); + --avatar-bg: var(--color-surface-info-base); + --avatar-fg: var(--color-text-base); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + border-radius: var(--radius-sm); + border: 1px solid var(--color-border-weak-base); + font-family: var(--font-mono); + font-weight: 500; + text-transform: uppercase; + background-color: var(--avatar-bg); + color: var(--avatar-fg); } [data-component="avatar"][data-has-image] { - background-color: transparent; - border: none; + background-color: transparent; + border: none; } [data-component="avatar"][data-size="small"] { - width: 1.25rem; - height: 1.25rem; - font-size: 0.75rem; - line-height: 1; + width: 1.25rem; + height: 1.25rem; + font-size: 0.75rem; + line-height: 1; } [data-component="avatar"][data-size="normal"] { - width: 1.5rem; - height: 1.5rem; - font-size: 1.125rem; - line-height: 1.5rem; + width: 1.5rem; + height: 1.5rem; + font-size: 1.125rem; + line-height: 1.5rem; } [data-component="avatar"][data-size="large"] { - width: 2rem; - height: 2rem; - font-size: 1.25rem; - line-height: 2rem; + width: 2rem; + height: 2rem; + font-size: 1.25rem; + line-height: 2rem; } [data-component="avatar"] [data-slot="avatar-image"] { - width: 100%; - height: 100%; - display: block; - object-fit: cover; - border-radius: inherit; + width: 100%; + height: 100%; + display: block; + object-fit: cover; + border-radius: inherit; } diff --git a/packages/ui/src/components/basic-tool.css b/packages/ui/src/components/basic-tool.css index 2c6bfeb6728c..cc58cfa730e8 100644 --- a/packages/ui/src/components/basic-tool.css +++ b/packages/ui/src/components/basic-tool.css @@ -1,97 +1,97 @@ [data-component="tool-trigger"] { - content-visibility: auto; - width: 100%; - display: flex; - align-items: center; - align-self: stretch; - gap: 20px; - justify-content: space-between; + content-visibility: auto; + width: 100%; + display: flex; + align-items: center; + align-self: stretch; + gap: 20px; + justify-content: space-between; - [data-slot="basic-tool-tool-trigger-content"] { - width: 100%; - display: flex; - align-items: center; - align-self: stretch; - gap: 20px; - } + [data-slot="basic-tool-tool-trigger-content"] { + width: 100%; + display: flex; + align-items: center; + align-self: stretch; + gap: 20px; + } - [data-slot="icon-svg"] { - flex-shrink: 0; - } + [data-slot="icon-svg"] { + flex-shrink: 0; + } - [data-slot="basic-tool-tool-info"] { - flex-grow: 1; - min-width: 0; - } + [data-slot="basic-tool-tool-info"] { + flex-grow: 1; + min-width: 0; + } - [data-slot="basic-tool-tool-info-structured"] { - width: 100%; - display: flex; - align-items: center; - gap: 8px; - justify-content: space-between; - } + [data-slot="basic-tool-tool-info-structured"] { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + justify-content: space-between; + } - [data-slot="basic-tool-tool-info-main"] { - display: flex; - align-items: center; - gap: 8px; - min-width: 0; - overflow: hidden; - } + [data-slot="basic-tool-tool-info-main"] { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + overflow: hidden; + } - [data-slot="basic-tool-tool-title"] { - flex-shrink: 0; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); + [data-slot="basic-tool-tool-title"] { + flex-shrink: 0; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); - &.capitalize { - text-transform: capitalize; - } - } + &.capitalize { + text-transform: capitalize; + } + } - [data-slot="basic-tool-tool-subtitle"] { - flex-shrink: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); + [data-slot="basic-tool-tool-subtitle"] { + flex-shrink: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); - &.clickable { - cursor: pointer; - text-decoration: underline; - transition: color 0.15s ease; + &.clickable { + cursor: pointer; + text-decoration: underline; + transition: color 0.15s ease; - &:hover { - color: var(--text-base); - } - } - } + &:hover { + color: var(--text-base); + } + } + } - [data-slot="basic-tool-tool-arg"] { - flex-shrink: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); - } + [data-slot="basic-tool-tool-arg"] { + flex-shrink: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + } } diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index 02a7ade712a2..56258bd84e70 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -1,167 +1,168 @@ [data-component="button"] { - display: inline-flex; - align-items: center; - justify-content: center; - border-style: solid; - border-width: 1px; - border-radius: var(--radius-md); - text-decoration: none; - user-select: none; - cursor: default; - padding: 4px 8px; - white-space: nowrap; - transition-property: background-color, border-color, color, box-shadow, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - outline: none; - line-height: 20px; - - &[data-variant="primary"] { - background-color: var(--button-primary-base); - border-color: var(--border-weak-base); - color: var(--icon-invert-base); - - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } - - &:hover:not(:disabled) { - background-color: var(--icon-strong-hover); - } - &:focus:not(:disabled) { - background-color: var(--icon-strong-focus); - } - &:active:not(:disabled) { - background-color: var(--icon-strong-active); - } - &:disabled { - background-color: var(--icon-strong-disabled); - - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } - } - } - - &[data-variant="ghost"] { - border-color: transparent; - background-color: transparent; - color: var(--text-strong); - - [data-slot="icon-svg"] { - color: var(--icon-base); - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:focus-visible:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:active:not(:disabled) { - background-color: var(--surface-raised-base-active); - } - &:disabled { - color: var(--text-weak); - cursor: not-allowed; - - [data-slot="icon-svg"] { - color: var(--icon-disabled); - } - } - &[data-selected="true"]:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &[data-active="true"] { - background-color: var(--surface-raised-base-active); - } - } - - &[data-variant="secondary"] { - border: transparent; - background-color: var(--button-secondary-base); - color: var(--text-strong); - box-shadow: var(--shadow-xs-border); - - &:hover:not(:disabled) { - background-color: var(--button-secondary-hover); - } - &:focus:not(:disabled) { - background-color: var(--button-secondary-base); - } - &:focus-visible:not(:active) { - background-color: var(--button-secondary-base); - box-shadow: var(--shadow-xs-border-focus); - } - &:focus-visible:active { - box-shadow: none; - } - &:active:not(:disabled) { - background-color: var(--button-secondary-base); - scale: 0.99; - } - &:disabled { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - color: var(--text-weak); - cursor: not-allowed; - } - - [data-slot="icon-svg"] { - color: var(--icon-strong-base); - } - } - - &[data-size="small"] { - padding: 2px 8px; - &[data-icon] { - padding: 2px 12px 2px 4px; - } - - gap: 4px; - - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - letter-spacing: var(--letter-spacing-normal); - } - - &[data-size="normal"] { - padding: 4px 6px; - &[data-icon] { - padding: 4px 12px 4px 4px; - } - - gap: 6px; - - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - letter-spacing: var(--letter-spacing-normal); - } - - &[data-size="large"] { - padding: 6px 12px; - - &[data-icon] { - padding: 6px 12px 6px 8px; - } - - gap: 4px; - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - letter-spacing: var(--letter-spacing-normal); - } - - &:focus { - outline: none; - } + display: inline-flex; + align-items: center; + justify-content: center; + border-style: solid; + border-width: 1px; + border-radius: var(--radius-md); + text-decoration: none; + user-select: none; + cursor: default; + padding: 4px 8px; + white-space: nowrap; + transition-property: + background-color, border-color, color, box-shadow, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + outline: none; + line-height: 20px; + + &[data-variant="primary"] { + background-color: var(--button-primary-base); + border-color: var(--border-weak-base); + color: var(--icon-invert-base); + + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } + + &:hover:not(:disabled) { + background-color: var(--icon-strong-hover); + } + &:focus:not(:disabled) { + background-color: var(--icon-strong-focus); + } + &:active:not(:disabled) { + background-color: var(--icon-strong-active); + } + &:disabled { + background-color: var(--icon-strong-disabled); + + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } + } + } + + &[data-variant="ghost"] { + border-color: transparent; + background-color: transparent; + color: var(--text-strong); + + [data-slot="icon-svg"] { + color: var(--icon-base); + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:focus-visible:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + &:disabled { + color: var(--text-weak); + cursor: not-allowed; + + [data-slot="icon-svg"] { + color: var(--icon-disabled); + } + } + &[data-selected="true"]:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &[data-active="true"] { + background-color: var(--surface-raised-base-active); + } + } + + &[data-variant="secondary"] { + border: transparent; + background-color: var(--button-secondary-base); + color: var(--text-strong); + box-shadow: var(--shadow-xs-border); + + &:hover:not(:disabled) { + background-color: var(--button-secondary-hover); + } + &:focus:not(:disabled) { + background-color: var(--button-secondary-base); + } + &:focus-visible:not(:active) { + background-color: var(--button-secondary-base); + box-shadow: var(--shadow-xs-border-focus); + } + &:focus-visible:active { + box-shadow: none; + } + &:active:not(:disabled) { + background-color: var(--button-secondary-base); + scale: 0.99; + } + &:disabled { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + color: var(--text-weak); + cursor: not-allowed; + } + + [data-slot="icon-svg"] { + color: var(--icon-strong-base); + } + } + + &[data-size="small"] { + padding: 2px 8px; + &[data-icon] { + padding: 2px 12px 2px 4px; + } + + gap: 4px; + + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } + + &[data-size="normal"] { + padding: 4px 6px; + &[data-icon] { + padding: 4px 12px 4px 4px; + } + + gap: 6px; + + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } + + &[data-size="large"] { + padding: 6px 12px; + + &[data-icon] { + padding: 6px 12px 6px 8px; + } + + gap: 4px; + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: var(--letter-spacing-normal); + } + + &:focus { + outline: none; + } } diff --git a/packages/ui/src/components/card.css b/packages/ui/src/components/card.css index 809fbdacde37..8ac839042181 100644 --- a/packages/ui/src/components/card.css +++ b/packages/ui/src/components/card.css @@ -1,31 +1,31 @@ [data-component="card"] { - width: 100%; - display: flex; - flex-direction: column; - background-color: var(--surface-inset-base); - border: 1px solid var(--border-weaker-base); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - border-radius: var(--radius-md); - padding: 6px 12px; - overflow: clip; + width: 100%; + display: flex; + flex-direction: column; + background-color: var(--surface-inset-base); + border: 1px solid var(--border-weaker-base); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + border-radius: var(--radius-md); + padding: 6px 12px; + overflow: clip; - &[data-variant="error"] { - background-color: var(--surface-critical-weak); - border: 1px solid var(--border-critical-base); - color: rgba(218, 51, 25, 0.6); + &[data-variant="error"] { + background-color: var(--surface-critical-weak); + border: 1px solid var(--border-critical-base); + color: rgba(218, 51, 25, 0.6); - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - &[data-component="icon"] { - color: var(--icon-critical-active); - } - } + &[data-component="icon"] { + color: var(--icon-critical-active); + } + } } diff --git a/packages/ui/src/components/checkbox.css b/packages/ui/src/components/checkbox.css index cad0dd2dd6bd..44cb1d8ae658 100644 --- a/packages/ui/src/components/checkbox.css +++ b/packages/ui/src/components/checkbox.css @@ -1,133 +1,136 @@ [data-component="checkbox"] { - display: flex; - align-items: center; - gap: 12px; - cursor: default; - - [data-slot="checkbox-checkbox-control"] { - transition-property: border-color, background-color, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } - - [data-slot="checkbox-checkbox-indicator"] { - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } - - [data-slot="checkbox-checkbox-input"] { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; - } - - [data-slot="checkbox-checkbox-control"] { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - padding: 2px; - aspect-ratio: 1; - flex-shrink: 0; - border-radius: var(--radius-sm); - border: 1px solid var(--border-weak-base); - /* background-color: var(--surface-weak); */ - } - - [data-slot="checkbox-checkbox-indicator"] { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - color: var(--icon-base); - opacity: 0; - } - - /* [data-slot="checkbox-checkbox-content"] { */ - /* } */ - - [data-slot="checkbox-checkbox-label"] { - user-select: none; - color: var(--text-base); - - /* text-12-regular */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } - - [data-slot="checkbox-checkbox-description"] { - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } - - [data-slot="checkbox-checkbox-error"] { - color: var(--text-error); - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-normal); - letter-spacing: var(--letter-spacing-normal); - } - - &:hover:not([data-disabled], [data-readonly]) [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } - - &:focus-within:not([data-readonly]) [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-focus); - box-shadow: 0 0 0 2px var(--surface-focus); - } - - &[data-checked] [data-slot="checkbox-checkbox-control"], - &[data-indeterminate] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-base); - background-color: var(--surface-weak); - } - - &[data-checked]:hover:not([data-disabled], [data-readonly]) [data-slot="checkbox-checkbox-control"], - &[data-indeterminate]:hover:not([data-disabled]) [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-hover); - background-color: var(--surface-hover); - } - - &[data-checked] [data-slot="checkbox-checkbox-indicator"], - &[data-indeterminate] [data-slot="checkbox-checkbox-indicator"] { - opacity: 1; - } - - &[data-disabled] { - cursor: not-allowed; - } - - &[data-disabled] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-disabled); - background-color: var(--surface-disabled); - } - - &[data-invalid] [data-slot="checkbox-checkbox-control"] { - border-color: var(--border-error); - } - - &[data-readonly] { - cursor: default; - pointer-events: none; - } + display: flex; + align-items: center; + gap: 12px; + cursor: default; + + [data-slot="checkbox-checkbox-control"] { + transition-property: border-color, background-color, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } + + [data-slot="checkbox-checkbox-indicator"] { + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } + + [data-slot="checkbox-checkbox-input"] { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } + + [data-slot="checkbox-checkbox-control"] { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + padding: 2px; + aspect-ratio: 1; + flex-shrink: 0; + border-radius: var(--radius-sm); + border: 1px solid var(--border-weak-base); + /* background-color: var(--surface-weak); */ + } + + [data-slot="checkbox-checkbox-indicator"] { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + color: var(--icon-base); + opacity: 0; + } + + /* [data-slot="checkbox-checkbox-content"] { */ + /* } */ + + [data-slot="checkbox-checkbox-label"] { + user-select: none; + color: var(--text-base); + + /* text-12-regular */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="checkbox-checkbox-description"] { + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="checkbox-checkbox-error"] { + color: var(--text-error); + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-normal); + letter-spacing: var(--letter-spacing-normal); + } + + &:hover:not([data-disabled], [data-readonly]) + [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } + + &:focus-within:not([data-readonly]) [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-focus); + box-shadow: 0 0 0 2px var(--surface-focus); + } + + &[data-checked] [data-slot="checkbox-checkbox-control"], + &[data-indeterminate] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-base); + background-color: var(--surface-weak); + } + + &[data-checked]:hover:not([data-disabled], [data-readonly]) + [data-slot="checkbox-checkbox-control"], + &[data-indeterminate]:hover:not([data-disabled]) + [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-hover); + background-color: var(--surface-hover); + } + + &[data-checked] [data-slot="checkbox-checkbox-indicator"], + &[data-indeterminate] [data-slot="checkbox-checkbox-indicator"] { + opacity: 1; + } + + &[data-disabled] { + cursor: not-allowed; + } + + &[data-disabled] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-disabled); + background-color: var(--surface-disabled); + } + + &[data-invalid] [data-slot="checkbox-checkbox-control"] { + border-color: var(--border-error); + } + + &[data-readonly] { + cursor: default; + pointer-events: none; + } } diff --git a/packages/ui/src/components/code.css b/packages/ui/src/components/code.css index 671b40512dea..553219bb8664 100644 --- a/packages/ui/src/components/code.css +++ b/packages/ui/src/components/code.css @@ -1,4 +1,4 @@ [data-component="code"] { - content-visibility: auto; - overflow: hidden; + content-visibility: auto; + overflow: hidden; } diff --git a/packages/ui/src/components/collapsible.css b/packages/ui/src/components/collapsible.css index cc62b2b87c54..312eec84a8cd 100644 --- a/packages/ui/src/components/collapsible.css +++ b/packages/ui/src/components/collapsible.css @@ -1,99 +1,99 @@ [data-component="collapsible"] { - width: 100%; - display: flex; - flex-direction: column; - background-color: var(--surface-inset-base); - border: 1px solid var(--border-weaker-base); - transition-property: background-color, border-color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - border-radius: var(--radius-md); - overflow: clip; + width: 100%; + display: flex; + flex-direction: column; + background-color: var(--surface-inset-base); + border: 1px solid var(--border-weaker-base); + transition-property: background-color, border-color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + border-radius: var(--radius-md); + overflow: clip; - [data-slot="collapsible-trigger"] { - width: 100%; - display: flex; - height: 32px; - padding: 6px 8px 6px 12px; - align-items: center; - align-self: stretch; - cursor: default; - user-select: none; - color: var(--text-base); + [data-slot="collapsible-trigger"] { + width: 100%; + display: flex; + height: 32px; + padding: 6px 8px 6px 12px; + align-items: center; + align-self: stretch; + cursor: default; + user-select: none; + color: var(--text-base); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); - /* &:hover { */ - /* background-color: var(--surface-base); */ - /* } */ - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } + /* &:hover { */ + /* background-color: var(--surface-base); */ + /* } */ + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } - [data-slot="collapsible-arrow"] { - flex-shrink: 0; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - color: var(--text-weak); - } - } + [data-slot="collapsible-arrow"] { + flex-shrink: 0; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weak); + } + } - [data-slot="collapsible-content"] { - display: grid; - grid-template-rows: 0fr; - transition-property: grid-template-rows, opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); + [data-slot="collapsible-content"] { + display: grid; + grid-template-rows: 0fr; + transition-property: grid-template-rows, opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); - > * { - overflow: hidden; - } + > * { + overflow: hidden; + } - &[data-expanded] { - grid-template-rows: 1fr; - } + &[data-expanded] { + grid-template-rows: 1fr; + } - &[data-closed] { - grid-template-rows: 0fr; - } - } + &[data-closed] { + grid-template-rows: 0fr; + } + } - &[data-variant="ghost"] { - background-color: transparent; - border: none; + &[data-variant="ghost"] { + background-color: transparent; + border: none; - > [data-slot="collapsible-trigger"] { - background-color: transparent; - border: none; - padding: 0; + > [data-slot="collapsible-trigger"] { + background-color: transparent; + border: none; + padding: 0; - /* &:hover { */ - /* color: var(--text-strong); */ - /* } */ - &:focus-visible { - outline: none; - } - &[data-disabled] { - cursor: not-allowed; - } - } - } + /* &:hover { */ + /* color: var(--text-strong); */ + /* } */ + &:focus-visible { + outline: none; + } + &[data-disabled] { + cursor: not-allowed; + } + } + } - &[data-variant="ghost"][data-scope="filetree"] { - > [data-slot="collapsible-trigger"] { - height: 24px; - } - } + &[data-variant="ghost"][data-scope="filetree"] { + > [data-slot="collapsible-trigger"] { + height: 24px; + } + } } diff --git a/packages/ui/src/components/cycle-label.css b/packages/ui/src/components/cycle-label.css index a67471fe5192..46a6408f01d7 100644 --- a/packages/ui/src/components/cycle-label.css +++ b/packages/ui/src/components/cycle-label.css @@ -1,51 +1,52 @@ .cycle-label { - --c-dur: 200ms; - --c-stag: 30ms; - --c-ease: cubic-bezier(0.25, 0, 0.5, 1); - --c-opacity-start: 0; - --c-opacity-end: 1; - --c-blur-start: 0px; - --c-blur-end: 0px; - --c-skew: 10deg; + --c-dur: 200ms; + --c-stag: 30ms; + --c-ease: cubic-bezier(0.25, 0, 0.5, 1); + --c-opacity-start: 0; + --c-opacity-end: 1; + --c-blur-start: 0px; + --c-blur-end: 0px; + --c-skew: 10deg; - display: inline-flex; - position: relative; - - transform-style: preserve-3d; - perspective: 500px; - transition: width 200ms var(--c-ease); - will-change: width; - overflow: hidden; + display: inline-flex; + position: relative; - .cycle-char { - display: inline-block; - transform-style: preserve-3d; - min-width: 0.25em; - backface-visibility: hidden; + transform-style: preserve-3d; + perspective: 500px; + transition: width 200ms var(--c-ease); + will-change: width; + overflow: hidden; - transition: - transform var(--c-dur) var(--c-ease), - opacity var(--c-dur) var(--c-ease), - filter var(--c-dur) var(--c-ease); - transition-delay: calc(var(--i, 0) * var(--c-stag)); + .cycle-char { + display: inline-block; + transform-style: preserve-3d; + min-width: 0.25em; + backface-visibility: hidden; - &.enter { - opacity: var(--c-opacity-end); - filter: blur(var(--c-blur-end)); - transform: translateY(0) rotateX(0) skewX(0); - } + transition: + transform var(--c-dur) var(--c-ease), + opacity var(--c-dur) var(--c-ease), + filter var(--c-dur) var(--c-ease); + transition-delay: calc(var(--i, 0) * var(--c-stag)); - &.exit { - opacity: var(--c-opacity-start); - filter: blur(var(--c-blur-start)); - transform: translateY(50%) rotateX(90deg) skewX(var(--c-skew)); - } + &.enter { + opacity: var(--c-opacity-end); + filter: blur(var(--c-blur-end)); + transform: translateY(0) rotateX(0) skewX(0); + } - &.pre { - opacity: var(--c-opacity-start); - filter: blur(var(--c-blur-start)); - transition: none; - transform: translateY(-50%) rotateX(-90deg) skewX(calc(var(--c-skew) * -1)); - } - } + &.exit { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transform: translateY(50%) rotateX(90deg) skewX(var(--c-skew)); + } + + &.pre { + opacity: var(--c-opacity-start); + filter: blur(var(--c-blur-start)); + transition: none; + transform: translateY(-50%) rotateX(-90deg) + skewX(calc(var(--c-skew) * -1)); + } + } } diff --git a/packages/ui/src/components/dialog.css b/packages/ui/src/components/dialog.css index b788945dceb6..5ff9ec595b22 100644 --- a/packages/ui/src/components/dialog.css +++ b/packages/ui/src/components/dialog.css @@ -1,192 +1,196 @@ /* [data-component="dialog-trigger"] { } */ [data-component="dialog-overlay"] { - position: fixed; - inset: 0; - z-index: 50; - background-color: hsl(from var(--background-base) h s l / 0.2); - - animation: overlayHide var(--transition-duration) var(--transition-easing) forwards; - - &[data-expanded] { - animation: overlayShow var(--transition-duration) var(--transition-easing) forwards; - } - - @starting-style { - animation: none; - } + position: fixed; + inset: 0; + z-index: 50; + background-color: hsl(from var(--background-base) h s l / 0.2); + + animation: overlayHide var(--transition-duration) var(--transition-easing) + forwards; + + &[data-expanded] { + animation: overlayShow var(--transition-duration) var(--transition-easing) + forwards; + } + + @starting-style { + animation: none; + } } [data-component="dialog"] { - position: fixed; - inset: 0; - z-index: 50; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; - - [data-slot="dialog-container"] { - position: relative; - z-index: 50; - width: min(calc(100vw - 16px), 640px); - height: min(calc(100vh - 16px), 512px); - display: flex; - flex-direction: column; - align-items: center; - justify-items: start; - - [data-slot="dialog-content"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - width: 100%; - max-height: 100%; - min-height: 280px; - pointer-events: auto; - - /* padding: 8px; */ - /* padding: 8px 8px 0 8px; */ - border-radius: var(--radius-xl); - background: var(--surface-raised-stronger-non-alpha); - background-clip: padding-box; - box-shadow: var(--shadow-lg-border-base); - - animation: contentHide var(--transition-duration) var(--transition-easing) forwards; - - &[data-expanded] { - animation: contentShow var(--transition-duration) var(--transition-easing) forwards; - } - - @starting-style { - animation: none; - } - - [data-slot="dialog-header"] { - display: flex; - padding: 20px; - justify-content: space-between; - align-items: center; - flex-shrink: 0; - align-self: stretch; - - [data-slot="dialog-title"] { - color: var(--text-strong); - - /* text-16-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-large); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-x-large); /* 150% */ - letter-spacing: var(--letter-spacing-tight); - } - /* [data-slot="dialog-close-button"] {} */ - } - - [data-slot="dialog-description"] { - display: flex; - padding: 16px; - padding-left: 24px; - padding-top: 0; - margin-top: -8px; - justify-content: space-between; - align-items: center; - flex-shrink: 0; - align-self: stretch; - - color: var(--text-base); - - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } - - [data-slot="dialog-body"] { - width: 100%; - position: relative; - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; - - &:focus-visible { - outline: none; - } - } - &:focus-visible { - outline: none; - } - } - } - - &[data-fit] { - [data-slot="dialog-container"] { - height: auto; - - [data-slot="dialog-content"] { - min-height: 0; - } - } - } - - &[data-size="large"] [data-slot="dialog-container"] { - width: min(calc(100vw - 32px), 800px); - height: min(calc(100vh - 32px), 600px); - } - - &[data-size="x-large"] [data-slot="dialog-container"] { - width: min(calc(100vw - 32px), 960px); - height: min(calc(100vh - 32px), 600px); - } + position: fixed; + inset: 0; + z-index: 50; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; + + [data-slot="dialog-container"] { + position: relative; + z-index: 50; + width: min(calc(100vw - 16px), 640px); + height: min(calc(100vh - 16px), 512px); + display: flex; + flex-direction: column; + align-items: center; + justify-items: start; + + [data-slot="dialog-content"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + width: 100%; + max-height: 100%; + min-height: 280px; + pointer-events: auto; + + /* padding: 8px; */ + /* padding: 8px 8px 0 8px; */ + border-radius: var(--radius-xl); + background: var(--surface-raised-stronger-non-alpha); + background-clip: padding-box; + box-shadow: var(--shadow-lg-border-base); + + animation: contentHide var(--transition-duration) var(--transition-easing) + forwards; + + &[data-expanded] { + animation: contentShow var(--transition-duration) + var(--transition-easing) forwards; + } + + @starting-style { + animation: none; + } + + [data-slot="dialog-header"] { + display: flex; + padding: 20px; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + align-self: stretch; + + [data-slot="dialog-title"] { + color: var(--text-strong); + + /* text-16-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-large); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-x-large); /* 150% */ + letter-spacing: var(--letter-spacing-tight); + } + /* [data-slot="dialog-close-button"] {} */ + } + + [data-slot="dialog-description"] { + display: flex; + padding: 16px; + padding-left: 24px; + padding-top: 0; + margin-top: -8px; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + align-self: stretch; + + color: var(--text-base); + + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="dialog-body"] { + width: 100%; + position: relative; + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; + + &:focus-visible { + outline: none; + } + } + &:focus-visible { + outline: none; + } + } + } + + &[data-fit] { + [data-slot="dialog-container"] { + height: auto; + + [data-slot="dialog-content"] { + min-height: 0; + } + } + } + + &[data-size="large"] [data-slot="dialog-container"] { + width: min(calc(100vw - 32px), 800px); + height: min(calc(100vh - 32px), 600px); + } + + &[data-size="x-large"] [data-slot="dialog-container"] { + width: min(calc(100vw - 32px), 960px); + height: min(calc(100vh - 32px), 600px); + } } [data-component="dialog"][data-transition] [data-slot="dialog-content"] { - animation: contentHide 100ms ease-in forwards; + animation: contentHide 100ms ease-in forwards; - &[data-expanded] { - animation: contentShow 150ms ease-out; - } + &[data-expanded] { + animation: contentShow 150ms ease-out; + } } @keyframes overlayShow { - from { - opacity: 0; - } - to { - opacity: 1; - } + from { + opacity: 0; + } + to { + opacity: 1; + } } @keyframes overlayHide { - from { - opacity: 1; - } - to { - opacity: 0; - } + from { + opacity: 1; + } + to { + opacity: 0; + } } @keyframes contentShow { - from { - opacity: 0; - transform: translateY(2.5%) scale(0.975); - } - to { - opacity: 1; - transform: scale(1); - } + from { + opacity: 0; + transform: translateY(2.5%) scale(0.975); + } + to { + opacity: 1; + transform: scale(1); + } } @keyframes contentHide { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: translateY(-2.5%) scale(0.975); - } + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: translateY(-2.5%) scale(0.975); + } } diff --git a/packages/ui/src/components/diff-changes.css b/packages/ui/src/components/diff-changes.css index be3cca885d4b..6e0c3d01ba7f 100644 --- a/packages/ui/src/components/diff-changes.css +++ b/packages/ui/src/components/diff-changes.css @@ -1,41 +1,41 @@ [data-component="diff-changes"] { - display: flex; - gap: 8px; - justify-content: flex-end; - align-items: center; + display: flex; + gap: 8px; + justify-content: flex-end; + align-items: center; - [data-slot="diff-changes-additions"] { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - text-align: right; - color: var(--text-diff-add-base); - } + [data-slot="diff-changes-additions"] { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + text-align: right; + color: var(--text-diff-add-base); + } - [data-slot="diff-changes-deletions"] { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - text-align: right; - color: var(--text-diff-delete-base); - } + [data-slot="diff-changes-deletions"] { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + text-align: right; + color: var(--text-diff-delete-base); + } } [data-component="diff-changes"][data-variant="bars"] { - width: 18px; - flex-shrink: 0; + width: 18px; + flex-shrink: 0; - svg { - display: block; - width: 100%; - height: auto; - } + svg { + display: block; + width: 100%; + height: auto; + } } diff --git a/packages/ui/src/components/diff.css b/packages/ui/src/components/diff.css index 1d94e417aefe..92c445012661 100644 --- a/packages/ui/src/components/diff.css +++ b/packages/ui/src/components/diff.css @@ -1,35 +1,35 @@ [data-component="diff"] { - content-visibility: auto; + content-visibility: auto; - [data-slot="diff-hunk-separator-line-number"] { - position: sticky; - left: 0; - background-color: var(--surface-diff-hidden-strong); - z-index: 2; - display: flex; - align-items: center; - justify-content: center; + [data-slot="diff-hunk-separator-line-number"] { + position: sticky; + left: 0; + background-color: var(--surface-diff-hidden-strong); + z-index: 2; + display: flex; + align-items: center; + justify-content: center; - [data-slot="diff-hunk-separator-line-number-icon"] { - aspect-ratio: 1; - width: 24px; - height: 24px; - color: var(--icon-strong-base); - } - } - [data-slot="diff-hunk-separator-content"] { - position: sticky; - background-color: var(--surface-diff-hidden-base); - color: var(--text-base); - width: var(--diffs-column-content-width); - left: var(--diffs-column-number-width); - padding-left: 8px; - user-select: none; - cursor: default; - text-align: left; + [data-slot="diff-hunk-separator-line-number-icon"] { + aspect-ratio: 1; + width: 24px; + height: 24px; + color: var(--icon-strong-base); + } + } + [data-slot="diff-hunk-separator-content"] { + position: sticky; + background-color: var(--surface-diff-hidden-base); + color: var(--text-base); + width: var(--diffs-column-content-width); + left: var(--diffs-column-number-width); + padding-left: 8px; + user-select: none; + cursor: default; + text-align: left; - [data-slot="diff-hunk-separator-content-span"] { - mix-blend-mode: var(--text-mix-blend-mode); - } - } + [data-slot="diff-hunk-separator-content-span"] { + mix-blend-mode: var(--text-mix-blend-mode); + } + } } diff --git a/packages/ui/src/components/dropdown-menu.css b/packages/ui/src/components/dropdown-menu.css index 2e00505a8fee..940132f9c09b 100644 --- a/packages/ui/src/components/dropdown-menu.css +++ b/packages/ui/src/components/dropdown-menu.css @@ -1,129 +1,131 @@ [data-component="dropdown-menu-content"], [data-component="dropdown-menu-sub-content"] { - min-width: 8rem; - overflow: hidden; - border: none; - border-radius: var(--radius-md); - box-shadow: var(--shadow-xs-border); - background-clip: padding-box; - background-color: var(--surface-raised-stronger-non-alpha); - padding: 4px; - z-index: 100; - transform-origin: var(--kb-menu-content-transform-origin); - - animation: dropdownMenuContentHide var(--transition-duration) var(--transition-easing) forwards; - - @starting-style { - animation: none; - } - - &[data-expanded] { - pointer-events: auto; - animation: dropdownMenuContentShow var(--transition-duration) var(--transition-easing) forwards; - } + min-width: 8rem; + overflow: hidden; + border: none; + border-radius: var(--radius-md); + box-shadow: var(--shadow-xs-border); + background-clip: padding-box; + background-color: var(--surface-raised-stronger-non-alpha); + padding: 4px; + z-index: 100; + transform-origin: var(--kb-menu-content-transform-origin); + + animation: dropdownMenuContentHide var(--transition-duration) + var(--transition-easing) forwards; + + @starting-style { + animation: none; + } + + &[data-expanded] { + pointer-events: auto; + animation: dropdownMenuContentShow var(--transition-duration) + var(--transition-easing) forwards; + } } [data-component="dropdown-menu-content"], [data-component="dropdown-menu-sub-content"] { - [data-slot="dropdown-menu-item"], - [data-slot="dropdown-menu-checkbox-item"], - [data-slot="dropdown-menu-radio-item"], - [data-slot="dropdown-menu-sub-trigger"] { - position: relative; - display: flex; - align-items: center; - gap: 8px; - padding: 4px 8px; - border-radius: var(--radius-sm); - cursor: default; - outline: none; - - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-strong); - - transition-property: background-color, color; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - user-select: none; - - &:hover { - background-color: var(--surface-raised-base-hover); - } - - &[data-disabled] { - color: var(--text-weak); - pointer-events: none; - } - } - - [data-slot="dropdown-menu-sub-trigger"] { - &[data-expanded] { - background: var(--surface-raised-base-hover); - outline: none; - border: none; - } - } - - [data-slot="dropdown-menu-item-indicator"] { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - } - - [data-slot="dropdown-menu-item-label"] { - flex: 1; - } - - [data-slot="dropdown-menu-item-description"] { - font-size: var(--font-size-x-small); - color: var(--text-weak); - } - - [data-slot="dropdown-menu-separator"] { - height: 1px; - margin: 4px -4px; - border-top-color: var(--border-weak-base); - } - - [data-slot="dropdown-menu-group-label"] { - padding: 4px 8px; - font-family: var(--font-family-sans); - font-size: var(--font-size-x-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); - } - - [data-slot="dropdown-menu-arrow"] { - fill: var(--surface-raised-stronger-non-alpha); - } + [data-slot="dropdown-menu-item"], + [data-slot="dropdown-menu-checkbox-item"], + [data-slot="dropdown-menu-radio-item"], + [data-slot="dropdown-menu-sub-trigger"] { + position: relative; + display: flex; + align-items: center; + gap: 8px; + padding: 4px 8px; + border-radius: var(--radius-sm); + cursor: default; + outline: none; + + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); + + transition-property: background-color, color; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + user-select: none; + + &:hover { + background-color: var(--surface-raised-base-hover); + } + + &[data-disabled] { + color: var(--text-weak); + pointer-events: none; + } + } + + [data-slot="dropdown-menu-sub-trigger"] { + &[data-expanded] { + background: var(--surface-raised-base-hover); + outline: none; + border: none; + } + } + + [data-slot="dropdown-menu-item-indicator"] { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + } + + [data-slot="dropdown-menu-item-label"] { + flex: 1; + } + + [data-slot="dropdown-menu-item-description"] { + font-size: var(--font-size-x-small); + color: var(--text-weak); + } + + [data-slot="dropdown-menu-separator"] { + height: 1px; + margin: 4px -4px; + border-top-color: var(--border-weak-base); + } + + [data-slot="dropdown-menu-group-label"] { + padding: 4px 8px; + font-family: var(--font-family-sans); + font-size: var(--font-size-x-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + } + + [data-slot="dropdown-menu-arrow"] { + fill: var(--surface-raised-stronger-non-alpha); + } } @keyframes dropdownMenuContentShow { - from { - opacity: 0; - transform: scaleY(0.95); - } - to { - opacity: 1; - transform: scaleY(1); - } + from { + opacity: 0; + transform: scaleY(0.95); + } + to { + opacity: 1; + transform: scaleY(1); + } } @keyframes dropdownMenuContentHide { - from { - opacity: 1; - transform: scaleY(1); - } - to { - opacity: 0; - transform: scaleY(0.95); - } + from { + opacity: 1; + transform: scaleY(1); + } + to { + opacity: 0; + transform: scaleY(0.95); + } } diff --git a/packages/ui/src/components/file-icon.css b/packages/ui/src/components/file-icon.css index e650f6dc723c..379247f0c874 100644 --- a/packages/ui/src/components/file-icon.css +++ b/packages/ui/src/components/file-icon.css @@ -1,5 +1,5 @@ [data-component="file-icon"] { - flex-shrink: 0; - width: 16px; - height: 16px; + flex-shrink: 0; + width: 16px; + height: 16px; } diff --git a/packages/ui/src/components/hover-card.css b/packages/ui/src/components/hover-card.css index d23e43946dac..2a588adc60d6 100644 --- a/packages/ui/src/components/hover-card.css +++ b/packages/ui/src/components/hover-card.css @@ -1,61 +1,63 @@ [data-slot="hover-card-trigger"] { - display: flex; - width: 100%; - min-width: 0; + display: flex; + width: 100%; + min-width: 0; } [data-component="hover-card-content"] { - z-index: 50; - min-width: 200px; - max-width: 320px; - max-height: calc(100vh - 1rem); - border-radius: 8px; - background-color: var(--surface-raised-stronger-non-alpha); - pointer-events: auto; - - border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); - background-clip: padding-box; - box-shadow: var(--shadow-md); - - transform-origin: var(--kb-hovercard-content-transform-origin); - - &:focus-within { - outline: none; - } - - &[data-closed] { - animation: hover-card-close var(--transition-duration) var(--transition-easing); - } - - &[data-expanded] { - animation: hover-card-open var(--transition-duration) var(--transition-easing); - } - - [data-slot="hover-card-body"] { - padding: 4px; - max-height: inherit; - overflow: hidden; - } + z-index: 50; + min-width: 200px; + max-width: 320px; + max-height: calc(100vh - 1rem); + border-radius: 8px; + background-color: var(--surface-raised-stronger-non-alpha); + pointer-events: auto; + + border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent); + background-clip: padding-box; + box-shadow: var(--shadow-md); + + transform-origin: var(--kb-hovercard-content-transform-origin); + + &:focus-within { + outline: none; + } + + &[data-closed] { + animation: hover-card-close var(--transition-duration) + var(--transition-easing); + } + + &[data-expanded] { + animation: hover-card-open var(--transition-duration) + var(--transition-easing); + } + + [data-slot="hover-card-body"] { + padding: 4px; + max-height: inherit; + overflow: hidden; + } } @keyframes hover-card-open { - from { - opacity: 0; - transform: scale(0.96); - } - to { - opacity: 1; - transform: scale(1); - } + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } } @keyframes hover-card-close { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: scale(0.96); - } + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } } diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index f1371bfa9aef..94aa80f026ab 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -1,143 +1,143 @@ [data-component="icon-button"] { - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-sm); - text-decoration: none; - user-select: none; - aspect-ratio: 1; - flex-shrink: 0; - transition-property: background-color, color, opacity, box-shadow; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - - &[data-variant="primary"] { - background-color: var(--icon-strong-base); - - [data-slot="icon-svg"] { - /* color: var(--icon-weak-base); */ - color: var(--icon-invert-base); - - /* &:hover:not(:disabled) { */ - /* color: var(--icon-weak-hover); */ - /* } */ - /* &:active:not(:disabled) { */ - /* color: var(--icon-strong-active); */ - /* } */ - } - - &:hover:not(:disabled) { - background-color: var(--icon-strong-hover); - } - &:focus:not(:disabled) { - background-color: var(--icon-strong-focus); - } - &:active:not(:disabled) { - background-color: var(--icon-strong-active); - } - &:disabled { - background-color: var(--icon-strong-disabled); - - [data-slot="icon-svg"] { - color: var(--icon-invert-base); - } - } - } - - &[data-variant="secondary"] { - border: transparent; - background-color: var(--button-secondary-base); - color: var(--text-strong); - box-shadow: var(--shadow-xs-border); - - &:hover:not(:disabled) { - background-color: var(--button-secondary-hover); - } - &:focus:not(:disabled) { - background-color: var(--button-secondary-base); - } - &:focus-visible:not(:active) { - background-color: var(--button-secondary-base); - box-shadow: var(--shadow-xs-border-focus); - } - &:focus-visible:active { - box-shadow: none; - } - &:active:not(:disabled) { - background-color: var(--button-secondary-base); - } - - [data-slot="icon-svg"] { - color: var(--icon-strong-base); - } - - &:disabled { - background-color: var(--icon-strong-disabled); - color: var(--icon-invert-base); - cursor: not-allowed; - } - } - - &[data-variant="ghost"] { - background-color: transparent; - /* color: var(--icon-base); */ - - [data-slot="icon-svg"] { - color: var(--icon-base); - } - - &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); - - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-hover); */ - /* } */ - } - &:focus-visible:not(:disabled) { - background-color: var(--surface-raised-base-hover); - } - &:active:not(:disabled) { - background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-active); */ - /* } */ - } - &[data-selected]:not(:disabled) { - background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-selected); */ - /* } */ - } - &:disabled { - color: var(--icon-invert-base); - cursor: not-allowed; - } - } - - &[data-size="normal"] { - width: 24px; - height: 24px; - - font-size: var(--font-size-small); - line-height: var(--line-height-large); - gap: calc(var(--spacing) * 0.5); - } - - &[data-size="large"] { - height: 32px; - /* padding: 0 8px 0 6px; */ - gap: 8px; - - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 166.667% */ - letter-spacing: var(--letter-spacing-normal); - } - - &:focus { - outline: none; - } + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-sm); + text-decoration: none; + user-select: none; + aspect-ratio: 1; + flex-shrink: 0; + transition-property: background-color, color, opacity, box-shadow; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + + &[data-variant="primary"] { + background-color: var(--icon-strong-base); + + [data-slot="icon-svg"] { + /* color: var(--icon-weak-base); */ + color: var(--icon-invert-base); + + /* &:hover:not(:disabled) { */ + /* color: var(--icon-weak-hover); */ + /* } */ + /* &:active:not(:disabled) { */ + /* color: var(--icon-strong-active); */ + /* } */ + } + + &:hover:not(:disabled) { + background-color: var(--icon-strong-hover); + } + &:focus:not(:disabled) { + background-color: var(--icon-strong-focus); + } + &:active:not(:disabled) { + background-color: var(--icon-strong-active); + } + &:disabled { + background-color: var(--icon-strong-disabled); + + [data-slot="icon-svg"] { + color: var(--icon-invert-base); + } + } + } + + &[data-variant="secondary"] { + border: transparent; + background-color: var(--button-secondary-base); + color: var(--text-strong); + box-shadow: var(--shadow-xs-border); + + &:hover:not(:disabled) { + background-color: var(--button-secondary-hover); + } + &:focus:not(:disabled) { + background-color: var(--button-secondary-base); + } + &:focus-visible:not(:active) { + background-color: var(--button-secondary-base); + box-shadow: var(--shadow-xs-border-focus); + } + &:focus-visible:active { + box-shadow: none; + } + &:active:not(:disabled) { + background-color: var(--button-secondary-base); + } + + [data-slot="icon-svg"] { + color: var(--icon-strong-base); + } + + &:disabled { + background-color: var(--icon-strong-disabled); + color: var(--icon-invert-base); + cursor: not-allowed; + } + } + + &[data-variant="ghost"] { + background-color: transparent; + /* color: var(--icon-base); */ + + [data-slot="icon-svg"] { + color: var(--icon-base); + } + + &:hover:not(:disabled) { + background-color: var(--surface-raised-base-hover); + + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-hover); */ + /* } */ + } + &:focus-visible:not(:disabled) { + background-color: var(--surface-raised-base-hover); + } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-active); */ + /* } */ + } + &[data-selected]:not(:disabled) { + background-color: var(--surface-raised-base-active); + /* [data-slot="icon-svg"] { */ + /* color: var(--icon-selected); */ + /* } */ + } + &:disabled { + color: var(--icon-invert-base); + cursor: not-allowed; + } + } + + &[data-size="normal"] { + width: 24px; + height: 24px; + + font-size: var(--font-size-small); + line-height: var(--line-height-large); + gap: calc(var(--spacing) * 0.5); + } + + &[data-size="large"] { + height: 32px; + /* padding: 0 8px 0 6px; */ + gap: 8px; + + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 166.667% */ + letter-spacing: var(--letter-spacing-normal); + } + + &:focus { + outline: none; + } } diff --git a/packages/ui/src/components/icon.css b/packages/ui/src/components/icon.css index a2ebee30bc1c..dd760ccbc28f 100644 --- a/packages/ui/src/components/icon.css +++ b/packages/ui/src/components/icon.css @@ -1,34 +1,34 @@ [data-component="icon"] { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - /* resize: both; */ - aspect-ratio: 1/1; - color: var(--icon-base); + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + /* resize: both; */ + aspect-ratio: 1 / 1; + color: var(--icon-base); - &[data-size="small"] { - width: 16px; - height: 16px; - } + &[data-size="small"] { + width: 16px; + height: 16px; + } - &[data-size="normal"] { - width: 20px; - height: 20px; - } + &[data-size="normal"] { + width: 20px; + height: 20px; + } - &[data-size="medium"] { - width: 24px; - height: 24px; - } + &[data-size="medium"] { + width: 24px; + height: 24px; + } - &[data-size="large"] { - width: 24px; - height: 24px; - } + &[data-size="large"] { + width: 24px; + height: 24px; + } - [data-slot="icon-svg"] { - width: 100%; - height: auto; - } + [data-slot="icon-svg"] { + width: 100%; + height: auto; + } } diff --git a/packages/ui/src/components/image-preview.css b/packages/ui/src/components/image-preview.css index 3c47f7a25842..b63f60ebaf8d 100644 --- a/packages/ui/src/components/image-preview.css +++ b/packages/ui/src/components/image-preview.css @@ -1,63 +1,63 @@ [data-component="image-preview"] { - position: fixed; - inset: 0; - z-index: 50; - display: flex; - align-items: center; - justify-content: center; + position: fixed; + inset: 0; + z-index: 50; + display: flex; + align-items: center; + justify-content: center; - [data-slot="image-preview-container"] { - position: relative; - z-index: 50; - width: min(calc(100vw - 32px), 90vw); - max-width: 1200px; - height: min(calc(100vh - 32px), 90vh); - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; + [data-slot="image-preview-container"] { + position: relative; + z-index: 50; + width: min(calc(100vw - 32px), 90vw); + max-width: 1200px; + height: min(calc(100vh - 32px), 90vh); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; - [data-slot="image-preview-content"] { - display: flex; - flex-direction: column; - align-items: center; - width: 100%; - max-height: 100%; - border-radius: var(--radius-lg); - background: var(--surface-raised-stronger-non-alpha); - box-shadow: - 0 15px 45px 0 rgba(19, 16, 16, 0.35), - 0 3.35px 10.051px 0 rgba(19, 16, 16, 0.25), - 0 0.998px 2.993px 0 rgba(19, 16, 16, 0.2); - overflow: hidden; + [data-slot="image-preview-content"] { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + max-height: 100%; + border-radius: var(--radius-lg); + background: var(--surface-raised-stronger-non-alpha); + box-shadow: + 0 15px 45px 0 rgba(19, 16, 16, 0.35), + 0 3.35px 10.051px 0 rgba(19, 16, 16, 0.25), + 0 0.998px 2.993px 0 rgba(19, 16, 16, 0.2); + overflow: hidden; - &:focus-visible { - outline: none; - } + &:focus-visible { + outline: none; + } - [data-slot="image-preview-header"] { - display: flex; - padding: 8px 8px 0; - justify-content: flex-end; - align-items: center; - align-self: stretch; - } + [data-slot="image-preview-header"] { + display: flex; + padding: 8px 8px 0; + justify-content: flex-end; + align-items: center; + align-self: stretch; + } - [data-slot="image-preview-body"] { - width: 100%; - display: flex; - align-items: center; - justify-content: center; - padding: 16px; - overflow: auto; - } + [data-slot="image-preview-body"] { + width: 100%; + display: flex; + align-items: center; + justify-content: center; + padding: 16px; + overflow: auto; + } - [data-slot="image-preview-image"] { - max-width: 100%; - max-height: calc(90vh - 100px); - object-fit: contain; - border-radius: var(--radius-md); - } - } - } + [data-slot="image-preview-image"] { + max-width: 100%; + max-height: calc(90vh - 100px); + object-fit: contain; + border-radius: var(--radius-md); + } + } + } } diff --git a/packages/ui/src/components/inline-input.css b/packages/ui/src/components/inline-input.css index 1d8a00e08d03..8bb0f9afb0ea 100644 --- a/packages/ui/src/components/inline-input.css +++ b/packages/ui/src/components/inline-input.css @@ -1,17 +1,17 @@ [data-component="inline-input"] { - color: inherit; - background: transparent; - border: 0; - border-radius: var(--radius-md); - padding: 0; - min-width: 0; - font: inherit; - letter-spacing: inherit; - line-height: inherit; - box-sizing: border-box; + color: inherit; + background: transparent; + border: 0; + border-radius: var(--radius-md); + padding: 0; + min-width: 0; + font: inherit; + letter-spacing: inherit; + line-height: inherit; + box-sizing: border-box; - &:focus { - outline: none; - box-shadow: 0 0 0 1px var(--border-interactive-focus); - } + &:focus { + outline: none; + box-shadow: 0 0 0 1px var(--border-interactive-focus); + } } diff --git a/packages/ui/src/components/keybind.css b/packages/ui/src/components/keybind.css index 1a9e5dce43e2..c3912ac93549 100644 --- a/packages/ui/src/components/keybind.css +++ b/packages/ui/src/components/keybind.css @@ -1,18 +1,18 @@ [data-component="keybind"] { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - height: 20px; - padding: 0 8px; - border-radius: 2px; - background: var(--surface-base); - box-shadow: var(--shadow-xxs-border); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + height: 20px; + padding: 0 8px; + border-radius: 2px; + background: var(--surface-base); + box-shadow: var(--shadow-xxs-border); - /* text-12-medium */ - font-family: var(--font-family-sans); - font-size: 12px; - font-weight: var(--font-weight-medium); - line-height: 1; - color: var(--text-weak); + /* text-12-medium */ + font-family: var(--font-family-sans); + font-size: 12px; + font-weight: var(--font-weight-medium); + line-height: 1; + color: var(--text-weak); } diff --git a/packages/ui/src/components/line-comment.css b/packages/ui/src/components/line-comment.css index 9dc8eb74f3d4..092461453df5 100644 --- a/packages/ui/src/components/line-comment.css +++ b/packages/ui/src/components/line-comment.css @@ -1,115 +1,117 @@ [data-component="line-comment"] { - position: absolute; - right: 24px; - z-index: var(--line-comment-z, 30); + position: absolute; + right: 24px; + z-index: var(--line-comment-z, 30); } [data-component="line-comment"][data-open] { - z-index: var(--line-comment-open-z, 100); + z-index: var(--line-comment-open-z, 100); } [data-component="line-comment"] [data-slot="line-comment-button"] { - width: 20px; - height: 20px; - border-radius: var(--radius-md); - display: flex; - align-items: center; - justify-content: center; - background: var(--icon-interactive-base); - box-shadow: var(--shadow-xs); - cursor: default; - border: none; + width: 20px; + height: 20px; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + background: var(--icon-interactive-base); + box-shadow: var(--shadow-xs); + cursor: default; + border: none; } [data-component="line-comment"] [data-component="icon"] { - color: var(--white); + color: var(--white); } [data-component="line-comment"] [data-slot="line-comment-button"]:focus { - outline: none; + outline: none; } -[data-component="line-comment"] [data-slot="line-comment-button"]:focus-visible { - box-shadow: var(--shadow-xs-border-focus); +[data-component="line-comment"] + [data-slot="line-comment-button"]:focus-visible { + box-shadow: var(--shadow-xs-border-focus); } [data-component="line-comment"] [data-slot="line-comment-popover"] { - position: absolute; - top: calc(100% + 4px); - right: -8px; - z-index: var(--line-comment-popover-z, 40); - min-width: 200px; - max-width: min(320px, calc(100vw - 48px)); - border-radius: 8px; - background: var(--surface-raised-stronger-non-alpha); - box-shadow: var(--shadow-lg-border-base); - padding: 12px; + position: absolute; + top: calc(100% + 4px); + right: -8px; + z-index: var(--line-comment-popover-z, 40); + min-width: 200px; + max-width: min(320px, calc(100vw - 48px)); + border-radius: 8px; + background: var(--surface-raised-stronger-non-alpha); + box-shadow: var(--shadow-lg-border-base); + padding: 12px; } -[data-component="line-comment"][data-variant="editor"] [data-slot="line-comment-popover"] { - width: 380px; - max-width: min(380px, calc(100vw - 48px)); - padding: 8px; - border-radius: 14px; +[data-component="line-comment"][data-variant="editor"] + [data-slot="line-comment-popover"] { + width: 380px; + max-width: min(380px, calc(100vw - 48px)); + padding: 8px; + border-radius: 14px; } [data-component="line-comment"] [data-slot="line-comment-content"] { - display: flex; - flex-direction: column; - gap: 6px; + display: flex; + flex-direction: column; + gap: 6px; } [data-component="line-comment"] [data-slot="line-comment-text"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-x-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-strong); - white-space: pre-wrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-x-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-strong); + white-space: pre-wrap; } [data-component="line-comment"] [data-slot="line-comment-label"], [data-component="line-comment"] [data-slot="line-comment-editor-label"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-weak); - white-space: nowrap; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-weak); + white-space: nowrap; } [data-component="line-comment"] [data-slot="line-comment-editor"] { - display: flex; - flex-direction: column; - gap: 8px; + display: flex; + flex-direction: column; + gap: 8px; } [data-component="line-comment"] [data-slot="line-comment-textarea"] { - width: 100%; - resize: vertical; - padding: 8px; - border-radius: var(--radius-md); - background: var(--surface-base); - border: 1px solid var(--border-base); - color: var(--text-strong); - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - line-height: var(--line-height-large); + width: 100%; + resize: vertical; + padding: 8px; + border-radius: var(--radius-md); + background: var(--surface-base); + border: 1px solid var(--border-base); + color: var(--text-strong); + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + line-height: var(--line-height-large); } [data-component="line-comment"] [data-slot="line-comment-textarea"]:focus { - outline: none; - box-shadow: var(--shadow-xs-border-select); + outline: none; + box-shadow: var(--shadow-xs-border-select); } [data-component="line-comment"] [data-slot="line-comment-actions"] { - display: flex; - align-items: center; - gap: 8px; + display: flex; + align-items: center; + gap: 8px; } [data-component="line-comment"] [data-slot="line-comment-editor-label"] { - margin-right: auto; + margin-right: auto; } diff --git a/packages/ui/src/components/list.css b/packages/ui/src/components/list.css index f0fdc538c9e5..ae99e9841882 100644 --- a/packages/ui/src/components/list.css +++ b/packages/ui/src/components/list.css @@ -1,333 +1,337 @@ @property --bottom-fade { - syntax: ""; - inherits: false; - initial-value: 0px; + syntax: ""; + inherits: false; + initial-value: 0px; } @keyframes scroll { - 0% { - --bottom-fade: 20px; - } - 90% { - --bottom-fade: 20px; - } - 100% { - --bottom-fade: 0; - } + 0% { + --bottom-fade: 20px; + } + 90% { + --bottom-fade: 20px; + } + 100% { + --bottom-fade: 0; + } } [data-component="list"] { - display: flex; - flex-direction: column; - gap: 8px; - overflow: hidden; - padding: 0 12px; - - [data-slot="list-search-wrapper"] { - display: flex; - flex-shrink: 0; - align-items: center; - gap: 8px; - align-self: stretch; - margin-bottom: 4px; - - > [data-component="icon-button"] { - width: 24px; - height: 24px; - flex-shrink: 0; - background-color: transparent; - opacity: 0.5; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - - &:hover:not(:disabled), - &:focus-visible:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - opacity: 0.7; - } - - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } - - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } - } - - [data-slot="list-search"] { - display: flex; - flex: 1; - padding: 8px; - align-items: center; - gap: 12px; - - border-radius: var(--radius-md); - background: var(--surface-base); - - [data-slot="list-search-container"] { - display: flex; - align-items: center; - gap: 8px; - flex: 1 0 0; - max-height: 20px; - - [data-slot="list-search-input"] { - width: 100%; - - &[data-slot="input-input"] { - line-height: 20px; - max-height: 20px; - } - } - } - - > [data-component="icon-button"] { - width: 20px; - height: 20px; - background-color: transparent; - opacity: 0.5; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - - &:hover:not(:disabled), - &:focus-visible:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - opacity: 0.7; - } - - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } - - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } - - > [data-component="icon-button"] { - background-color: transparent; - - &:hover:not(:disabled), - &:focus:not(:disabled), - &:active:not(:disabled) { - background-color: transparent; - } - - &:hover:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-hover); - } - - &:active:not(:disabled) [data-slot="icon-svg"] { - color: var(--icon-active); - } - } - } - - [data-slot="list-scroll"] { - display: flex; - flex-direction: column; - gap: 12px; - overflow-y: auto; - overscroll-behavior: contain; - - [data-slot="list-empty-state"] { - display: flex; - padding: 32px 48px; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 8px; - align-self: stretch; - - [data-slot="list-message"] { - display: flex; - justify-content: center; - align-items: center; - gap: 2px; - max-width: 100%; - color: var(--text-weak); - white-space: nowrap; - - /* text-14-regular */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - } - - [data-slot="list-filter"] { - color: var(--text-strong); - overflow: hidden; - text-overflow: ellipsis; - } - } - - [data-slot="list-group"] { - position: relative; - display: flex; - flex-direction: column; - - &:last-child { - padding-bottom: 12px; - } - - [data-slot="list-header"] { - display: flex; - z-index: 10; - padding: 8px 12px 8px 8px; - justify-content: space-between; - align-items: center; - align-self: stretch; - background: var(--surface-raised-stronger-non-alpha); - position: sticky; - top: 0; - - color: var(--text-weak); - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - - &::after { - content: ""; - position: absolute; - top: 100%; - left: 0; - right: 0; - height: 16px; - background: linear-gradient(to bottom, var(--surface-raised-stronger-non-alpha), transparent); - pointer-events: none; - opacity: 0; - transition-property: opacity; - transition-duration: var(--transition-duration); - transition-timing-function: var(--transition-easing); - } - - &[data-stuck="true"]::after { - opacity: 1; - } - } - - [data-slot="list-items"] { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - - [data-slot="list-item"] { - display: flex; - position: relative; - width: 100%; - padding: 6px 8px 6px 8px; - align-items: center; - color: var(--text-strong); - scroll-margin-top: 28px; - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - - [data-slot="list-item-selected-icon"] { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - aspect-ratio: 1/1; - [data-component="icon"] { - color: var(--icon-strong-base); - } - } - - [name="check"] { - color: var(--icon-strong-base); - } - - [data-slot="list-item-active-icon"] { - display: none; - align-items: center; - justify-content: center; - flex-shrink: 0; - aspect-ratio: 1/1; - [data-component="icon"] { - color: var(--icon-strong-base); - } - } - - [data-slot="list-item-extra-icon"] { - color: var(--icon-base); - margin-left: -4px; - } - - [data-slot="list-item-divider"] { - position: absolute; - bottom: 0; - left: var(--list-divider-inset, 16px); - right: var(--list-divider-inset, 16px); - height: 1px; - background: var(--border-weak-base); - pointer-events: none; - } - - [data-slot="list-item"]:last-child [data-slot="list-item-divider"] { - display: none; - } - - &[data-active="true"] { - border-radius: var(--radius-md); - background: var(--surface-raised-base-hover); - [data-slot="list-item-active-icon"] { - display: inline-flex; - } - [data-slot="list-item-extra-icon"] { - display: block !important; - color: var(--icon-strong-base) !important; - } - } - &:active { - background: var(--surface-raised-base-active); - } - &:focus-visible { - outline: none; - } - } - - [data-slot="list-item-add"] { - display: flex; - position: relative; - width: 100%; - padding: 6px 8px 6px 8px; - align-items: center; - color: var(--text-strong); - - /* text-14-medium */ - font-family: var(--font-family-sans); - font-size: 14px; - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); /* 142.857% */ - letter-spacing: var(--letter-spacing-normal); - - [data-component="input"] { - width: 100%; - } - } - } - } - } + display: flex; + flex-direction: column; + gap: 8px; + overflow: hidden; + padding: 0 12px; + + [data-slot="list-search-wrapper"] { + display: flex; + flex-shrink: 0; + align-items: center; + gap: 8px; + align-self: stretch; + margin-bottom: 4px; + + > [data-component="icon-button"] { + width: 24px; + height: 24px; + flex-shrink: 0; + background-color: transparent; + opacity: 0.5; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + + &:hover:not(:disabled), + &:focus-visible:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + opacity: 0.7; + } + + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } + + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } + } + + [data-slot="list-search"] { + display: flex; + flex: 1; + padding: 8px; + align-items: center; + gap: 12px; + + border-radius: var(--radius-md); + background: var(--surface-base); + + [data-slot="list-search-container"] { + display: flex; + align-items: center; + gap: 8px; + flex: 1 0 0; + max-height: 20px; + + [data-slot="list-search-input"] { + width: 100%; + + &[data-slot="input-input"] { + line-height: 20px; + max-height: 20px; + } + } + } + + > [data-component="icon-button"] { + width: 20px; + height: 20px; + background-color: transparent; + opacity: 0.5; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + + &:hover:not(:disabled), + &:focus-visible:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + opacity: 0.7; + } + + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } + + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } + + > [data-component="icon-button"] { + background-color: transparent; + + &:hover:not(:disabled), + &:focus:not(:disabled), + &:active:not(:disabled) { + background-color: transparent; + } + + &:hover:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-hover); + } + + &:active:not(:disabled) [data-slot="icon-svg"] { + color: var(--icon-active); + } + } + } + + [data-slot="list-scroll"] { + display: flex; + flex-direction: column; + gap: 12px; + overflow-y: auto; + overscroll-behavior: contain; + + [data-slot="list-empty-state"] { + display: flex; + padding: 32px 48px; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 8px; + align-self: stretch; + + [data-slot="list-message"] { + display: flex; + justify-content: center; + align-items: center; + gap: 2px; + max-width: 100%; + color: var(--text-weak); + white-space: nowrap; + + /* text-14-regular */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + } + + [data-slot="list-filter"] { + color: var(--text-strong); + overflow: hidden; + text-overflow: ellipsis; + } + } + + [data-slot="list-group"] { + position: relative; + display: flex; + flex-direction: column; + + &:last-child { + padding-bottom: 12px; + } + + [data-slot="list-header"] { + display: flex; + z-index: 10; + padding: 8px 12px 8px 8px; + justify-content: space-between; + align-items: center; + align-self: stretch; + background: var(--surface-raised-stronger-non-alpha); + position: sticky; + top: 0; + + color: var(--text-weak); + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + + &::after { + content: ""; + position: absolute; + top: 100%; + left: 0; + right: 0; + height: 16px; + background: linear-gradient( + to bottom, + var(--surface-raised-stronger-non-alpha), + transparent + ); + pointer-events: none; + opacity: 0; + transition-property: opacity; + transition-duration: var(--transition-duration); + transition-timing-function: var(--transition-easing); + } + + &[data-stuck="true"]::after { + opacity: 1; + } + } + + [data-slot="list-items"] { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + + [data-slot="list-item"] { + display: flex; + position: relative; + width: 100%; + padding: 6px 8px 6px 8px; + align-items: center; + color: var(--text-strong); + scroll-margin-top: 28px; + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + + [data-slot="list-item-selected-icon"] { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + aspect-ratio: 1 / 1; + [data-component="icon"] { + color: var(--icon-strong-base); + } + } + + [name="check"] { + color: var(--icon-strong-base); + } + + [data-slot="list-item-active-icon"] { + display: none; + align-items: center; + justify-content: center; + flex-shrink: 0; + aspect-ratio: 1 / 1; + [data-component="icon"] { + color: var(--icon-strong-base); + } + } + + [data-slot="list-item-extra-icon"] { + color: var(--icon-base); + margin-left: -4px; + } + + [data-slot="list-item-divider"] { + position: absolute; + bottom: 0; + left: var(--list-divider-inset, 16px); + right: var(--list-divider-inset, 16px); + height: 1px; + background: var(--border-weak-base); + pointer-events: none; + } + + [data-slot="list-item"]:last-child [data-slot="list-item-divider"] { + display: none; + } + + &[data-active="true"] { + border-radius: var(--radius-md); + background: var(--surface-raised-base-hover); + [data-slot="list-item-active-icon"] { + display: inline-flex; + } + [data-slot="list-item-extra-icon"] { + display: block !important; + color: var(--icon-strong-base) !important; + } + } + &:active { + background: var(--surface-raised-base-active); + } + &:focus-visible { + outline: none; + } + } + + [data-slot="list-item-add"] { + display: flex; + position: relative; + width: 100%; + padding: 6px 8px 6px 8px; + align-items: center; + color: var(--text-strong); + + /* text-14-medium */ + font-family: var(--font-family-sans); + font-size: 14px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); /* 142.857% */ + letter-spacing: var(--letter-spacing-normal); + + [data-component="input"] { + width: 100%; + } + } + } + } + } } diff --git a/packages/ui/src/components/logo.css b/packages/ui/src/components/logo.css index a909782b7708..b16c441d2b4f 100644 --- a/packages/ui/src/components/logo.css +++ b/packages/ui/src/components/logo.css @@ -1,4 +1,4 @@ [data-component="logo-mark"] { - width: 16px; - aspect-ratio: 4/5; + width: 16px; + aspect-ratio: 4 / 5; } diff --git a/packages/ui/src/components/markdown.css b/packages/ui/src/components/markdown.css index ef43187336e6..5d7f26e3d3c5 100644 --- a/packages/ui/src/components/markdown.css +++ b/packages/ui/src/components/markdown.css @@ -1,209 +1,211 @@ [data-component="markdown"] { - /* Reset & Base Typography */ - min-width: 0; - max-width: 100%; - overflow-wrap: break-word; - color: var(--text-base); - font-family: var(--font-family-sans); - font-size: var(--font-size-base); /* 14px */ - line-height: var(--line-height-x-large); - - /* Spacing for flow */ - > *:first-child { - margin-top: 0; - } - > *:last-child { - margin-bottom: 0; - } - - /* Headings: Same size, distinguished by color and spacing */ - h1, - h2, - h3, - h4, - h5, - h6 { - font-size: var(--font-size-base); - color: var(--text-strong); - font-weight: var(--font-weight-medium); - margin-top: 2rem; - margin-bottom: 0.75rem; - line-height: var(--line-height-large); - } - - /* Emphasis & Strong: Neutral strong color */ - strong, - b { - color: var(--text-strong); - font-weight: var(--font-weight-medium); - } - - /* Paragraphs */ - p { - margin-bottom: 1rem; - } - - /* Links */ - a { - color: var(--text-interactive-base); - text-decoration: none; - font-weight: inherit; - } - - a:hover { - text-decoration: underline; - text-underline-offset: 2px; - } - - /* Lists */ - ul, - ol { - margin-top: 0.5rem; - margin-bottom: 1rem; - padding-left: 1.5rem; - list-style-position: outside; - } - - ul { - list-style-type: disc; - } - - ol { - list-style-type: decimal; - } - - li { - margin-bottom: 0.5rem; - } - - li > p:first-child { - display: inline; - margin: 0; - } - - li > p + p { - display: block; - margin-top: 0.5rem; - } - - li::marker { - color: var(--text-weak); - } - - /* Nested lists spacing */ - li > ul, - li > ol { - margin-top: 0.25rem; - margin-bottom: 0.25rem; - padding-left: 1rem; /* Minimal indent for nesting only */ - } - - /* Blockquotes */ - blockquote { - border-left: 2px solid var(--border-weak-base); - margin: 1.5rem 0; - padding-left: 0.5rem; - color: var(--text-weak); - font-style: normal; - } - - /* Horizontal Rule - Invisible spacing only */ - hr { - border: none; - height: 0; - margin: 2.5rem 0; - } - - .shiki { - font-size: 13px; - padding: 8px 12px; - border-radius: 4px; - border: 0.5px solid var(--border-weak-base); - } - - [data-component="markdown-code"] { - position: relative; - } - - [data-slot="markdown-copy-button"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } - - [data-component="markdown-code"]:hover [data-slot="markdown-copy-button"] { - opacity: 1; - } - - [data-slot="markdown-copy-button"] [data-slot="check-icon"] { - display: none; - } - - [data-slot="markdown-copy-button"][data-copied="true"] [data-slot="copy-icon"] { - display: none; - } - - [data-slot="markdown-copy-button"][data-copied="true"] [data-slot="check-icon"] { - display: inline-flex; - } - - pre { - margin-top: 2rem; - margin-bottom: 2rem; - overflow: auto; - - scrollbar-width: none; - &::-webkit-scrollbar { - display: none; - } - } - - :not(pre) > code { - font-family: var(--font-family-mono); - font-feature-settings: var(--font-family-mono--font-feature-settings); - color: var(--syntax-string); - font-weight: var(--font-weight-medium); - /* font-size: 13px; */ - - /* padding: 2px 2px; */ - /* margin: 0 1.5px; */ - /* border-radius: 2px; */ - /* background: var(--surface-base); */ - /* box-shadow: 0 0 0 0.5px var(--border-weak-base); */ - } - - /* Tables */ - table { - width: 100%; - border-collapse: collapse; - margin: 1.5rem 0; - font-size: var(--font-size-base); - } - - th, - td { - /* Minimal borders for structure, matching TUI "lines" roughly but keeping it web-clean */ - border-bottom: 1px solid var(--border-weaker-base); - padding: 0.75rem 0.5rem; - text-align: left; - vertical-align: top; - } - - th { - color: var(--text-strong); - font-weight: var(--font-weight-medium); - border-bottom: 1px solid var(--border-weak-base); - } - - /* Images */ - img { - max-width: 100%; - height: auto; - border-radius: 4px; - margin: 1.5rem 0; - display: block; - } + /* Reset & Base Typography */ + min-width: 0; + max-width: 100%; + overflow-wrap: break-word; + color: var(--text-base); + font-family: var(--font-family-sans); + font-size: var(--font-size-base); /* 14px */ + line-height: var(--line-height-x-large); + + /* Spacing for flow */ + > *:first-child { + margin-top: 0; + } + > *:last-child { + margin-bottom: 0; + } + + /* Headings: Same size, distinguished by color and spacing */ + h1, + h2, + h3, + h4, + h5, + h6 { + font-size: var(--font-size-base); + color: var(--text-strong); + font-weight: var(--font-weight-medium); + margin-top: 2rem; + margin-bottom: 0.75rem; + line-height: var(--line-height-large); + } + + /* Emphasis & Strong: Neutral strong color */ + strong, + b { + color: var(--text-strong); + font-weight: var(--font-weight-medium); + } + + /* Paragraphs */ + p { + margin-bottom: 1rem; + } + + /* Links */ + a { + color: var(--text-interactive-base); + text-decoration: none; + font-weight: inherit; + } + + a:hover { + text-decoration: underline; + text-underline-offset: 2px; + } + + /* Lists */ + ul, + ol { + margin-top: 0.5rem; + margin-bottom: 1rem; + padding-left: 1.5rem; + list-style-position: outside; + } + + ul { + list-style-type: disc; + } + + ol { + list-style-type: decimal; + } + + li { + margin-bottom: 0.5rem; + } + + li > p:first-child { + display: inline; + margin: 0; + } + + li > p + p { + display: block; + margin-top: 0.5rem; + } + + li::marker { + color: var(--text-weak); + } + + /* Nested lists spacing */ + li > ul, + li > ol { + margin-top: 0.25rem; + margin-bottom: 0.25rem; + padding-left: 1rem; /* Minimal indent for nesting only */ + } + + /* Blockquotes */ + blockquote { + border-left: 2px solid var(--border-weak-base); + margin: 1.5rem 0; + padding-left: 0.5rem; + color: var(--text-weak); + font-style: normal; + } + + /* Horizontal Rule - Invisible spacing only */ + hr { + border: none; + height: 0; + margin: 2.5rem 0; + } + + .shiki { + font-size: 13px; + padding: 8px 12px; + border-radius: 4px; + border: 0.5px solid var(--border-weak-base); + } + + [data-component="markdown-code"] { + position: relative; + } + + [data-slot="markdown-copy-button"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } + + [data-component="markdown-code"]:hover [data-slot="markdown-copy-button"] { + opacity: 1; + } + + [data-slot="markdown-copy-button"] [data-slot="check-icon"] { + display: none; + } + + [data-slot="markdown-copy-button"][data-copied="true"] + [data-slot="copy-icon"] { + display: none; + } + + [data-slot="markdown-copy-button"][data-copied="true"] + [data-slot="check-icon"] { + display: inline-flex; + } + + pre { + margin-top: 2rem; + margin-bottom: 2rem; + overflow: auto; + + scrollbar-width: none; + &::-webkit-scrollbar { + display: none; + } + } + + :not(pre) > code { + font-family: var(--font-family-mono); + font-feature-settings: var(--font-family-mono--font-feature-settings); + color: var(--syntax-string); + font-weight: var(--font-weight-medium); + /* font-size: 13px; */ + + /* padding: 2px 2px; */ + /* margin: 0 1.5px; */ + /* border-radius: 2px; */ + /* background: var(--surface-base); */ + /* box-shadow: 0 0 0 0.5px var(--border-weak-base); */ + } + + /* Tables */ + table { + width: 100%; + border-collapse: collapse; + margin: 1.5rem 0; + font-size: var(--font-size-base); + } + + th, + td { + /* Minimal borders for structure, matching TUI "lines" roughly but keeping it web-clean */ + border-bottom: 1px solid var(--border-weaker-base); + padding: 0.75rem 0.5rem; + text-align: left; + vertical-align: top; + } + + th { + color: var(--text-strong); + font-weight: var(--font-weight-medium); + border-bottom: 1px solid var(--border-weak-base); + } + + /* Images */ + img { + max-width: 100%; + height: auto; + border-radius: 4px; + margin: 1.5rem 0; + display: block; + } } diff --git a/packages/ui/src/components/message-nav.css b/packages/ui/src/components/message-nav.css index b1454ad42594..6b82dc91c2a6 100644 --- a/packages/ui/src/components/message-nav.css +++ b/packages/ui/src/components/message-nav.css @@ -1,122 +1,123 @@ [data-component="message-nav"] { - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: flex-start; - padding-left: 0; - list-style: none; - - &[data-size="normal"] { - width: 240px; - gap: 4px; - } - - &[data-size="compact"] { - width: 24px; - } + flex-shrink: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + padding-left: 0; + list-style: none; + + &[data-size="normal"] { + width: 240px; + gap: 4px; + } + + &[data-size="compact"] { + width: 24px; + } } [data-slot="message-nav-item"] { - display: flex; - align-items: center; - align-self: stretch; - justify-content: flex-end; - - [data-component="message-nav"][data-size="normal"] & { - justify-content: flex-start; - } + display: flex; + align-items: center; + align-self: stretch; + justify-content: flex-end; + + [data-component="message-nav"][data-size="normal"] & { + justify-content: flex-start; + } } [data-slot="message-nav-tick-button"] { - display: flex; - align-items: center; - justify-content: flex-start; - height: 12px; - width: 24px; - border: none; - background: none; - padding: 0; - - &[data-active] [data-slot="message-nav-tick-line"] { - background-color: var(--icon-strong-base); - width: 100%; - } + display: flex; + align-items: center; + justify-content: flex-start; + height: 12px; + width: 24px; + border: none; + background: none; + padding: 0; + + &[data-active] [data-slot="message-nav-tick-line"] { + background-color: var(--icon-strong-base); + width: 100%; + } } [data-slot="message-nav-tick-line"] { - height: 1px; - width: 16px; - background-color: var(--icon-base); - transition: - width 0.2s, - background-color 0.2s; + height: 1px; + width: 16px; + background-color: var(--icon-base); + transition: + width 0.2s, + background-color 0.2s; } -[data-slot="message-nav-tick-button"]:hover [data-slot="message-nav-tick-line"] { - width: 100%; - background-color: var(--icon-strong-base); +[data-slot="message-nav-tick-button"]:hover + [data-slot="message-nav-tick-line"] { + width: 100%; + background-color: var(--icon-strong-base); } [data-slot="message-nav-message-button"] { - display: flex; - align-items: center; - align-self: stretch; - width: 100%; - column-gap: 12px; - cursor: default; - border: none; - background: none; - padding: 4px 12px; - border-radius: var(--radius-sm); + display: flex; + align-items: center; + align-self: stretch; + width: 100%; + column-gap: 12px; + cursor: default; + border: none; + background: none; + padding: 4px 12px; + border-radius: var(--radius-sm); } [data-slot="message-nav-title-preview"] { - font-size: 14px; /* text-14-regular */ - color: var(--text-base); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; - text-align: left; - - &[data-active] { - color: var(--text-strong); - } + font-size: 14px; /* text-14-regular */ + color: var(--text-base); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + text-align: left; + + &[data-active] { + color: var(--text-strong); + } } [data-slot="message-nav-item"]:hover [data-slot="message-nav-message-button"] { - background-color: var(--surface-base); + background-color: var(--surface-base); } [data-slot="message-nav-item"]:active [data-slot="message-nav-message-button"] { - background-color: var(--surface-base-active); + background-color: var(--surface-base-active); } [data-slot="message-nav-item"]:active [data-slot="message-nav-title-preview"] { - color: var(--text-base); + color: var(--text-base); } [data-slot="message-nav-tooltip"] { - z-index: 1000; + z-index: 1000; } [data-slot="message-nav-tooltip-content"] { - display: flex; - padding: 4px 4px 6px 4px; - justify-content: center; - align-items: center; - border-radius: var(--radius-md); - background: var(--surface-raised-stronger-non-alpha); - max-height: calc(100vh - 6rem); - overflow-y: auto; - - /* border/shadow-xs/base */ - box-shadow: - 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), - 0 1px 2px -1px rgba(19, 16, 16, 0.04), - 0 1px 2px 0 rgba(19, 16, 16, 0.06), - 0 1px 3px 0 rgba(19, 16, 16, 0.08); - - * { - margin: 0 !important; - } + display: flex; + padding: 4px 4px 6px 4px; + justify-content: center; + align-items: center; + border-radius: var(--radius-md); + background: var(--surface-raised-stronger-non-alpha); + max-height: calc(100vh - 6rem); + overflow-y: auto; + + /* border/shadow-xs/base */ + box-shadow: + 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), + 0 1px 2px -1px rgba(19, 16, 16, 0.04), + 0 1px 2px 0 rgba(19, 16, 16, 0.06), + 0 1px 3px 0 rgba(19, 16, 16, 0.08); + + * { + margin: 0 !important; + } } diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css index 91a771273e61..dba0a59b72db 100644 --- a/packages/ui/src/components/message-part.css +++ b/packages/ui/src/components/message-part.css @@ -1,440 +1,439 @@ [data-component="assistant-message"] { - content-visibility: auto; - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; + content-visibility: auto; + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; } [data-component="user-message"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); - display: flex; - flex-direction: column; - gap: 8px; - - [data-slot="user-message-attachments"] { - display: flex; - flex-wrap: wrap; - gap: 8px; - } - - [data-slot="user-message-attachment"] { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - border-radius: 6px; - overflow: hidden; - background: var(--surface-weak); - border: 1px solid var(--border-weak-base); - transition: border-color 0.15s ease; - - &:hover { - border-color: var(--border-strong-base); - } - - &[data-type="image"] { - width: 48px; - height: 48px; - } - - &[data-type="file"] { - width: 48px; - height: 48px; - } - } - - [data-slot="user-message-attachment-image"] { - width: 100%; - height: 100%; - object-fit: cover; - } - - [data-slot="user-message-attachment-icon"] { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - color: var(--icon-weak); - - [data-component="icon"] { - width: 20px; - height: 20px; - } - } - - [data-slot="user-message-text"] { - position: relative; - white-space: pre-wrap; - word-break: break-word; - overflow: hidden; - background: var(--surface-weak); - border: 1px solid var(--border-weak-base); - padding: 8px 12px; - border-radius: 4px; - - [data-highlight="file"] { - color: var(--syntax-property); - } - - [data-highlight="agent"] { - color: var(--syntax-type); - } - - [data-slot="user-message-copy-wrapper"] { - position: absolute; - top: 7px; - right: 7px; - opacity: 0; - transition: opacity 0.15s ease; - } - - &:hover [data-slot="user-message-copy-wrapper"] { - opacity: 1; - } - } - - .text-text-strong { - color: var(--text-strong); - } - - .font-medium { - font-weight: var(--font-weight-medium); - } + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); + display: flex; + flex-direction: column; + gap: 8px; + + [data-slot="user-message-attachments"] { + display: flex; + flex-wrap: wrap; + gap: 8px; + } + + [data-slot="user-message-attachment"] { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 6px; + overflow: hidden; + background: var(--surface-weak); + border: 1px solid var(--border-weak-base); + transition: border-color 0.15s ease; + + &:hover { + border-color: var(--border-strong-base); + } + + &[data-type="image"] { + width: 48px; + height: 48px; + } + + &[data-type="file"] { + width: 48px; + height: 48px; + } + } + + [data-slot="user-message-attachment-image"] { + width: 100%; + height: 100%; + object-fit: cover; + } + + [data-slot="user-message-attachment-icon"] { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: var(--icon-weak); + + [data-component="icon"] { + width: 20px; + height: 20px; + } + } + + [data-slot="user-message-text"] { + position: relative; + white-space: pre-wrap; + word-break: break-word; + overflow: hidden; + background: var(--surface-weak); + border: 1px solid var(--border-weak-base); + padding: 8px 12px; + border-radius: 4px; + + [data-highlight="file"] { + color: var(--syntax-property); + } + + [data-highlight="agent"] { + color: var(--syntax-type); + } + + [data-slot="user-message-copy-wrapper"] { + position: absolute; + top: 7px; + right: 7px; + opacity: 0; + transition: opacity 0.15s ease; + } + + &:hover [data-slot="user-message-copy-wrapper"] { + opacity: 1; + } + } + + .text-text-strong { + color: var(--text-strong); + } + + .font-medium { + font-weight: var(--font-weight-medium); + } } - [data-component="text-part"] { - width: 100%; - - [data-slot="text-part-body"] { - position: relative; - margin-top: 32px; - } - - [data-slot="text-part-copy-wrapper"] { - position: absolute; - top: 8px; - right: 8px; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 1; - } - - [data-slot="text-part-body"]:hover [data-slot="text-part-copy-wrapper"] { - opacity: 1; - } - - [data-component="markdown"] { - margin-top: 0; - font-size: var(--font-size-base); - } + width: 100%; + + [data-slot="text-part-body"] { + position: relative; + margin-top: 32px; + } + + [data-slot="text-part-copy-wrapper"] { + position: absolute; + top: 8px; + right: 8px; + opacity: 0; + transition: opacity 0.15s ease; + z-index: 1; + } + + [data-slot="text-part-body"]:hover [data-slot="text-part-copy-wrapper"] { + opacity: 1; + } + + [data-component="markdown"] { + margin-top: 0; + font-size: var(--font-size-base); + } } [data-component="reasoning-part"] { - width: 100%; - color: var(--text-base); - opacity: 0.8; - line-height: var(--line-height-large); - - [data-component="markdown"] { - margin-top: 24px; - font-style: italic !important; - - p:has(strong) { - margin-top: 24px; - margin-bottom: 0; - - &:first-child { - margin-top: 0; - } - } - } + width: 100%; + color: var(--text-base); + opacity: 0.8; + line-height: var(--line-height-large); + + [data-component="markdown"] { + margin-top: 24px; + font-style: italic !important; + + p:has(strong) { + margin-top: 24px; + margin-bottom: 0; + + &:first-child { + margin-top: 0; + } + } + } } [data-component="tool-error"] { - display: flex; - align-items: start; - gap: 8px; - - [data-slot="icon-svg"] { - color: var(--icon-critical-base); - margin-top: 4px; - } - - [data-slot="message-part-tool-error-content"] { - display: flex; - align-items: start; - gap: 8px; - } - - [data-slot="message-part-tool-error-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-on-critical-base); - white-space: nowrap; - } - - [data-slot="message-part-tool-error-message"] { - color: var(--text-on-critical-weak); - max-height: 240px; - overflow-y: auto; - word-break: break-word; - } + display: flex; + align-items: start; + gap: 8px; + + [data-slot="icon-svg"] { + color: var(--icon-critical-base); + margin-top: 4px; + } + + [data-slot="message-part-tool-error-content"] { + display: flex; + align-items: start; + gap: 8px; + } + + [data-slot="message-part-tool-error-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-on-critical-base); + white-space: nowrap; + } + + [data-slot="message-part-tool-error-message"] { + color: var(--text-on-critical-weak); + max-height: 240px; + overflow-y: auto; + word-break: break-word; + } } [data-component="tool-output"] { - white-space: pre; - padding: 8px 12px; - height: fit-content; - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; - - [data-component="markdown"] { - width: 100%; - min-width: 0; - - pre { - margin: 0; - padding: 0; - background-color: transparent !important; - border: none !important; - } - } - - pre { - margin: 0; - padding: 0; - background: none; - } - - &[data-scrollable] { - height: auto; - max-height: 240px; - overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; - - &::-webkit-scrollbar { - display: none; - } - - [data-component="markdown"] { - overflow: visible; - } - } + white-space: pre; + padding: 8px 12px; + height: fit-content; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + + [data-component="markdown"] { + width: 100%; + min-width: 0; + + pre { + margin: 0; + padding: 0; + background-color: transparent !important; + border: none !important; + } + } + + pre { + margin: 0; + padding: 0; + background: none; + } + + &[data-scrollable] { + height: auto; + max-height: 240px; + overflow-y: auto; + scrollbar-width: none; + -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } + + [data-component="markdown"] { + overflow: visible; + } + } } [data-component="edit-trigger"], [data-component="write-trigger"] { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - width: 100%; - - [data-slot="message-part-title-area"] { - flex-grow: 1; - display: flex; - align-items: center; - gap: 8px; - min-width: 0; - } - - [data-slot="message-part-title"] { - flex-shrink: 0; - display: flex; - align-items: center; - gap: 4px; - font-family: var(--font-family-sans); - font-size: var(--font-size-base); - font-style: normal; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - letter-spacing: var(--letter-spacing-normal); - color: var(--text-base); - } - - [data-slot="message-part-title-text"] { - text-transform: capitalize; - } - - [data-slot="message-part-title-filename"] { - /* No text-transform - preserve original filename casing */ - } - - [data-slot="message-part-path"] { - display: flex; - flex-grow: 1; - min-width: 0; - } - - [data-slot="message-part-directory"] { - color: var(--text-weak); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - direction: rtl; - text-align: left; - } - - [data-slot="message-part-filename"] { - color: var(--text-strong); - flex-shrink: 0; - } - - [data-slot="message-part-actions"] { - display: flex; - gap: 16px; - align-items: center; - justify-content: flex-end; - } + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + width: 100%; + + [data-slot="message-part-title-area"] { + flex-grow: 1; + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + } + + [data-slot="message-part-title"] { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 4px; + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + letter-spacing: var(--letter-spacing-normal); + color: var(--text-base); + } + + [data-slot="message-part-title-text"] { + text-transform: capitalize; + } + + [data-slot="message-part-title-filename"] { + /* No text-transform - preserve original filename casing */ + } + + [data-slot="message-part-path"] { + display: flex; + flex-grow: 1; + min-width: 0; + } + + [data-slot="message-part-directory"] { + color: var(--text-weak); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + direction: rtl; + text-align: left; + } + + [data-slot="message-part-filename"] { + color: var(--text-strong); + flex-shrink: 0; + } + + [data-slot="message-part-actions"] { + display: flex; + gap: 16px; + align-items: center; + justify-content: flex-end; + } } [data-component="edit-content"] { - border-top: 1px solid var(--border-weaker-base); - max-height: 420px; - overflow-y: auto; + border-top: 1px solid var(--border-weaker-base); + max-height: 420px; + overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="write-content"] { - border-top: 1px solid var(--border-weaker-base); - max-height: 240px; - overflow-y: auto; + border-top: 1px solid var(--border-weaker-base); + max-height: 240px; + overflow-y: auto; - [data-component="code"] { - padding-bottom: 0px !important; - } + [data-component="code"] { + padding-bottom: 0px !important; + } - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } + &::-webkit-scrollbar { + display: none; + } } [data-component="tool-action"] { - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; } [data-component="todos"] { - padding: 10px 12px 24px 48px; - display: flex; - flex-direction: column; - gap: 8px; - - [data-slot="message-part-todo-content"] { - &[data-completed="completed"] { - text-decoration: line-through; - color: var(--text-weaker); - } - } + padding: 10px 12px 24px 48px; + display: flex; + flex-direction: column; + gap: 8px; + + [data-slot="message-part-todo-content"] { + &[data-completed="completed"] { + text-decoration: line-through; + color: var(--text-weaker); + } + } } [data-component="task-tools"] { - padding: 8px 12px; - display: flex; - flex-direction: column; - gap: 6px; - - [data-slot="task-tool-item"] { - display: flex; - align-items: center; - gap: 8px; - color: var(--text-weak); - - [data-slot="icon-svg"] { - flex-shrink: 0; - color: var(--icon-weak); - } - } - - [data-slot="task-tool-title"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-weak); - } - - [data-slot="task-tool-subtitle"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - color: var(--text-weaker); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } + padding: 8px 12px; + display: flex; + flex-direction: column; + gap: 6px; + + [data-slot="task-tool-item"] { + display: flex; + align-items: center; + gap: 8px; + color: var(--text-weak); + + [data-slot="icon-svg"] { + flex-shrink: 0; + color: var(--icon-weak); + } + } + + [data-slot="task-tool-title"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-weak); + } + + [data-slot="task-tool-subtitle"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + color: var(--text-weaker); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } } [data-component="diagnostics"] { - display: flex; - flex-direction: column; - gap: 4px; - padding: 8px 12px; - background-color: var(--surface-critical-weak); - border-top: 1px solid var(--border-critical-base); - - [data-slot="diagnostic"] { - display: flex; - align-items: baseline; - gap: 6px; - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - line-height: var(--line-height-large); - } - - [data-slot="diagnostic-label"] { - color: var(--text-on-critical-base); - font-weight: var(--font-weight-medium); - text-transform: uppercase; - letter-spacing: -0.5px; - flex-shrink: 0; - } - - [data-slot="diagnostic-location"] { - color: var(--text-on-critical-weak); - flex-shrink: 0; - } - - [data-slot="diagnostic-message"] { - color: var(--text-on-critical-base); - word-break: break-word; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - line-clamp: 3; - overflow: hidden; - } + display: flex; + flex-direction: column; + gap: 4px; + padding: 8px 12px; + background-color: var(--surface-critical-weak); + border-top: 1px solid var(--border-critical-base); + + [data-slot="diagnostic"] { + display: flex; + align-items: baseline; + gap: 6px; + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + line-height: var(--line-height-large); + } + + [data-slot="diagnostic-label"] { + color: var(--text-on-critical-base); + font-weight: var(--font-weight-medium); + text-transform: uppercase; + letter-spacing: -0.5px; + flex-shrink: 0; + } + + [data-slot="diagnostic-location"] { + color: var(--text-on-critical-weak); + flex-shrink: 0; + } + + [data-slot="diagnostic-message"] { + color: var(--text-on-critical-base); + word-break: break-word; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 3; + line-clamp: 3; + overflow: hidden; + } } [data-component="user-message"] [data-slot="user-message-text"], @@ -447,383 +446,383 @@ [data-component="todos"], [data-component="diagnostics"], .error-card { - -webkit-user-select: text; - user-select: text; + -webkit-user-select: text; + user-select: text; } [data-component="tool-part-wrapper"] { - width: 100%; - - &[data-permission="true"], - &[data-question="true"] { - position: sticky; - top: calc(2px + var(--sticky-header-height, 40px)); - bottom: 0px; - z-index: 20; - border-radius: 6px; - border: none; - box-shadow: var(--shadow-xs-border-base); - background-color: var(--surface-raised-base); - overflow: visible; - overflow-anchor: none; - - & > *:first-child { - border-top-left-radius: 6px; - border-top-right-radius: 6px; - overflow: hidden; - } - - & > *:last-child { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - overflow: hidden; - } - - [data-component="collapsible"] { - border: none; - } - - [data-component="card"] { - border: none; - } - } - - &[data-permission="true"] { - &::before { - content: ""; - position: absolute; - inset: -1.5px; - top: -5px; - border-radius: 7.5px; - border: 1.5px solid transparent; - background: - linear-gradient(var(--background-base) 0 0) padding-box, - conic-gradient( - from var(--border-angle), - transparent 0deg, - transparent 0deg, - var(--border-warning-strong, var(--border-warning-selected)) 300deg, - var(--border-warning-base) 360deg - ) - border-box; - animation: chase-border 2.5s linear infinite; - pointer-events: none; - z-index: -1; - } - } - - &[data-question="true"] { - background: var(--background-base); - border: 1px solid var(--border-weak-base); - } + width: 100%; + + &[data-permission="true"], + &[data-question="true"] { + position: sticky; + top: calc(2px + var(--sticky-header-height, 40px)); + bottom: 0px; + z-index: 20; + border-radius: 6px; + border: none; + box-shadow: var(--shadow-xs-border-base); + background-color: var(--surface-raised-base); + overflow: visible; + overflow-anchor: none; + + & > *:first-child { + border-top-left-radius: 6px; + border-top-right-radius: 6px; + overflow: hidden; + } + + & > *:last-child { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + overflow: hidden; + } + + [data-component="collapsible"] { + border: none; + } + + [data-component="card"] { + border: none; + } + } + + &[data-permission="true"] { + &::before { + content: ""; + position: absolute; + inset: -1.5px; + top: -5px; + border-radius: 7.5px; + border: 1.5px solid transparent; + background: + linear-gradient(var(--background-base) 0 0) padding-box, + conic-gradient( + from var(--border-angle), + transparent 0deg, + transparent 0deg, + var(--border-warning-strong, var(--border-warning-selected)) 300deg, + var(--border-warning-base) 360deg + ) + border-box; + animation: chase-border 2.5s linear infinite; + pointer-events: none; + z-index: -1; + } + } + + &[data-question="true"] { + background: var(--background-base); + border: 1px solid var(--border-weak-base); + } } @property --border-angle { - syntax: ""; - initial-value: 0deg; - inherits: false; + syntax: ""; + initial-value: 0deg; + inherits: false; } @keyframes chase-border { - from { - --border-angle: 0deg; - } + from { + --border-angle: 0deg; + } - to { - --border-angle: 360deg; - } + to { + --border-angle: 360deg; + } } [data-component="permission-prompt"] { - display: flex; - flex-direction: column; - padding: 8px 12px; - background-color: var(--surface-raised-strong); - border-radius: 0 0 6px 6px; - - [data-slot="permission-actions"] { - display: flex; - align-items: center; - gap: 8px; - justify-content: flex-end; - } + display: flex; + flex-direction: column; + padding: 8px 12px; + background-color: var(--surface-raised-strong); + border-radius: 0 0 6px 6px; + + [data-slot="permission-actions"] { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-end; + } } [data-component="question-prompt"] { - display: flex; - flex-direction: column; - padding: 12px; - background-color: var(--surface-inset-base); - border-radius: 0 0 6px 6px; - gap: 12px; - - [data-slot="question-tabs"] { - display: flex; - gap: 4px; - flex-wrap: wrap; - - [data-slot="question-tab"] { - padding: 4px 12px; - font-size: 13px; - border-radius: 4px; - background-color: var(--surface-base); - color: var(--text-base); - border: none; - cursor: pointer; - transition: - color 0.15s, - background-color 0.15s; - - &:hover { - background-color: var(--surface-base-hover); - } - - &[data-active="true"] { - background-color: var(--surface-raised-base); - } - - &[data-answered="true"] { - color: var(--text-strong); - } - } - } - - [data-slot="question-content"] { - display: flex; - flex-direction: column; - gap: 8px; - - [data-slot="question-text"] { - font-size: 14px; - color: var(--text-base); - line-height: 1.5; - } - } - - [data-slot="question-options"] { - display: flex; - flex-direction: column; - gap: 4px; - - [data-slot="question-option"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 2px; - padding: 8px 12px; - background-color: var(--surface-base); - border: 1px solid var(--border-weaker-base); - border-radius: 6px; - cursor: pointer; - text-align: left; - width: 100%; - transition: - background-color 0.15s, - border-color 0.15s; - position: relative; - - &:hover { - background-color: var(--surface-base-hover); - border-color: var(--border-default); - } - - &[data-picked="true"] { - [data-component="icon"] { - position: absolute; - right: 12px; - top: 50%; - transform: translateY(-50%); - color: var(--text-strong); - } - } - - [data-slot="option-label"] { - font-size: 14px; - color: var(--text-base); - font-weight: 500; - } - - [data-slot="option-description"] { - font-size: 12px; - color: var(--text-weak); - } - } - - [data-slot="custom-input-form"] { - display: flex; - gap: 8px; - padding: 8px 0; - align-items: stretch; - - [data-slot="custom-input"] { - flex: 1; - padding: 8px 12px; - font-size: 14px; - border: 1px solid var(--border-default); - border-radius: 6px; - background-color: var(--surface-base); - color: var(--text-base); - outline: none; - - &:focus { - border-color: var(--border-focus); - } - - &::placeholder { - color: var(--text-weak); - } - } - - [data-component="button"] { - height: auto; - } - } - } - - [data-slot="question-review"] { - display: flex; - flex-direction: column; - gap: 12px; - - [data-slot="review-title"] { - display: none; - } - - [data-slot="review-item"] { - display: flex; - flex-direction: column; - gap: 2px; - font-size: 13px; - - [data-slot="review-label"] { - color: var(--text-weak); - } - - [data-slot="review-value"] { - color: var(--text-strong); - - &[data-answered="false"] { - color: var(--text-weak); - } - } - } - } - - [data-slot="question-actions"] { - display: flex; - align-items: center; - gap: 8px; - justify-content: flex-end; - } + display: flex; + flex-direction: column; + padding: 12px; + background-color: var(--surface-inset-base); + border-radius: 0 0 6px 6px; + gap: 12px; + + [data-slot="question-tabs"] { + display: flex; + gap: 4px; + flex-wrap: wrap; + + [data-slot="question-tab"] { + padding: 4px 12px; + font-size: 13px; + border-radius: 4px; + background-color: var(--surface-base); + color: var(--text-base); + border: none; + cursor: pointer; + transition: + color 0.15s, + background-color 0.15s; + + &:hover { + background-color: var(--surface-base-hover); + } + + &[data-active="true"] { + background-color: var(--surface-raised-base); + } + + &[data-answered="true"] { + color: var(--text-strong); + } + } + } + + [data-slot="question-content"] { + display: flex; + flex-direction: column; + gap: 8px; + + [data-slot="question-text"] { + font-size: 14px; + color: var(--text-base); + line-height: 1.5; + } + } + + [data-slot="question-options"] { + display: flex; + flex-direction: column; + gap: 4px; + + [data-slot="question-option"] { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + padding: 8px 12px; + background-color: var(--surface-base); + border: 1px solid var(--border-weaker-base); + border-radius: 6px; + cursor: pointer; + text-align: left; + width: 100%; + transition: + background-color 0.15s, + border-color 0.15s; + position: relative; + + &:hover { + background-color: var(--surface-base-hover); + border-color: var(--border-default); + } + + &[data-picked="true"] { + [data-component="icon"] { + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + color: var(--text-strong); + } + } + + [data-slot="option-label"] { + font-size: 14px; + color: var(--text-base); + font-weight: 500; + } + + [data-slot="option-description"] { + font-size: 12px; + color: var(--text-weak); + } + } + + [data-slot="custom-input-form"] { + display: flex; + gap: 8px; + padding: 8px 0; + align-items: stretch; + + [data-slot="custom-input"] { + flex: 1; + padding: 8px 12px; + font-size: 14px; + border: 1px solid var(--border-default); + border-radius: 6px; + background-color: var(--surface-base); + color: var(--text-base); + outline: none; + + &:focus { + border-color: var(--border-focus); + } + + &::placeholder { + color: var(--text-weak); + } + } + + [data-component="button"] { + height: auto; + } + } + } + + [data-slot="question-review"] { + display: flex; + flex-direction: column; + gap: 12px; + + [data-slot="review-title"] { + display: none; + } + + [data-slot="review-item"] { + display: flex; + flex-direction: column; + gap: 2px; + font-size: 13px; + + [data-slot="review-label"] { + color: var(--text-weak); + } + + [data-slot="review-value"] { + color: var(--text-strong); + + &[data-answered="false"] { + color: var(--text-weak); + } + } + } + } + + [data-slot="question-actions"] { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-end; + } } [data-component="question-answers"] { - display: flex; - flex-direction: column; - gap: 12px; - padding: 8px 12px; - - [data-slot="question-answer-item"] { - display: flex; - flex-direction: column; - gap: 2px; - font-size: 13px; - - [data-slot="question-text"] { - color: var(--text-weak); - } - - [data-slot="answer-text"] { - color: var(--text-strong); - } - } + display: flex; + flex-direction: column; + gap: 12px; + padding: 8px 12px; + + [data-slot="question-answer-item"] { + display: flex; + flex-direction: column; + gap: 2px; + font-size: 13px; + + [data-slot="question-text"] { + color: var(--text-weak); + } + + [data-slot="answer-text"] { + color: var(--text-strong); + } + } } [data-component="apply-patch-files"] { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } [data-component="apply-patch-file"] { - display: flex; - flex-direction: column; - border-top: 1px solid var(--border-weaker-base); - - &:first-child { - border-top: 1px solid var(--border-weaker-base); - } - - [data-slot="apply-patch-file-header"] { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - background-color: var(--surface-inset-base); - } - - [data-slot="apply-patch-file-action"] { - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-base); - flex-shrink: 0; - - &[data-type="delete"] { - color: var(--text-critical-base); - } - - &[data-type="add"] { - color: var(--text-success-base); - } - - &[data-type="move"] { - color: var(--text-warning-base); - } - } - - [data-slot="apply-patch-file-path"] { - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - color: var(--text-weak); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex-grow: 1; - } - - [data-slot="apply-patch-deletion-count"] { - font-family: var(--font-family-mono); - font-size: var(--font-size-small); - color: var(--text-critical-base); - flex-shrink: 0; - } + display: flex; + flex-direction: column; + border-top: 1px solid var(--border-weaker-base); + + &:first-child { + border-top: 1px solid var(--border-weaker-base); + } + + [data-slot="apply-patch-file-header"] { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background-color: var(--surface-inset-base); + } + + [data-slot="apply-patch-file-action"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-large); + color: var(--text-base); + flex-shrink: 0; + + &[data-type="delete"] { + color: var(--text-critical-base); + } + + &[data-type="add"] { + color: var(--text-success-base); + } + + &[data-type="move"] { + color: var(--text-warning-base); + } + } + + [data-slot="apply-patch-file-path"] { + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + color: var(--text-weak); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-grow: 1; + } + + [data-slot="apply-patch-deletion-count"] { + font-family: var(--font-family-mono); + font-size: var(--font-size-small); + color: var(--text-critical-base); + flex-shrink: 0; + } } [data-component="apply-patch-file-diff"] { - max-height: 420px; - overflow-y: auto; - scrollbar-width: none; - -ms-overflow-style: none; - - &::-webkit-scrollbar { - display: none; - } + max-height: 420px; + overflow-y: auto; + scrollbar-width: none; + -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } } [data-component="tool-loaded-file"] { - display: flex; - align-items: center; - gap: 8px; - padding: 4px 0 4px 28px; - font-family: var(--font-family-sans); - font-size: var(--font-size-small); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-large); - color: var(--text-weak); - - [data-component="icon"] { - flex-shrink: 0; - color: var(--icon-weak); - } + display: flex; + align-items: center; + gap: 8px; + padding: 4px 0 4px 28px; + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-large); + color: var(--text-weak); + + [data-component="icon"] { + flex-shrink: 0; + color: var(--icon-weak); + } } diff --git a/packages/ui/src/components/morph-chevron.css b/packages/ui/src/components/morph-chevron.css index f6edb3f649ac..c7bab9081fe4 100644 --- a/packages/ui/src/components/morph-chevron.css +++ b/packages/ui/src/components/morph-chevron.css @@ -1,10 +1,10 @@ [data-slot="morph-chevron-svg"] { - width: 16px; - height: 16px; - display: block; - fill: none; - stroke-width: 1.5; - stroke: currentcolor; - stroke-linecap: round; - stroke-linejoin: round; + width: 16px; + height: 16px; + display: block; + fill: none; + stroke-width: 1.5; + stroke: currentcolor; + stroke-linecap: round; + stroke-linejoin: round; } diff --git a/packages/ui/src/components/morph-chevron.tsx b/packages/ui/src/components/morph-chevron.tsx index 1273146e7717..baf5bf008c35 100644 --- a/packages/ui/src/components/morph-chevron.tsx +++ b/packages/ui/src/components/morph-chevron.tsx @@ -25,10 +25,16 @@ export function MorphChevron(props: MorphChevronProps) { ) return ( - +
- +
{getFilenameTruncated(item.path, 14)} @@ -1808,7 +1812,7 @@ export const PromptInput: Component = (props) => { type="button" icon="close-small" variant="ghost" - class="ml-auto h-5 w-5 opacity-0 group-hover:opacity-100 transition-all" + class="ml-auto size-7 opacity-0 group-hover:opacity-100 transition-all" onClick={(e) => { e.stopPropagation() if (item.commentID) comments.remove(item.path, item.commentID) @@ -1838,7 +1842,7 @@ export const PromptInput: Component = (props) => { when={attachment.mime.startsWith("image/")} fallback={
- +
} > @@ -1912,7 +1916,7 @@ export const PromptInput: Component = (props) => {
-
+
@@ -1943,7 +1947,12 @@ export const PromptInput: Component = (props) => { title={language.t("command.model.choose")} keybind={command.keybind("model.choose")} > -
-
+
= (props) => { e.currentTarget.value = "" }} /> -
+
@@ -2074,7 +2084,7 @@ export const PromptInput: Component = (props) => { disabled={!prompt.dirty() && !working()} icon={working() ? "stop" : "arrow-up"} variant="primary" - class="h-6 w-5" + class="h-6 w-5.5" aria-label={working() ? language.t("prompt.action.stop") : language.t("prompt.action.send")} /> diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index bed6764378d1..92b060212d66 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -64,8 +64,8 @@ export function SessionContextUsage(props: SessionContextUsageProps) { } const circle = () => ( -
- +
+
) @@ -101,7 +101,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {