fix(app): clarify skill timeline presentation (#42945)

This commit is contained in:
Luke Parker
2026-08-17 08:49:18 +10:00
committed by GitHub
parent fd2699b4d7
commit e73fa8f4b7
4 changed files with 43 additions and 13 deletions
@@ -59,6 +59,8 @@ test("renders current protocol notices in CLI order", async ({ page }) => {
await expect(notices.nth(1)).toContainText("explore finished · Search code")
await expect(notices.nth(2)).toContainText("Continuing after restart")
await expect(notices.nth(3)).toContainText("Skill · Review")
await expect(notices).toHaveClass([/text-text-weak/, /text-text-weak/, /text-text-weak/, /text-text-weak/])
await expect(notices.locator(".text-text-strong")).toHaveCount(0)
expect(ownerWarnings).toEqual([])
})
@@ -115,6 +115,12 @@ test("labels V2 skill tools from IDs and result metadata", async ({ page }) => {
"aria-label",
"OpenCode",
)
for (const id of [pending, completed]) {
const skill = page.locator(`[data-timeline-part-id="${id}"]`)
await expect(skill.locator('[data-slot="skill-tool-label"]')).toHaveText("Skill")
await expect(skill.locator('[data-slot="skill-tool-separator"]')).toHaveText("·")
await expect(skill.locator('use[href="#opencode-icon-post-skill"]')).toBeVisible()
}
})
function questionInput() {
@@ -1057,9 +1057,12 @@ function MessageTimelineView(
<TimelineRowFrame row={noticeRow()}>
<Show when={content()}>
{(content) => (
<div data-slot="session-timeline-notice" class={`w-full pt-3 pb-1 text-13-regular ${turnPadding()}`}>
<span class="text-13-medium text-text-strong">{content().label}</span>
<Show when={content().data}>{(data) => <span class="text-text-weak"> · {data()}</span>}</Show>
<div
data-slot="session-timeline-notice"
class={`w-full pt-3 pb-1 text-13-regular text-text-weak ${turnPadding()}`}
>
<span class="text-13-medium">{content().label}</span>
<Show when={content().data}>{(data) => <span> · {data()}</span>}</Show>
</div>
)}
</Show>
@@ -2637,21 +2637,40 @@ ToolRegistry.register({
name: "skill",
render(props) {
const i18n = useI18n()
const title = createMemo(() => skillToolName(props.input, props.metadata) || i18n.t("ui.tool.skill"))
const name = createMemo(() => skillToolName(props.input, props.metadata))
const running = createMemo(() => props.status === "pending" || props.status === "running")
const titleContent = () => <TextShimmer text={title()} active={running()} />
const trigger = () => (
<div data-slot="basic-tool-tool-info-structured">
<div data-slot="basic-tool-tool-info-main">
<span data-slot="basic-tool-tool-title" class="capitalize agent-title">
{titleContent()}
</span>
</div>
<div data-slot="skill-tool-trigger" class="flex min-w-0 items-center gap-1.5">
<Icon name="post-skill" size="small" class="shrink-0 text-v2-icon-icon-muted" />
<span
data-slot="skill-tool-label"
class="shrink-0 text-[13px] font-[530] leading-5 tracking-[-0.04px] text-v2-text-text-muted"
>
{i18n.t("ui.tool.skill")}
</span>
<Show when={name()}>
{(name) => (
<>
<span
data-slot="skill-tool-separator"
aria-hidden="true"
class="shrink-0 text-v2-text-text-muted"
>
·
</span>
<TextShimmer
as="bdi"
text={name()}
active={running()}
class="min-w-0 truncate text-[13px] font-[440] leading-5 tracking-[-0.04px] text-v2-text-text-muted"
/>
</>
)}
</Show>
</div>
)
return <BasicTool icon="brain" status={props.status} trigger={trigger()} hideDetails />
return <BasicTool icon="post-skill" status={props.status} trigger={trigger()} hideDetails />
},
})