docs: share page fix terminal part

This commit is contained in:
Jay V 2025-07-10 17:21:18 -04:00
parent 1c4fd7f28f
commit c7f30e1065
4 changed files with 175 additions and 95 deletions

View file

@ -0,0 +1,92 @@
.root {
width: 100%;
max-width: var(--sm-tool-width);
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
[data-slot="expand-button"] {
flex: 0 0 auto;
padding: 2px 0;
font-size: 0.75rem;
}
[data-slot="body"] {
display: flex;
flex-direction: column;
border: 1px solid var(--sl-color-divider);
border-radius: 0.25rem;
overflow: hidden;
width: 100%;
}
[data-slot="header"] {
position: relative;
border-bottom: 1px solid var(--sl-color-divider);
width: 100%;
height: 1.625rem;
text-align: center;
padding: 0 3.25rem;
> span {
max-width: min(100%, 140ch);
display: inline-block;
white-space: nowrap;
overflow: hidden;
line-height: 1.625rem;
font-size: 0.75rem;
text-overflow: ellipsis;
color: var(--sl-color-text-dimmed);
}
&::before {
content: "";
position: absolute;
pointer-events: none;
top: 8px;
left: 10px;
width: 2rem;
height: 0.5rem;
line-height: 0;
background-color: var(--sl-color-hairline);
mask-image: var(--term-icon);
mask-repeat: no-repeat;
}
}
[data-slot="content"] {
display: flex;
flex-direction: column;
padding: 0.5rem calc(0.5rem + 3px);
pre {
--shiki-dark-bg: var(--sl-color-bg) !important;
background-color: var(--sl-color-bg) !important;
line-height: 1.6;
font-size: 0.75rem;
white-space: pre-wrap;
word-break: break-word;
margin: 0;
span {
white-space: break-spaces;
}
}
}
[data-slot="output"] {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 10;
line-clamp: 10;
overflow: hidden;
}
&[data-expanded] [data-slot="output"] {
display: block;
-webkit-line-clamp: none;
line-clamp: none;
overflow: visible;
}
}

View file

@ -0,0 +1,67 @@
import style from "./content-bash.module.css"
import { createResource, createSignal } from "solid-js"
import { createOverflow } from "./common"
import { codeToHtml } from "shiki"
interface Props {
command: string
output: string
description?: string
expand?: boolean
}
export function ContentBash(props: Props) {
const [commandHtml] = createResource(
() => props.command,
async (command) => {
return codeToHtml(command || "", {
lang: "bash",
themes: {
light: "github-light",
dark: "github-dark",
},
})
},
)
const [outputHtml] = createResource(
() => props.output,
async (output) => {
return codeToHtml(output || "", {
lang: "console",
themes: {
light: "github-light",
dark: "github-dark",
},
})
},
)
const [expanded, setExpanded] = createSignal(false)
const overflow = createOverflow()
return (
<div class={style.root} data-expanded={expanded() || props.expand === true ? true : undefined}>
<div data-slot="body">
<div data-slot="header">
<span>{props.description}</span>
</div>
<div data-slot="content">
<div innerHTML={commandHtml()} />
<div data-slot="output" ref={overflow.ref} innerHTML={outputHtml()} />
</div>
</div>
{!props.expand && overflow.status && (
<button
type="button"
data-component="text-button"
data-slot="expand-button"
onClick={() => setExpanded((e) => !e)}
>
{expanded() ? "Show less" : "Show more"}
</button>
)}
</div>
)
}

View file

@ -307,68 +307,6 @@
}
}
[data-component="terminal"] {
width: 100%;
max-width: var(--sm-tool-width);
[data-slot="body"] {
display: flex;
flex-direction: column;
border: 1px solid var(--sl-color-divider);
border-radius: 0.25rem;
overflow: hidden;
}
[data-slot="header"] {
position: relative;
border-bottom: 1px solid var(--sl-color-divider);
width: 100%;
height: 1.625rem;
text-align: center;
padding: 0 3.25rem;
> span {
max-width: min(100%, 140ch);
display: inline-block;
white-space: nowrap;
overflow: hidden;
line-height: 1.625rem;
font-size: 0.75rem;
text-overflow: ellipsis;
color: var(--sl-color-text-dimmed);
}
&::before {
content: "";
position: absolute;
pointer-events: none;
top: 8px;
left: 10px;
width: 2rem;
height: 0.5rem;
line-height: 0;
background-color: var(--sl-color-hairline);
mask-image: var(--term-icon);
mask-repeat: no-repeat;
}
}
[data-slot="content"] {
display: flex;
flex-direction: column;
padding: 0.5rem calc(0.5rem + 3px);
pre {
--shiki-dark-bg: var(--sl-color-bg) !important;
background-color: var(--sl-color-bg) !important;
line-height: 1.6;
font-size: 0.75rem;
white-space: pre-wrap;
word-break: break-word;
}
}
}
[data-component="tool-args"] {
display: inline-grid;
align-items: center;

View file

@ -1,15 +1,6 @@
import map from "lang-map"
import { DateTime } from "luxon"
import {
For,
Show,
Match,
Switch,
type JSX,
createMemo,
createSignal,
type ParentProps
} from "solid-js"
import { For, Show, Match, Switch, type JSX, createMemo, createSignal, type ParentProps } from "solid-js"
import {
IconHashtag,
IconSparkles,
@ -34,6 +25,7 @@ import { ContentDiff } from "./content-diff"
import { ContentText } from "./content-text"
import { ContentError } from "./content-error"
import { ContentMarkdown } from "./content-markdown"
import { ContentBash } from "./content-bash"
import type { MessageV2 } from "opencode/session/message-v2"
import type { Diagnostic } from "vscode-languageserver-types"
@ -83,8 +75,10 @@ export function Part(props: PartProps) {
<Match when={props.message.role === "user" && props.part.type === "file"}>
<IconPaperClip width={18} height={18} />
</Match>
<Match when={props.part.type === "step-start" && props.message.role === "assistant" && props.message.modelID}>
{model => <ProviderIcon model={model()} size={18} />}
<Match
when={props.part.type === "step-start" && props.message.role === "assistant" && props.message.modelID}
>
{(model) => <ProviderIcon model={model()} size={18} />}
</Match>
<Match when={props.part.type === "tool" && props.part.tool === "todowrite"}>
<IconQueueList width={18} height={18} />
@ -164,14 +158,11 @@ export function Part(props: PartProps) {
<div data-slot="model">{props.message.modelID}</div>
</div>
)}
{props.part.type === "tool" &&
props.part.state.status === "error" && (
<div data-component="tool">
<ContentError>
{formatErrorString(props.part.state.error)}
</ContentError>
</div>
)}
{props.part.type === "tool" && props.part.state.status === "error" && (
<div data-component="tool">
<ContentError>{formatErrorString(props.part.state.error)}</ContentError>
</div>
)}
{props.part.type === "tool" &&
props.part.state.status === "completed" &&
props.message.role === "assistant" && (
@ -565,19 +556,11 @@ export function EditTool(props: ToolProps) {
export function BashTool(props: ToolProps) {
return (
<>
<div data-component="terminal" data-size="sm">
<div data-slot="body">
<div data-slot="header">
<span>{props.state.metadata.description}</span>
</div>
<div data-slot="content">
<ContentCode flush lang="bash" code={props.state.input.command} />
<ContentCode flush lang="console" code={props.state.metadata?.stdout || ""} />
</div>
</div>
</div>
</>
<ContentBash
command={props.state.input.command}
output={props.state.metadata?.stdout || ""}
description={props.state.metadata.description}
/>
)
}