docs: share page add time footer back

This commit is contained in:
Jay V 2025-07-11 14:24:18 -04:00
parent 9ca54020ac
commit 2f1acee5a1
4 changed files with 128 additions and 86 deletions

View file

@ -364,7 +364,6 @@ export default function Share(props: {
<div data-section="part" data-part-type="summary">
<div data-section="decoration">
<span data-status={connectionStatus()[0]}></span>
<div></div>
</div>
<div data-section="content">
<p data-section="copy">{getStatusText(connectionStatus())}</p>

View file

@ -58,3 +58,20 @@ export function createOverflow() {
},
}
}
export function formatDuration(ms: number): string {
const ONE_SECOND = 1000
const ONE_MINUTE = 60 * ONE_SECOND
if (ms >= ONE_MINUTE) {
const minutes = Math.floor(ms / ONE_MINUTE)
return minutes === 1 ? `1min` : `${minutes}mins`
}
if (ms >= ONE_SECOND) {
const seconds = Math.floor(ms / ONE_SECOND)
return `${seconds}s`
}
return `${ms}ms`
}

View file

@ -101,7 +101,12 @@
}
[data-component="content"] {
flex: 1 1 auto;
min-width: 0;
padding: 0 0 0.375rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
[data-component="spacer"] {
@ -209,7 +214,6 @@
flex-direction: column;
align-items: flex-start;
gap: 0.375rem;
padding-bottom: 1rem;
&[data-tool="bash"] {
max-width: var(--sm-tool-width);

View file

@ -20,6 +20,7 @@ import {
IconDocumentMagnifyingGlass,
} from "../icons"
import { IconMeta, IconOpenAI, IconGemini, IconAnthropic } from "../icons/custom"
import { formatDuration } from "../share/common"
import { ContentCode } from "./content-code"
import { ContentDiff } from "./content-diff"
import { ContentText } from "./content-text"
@ -31,6 +32,8 @@ import type { Diagnostic } from "vscode-languageserver-types"
import styles from "./part.module.css"
const MIN_DURATION = 2
export interface PartProps {
index: number
message: MessageV2.Info
@ -161,95 +164,104 @@ export function Part(props: PartProps) {
{props.part.type === "tool" && props.part.state.status === "error" && (
<div data-component="tool" data-tool="error">
<ContentError>{formatErrorString(props.part.state.error)}</ContentError>
<Spacer />
</div>
)}
{props.part.type === "tool" &&
props.part.state.status === "completed" &&
props.message.role === "assistant" && (
<div data-component="tool" data-tool={props.part.tool}>
<Switch>
<Match when={props.part.tool === "grep"}>
<GrepTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "glob"}>
<GlobTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "list"}>
<ListTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "read"}>
<ReadTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "write"}>
<WriteTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "edit"}>
<EditTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "bash"}>
<BashTool
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
message={props.message}
/>
</Match>
<Match when={props.part.tool === "todowrite"}>
<TodoWriteTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "webfetch"}>
<WebFetchTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={true}>
<FallbackTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
</Switch>
</div>
<>
<div data-component="tool" data-tool={props.part.tool}>
<Switch>
<Match when={props.part.tool === "grep"}>
<GrepTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "glob"}>
<GlobTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "list"}>
<ListTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "read"}>
<ReadTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "write"}>
<WriteTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "edit"}>
<EditTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "bash"}>
<BashTool
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
message={props.message}
/>
</Match>
<Match when={props.part.tool === "todowrite"}>
<TodoWriteTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={props.part.tool === "webfetch"}>
<WebFetchTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
<Match when={true}>
<FallbackTool
message={props.message}
id={props.part.id}
tool={props.part.tool}
state={props.part.state}
/>
</Match>
</Switch>
</div>
<ToolFooter
time={
DateTime.fromMillis(props.message.time.completed || 0)
.diff(DateTime.fromMillis(props.message.time.created || 0))
.toMillis()
} />
</>
)}
</div>
</div>
@ -623,6 +635,16 @@ function Footer(props: ParentProps<{ title: string }>) {
)
}
function ToolFooter(props: { time: number }) {
return props.time > MIN_DURATION ? (
<Footer title={`${props.time}ms`}>
{formatDuration(props.time)}
</Footer>
) : (
<Spacer />
)
}
export function FallbackTool(props: ToolProps) {
return (
<>