fix(gui): expand thinking rows on click
This commit is contained in:
@@ -32,6 +32,7 @@ function ThinkRow({ text, running }: { text: string; running: boolean }) {
|
||||
summary={firstLine(text)}
|
||||
body={text}
|
||||
state={running ? 'running' : 'ok'}
|
||||
expandOnRowClick
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// no inline output (full results live in the details panel). Expand state is
|
||||
// component-local view state; row click hands the selection off to the owner.
|
||||
|
||||
import { useState, type ReactNode } from 'react'
|
||||
import { useState, type KeyboardEvent, type MouseEvent, type ReactNode } from 'react'
|
||||
import clsx from 'clsx'
|
||||
import { StateDot } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
@@ -20,6 +20,8 @@ export interface ToolRowProps {
|
||||
/** Expanded-body text; null = not expandable (leading slot never toggles). */
|
||||
body: string | null
|
||||
state: ToolRowState
|
||||
/** Makes the row itself the expand control instead of only its leading icon. */
|
||||
expandOnRowClick?: boolean | undefined
|
||||
/** Selection handoff (row click), already bound to this call by the owner. */
|
||||
onOpenDetails?: (() => void) | undefined
|
||||
}
|
||||
@@ -35,31 +37,56 @@ function leadingFor(state: ToolRowState, icon: ReactNode): ReactNode {
|
||||
}
|
||||
}
|
||||
|
||||
export function ToolRow({ variant, icon, title, summary, body, state, onOpenDetails }: ToolRowProps) {
|
||||
export function ToolRow({
|
||||
variant,
|
||||
icon,
|
||||
title,
|
||||
summary,
|
||||
body,
|
||||
state,
|
||||
expandOnRowClick = false,
|
||||
onOpenDetails,
|
||||
}: ToolRowProps) {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const expandable = body !== null
|
||||
const open = expanded && expandable
|
||||
const rowExpands = expandable && expandOnRowClick
|
||||
const toggleExpand = () => {
|
||||
setExpanded((v) => !v)
|
||||
}
|
||||
const toggleFromLeading = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
event.stopPropagation()
|
||||
toggleExpand()
|
||||
}
|
||||
const toggleFromKeyboard = (event: KeyboardEvent<HTMLDivElement>) => {
|
||||
if (!rowExpands || (event.key !== 'Enter' && event.key !== ' ')) return
|
||||
event.preventDefault()
|
||||
toggleExpand()
|
||||
}
|
||||
return (
|
||||
<div className={css.root} data-variant={variant} data-state={state}>
|
||||
<div
|
||||
className={css.row}
|
||||
data-clickable={onOpenDetails !== undefined || undefined}
|
||||
onClick={onOpenDetails}
|
||||
data-clickable={rowExpands || onOpenDetails !== undefined || undefined}
|
||||
role={rowExpands ? 'button' : undefined}
|
||||
tabIndex={rowExpands ? 0 : undefined}
|
||||
aria-expanded={rowExpands ? open : undefined}
|
||||
onClick={rowExpands ? toggleExpand : onOpenDetails}
|
||||
onKeyDown={rowExpands ? toggleFromKeyboard : undefined}
|
||||
>
|
||||
{expandable ? (
|
||||
{expandable && !rowExpands ? (
|
||||
<button
|
||||
type="button"
|
||||
className={css.leading}
|
||||
aria-expanded={open}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setExpanded((v) => !v)
|
||||
}}
|
||||
onClick={toggleFromLeading}
|
||||
>
|
||||
{open ? <IconChevronDownOutline14 className={clsx(css.chevron)} /> : leadingFor(state, icon)}
|
||||
</button>
|
||||
) : (
|
||||
<span className={css.leading}>{leadingFor(state, icon)}</span>
|
||||
<span className={css.leading}>
|
||||
{open ? <IconChevronDownOutline14 className={clsx(css.chevron)} /> : leadingFor(state, icon)}
|
||||
</span>
|
||||
)}
|
||||
<span className={css.title}>{title}</span>
|
||||
{!open && (
|
||||
|
||||
Reference in New Issue
Block a user