mirror of
https://github.com/anomalyco/opencode.git
synced 2026-04-24 06:45:22 +00:00
refactor(ui): standardize tool call variants
This commit is contained in:
@@ -4,19 +4,21 @@ import * as mod from "./basic-tool"
|
||||
import { create } from "../storybook/scaffold"
|
||||
|
||||
const docs = `### Overview
|
||||
Expandable tool panel with a structured trigger and optional details.
|
||||
Tool call surface with explicit row and panel variants.
|
||||
|
||||
Use structured triggers for consistent layout; custom triggers allowed.
|
||||
|
||||
### API
|
||||
- Required: \`icon\` and \`trigger\` (structured or custom JSX).
|
||||
- Optional: \`status\`, \`defaultOpen\`, \`forceOpen\`, \`defer\`, \`locked\`.
|
||||
- Required: \`variant\`, \`icon\`, and \`trigger\`.
|
||||
- Row tools render summary-only.
|
||||
- Panel/group tools support \`defaultOpen\`, \`forceOpen\`, \`defer\`, and \`locked\`.
|
||||
|
||||
### Variants and states
|
||||
- Pending/running status animates the title via TextShimmer.
|
||||
|
||||
### Behavior
|
||||
- Uses Collapsible; can defer content rendering until open.
|
||||
- Row tools skip collapsible state and render lightweight trigger-only markup.
|
||||
- Panel/group tools use Collapsible and can defer content rendering until open.
|
||||
- Locked state prevents closing.
|
||||
|
||||
### Accessibility
|
||||
@@ -28,13 +30,15 @@ Use structured triggers for consistent layout; custom triggers allowed.
|
||||
`
|
||||
|
||||
const story = create({
|
||||
title: "UI/Basic Tool",
|
||||
title: "UI/Tool Call",
|
||||
mod,
|
||||
name: "ToolCall",
|
||||
args: {
|
||||
variant: "panel",
|
||||
icon: "mcp",
|
||||
defaultOpen: true,
|
||||
trigger: {
|
||||
title: "Basic Tool",
|
||||
title: "Tool Call",
|
||||
subtitle: "Example subtitle",
|
||||
args: ["--flag", "value"],
|
||||
},
|
||||
@@ -43,8 +47,8 @@ const story = create({
|
||||
})
|
||||
|
||||
export default {
|
||||
title: "UI/Basic Tool",
|
||||
id: "components-basic-tool",
|
||||
title: "UI/Tool Call",
|
||||
id: "components-tool-call",
|
||||
component: story.meta.component,
|
||||
tags: ["autodocs"],
|
||||
parameters: {
|
||||
@@ -60,6 +64,7 @@ export const Basic = story.Basic
|
||||
|
||||
export const Pending = {
|
||||
args: {
|
||||
variant: "panel",
|
||||
status: "pending",
|
||||
trigger: {
|
||||
title: "Running tool",
|
||||
@@ -71,6 +76,7 @@ export const Pending = {
|
||||
|
||||
export const Locked = {
|
||||
args: {
|
||||
variant: "panel",
|
||||
locked: true,
|
||||
trigger: {
|
||||
title: "Locked tool",
|
||||
@@ -82,6 +88,7 @@ export const Locked = {
|
||||
|
||||
export const Deferred = {
|
||||
args: {
|
||||
variant: "panel",
|
||||
defer: true,
|
||||
defaultOpen: false,
|
||||
trigger: {
|
||||
@@ -94,6 +101,7 @@ export const Deferred = {
|
||||
|
||||
export const ForceOpen = {
|
||||
args: {
|
||||
variant: "panel",
|
||||
forceOpen: true,
|
||||
trigger: {
|
||||
title: "Forced open",
|
||||
@@ -103,14 +111,14 @@ export const ForceOpen = {
|
||||
},
|
||||
}
|
||||
|
||||
export const HideDetails = {
|
||||
export const Row = {
|
||||
args: {
|
||||
hideDetails: true,
|
||||
variant: "row",
|
||||
icon: "mcp",
|
||||
trigger: {
|
||||
title: "Summary only",
|
||||
subtitle: "Details hidden",
|
||||
subtitle: "Lightweight row",
|
||||
},
|
||||
children: "Hidden content",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -120,13 +128,14 @@ export const SubtitleAction = {
|
||||
return (
|
||||
<div style={{ display: "grid", gap: "8px" }}>
|
||||
<div style={{ "font-size": "12px", color: "var(--text-weak)" }}>{message()}</div>
|
||||
<mod.BasicTool
|
||||
<mod.ToolCall
|
||||
variant="panel"
|
||||
icon="mcp"
|
||||
trigger={{ title: "Clickable subtitle", subtitle: "Click me" }}
|
||||
onSubtitleClick={() => setMessage("Subtitle clicked")}
|
||||
>
|
||||
Subtitle action details
|
||||
</mod.BasicTool>
|
||||
</mod.ToolCall>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
import { createEffect, createSignal, For, Match, on, onCleanup, onMount, Show, Switch, type JSX } from "solid-js"
|
||||
import {
|
||||
createEffect,
|
||||
createSignal,
|
||||
For,
|
||||
Match,
|
||||
on,
|
||||
onCleanup,
|
||||
onMount,
|
||||
Show,
|
||||
splitProps,
|
||||
Switch,
|
||||
type JSX,
|
||||
} from "solid-js"
|
||||
import {
|
||||
animate,
|
||||
type AnimationPlaybackControls,
|
||||
@@ -26,7 +38,7 @@ const isTriggerTitle = (val: any): val is TriggerTitle => {
|
||||
)
|
||||
}
|
||||
|
||||
export interface BasicToolProps {
|
||||
interface ToolCallPanelBaseProps {
|
||||
icon: IconProps["name"]
|
||||
trigger: TriggerTitle | JSX.Element
|
||||
children?: JSX.Element
|
||||
@@ -44,7 +56,78 @@ export interface BasicToolProps {
|
||||
onSubtitleClick?: () => void
|
||||
}
|
||||
|
||||
export function BasicTool(props: BasicToolProps) {
|
||||
function ToolCallTriggerBody(props: {
|
||||
trigger: TriggerTitle | JSX.Element
|
||||
pending: boolean
|
||||
onSubtitleClick?: () => void
|
||||
arrow?: boolean
|
||||
}) {
|
||||
return (
|
||||
<div data-component="tool-trigger">
|
||||
<div data-slot="basic-tool-tool-trigger-content">
|
||||
<div data-slot="basic-tool-tool-info">
|
||||
<Switch>
|
||||
<Match when={isTriggerTitle(props.trigger) && props.trigger}>
|
||||
{(trigger) => (
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span
|
||||
data-slot="basic-tool-tool-title"
|
||||
classList={{
|
||||
[trigger().titleClass ?? ""]: !!trigger().titleClass,
|
||||
}}
|
||||
>
|
||||
<TextShimmer text={trigger().title} active={props.pending} />
|
||||
</span>
|
||||
<Show when={!props.pending}>
|
||||
<Show when={trigger().subtitle}>
|
||||
<span
|
||||
data-slot="basic-tool-tool-subtitle"
|
||||
classList={{
|
||||
[trigger().subtitleClass ?? ""]: !!trigger().subtitleClass,
|
||||
clickable: !!props.onSubtitleClick,
|
||||
}}
|
||||
onClick={(e) => {
|
||||
if (!props.onSubtitleClick) return
|
||||
e.stopPropagation()
|
||||
props.onSubtitleClick()
|
||||
}}
|
||||
>
|
||||
{trigger().subtitle}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={trigger().args?.length}>
|
||||
<For each={trigger().args}>
|
||||
{(arg) => (
|
||||
<span
|
||||
data-slot="basic-tool-tool-arg"
|
||||
classList={{
|
||||
[trigger().argsClass ?? ""]: !!trigger().argsClass,
|
||||
}}
|
||||
>
|
||||
{arg}
|
||||
</span>
|
||||
)}
|
||||
</For>
|
||||
</Show>
|
||||
</Show>
|
||||
</div>
|
||||
<Show when={!props.pending && trigger().action}>{trigger().action}</Show>
|
||||
</div>
|
||||
)}
|
||||
</Match>
|
||||
<Match when={true}>{props.trigger as JSX.Element}</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
<Show when={props.arrow}>
|
||||
<Collapsible.Arrow />
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function ToolCallPanel(props: ToolCallPanelBaseProps) {
|
||||
const [open, setOpen] = createSignal(props.defaultOpen ?? false)
|
||||
const [ready, setReady] = createSignal(open())
|
||||
const pending = () => props.status === "pending" || props.status === "running"
|
||||
@@ -197,68 +280,12 @@ export function BasicTool(props: BasicToolProps) {
|
||||
return (
|
||||
<Collapsible open={open()} onOpenChange={handleOpenChange} class="tool-collapsible">
|
||||
<Collapsible.Trigger>
|
||||
<div data-component="tool-trigger">
|
||||
<div data-slot="basic-tool-tool-trigger-content">
|
||||
<div data-slot="basic-tool-tool-info">
|
||||
<Switch>
|
||||
<Match when={isTriggerTitle(props.trigger) && props.trigger}>
|
||||
{(trigger) => (
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span
|
||||
data-slot="basic-tool-tool-title"
|
||||
classList={{
|
||||
[trigger().titleClass ?? ""]: !!trigger().titleClass,
|
||||
}}
|
||||
>
|
||||
<TextShimmer text={trigger().title} active={pending()} />
|
||||
</span>
|
||||
<Show when={!pending()}>
|
||||
<Show when={trigger().subtitle}>
|
||||
<span
|
||||
data-slot="basic-tool-tool-subtitle"
|
||||
classList={{
|
||||
[trigger().subtitleClass ?? ""]: !!trigger().subtitleClass,
|
||||
clickable: !!props.onSubtitleClick,
|
||||
}}
|
||||
onClick={(e) => {
|
||||
if (props.onSubtitleClick) {
|
||||
e.stopPropagation()
|
||||
props.onSubtitleClick()
|
||||
}
|
||||
}}
|
||||
>
|
||||
{trigger().subtitle}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={trigger().args?.length}>
|
||||
<For each={trigger().args}>
|
||||
{(arg) => (
|
||||
<span
|
||||
data-slot="basic-tool-tool-arg"
|
||||
classList={{
|
||||
[trigger().argsClass ?? ""]: !!trigger().argsClass,
|
||||
}}
|
||||
>
|
||||
{arg}
|
||||
</span>
|
||||
)}
|
||||
</For>
|
||||
</Show>
|
||||
</Show>
|
||||
</div>
|
||||
<Show when={!pending() && trigger().action}>{trigger().action}</Show>
|
||||
</div>
|
||||
)}
|
||||
</Match>
|
||||
<Match when={true}>{props.trigger as JSX.Element}</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
<Show when={props.children && !props.hideDetails && !props.locked && !pending()}>
|
||||
<Collapsible.Arrow />
|
||||
</Show>
|
||||
</div>
|
||||
<ToolCallTriggerBody
|
||||
trigger={props.trigger}
|
||||
pending={pending()}
|
||||
onSubtitleClick={props.onSubtitleClick}
|
||||
arrow={!!props.children && !props.hideDetails && !props.locked && !pending()}
|
||||
/>
|
||||
</Collapsible.Trigger>
|
||||
<Show when={props.animated && props.animate !== false && props.children && !props.hideDetails}>
|
||||
<div
|
||||
@@ -287,6 +314,67 @@ export function BasicTool(props: BasicToolProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export function GenericTool(props: { tool: string; status?: string; hideDetails?: boolean }) {
|
||||
return <BasicTool icon="mcp" status={props.status} trigger={{ title: props.tool }} hideDetails={props.hideDetails} />
|
||||
export interface ToolCallRowProps {
|
||||
variant: "row"
|
||||
icon: IconProps["name"]
|
||||
trigger: TriggerTitle | JSX.Element
|
||||
status?: string
|
||||
animate?: boolean
|
||||
onSubtitleClick?: () => void
|
||||
}
|
||||
|
||||
// `group` currently shares the same behavior as `panel`; the separate variant is semantic so grouped call sites can stay explicit.
|
||||
export interface ToolCallPanelProps extends Omit<ToolCallPanelBaseProps, "hideDetails"> {
|
||||
variant: "panel" | "group"
|
||||
}
|
||||
|
||||
export type ToolCallProps = ToolCallRowProps | ToolCallPanelProps
|
||||
function ToolCallRoot(props: ToolCallProps) {
|
||||
const [local, rest] = splitProps(props, ["variant", "trigger", "status", "onSubtitleClick"])
|
||||
const pending = () => local.status === "pending" || local.status === "running"
|
||||
if (local.variant === "row") {
|
||||
return (
|
||||
<div data-component="collapsible" data-variant="normal" class="tool-collapsible">
|
||||
<div data-slot="collapsible-trigger">
|
||||
<ToolCallTriggerBody trigger={local.trigger} pending={pending()} onSubtitleClick={local.onSubtitleClick} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ToolCallPanel {...rest} trigger={local.trigger} status={local.status} onSubtitleClick={local.onSubtitleClick} />
|
||||
)
|
||||
}
|
||||
|
||||
function ToolCallList(props: { children?: JSX.Element }) {
|
||||
return <div data-component="tool-call-list">{props.children}</div>
|
||||
}
|
||||
|
||||
function ToolCallRow(props: { children: JSX.Element }) {
|
||||
return (
|
||||
<div data-slot="tool-call-item">
|
||||
<div data-component="tool-trigger">
|
||||
<div data-slot="basic-tool-tool-trigger-content">
|
||||
<div data-slot="basic-tool-tool-info">{props.children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const ToolCall = Object.assign(ToolCallRoot, {
|
||||
List: ToolCallList,
|
||||
Row: ToolCallRow,
|
||||
})
|
||||
|
||||
export function GenericTool(props: { tool: string; status?: string; hideDetails?: boolean }) {
|
||||
return (
|
||||
<ToolCall
|
||||
variant={props.hideDetails ? "row" : "panel"}
|
||||
icon="mcp"
|
||||
status={props.status}
|
||||
trigger={{ title: props.tool }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -637,16 +637,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="context-tool-group-list"] {
|
||||
[data-component="context-tool-group-list"],
|
||||
[data-component="tool-call-list"] {
|
||||
margin-top: -4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0px;
|
||||
}
|
||||
|
||||
[data-slot="context-tool-group-item"] {
|
||||
min-width: 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
[data-component="context-tool-group-list"] [data-slot="context-tool-group-item"],
|
||||
[data-component="tool-call-list"] [data-slot="tool-call-item"] {
|
||||
min-width: 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
[data-component="diagnostics"] {
|
||||
|
||||
@@ -33,8 +33,7 @@ import { useData } from "../context"
|
||||
import { useFileComponent } from "../context/file"
|
||||
import { useDialog } from "../context/dialog"
|
||||
import { useI18n } from "../context/i18n"
|
||||
import { BasicTool } from "./basic-tool"
|
||||
import { GenericTool } from "./basic-tool"
|
||||
import { GenericTool, ToolCall } from "./basic-tool"
|
||||
import { Accordion } from "./accordion"
|
||||
import { StickyAccordionHeader } from "./sticky-accordion-header"
|
||||
import { Card } from "./card"
|
||||
@@ -653,7 +652,8 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean; animate?:
|
||||
const summary = createMemo(() => contextToolSummary(props.parts))
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="group"
|
||||
icon="magnifying-glass-menu"
|
||||
animated
|
||||
animate
|
||||
@@ -703,39 +703,33 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean; animate?:
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div data-component="context-tool-group-list">
|
||||
<ToolCall.List>
|
||||
<For each={props.parts}>
|
||||
{(part) => {
|
||||
const trigger = contextToolTrigger(part, i18n)
|
||||
const running = createMemo(() => busy(part.state.status))
|
||||
const reveal = useToolReveal(running, () => props.animate !== false)
|
||||
return (
|
||||
<div data-slot="context-tool-group-item">
|
||||
<div data-component="tool-trigger">
|
||||
<div data-slot="basic-tool-tool-trigger-content">
|
||||
<div data-slot="basic-tool-tool-info">
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span data-slot="basic-tool-tool-title">
|
||||
<TextShimmer text={trigger.title} active={running()} />
|
||||
</span>
|
||||
<Show when={trigger.subtitle}>{(text) => <ToolText text={text()} animate={reveal()} />}</Show>
|
||||
<Show when={trigger.args?.length}>
|
||||
<For each={trigger.args}>
|
||||
{(arg, idx) => <ToolArg text={arg} delay={0.02 * (idx() + 1)} animate={reveal()} />}
|
||||
</For>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ToolCall.Row>
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span data-slot="basic-tool-tool-title">
|
||||
<TextShimmer text={trigger.title} active={running()} />
|
||||
</span>
|
||||
<Show when={trigger.subtitle}>{(text) => <ToolText text={text()} animate={reveal()} />}</Show>
|
||||
<Show when={trigger.args?.length}>
|
||||
<For each={trigger.args}>
|
||||
{(arg, idx) => <ToolArg text={arg} delay={0.02 * (idx() + 1)} animate={reveal()} />}
|
||||
</For>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ToolCall.Row>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
</BasicTool>
|
||||
</ToolCall.List>
|
||||
</ToolCall>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1251,7 +1245,8 @@ ToolRegistry.register({
|
||||
const pending = createMemo(() => busy(props.status))
|
||||
return (
|
||||
<>
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="row"
|
||||
{...props}
|
||||
icon="glasses"
|
||||
trigger={
|
||||
@@ -1285,7 +1280,8 @@ ToolRegistry.register({
|
||||
const i18n = useI18n()
|
||||
const pending = createMemo(() => busy(props.status))
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
icon="bullet-list"
|
||||
trigger={
|
||||
@@ -1304,7 +1300,7 @@ ToolRegistry.register({
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -1315,7 +1311,8 @@ ToolRegistry.register({
|
||||
const i18n = useI18n()
|
||||
const pending = createMemo(() => busy(props.status))
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
icon="magnifying-glass-menu"
|
||||
trigger={
|
||||
@@ -1335,7 +1332,7 @@ ToolRegistry.register({
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -1349,7 +1346,8 @@ ToolRegistry.register({
|
||||
if (props.input.include) args.push("include=" + props.input.include)
|
||||
const pending = createMemo(() => busy(props.status))
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
icon="magnifying-glass-menu"
|
||||
trigger={
|
||||
@@ -1369,7 +1367,7 @@ ToolRegistry.register({
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -1623,9 +1621,9 @@ ToolRegistry.register({
|
||||
return value
|
||||
})
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="row"
|
||||
{...props}
|
||||
hideDetails
|
||||
icon="window-cursor"
|
||||
trigger={
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
@@ -1716,7 +1714,7 @@ ToolRegistry.register({
|
||||
</div>
|
||||
)
|
||||
|
||||
return <BasicTool icon="task" status={props.status} trigger={trigger()} hideDetails animate />
|
||||
return <ToolCall variant="row" icon="task" status={props.status} trigger={trigger()} animate />
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1753,7 +1751,8 @@ ToolRegistry.register({
|
||||
}
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
icon="console"
|
||||
animate
|
||||
@@ -1794,7 +1793,7 @@ ToolRegistry.register({
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -1811,7 +1810,8 @@ ToolRegistry.register({
|
||||
const reveal = useToolReveal(pending, () => props.reveal !== false)
|
||||
return (
|
||||
<div data-component="edit-tool">
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
icon="code-lines"
|
||||
animated
|
||||
@@ -1861,7 +1861,7 @@ ToolRegistry.register({
|
||||
</ToolFileAccordion>
|
||||
</Show>
|
||||
<DiagnosticsDisplay diagnostics={diagnostics()} />
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
@@ -1879,7 +1879,8 @@ ToolRegistry.register({
|
||||
const reveal = useToolReveal(pending, () => props.reveal !== false)
|
||||
return (
|
||||
<div data-component="write-tool">
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
icon="code-lines"
|
||||
animated
|
||||
@@ -1919,7 +1920,7 @@ ToolRegistry.register({
|
||||
</ToolFileAccordion>
|
||||
</Show>
|
||||
<DiagnosticsDisplay diagnostics={diagnostics()} />
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
@@ -1967,7 +1968,8 @@ ToolRegistry.register({
|
||||
|
||||
return (
|
||||
<div data-component="apply-patch-tool">
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
icon="code-lines"
|
||||
defer
|
||||
@@ -2122,7 +2124,7 @@ ToolRegistry.register({
|
||||
</ToolFileAccordion>
|
||||
)}
|
||||
</Show>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
@@ -2150,7 +2152,8 @@ ToolRegistry.register({
|
||||
})
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
defaultOpen
|
||||
icon="checklist"
|
||||
@@ -2179,7 +2182,7 @@ ToolRegistry.register({
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -2201,7 +2204,8 @@ ToolRegistry.register({
|
||||
})
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
{...props}
|
||||
defaultOpen={false}
|
||||
icon="bubble-5"
|
||||
@@ -2229,7 +2233,7 @@ ToolRegistry.register({
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -2252,6 +2256,6 @@ ToolRegistry.register({
|
||||
</div>
|
||||
)
|
||||
|
||||
return <BasicTool icon="brain" status={props.status} trigger={trigger()} hideDetails animate />
|
||||
return <ToolCall variant="row" icon="brain" status={props.status} trigger={trigger()} animate />
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import { createEffect, createSignal, onCleanup } from "solid-js"
|
||||
import { BasicTool } from "./basic-tool"
|
||||
import { ToolCall } from "./basic-tool"
|
||||
import { animate } from "motion"
|
||||
|
||||
export default {
|
||||
@@ -97,12 +97,7 @@ const ease = {
|
||||
linear: "linear",
|
||||
}
|
||||
|
||||
function SpringSubmessage(props: {
|
||||
text: string
|
||||
visible: boolean
|
||||
visualDuration: number
|
||||
bounce: number
|
||||
}) {
|
||||
function SpringSubmessage(props: { text: string; visible: boolean; visualDuration: number; bounce: number }) {
|
||||
let ref: HTMLSpanElement | undefined
|
||||
let widthRef: HTMLSpanElement | undefined
|
||||
|
||||
@@ -194,19 +189,15 @@ export const Playground = {
|
||||
>
|
||||
<style>{shellCss}</style>
|
||||
|
||||
<BasicTool
|
||||
<ToolCall
|
||||
variant="panel"
|
||||
icon="console"
|
||||
defaultOpen
|
||||
trigger={
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span data-slot="basic-tool-tool-title">Shell</span>
|
||||
<SpringSubmessage
|
||||
text={text()}
|
||||
visible={show()}
|
||||
visualDuration={visualDuration()}
|
||||
bounce={bounce()}
|
||||
/>
|
||||
<SpringSubmessage text={text()} visible={show()} visualDuration={visualDuration()} bounce={bounce()} />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -225,7 +216,7 @@ export const Playground = {
|
||||
>
|
||||
{"$ cat <<'TOPIC1'"}
|
||||
</div>
|
||||
</BasicTool>
|
||||
</ToolCall>
|
||||
|
||||
<div style={{ display: "flex", gap: "8px", "flex-wrap": "wrap" }}>
|
||||
<button onClick={replay} style={btn()}>
|
||||
|
||||
Reference in New Issue
Block a user