diff options
| author | Shoubhit Dash <[email protected]> | 2026-04-16 17:30:14 +0530 |
|---|---|---|
| committer | Shoubhit Dash <[email protected]> | 2026-04-16 17:30:14 +0530 |
| commit | 2e18a603f0ea24154908e748493fd4bfaa74fc00 (patch) | |
| tree | b723e00af2821b213573b16fa199b64babd5f1f5 /packages/ui | |
| parent | 9819eb04614fd607cacb07d754052f1531a82331 (diff) | |
| parent | 7341718f9234b0cf3a8758c87e91d2006b71bff6 (diff) | |
| download | opencode-2e18a603f0ea24154908e748493fd4bfaa74fc00.tar.gz opencode-2e18a603f0ea24154908e748493fd4bfaa74fc00.zip | |
merge dev
Diffstat (limited to 'packages/ui')
54 files changed, 239 insertions, 182 deletions
diff --git a/packages/ui/package.json b/packages/ui/package.json index 12325ecc7..21974e3ec 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.4.3", + "version": "1.4.6", "type": "module", "license": "MIT", "exports": { @@ -44,7 +44,7 @@ "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", - "@opencode-ai/util": "workspace:*", + "@opencode-ai/shared": "workspace:*", "@pierre/diffs": "catalog:", "@shikijs/transformers": "3.9.2", "@solid-primitives/bounds": "0.1.3", diff --git a/packages/ui/src/components/accordion.css b/packages/ui/src/components/accordion.css index b4d6323d0..cebb887f1 100644 --- a/packages/ui/src/components/accordion.css +++ b/packages/ui/src/components/accordion.css @@ -51,10 +51,10 @@ line-height: var(--line-height-large); /* 166.667% */ letter-spacing: var(--letter-spacing-normal); - &:hover { + &:hover:not([data-disabled]) { background-color: var(--surface-base-hover); } - &:active { + &:active:not([data-disabled]) { background-color: var(--surface-base-active); } &:focus-visible { diff --git a/packages/ui/src/components/accordion.tsx b/packages/ui/src/components/accordion.tsx index 535d38e3d..3179b8a15 100644 --- a/packages/ui/src/components/accordion.tsx +++ b/packages/ui/src/components/accordion.tsx @@ -15,7 +15,7 @@ function AccordionRoot(props: AccordionProps) { {...rest} data-component="accordion" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} /> @@ -29,7 +29,7 @@ function AccordionItem(props: AccordionItemProps) { {...rest} data-slot="accordion-item" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} /> @@ -43,7 +43,7 @@ function AccordionHeader(props: ParentProps<AccordionHeaderProps>) { {...rest} data-slot="accordion-header" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > @@ -59,7 +59,7 @@ function AccordionTrigger(props: ParentProps<AccordionTriggerProps>) { {...rest} data-slot="accordion-trigger" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > @@ -75,7 +75,7 @@ function AccordionContent(props: ParentProps<AccordionContentProps>) { {...rest} data-slot="accordion-content" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/app-icon.tsx b/packages/ui/src/components/app-icon.tsx index f8b587ff2..541dfc570 100644 --- a/packages/ui/src/components/app-icon.tsx +++ b/packages/ui/src/components/app-icon.tsx @@ -77,7 +77,7 @@ export const AppIcon: Component<AppIconProps> = (props) => { alt={local.alt ?? ""} draggable={local.draggable ?? false} classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} /> diff --git a/packages/ui/src/components/avatar.tsx b/packages/ui/src/components/avatar.tsx index c1617b265..035c2d304 100644 --- a/packages/ui/src/components/avatar.tsx +++ b/packages/ui/src/components/avatar.tsx @@ -38,7 +38,7 @@ export function Avatar(props: AvatarProps) { data-size={split.size || "normal"} data-has-image={src ? "" : undefined} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} style={{ diff --git a/packages/ui/src/components/basic-tool.tsx b/packages/ui/src/components/basic-tool.tsx index 7d18dfacd..27ad7c3c7 100644 --- a/packages/ui/src/components/basic-tool.tsx +++ b/packages/ui/src/components/basic-tool.tsx @@ -100,7 +100,7 @@ export function BasicTool(props: BasicToolProps) { if (isOpen) { contentRef.style.overflow = "hidden" heightAnim = animate(contentRef, { height: "auto" }, SPRING) - heightAnim.finished.then(() => { + void heightAnim.finished.then(() => { if (!contentRef || !open()) return contentRef.style.overflow = "visible" contentRef.style.height = "auto" diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx index 7f974b2f7..d1652145f 100644 --- a/packages/ui/src/components/button.tsx +++ b/packages/ui/src/components/button.tsx @@ -20,7 +20,7 @@ export function Button(props: ButtonProps) { data-variant={split.variant || "secondary"} data-icon={split.icon} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/card.tsx b/packages/ui/src/components/card.tsx index 7a1bd5e45..320aba718 100644 --- a/packages/ui/src/components/card.tsx +++ b/packages/ui/src/components/card.tsx @@ -53,7 +53,7 @@ export function Card(props: CardProps) { data-variant={variant()} style={mix(split.style, accent())} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > @@ -76,7 +76,7 @@ export function CardTitle(props: CardTitleProps) { {...rest} data-slot="card-title" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > @@ -97,7 +97,7 @@ export function CardDescription(props: ComponentProps<"div">) { {...rest} data-slot="card-description" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > @@ -113,7 +113,7 @@ export function CardActions(props: ComponentProps<"div">) { {...rest} data-slot="card-actions" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/collapsible.css b/packages/ui/src/components/collapsible.css index 608ca6e0e..82c133f73 100644 --- a/packages/ui/src/components/collapsible.css +++ b/packages/ui/src/components/collapsible.css @@ -9,7 +9,7 @@ overflow: visible; &.tool-collapsible { - --tool-content-gap: 8px; + --tool-content-gap: 4px; gap: var(--tool-content-gap); } diff --git a/packages/ui/src/components/collapsible.tsx b/packages/ui/src/components/collapsible.tsx index 8b5cd825c..b2a603264 100644 --- a/packages/ui/src/components/collapsible.tsx +++ b/packages/ui/src/components/collapsible.tsx @@ -15,7 +15,7 @@ function CollapsibleRoot(props: CollapsibleProps) { data-component="collapsible" data-variant={local.variant || "normal"} classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} {...others} diff --git a/packages/ui/src/components/context-menu.tsx b/packages/ui/src/components/context-menu.tsx index afdaff7b8..f4566a17a 100644 --- a/packages/ui/src/components/context-menu.tsx +++ b/packages/ui/src/components/context-menu.tsx @@ -33,7 +33,7 @@ function ContextMenuTrigger(props: ParentProps<ContextMenuTriggerProps>) { {...rest} data-slot="context-menu-trigger" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -49,7 +49,7 @@ function ContextMenuIcon(props: ParentProps<ContextMenuIconProps>) { {...rest} data-slot="context-menu-icon" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -69,7 +69,7 @@ function ContextMenuContent(props: ParentProps<ContextMenuContentProps>) { {...rest} data-component="context-menu-content" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -85,7 +85,7 @@ function ContextMenuArrow(props: ContextMenuArrowProps) { {...rest} data-slot="context-menu-arrow" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} /> @@ -99,7 +99,7 @@ function ContextMenuSeparator(props: ContextMenuSeparatorProps) { {...rest} data-slot="context-menu-separator" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} /> @@ -113,7 +113,7 @@ function ContextMenuGroup(props: ParentProps<ContextMenuGroupProps>) { {...rest} data-slot="context-menu-group" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -129,7 +129,7 @@ function ContextMenuGroupLabel(props: ParentProps<ContextMenuGroupLabelProps>) { {...rest} data-slot="context-menu-group-label" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -145,7 +145,7 @@ function ContextMenuItem(props: ParentProps<ContextMenuItemProps>) { {...rest} data-slot="context-menu-item" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -161,7 +161,7 @@ function ContextMenuItemLabel(props: ParentProps<ContextMenuItemLabelProps>) { {...rest} data-slot="context-menu-item-label" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -177,7 +177,7 @@ function ContextMenuItemDescription(props: ParentProps<ContextMenuItemDescriptio {...rest} data-slot="context-menu-item-description" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -193,7 +193,7 @@ function ContextMenuItemIndicator(props: ParentProps<ContextMenuItemIndicatorPro {...rest} data-slot="context-menu-item-indicator" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -209,7 +209,7 @@ function ContextMenuRadioGroup(props: ParentProps<ContextMenuRadioGroupProps>) { {...rest} data-slot="context-menu-radio-group" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -225,7 +225,7 @@ function ContextMenuRadioItem(props: ParentProps<ContextMenuRadioItemProps>) { {...rest} data-slot="context-menu-radio-item" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -241,7 +241,7 @@ function ContextMenuCheckboxItem(props: ParentProps<ContextMenuCheckboxItemProps {...rest} data-slot="context-menu-checkbox-item" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -261,7 +261,7 @@ function ContextMenuSubTrigger(props: ParentProps<ContextMenuSubTriggerProps>) { {...rest} data-slot="context-menu-sub-trigger" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -277,7 +277,7 @@ function ContextMenuSubContent(props: ParentProps<ContextMenuSubContentProps>) { {...rest} data-component="context-menu-sub-content" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > diff --git a/packages/ui/src/components/dialog.tsx b/packages/ui/src/components/dialog.tsx index ce7704f37..981e3f45d 100644 --- a/packages/ui/src/components/dialog.tsx +++ b/packages/ui/src/components/dialog.tsx @@ -28,7 +28,7 @@ export function Dialog(props: DialogProps) { data-slot="dialog-content" data-no-header={!props.title && !props.action ? "" : undefined} classList={{ - ...(props.classList ?? {}), + ...props.classList, [props.class ?? ""]: !!props.class, }} onOpenAutoFocus={(e) => { diff --git a/packages/ui/src/components/dock-surface.tsx b/packages/ui/src/components/dock-surface.tsx index 1c4af2ed5..06cf2a5eb 100644 --- a/packages/ui/src/components/dock-surface.tsx +++ b/packages/ui/src/components/dock-surface.tsx @@ -11,7 +11,7 @@ export function DockShell(props: ComponentProps<"div">) { {...rest} data-dock-surface="shell" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > @@ -27,7 +27,7 @@ export function DockShellForm(props: ComponentProps<"form">) { {...rest} data-dock-surface="shell" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > @@ -44,7 +44,7 @@ export function DockTray(props: DockTrayProps) { data-dock-surface="tray" data-dock-attach={split.attach || "none"} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/dropdown-menu.tsx b/packages/ui/src/components/dropdown-menu.tsx index efb2b45ca..259cb791a 100644 --- a/packages/ui/src/components/dropdown-menu.tsx +++ b/packages/ui/src/components/dropdown-menu.tsx @@ -33,7 +33,7 @@ function DropdownMenuTrigger(props: ParentProps<DropdownMenuTriggerProps>) { {...rest} data-slot="dropdown-menu-trigger" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -49,7 +49,7 @@ function DropdownMenuIcon(props: ParentProps<DropdownMenuIconProps>) { {...rest} data-slot="dropdown-menu-icon" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -69,7 +69,7 @@ function DropdownMenuContent(props: ParentProps<DropdownMenuContentProps>) { {...rest} data-component="dropdown-menu-content" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -85,7 +85,7 @@ function DropdownMenuArrow(props: DropdownMenuArrowProps) { {...rest} data-slot="dropdown-menu-arrow" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} /> @@ -99,7 +99,7 @@ function DropdownMenuSeparator(props: DropdownMenuSeparatorProps) { {...rest} data-slot="dropdown-menu-separator" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} /> @@ -113,7 +113,7 @@ function DropdownMenuGroup(props: ParentProps<DropdownMenuGroupProps>) { {...rest} data-slot="dropdown-menu-group" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -129,7 +129,7 @@ function DropdownMenuGroupLabel(props: ParentProps<DropdownMenuGroupLabelProps>) {...rest} data-slot="dropdown-menu-group-label" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -145,7 +145,7 @@ function DropdownMenuItem(props: ParentProps<DropdownMenuItemProps>) { {...rest} data-slot="dropdown-menu-item" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -161,7 +161,7 @@ function DropdownMenuItemLabel(props: ParentProps<DropdownMenuItemLabelProps>) { {...rest} data-slot="dropdown-menu-item-label" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -177,7 +177,7 @@ function DropdownMenuItemDescription(props: ParentProps<DropdownMenuItemDescript {...rest} data-slot="dropdown-menu-item-description" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -193,7 +193,7 @@ function DropdownMenuItemIndicator(props: ParentProps<DropdownMenuItemIndicatorP {...rest} data-slot="dropdown-menu-item-indicator" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -209,7 +209,7 @@ function DropdownMenuRadioGroup(props: ParentProps<DropdownMenuRadioGroupProps>) {...rest} data-slot="dropdown-menu-radio-group" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -225,7 +225,7 @@ function DropdownMenuRadioItem(props: ParentProps<DropdownMenuRadioItemProps>) { {...rest} data-slot="dropdown-menu-radio-item" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -241,7 +241,7 @@ function DropdownMenuCheckboxItem(props: ParentProps<DropdownMenuCheckboxItemPro {...rest} data-slot="dropdown-menu-checkbox-item" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -261,7 +261,7 @@ function DropdownMenuSubTrigger(props: ParentProps<DropdownMenuSubTriggerProps>) {...rest} data-slot="dropdown-menu-sub-trigger" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -277,7 +277,7 @@ function DropdownMenuSubContent(props: ParentProps<DropdownMenuSubContentProps>) {...rest} data-component="dropdown-menu-sub-content" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > diff --git a/packages/ui/src/components/file-icon.tsx b/packages/ui/src/components/file-icon.tsx index 133cb169c..d66ee1c25 100644 --- a/packages/ui/src/components/file-icon.tsx +++ b/packages/ui/src/components/file-icon.tsx @@ -18,7 +18,7 @@ export const FileIcon: Component<FileIconProps> = (props) => { data-component="file-icon" {...rest} classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > diff --git a/packages/ui/src/components/file-ssr.tsx b/packages/ui/src/components/file-ssr.tsx index fed5c8931..ad05555bd 100644 --- a/packages/ui/src/components/file-ssr.tsx +++ b/packages/ui/src/components/file-ssr.tsx @@ -99,7 +99,7 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) { { ...createDefaultOptions(props.diffStyle), ...others, - ...(local.preloadedDiff.options ?? {}), + ...local.preloadedDiff.options, }, virtualizer, virtualMetrics, @@ -109,7 +109,7 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) { { ...createDefaultOptions(props.diffStyle), ...others, - ...(local.preloadedDiff.options ?? {}), + ...local.preloadedDiff.options, }, workerPool, ) diff --git a/packages/ui/src/components/file.tsx b/packages/ui/src/components/file.tsx index b78f0bae4..633b23b70 100644 --- a/packages/ui/src/components/file.tsx +++ b/packages/ui/src/components/file.tsx @@ -1,4 +1,4 @@ -import { sampledChecksum } from "@opencode-ai/util/encode" +import { sampledChecksum } from "@opencode-ai/shared/util/encode" import { DEFAULT_VIRTUAL_FILE_METRICS, type DiffLineAnnotation, @@ -655,7 +655,7 @@ function ViewerShell(props: { style={styleVariables} class="relative outline-none" classList={{ - ...(props.classList || {}), + ...props.classList, [props.class ?? ""]: !!props.class, }} ref={(el) => (props.viewer.wrapper = el)} @@ -698,6 +698,7 @@ function TextViewer<T>(props: TextFileProps<T>) { if (typeof value === "string") return value if (Array.isArray(value)) return value.join("\n") if (value == null) return "" + // oxlint-disable-next-line no-base-to-string -- file contents cast to unknown, coercion is intentional return String(value) } @@ -712,11 +713,13 @@ function TextViewer<T>(props: TextFileProps<T>) { if (typeof value === "string") return value.length if (Array.isArray(value)) { return value.reduce( + // oxlint-disable-next-line no-base-to-string -- array parts coerced intentionally (sum, part) => sum + (typeof part === "string" ? part.length + 1 : String(part).length + 1), 0, ) } if (value == null) return 0 + // oxlint-disable-next-line no-base-to-string -- file contents cast to unknown, coercion is intentional return String(value).length }) diff --git a/packages/ui/src/components/hover-card.tsx b/packages/ui/src/components/hover-card.tsx index 8330375aa..4e6647313 100644 --- a/packages/ui/src/components/hover-card.tsx +++ b/packages/ui/src/components/hover-card.tsx @@ -20,7 +20,7 @@ export function HoverCard(props: HoverCardProps) { <Kobalte.Content data-component="hover-card-content" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > diff --git a/packages/ui/src/components/icon-button.tsx b/packages/ui/src/components/icon-button.tsx index 89ab00fcd..457283aa0 100644 --- a/packages/ui/src/components/icon-button.tsx +++ b/packages/ui/src/components/icon-button.tsx @@ -19,7 +19,7 @@ export function IconButton(props: ComponentProps<"button"> & IconButtonProps) { data-size={split.size || "normal"} data-variant={split.variant || "secondary"} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index e2eaf107a..08726d0ff 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -117,7 +117,7 @@ export function Icon(props: IconProps) { <svg data-slot="icon-svg" classList={{ - ...(local.classList || {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} fill="none" diff --git a/packages/ui/src/components/keybind.tsx b/packages/ui/src/components/keybind.tsx index a0fa0483f..5c347cb54 100644 --- a/packages/ui/src/components/keybind.tsx +++ b/packages/ui/src/components/keybind.tsx @@ -10,7 +10,7 @@ export function Keybind(props: KeybindProps) { <span data-component="keybind" classList={{ - ...(props.classList ?? {}), + ...props.classList, [props.class ?? ""]: !!props.class, }} > diff --git a/packages/ui/src/components/line-comment.tsx b/packages/ui/src/components/line-comment.tsx index 26e763bb3..e20da5a8d 100644 --- a/packages/ui/src/components/line-comment.tsx +++ b/packages/ui/src/components/line-comment.tsx @@ -1,5 +1,5 @@ import { useFilteredList } from "@opencode-ai/ui/hooks" -import { getDirectory, getFilename } from "@opencode-ai/util/path" +import { getDirectory, getFilename } from "@opencode-ai/shared/util/path" import { createSignal, For, onMount, Show, splitProps, type JSX } from "solid-js" import { Button } from "./button" import { FileIcon } from "./file-icon" diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx index b5879624e..cc5fc0ce5 100644 --- a/packages/ui/src/components/list.tsx +++ b/packages/ui/src/components/list.tsx @@ -107,7 +107,7 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void }) // Force a refetch even if the value is unchanged. // This is important for programmatic changes like Tab completion. if (prev === value) { - refetch() + void refetch() return } queueMicrotask(() => refetch()) diff --git a/packages/ui/src/components/markdown.css b/packages/ui/src/components/markdown.css index f82723807..26c9efd47 100644 --- a/packages/ui/src/components/markdown.css +++ b/packages/ui/src/components/markdown.css @@ -6,7 +6,7 @@ color: var(--text-strong); font-family: var(--font-family-sans); font-size: var(--font-size-base); /* 14px */ - line-height: var(--line-height-x-large); + line-height: 160%; /* Spacing for flow */ > *:first-child { @@ -23,11 +23,11 @@ h4, h5, h6 { - font-size: var(--font-size-base); + font-size: 14px; color: var(--text-strong); font-weight: var(--font-weight-medium); - margin-top: 2rem; - margin-bottom: 0.75rem; + margin-top: 0px; + margin-bottom: 24px; line-height: var(--line-height-large); } @@ -40,7 +40,7 @@ /* Paragraphs */ p { - margin-bottom: 1rem; + margin-bottom: 12px; } /* Links */ @@ -58,10 +58,10 @@ /* Lists */ ul, ol { - margin-top: 0.5rem; - margin-bottom: 1rem; + margin-top: 8px; + margin-bottom: 12px; margin-left: 0; - padding-left: 1.5rem; + padding-left: 32px; list-style-position: outside; } @@ -75,7 +75,7 @@ } li { - margin-bottom: 0.5rem; + margin-bottom: 8px; } li > p:first-child { @@ -117,12 +117,12 @@ hr { border: none; height: 0; - margin: 2.5rem 0; + margin: 40px 0; } .shiki { font-size: 13px; - padding: 8px 12px; + padding: 12px; border-radius: 6px; border: 0.5px solid var(--border-weak-base); } @@ -201,8 +201,8 @@ } pre { - margin-top: 2rem; - margin-bottom: 2rem; + margin-top: 12px; + margin-bottom: 32px; overflow: auto; scrollbar-width: none; @@ -229,7 +229,7 @@ table { width: 100%; border-collapse: collapse; - margin: 1.5rem 0; + margin: 24px 0; font-size: var(--font-size-base); display: block; overflow-x: auto; @@ -239,7 +239,7 @@ 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; + padding: 12px; text-align: left; vertical-align: top; } diff --git a/packages/ui/src/components/markdown.tsx b/packages/ui/src/components/markdown.tsx index ceab10df9..28653512e 100644 --- a/packages/ui/src/components/markdown.tsx +++ b/packages/ui/src/components/markdown.tsx @@ -2,7 +2,7 @@ import { useMarked } from "../context/marked" import { useI18n } from "../context/i18n" import DOMPurify from "dompurify" import morphdom from "morphdom" -import { checksum } from "@opencode-ai/util/encode" +import { checksum } from "@opencode-ai/shared/util/encode" import { ComponentProps, createEffect, createResource, createSignal, onCleanup, splitProps } from "solid-js" import { isServer } from "solid-js/web" import { stream } from "./markdown-stream" @@ -50,7 +50,7 @@ function escape(text: string) { .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") - .replace(/\"/g, """) + .replace(/"/g, """) .replace(/'/g, "'") } @@ -338,7 +338,7 @@ export function Markdown( <div data-component="markdown" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} ref={setRoot} diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css index d9893503f..c84a36892 100644 --- a/packages/ui/src/components/message-part.css +++ b/packages/ui/src/components/message-part.css @@ -283,9 +283,9 @@ line-height: var(--line-height-normal); [data-component="markdown"] { - margin-top: 24px; + margin-top: 16px; font-style: normal; - font-size: var(--font-size-base); + font-size: 13px; color: var(--text-weak); strong, @@ -556,9 +556,12 @@ [data-component="exa-tool-output"] { width: 100%; - padding-top: 8px; display: flex; flex-direction: column; + font-family: var(--font-family-sans); + font-size: var(--font-size-base); + line-height: var(--line-height-large); + color: var(--text-base); } [data-slot="basic-tool-tool-subtitle"].exa-tool-query { @@ -578,6 +581,8 @@ [data-slot="exa-tool-link"] { display: block; max-width: 100%; + font: inherit; + line-height: inherit; color: var(--text-interactive-base); text-decoration: underline; text-underline-offset: 2px; @@ -636,13 +641,13 @@ } [data-component="context-tool-group-list"] { - padding-top: 6px; + padding-top: 0; padding-right: 0; - padding-bottom: 4px; - padding-left: 13px; + padding-bottom: 0; + padding-left: 12px; display: flex; flex-direction: column; - gap: 8px; + gap: 4px; [data-slot="context-tool-group-item"] { min-width: 0; diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index 02bd80ac9..a47ff1804 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -37,7 +37,6 @@ import { type UiI18n, useI18n } from "../context/i18n" import { BasicTool, GenericTool } from "./basic-tool" import { Accordion } from "./accordion" import { StickyAccordionHeader } from "./sticky-accordion-header" -import { Card } from "./card" import { Collapsible } from "./collapsible" import { FileIcon } from "./file-icon" import { Icon } from "./icon" @@ -46,8 +45,8 @@ import { Checkbox } from "./checkbox" import { DiffChanges } from "./diff-changes" import { Markdown } from "./markdown" import { ImagePreview } from "./image-preview" -import { getDirectory as _getDirectory, getFilename } from "@opencode-ai/util/path" -import { checksum } from "@opencode-ai/util/encode" +import { getDirectory as _getDirectory, getFilename } from "@opencode-ai/shared/util/path" +import { checksum } from "@opencode-ai/shared/util/encode" import { Tooltip } from "./tooltip" import { IconButton } from "./icon-button" import { Spinner } from "./spinner" @@ -1159,7 +1158,7 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp onMouseDown={(e) => e.preventDefault()} onClick={(event) => { event.stopPropagation() - handleCopy() + void handleCopy() }} aria-label={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.message.copyMessage")} /> diff --git a/packages/ui/src/components/popover.tsx b/packages/ui/src/components/popover.tsx index 8263640a5..be5b78519 100644 --- a/packages/ui/src/components/popover.tsx +++ b/packages/ui/src/components/popover.tsx @@ -106,7 +106,7 @@ export function Popover<T extends ValidComponent = "div">(props: PopoverProps<T> ref={(el: HTMLElement | undefined) => setState("contentRef", el)} data-component="popover-content" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} style={local.style} diff --git a/packages/ui/src/components/progress-circle.tsx b/packages/ui/src/components/progress-circle.tsx index 02bd36bb7..992fb62e8 100644 --- a/packages/ui/src/components/progress-circle.tsx +++ b/packages/ui/src/components/progress-circle.tsx @@ -32,7 +32,7 @@ export function ProgressCircle(props: ProgressCircleProps) { fill="none" data-component="progress-circle" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/progress.tsx b/packages/ui/src/components/progress.tsx index bfe10a1d1..7cbe5d6bc 100644 --- a/packages/ui/src/components/progress.tsx +++ b/packages/ui/src/components/progress.tsx @@ -15,7 +15,7 @@ export function Progress(props: ProgressProps) { {...others} data-component="progress" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > diff --git a/packages/ui/src/components/provider-icon.tsx b/packages/ui/src/components/provider-icon.tsx index edfdd0357..7c0eb3d04 100644 --- a/packages/ui/src/components/provider-icon.tsx +++ b/packages/ui/src/components/provider-icon.tsx @@ -15,7 +15,7 @@ export const ProviderIcon: Component<ProviderIconProps> = (props) => { data-component="provider-icon" {...rest} classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > diff --git a/packages/ui/src/components/radio-group.tsx b/packages/ui/src/components/radio-group.tsx index 544e852e4..9151a24b0 100644 --- a/packages/ui/src/components/radio-group.tsx +++ b/packages/ui/src/components/radio-group.tsx @@ -56,7 +56,7 @@ export function RadioGroup<T>(props: RadioGroupProps<T>) { data-fill={local.fill ? "" : undefined} data-pad={local.pad ?? "normal"} classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} value={local.current ? getValue(local.current) : undefined} diff --git a/packages/ui/src/components/resize-handle.tsx b/packages/ui/src/components/resize-handle.tsx index e2eed1bb7..d7774a684 100644 --- a/packages/ui/src/components/resize-handle.tsx +++ b/packages/ui/src/components/resize-handle.tsx @@ -73,7 +73,7 @@ export function ResizeHandle(props: ResizeHandleProps) { data-direction={local.direction} data-edge={local.edge ?? (local.direction === "vertical" ? "start" : "end")} classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} onMouseDown={handleMouseDown} diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index 61804a951..67becf2d9 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -104,7 +104,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">) {...itemProps} data-slot="select-select-item" classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} onPointerEnter={() => move(itemProps.item.rawValue)} @@ -141,7 +141,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">) variant={props.variant} style={local.triggerStyle} classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} > @@ -160,7 +160,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">) <Kobalte.Portal> <Kobalte.Content classList={{ - ...(local.classList ?? {}), + ...local.classList, [local.class ?? ""]: !!local.class, }} data-component="select-content" diff --git a/packages/ui/src/components/session-diff.ts b/packages/ui/src/components/session-diff.ts index cc2b1ce52..a5fbdbc5c 100644 --- a/packages/ui/src/components/session-diff.ts +++ b/packages/ui/src/components/session-diff.ts @@ -1,6 +1,5 @@ -import { parsePatchFiles, type FileDiffMetadata } from "@pierre/diffs" -import { sampledChecksum } from "@opencode-ai/util/encode" -import { formatPatch, structuredPatch } from "diff" +import { parseDiffFromFile, type FileDiffMetadata } from "@pierre/diffs" +import { formatPatch, parsePatch, structuredPatch } from "diff" import type { SnapshotFileDiff, VcsFileDiff } from "@opencode-ai/sdk/v2" type LegacyDiff = { @@ -26,41 +25,51 @@ export type ViewDiff = { const cache = new Map<string, FileDiffMetadata>() -function empty(file: string, key: string) { - return { - name: file, - type: "change", - hunks: [], - splitLineCount: 0, - unifiedLineCount: 0, - isPartial: true, - deletionLines: [], - additionLines: [], - cacheKey: key, - } satisfies FileDiffMetadata -} - function patch(diff: ReviewDiff) { - if (typeof diff.patch === "string") return diff.patch - return formatPatch( - structuredPatch( - diff.file, - diff.file, - "before" in diff && typeof diff.before === "string" ? diff.before : "", - "after" in diff && typeof diff.after === "string" ? diff.after : "", - "", - "", - { context: Number.MAX_SAFE_INTEGER }, + if (typeof diff.patch === "string") { + const [patch] = parsePatch(diff.patch) + + const beforeLines = [] + const afterLines = [] + + for (const hunk of patch.hunks) { + for (const line of hunk.lines) { + if (line.startsWith("-")) { + beforeLines.push(line.slice(1)) + } else if (line.startsWith("+")) { + afterLines.push(line.slice(1)) + } else { + // context line (starts with ' ') + beforeLines.push(line.slice(1)) + afterLines.push(line.slice(1)) + } + } + } + + return { before: beforeLines.join("\n"), after: afterLines.join("\n"), patch: diff.patch } + } + return { + before: "before" in diff && typeof diff.before === "string" ? diff.before : "", + after: "after" in diff && typeof diff.after === "string" ? diff.after : "", + patch: formatPatch( + structuredPatch( + diff.file, + diff.file, + "before" in diff && typeof diff.before === "string" ? diff.before : "", + "after" in diff && typeof diff.after === "string" ? diff.after : "", + "", + "", + { context: Number.MAX_SAFE_INTEGER }, + ), ), - ) + } } -function file(file: string, patch: string) { +function file(file: string, patch: string, before: string, after: string) { const hit = cache.get(patch) if (hit) return hit - const key = sampledChecksum(patch) ?? file - const value = parsePatchFiles(patch, key).flatMap((item) => item.files)[0] ?? empty(file, key) + const value = parseDiffFromFile({ name: file, contents: before }, { name: file, contents: after }) cache.set(patch, value) return value } @@ -69,11 +78,11 @@ export function normalize(diff: ReviewDiff): ViewDiff { const next = patch(diff) return { file: diff.file, - patch: next, + patch: next.patch, additions: diff.additions, deletions: diff.deletions, status: diff.status, - fileDiff: file(diff.file, next), + fileDiff: file(diff.file, next.patch, next.before, next.after), } } diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index 4a7205a5d..6e2b0853a 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -11,8 +11,8 @@ import { Tooltip } from "./tooltip" import { ScrollView } from "./scroll-view" import { useFileComponent } from "../context/file" import { useI18n } from "../context/i18n" -import { getDirectory, getFilename } from "@opencode-ai/util/path" -import { checksum } from "@opencode-ai/util/encode" +import { getDirectory, getFilename } from "@opencode-ai/shared/util/path" +import { checksum } from "@opencode-ai/shared/util/encode" import { createEffect, createMemo, For, Match, onCleanup, Show, Switch, untrack, type JSX } from "solid-js" import { createStore } from "solid-js/store" import { type FileContent, type SnapshotFileDiff, type VcsFileDiff } from "@opencode-ai/sdk/v2" @@ -385,9 +385,11 @@ export const SessionReview = (props: SessionReviewProps) => { <Accordion multiple value={open()} onChange={handleChange}> <For each={items()}> {(diff) => { - let wrapper: HTMLDivElement | undefined const file = diff.file + // binary files have empty diffs that we can't render + const diffCanRender = () => diff.additions !== 0 && diff.deletions !== 0 + const expanded = createMemo(() => open().includes(file)) const mounted = createMemo(() => expanded() && (!!store.visible[file] || pinned(file))) const force = () => !!store.force[file] @@ -496,14 +498,14 @@ export const SessionReview = (props: SessionReviewProps) => { return ( <Accordion.Item - value={file} + value={diffCanRender() ? file : null!} id={diffId(file)} data-file={file} data-slot="session-review-accordion-item" data-selected={props.focusedFile === file ? "" : undefined} > <StickyAccordionHeader> - <Accordion.Trigger> + <Accordion.Trigger disabled={!diffCanRender()} class="cursor-default"> <div data-slot="session-review-trigger-content"> <div data-slot="session-review-file-info"> <FileIcon node={{ path: file, type: "file" }} /> @@ -512,7 +514,7 @@ export const SessionReview = (props: SessionReviewProps) => { <span data-slot="session-review-directory">{`\u202A${getDirectory(file)}\u202C`}</span> </Show> <span data-slot="session-review-filename">{getFilename(file)}</span> - <Show when={props.onViewFile}> + <Show when={props.onViewFile && diffCanRender()}> <Tooltip value={openFileLabel()} placement="top" gutter={4}> <button data-slot="session-review-view-button" @@ -553,9 +555,11 @@ export const SessionReview = (props: SessionReviewProps) => { <DiffChanges changes={diff} /> </Match> </Switch> - <span data-slot="session-review-diff-chevron"> - <Icon name="chevron-down" size="small" /> - </span> + <Show when={diffCanRender()}> + <span data-slot="session-review-diff-chevron"> + <Icon name="chevron-down" size="small" /> + </span> + </Show> </div> </div> </Accordion.Trigger> @@ -564,7 +568,6 @@ export const SessionReview = (props: SessionReviewProps) => { <div data-slot="session-review-diff-wrapper" ref={(el) => { - wrapper = el anchors.set(file, el) nodes.set(file, el) queue() diff --git a/packages/ui/src/components/session-turn.css b/packages/ui/src/components/session-turn.css index b01343a01..54076f3f8 100644 --- a/packages/ui/src/components/session-turn.css +++ b/packages/ui/src/components/session-turn.css @@ -26,7 +26,7 @@ align-items: flex-start; align-self: stretch; min-width: 0; - gap: 18px; + gap: 0px; overflow-anchor: none; } @@ -47,6 +47,7 @@ display: flex; align-items: center; gap: 8px; + margin-top: 12px; width: 100%; min-width: 0; color: var(--text-weak); @@ -226,5 +227,5 @@ } [data-slot="session-turn-list"] { - gap: 48px; + gap: 24px; } diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index e891a6feb..75279a90e 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -8,8 +8,8 @@ import type { SessionStatus } from "@opencode-ai/sdk/v2" import { useData } from "../context" import { useFileComponent } from "../context/file" -import { Binary } from "@opencode-ai/util/binary" -import { getDirectory, getFilename } from "@opencode-ai/util/path" +import { Binary } from "@opencode-ai/shared/util/binary" +import { getDirectory, getFilename } from "@opencode-ai/shared/util/path" import { createEffect, createMemo, createSignal, For, on, ParentProps, Show } from "solid-js" import { createStore } from "solid-js/store" import { Dynamic } from "solid-js/web" @@ -110,7 +110,7 @@ function partState(part: PartType, showReasoningSummaries: boolean) { function clean(value: string) { return value .replace(/`([^`]+)`/g, "$1") - .replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1") + .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") .replace(/[*_~]+/g, "") .trim() } @@ -313,6 +313,7 @@ export function SessionTurn( const msg = error()?.data?.message if (typeof msg === "string") return unwrap(msg) if (msg === undefined || msg === null) return "" + // oxlint-disable-next-line no-base-to-string -- msg is unknown from error data, coercion is intentional return unwrap(String(msg)) }) diff --git a/packages/ui/src/components/spinner.tsx b/packages/ui/src/components/spinner.tsx index 3d029d976..f8aacb6e2 100644 --- a/packages/ui/src/components/spinner.tsx +++ b/packages/ui/src/components/spinner.tsx @@ -23,7 +23,7 @@ export function Spinner(props: { viewBox="0 0 15 15" data-component="spinner" classList={{ - ...(props.classList ?? {}), + ...props.classList, [props.class ?? ""]: !!props.class, }} fill="currentColor" diff --git a/packages/ui/src/components/sticky-accordion-header.tsx b/packages/ui/src/components/sticky-accordion-header.tsx index 89d733449..b877aa16e 100644 --- a/packages/ui/src/components/sticky-accordion-header.tsx +++ b/packages/ui/src/components/sticky-accordion-header.tsx @@ -8,7 +8,7 @@ export function StickyAccordionHeader( <Accordion.Header data-component="sticky-accordion-header" classList={{ - ...(props.classList ?? {}), + ...props.classList, [props.class ?? ""]: !!props.class, }} > diff --git a/packages/ui/src/components/tabs.tsx b/packages/ui/src/components/tabs.tsx index 396504dd7..f46e9bfb3 100644 --- a/packages/ui/src/components/tabs.tsx +++ b/packages/ui/src/components/tabs.tsx @@ -27,7 +27,7 @@ function TabsRoot(props: TabsProps) { data-variant={split.variant || "normal"} data-orientation={split.orientation || "horizontal"} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} /> @@ -41,7 +41,7 @@ function TabsList(props: TabsListProps) { {...rest} data-slot="tabs-list" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} /> @@ -63,7 +63,7 @@ function TabsTrigger(props: ParentProps<TabsTriggerProps>) { data-slot="tabs-trigger-wrapper" data-value={props.value} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} onMouseDown={(e) => { @@ -104,7 +104,7 @@ function TabsContent(props: ParentProps<TabsContentProps>) { {...rest} data-slot="tabs-content" classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/tag.tsx b/packages/ui/src/components/tag.tsx index 428eedd0f..c54e4d474 100644 --- a/packages/ui/src/components/tag.tsx +++ b/packages/ui/src/components/tag.tsx @@ -12,7 +12,7 @@ export function Tag(props: TagProps) { data-component="tag" data-size={split.size || "normal"} classList={{ - ...(split.classList ?? {}), + ...split.classList, [split.class ?? ""]: !!split.class, }} > diff --git a/packages/ui/src/components/text-field.tsx b/packages/ui/src/components/text-field.tsx index d10f5d6ac..82be20f9e 100644 --- a/packages/ui/src/components/text-field.tsx +++ b/packages/ui/src/components/text-field.tsx @@ -75,7 +75,7 @@ export function TextField(props: TextFieldProps) { } function handleClick() { - if (local.copyable) handleCopy() + if (local.copyable) void handleCopy() } return ( diff --git a/packages/ui/src/components/text-reveal.tsx b/packages/ui/src/components/text-reveal.tsx index 02bf8084c..2d2a94e6a 100644 --- a/packages/ui/src/components/text-reveal.tsx +++ b/packages/ui/src/components/text-reveal.tsx @@ -102,7 +102,7 @@ export function TextReveal(props: { requestAnimationFrame(() => setState("ready", true)) return } - fonts.ready.finally(() => { + void fonts.ready.finally(() => { widen(win()) requestAnimationFrame(() => setState("ready", true)) }) diff --git a/packages/ui/src/components/thinking-heading.stories.tsx b/packages/ui/src/components/thinking-heading.stories.tsx index 3a65619ce..12a06b4d8 100644 --- a/packages/ui/src/components/thinking-heading.stories.tsx +++ b/packages/ui/src/components/thinking-heading.stories.tsx @@ -442,7 +442,7 @@ function AnimatedHeading(props) { onMount(() => { measure() - document.fonts?.ready.finally(() => { + void document.fonts?.ready.finally(() => { measure() requestAnimationFrame(() => setState("ready", true)) }) diff --git a/packages/ui/src/components/timeline-playground.stories.tsx b/packages/ui/src/components/timeline-playground.stories.tsx index e79e97a3a..c071db303 100644 --- a/packages/ui/src/components/timeline-playground.stories.tsx +++ b/packages/ui/src/components/timeline-playground.stories.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import { createSignal, createMemo, createEffect, on, For, Show, Index, batch } from "solid-js" +import { createSignal, createMemo, createEffect, on, For, Show, batch } from "solid-js" import { createStore, produce } from "solid-js/store" import type { Message, @@ -9,7 +9,6 @@ import type { TextPart, ReasoningPart, ToolPart, - CompactionPart, FilePart, AgentPart, } from "@opencode-ai/sdk/v2" @@ -555,10 +554,6 @@ function toolPart(sample: (typeof TOOL_SAMPLES)[keyof typeof TOOL_SAMPLES], stat } as ToolPart } -function compactionPart(): CompactionPart { - return { id: uid(), type: "compaction", auto: true } as CompactionPart -} - // --------------------------------------------------------------------------- // CSS Controls definition // --------------------------------------------------------------------------- @@ -568,6 +563,7 @@ const MD = "markdown.css" const MP = "message-part.css" const ST = "session-turn.css" const CL = "collapsible.css" +const BT = "basic-tool.css" /** * Source mapping for a CSS control. @@ -607,10 +603,10 @@ const CSS_CONTROLS: CSSControl[] = [ // --- Timeline spacing --- { key: "turn-gap", - label: "Turn gap", + label: "Above user messages", group: "Timeline Spacing", type: "range", - initial: "48", + initial: "32", selector: '[data-slot="session-turn-list"]', property: "gap", min: "0", @@ -621,10 +617,10 @@ const CSS_CONTROLS: CSSControl[] = [ }, { key: "container-gap", - label: "Container gap", + label: "Below user messages", group: "Timeline Spacing", type: "range", - initial: "18", + initial: "0", selector: '[data-slot="session-turn-message-container"]', property: "gap", min: "0", @@ -1041,11 +1037,39 @@ const CSS_CONTROLS: CSSControl[] = [ // --- Tool parts --- { + key: "tool-subtitle-font-size", + label: "Subtitle font size", + group: "Tool Parts", + type: "range", + initial: "14", + selector: '[data-slot="basic-tool-tool-subtitle"]', + property: "font-size", + min: "10", + max: "22", + step: "1", + unit: "px", + source: { file: BT, anchor: '[data-slot="basic-tool-tool-subtitle"]', prop: "font-size", format: px }, + }, + { + key: "exa-output-font-size", + label: "Search output font size", + group: "Tool Parts", + type: "range", + initial: "14", + selector: '[data-component="exa-tool-output"]', + property: "font-size", + min: "10", + max: "22", + step: "1", + unit: "px", + source: { file: MP, anchor: '[data-component="exa-tool-output"]', prop: "font-size", format: px }, + }, + { key: "tool-content-gap", label: "Trigger/content gap", group: "Tool Parts", type: "range", - initial: "8", + initial: "4", selector: '[data-component="collapsible"].tool-collapsible', property: "--tool-content-gap", min: "0", @@ -1059,7 +1083,7 @@ const CSS_CONTROLS: CSSControl[] = [ label: "Explored tool gap", group: "Explored Group", type: "range", - initial: "14", + initial: "4", selector: '[data-component="context-tool-group-list"]', property: "gap", min: "0", diff --git a/packages/ui/src/components/toast.tsx b/packages/ui/src/components/toast.tsx index e8062a2a8..599cf2a9e 100644 --- a/packages/ui/src/components/toast.tsx +++ b/packages/ui/src/components/toast.tsx @@ -30,7 +30,7 @@ function ToastRoot(props: ToastRootComponentProps) { <Kobalte data-component="toast" classList={{ - ...(props.classList ?? {}), + ...props.classList, [props.class ?? ""]: !!props.class, }} {...props} diff --git a/packages/ui/src/components/tool-error-card.tsx b/packages/ui/src/components/tool-error-card.tsx index 038870d38..9983e2fe7 100644 --- a/packages/ui/src/components/tool-error-card.tsx +++ b/packages/ui/src/components/tool-error-card.tsx @@ -128,7 +128,7 @@ export function ToolErrorCard(props: ToolErrorCardProps) { onMouseDown={(e) => e.preventDefault()} onClick={(e) => { e.stopPropagation() - copy() + void copy() }} aria-label={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.toolErrorCard.copyError")} /> diff --git a/packages/ui/src/components/tool-status-title.tsx b/packages/ui/src/components/tool-status-title.tsx index 2a58e0e5b..412d92e3d 100644 --- a/packages/ui/src/components/tool-status-title.tsx +++ b/packages/ui/src/components/tool-status-title.tsx @@ -86,7 +86,7 @@ export function ToolStatusTitle(props: { finish() return } - fonts.ready.finally(() => { + void fonts.ready.finally(() => { measure() finish() }) diff --git a/packages/ui/src/components/tooltip.tsx b/packages/ui/src/components/tooltip.tsx index ada597d0f..4366651d2 100644 --- a/packages/ui/src/components/tooltip.tsx +++ b/packages/ui/src/components/tooltip.tsx @@ -99,6 +99,8 @@ export function Tooltip(props: TooltipProps) { onCleanup(() => obs.disconnect()) }) + let justClickedTrigger = false + return ( <Switch> <Match when={local.inactive}>{local.children}</Match> @@ -112,6 +114,10 @@ export function Tooltip(props: TooltipProps) { onOpenChange={(open) => { if (local.forceOpen) return if (state.block && open) return + if (justClickedTrigger) { + justClickedTrigger = false + return + } setState("open", open) }} > @@ -137,6 +143,12 @@ export function Tooltip(props: TooltipProps) { data-force-open={local.forceOpen} class={local.contentClass} style={local.contentStyle} + onPointerDownOutside={(e) => { + if (ref === e.target || (e.target instanceof Node && ref?.contains(e.target))) { + justClickedTrigger = true + } + e.preventDefault() + }} > {local.value} {/* <KobalteTooltip.Arrow data-slot="tooltip-arrow" /> */} diff --git a/packages/ui/src/pierre/commented-lines.ts b/packages/ui/src/pierre/commented-lines.ts index d2fa64866..e970b7841 100644 --- a/packages/ui/src/pierre/commented-lines.ts +++ b/packages/ui/src/pierre/commented-lines.ts @@ -1,5 +1,5 @@ import { type SelectedLineRange } from "@pierre/diffs" -import { diffLineIndex, diffRowIndex, findDiffSide } from "./diff-selection" +import { diffLineIndex, diffRowIndex } from "./diff-selection" export type CommentSide = "additions" | "deletions" diff --git a/packages/ui/src/pierre/worker.ts b/packages/ui/src/pierre/worker.ts index 1993ad7aa..d25dee4d9 100644 --- a/packages/ui/src/pierre/worker.ts +++ b/packages/ui/src/pierre/worker.ts @@ -25,7 +25,7 @@ function createPool(lineDiffType: "none" | "word-alt") { }, ) - pool.initialize() + void pool.initialize() return pool } diff --git a/packages/ui/src/styles/base.css b/packages/ui/src/styles/base.css index b5604ad61..a032f9ea2 100644 --- a/packages/ui/src/styles/base.css +++ b/packages/ui/src/styles/base.css @@ -82,7 +82,7 @@ a { cursor: default; } -*[data-tauri-drag-region] { +#root:not([aria-hidden]) *[data-tauri-drag-region] { app-region: drag; } diff --git a/packages/ui/vite.config.ts b/packages/ui/vite.config.ts index 335084bd6..1e38adede 100644 --- a/packages/ui/vite.config.ts +++ b/packages/ui/vite.config.ts @@ -36,10 +36,10 @@ function providerIconsPlugin() { return { name: "provider-icons-plugin", configureServer() { - fetchProviderIcons() + void fetchProviderIcons() }, buildStart() { - fetchProviderIcons() + void fetchProviderIcons() }, } } |
