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="part" data-part-type="summary">
<div data-section="decoration"> <div data-section="decoration">
<span data-status={connectionStatus()[0]}></span> <span data-status={connectionStatus()[0]}></span>
<div></div>
</div> </div>
<div data-section="content"> <div data-section="content">
<p data-section="copy">{getStatusText(connectionStatus())}</p> <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"] { [data-component="content"] {
flex: 1 1 auto;
min-width: 0; min-width: 0;
padding: 0 0 0.375rem;
display: flex;
flex-direction: column;
gap: 1rem;
} }
[data-component="spacer"] { [data-component="spacer"] {
@ -209,7 +214,6 @@
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
gap: 0.375rem; gap: 0.375rem;
padding-bottom: 1rem;
&[data-tool="bash"] { &[data-tool="bash"] {
max-width: var(--sm-tool-width); max-width: var(--sm-tool-width);

View file

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