diff options
| author | Jay V <[email protected]> | 2025-06-18 14:10:07 -0400 |
|---|---|---|
| committer | Jay V <[email protected]> | 2025-06-18 14:10:14 -0400 |
| commit | 6e4ef585d8fe1d7a7a969ad463526cec2732a3cb (patch) | |
| tree | f301e29a781014aa2bf6b367eeac47df9f718090 /packages | |
| parent | e05c3b7a761632c573d08979530f261b136ad986 (diff) | |
| download | opencode-6e4ef585d8fe1d7a7a969ad463526cec2732a3cb.tar.gz opencode-6e4ef585d8fe1d7a7a969ad463526cec2732a3cb.zip | |
ignore: share error styles
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/web/src/components/Share.tsx | 114 | ||||
| -rw-r--r-- | packages/web/src/components/share.module.css | 41 |
2 files changed, 93 insertions, 62 deletions
diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx index ff2d4e825..3d392d886 100644 --- a/packages/web/src/components/Share.tsx +++ b/packages/web/src/components/Share.tsx @@ -172,13 +172,29 @@ function flattenToolArgs(obj: any, prefix: string = ""): Array<[string, any]> { return entries } -export function getDiagnostics( +function formatErrorString(error: string): JSX.Element { + const errorMarker = "Error: " + const startsWithError = error.startsWith(errorMarker) + + return startsWithError ? ( + <p> + <span data-color="red" data-marker="label" data-separator> + Error + </span> + <span>{error.slice(errorMarker.length)}</span> + </p> + ) : ( + <p><span data-color="dimmed">{error}</span></p> + ) +} + +function getDiagnostics( diagnosticsByFile: Record<string, Diagnostic[]>, currentFile: string -): string[] { +): JSX.Element[] { // Return a flat array of error diagnostics, in the format: - // "ERROR [65:20] Property 'x' does not exist on type 'Y'" - const result: string[] = [] + // "Error [65:20] Property 'x' does not exist on type 'Y'" + const result: JSX.Element[] = [] if ( diagnosticsByFile === undefined || diagnosticsByFile[currentFile] === undefined @@ -192,7 +208,15 @@ export function getDiagnostics( const line = d.range.start.line + 1 // 1-based const column = d.range.start.character + 1 // 1-based - result.push(`\x1b[31mERROR\x1b[0m \x1b[2m[${line}:${column}]\x1b[0m ${d.message}`) + result.push( + <p> + <span data-color="red" data-marker="label">Error</span> + <span data-color="dimmed" data-separator> + [{line}:{column}] + </span> + <span>{d.message}</span> + </p> + ) } } @@ -324,46 +348,44 @@ function TextPart(props: TextPartProps) { ) } -interface LspPartProps extends JSX.HTMLAttributes<HTMLDivElement> { - text: string +interface ErrorPartProps extends JSX.HTMLAttributes<HTMLDivElement> { expand?: boolean } -function LspPart(props: LspPartProps) { - const [local, rest] = splitProps(props, ["text", "expand"]) +function ErrorPart(props: ErrorPartProps) { + const [local, rest] = splitProps(props, ["expand", "children"]) const [expanded, setExpanded] = createSignal(false) const [overflowed, setOverflowed] = createSignal(false) let preEl: HTMLElement | undefined function checkOverflow() { - if (!preEl) return - - const code = preEl.getElementsByTagName("code")[0] - - if (code && !local.expand) { - setOverflowed(preEl.clientHeight < code.offsetHeight) + if (preEl && !local.expand) { + setOverflowed(preEl.scrollHeight > preEl.clientHeight + 1) } } onMount(() => { + checkOverflow() window.addEventListener("resize", checkOverflow) }) + createEffect(() => { + local.children + setTimeout(checkOverflow, 0) + }) + onCleanup(() => { window.removeEventListener("resize", checkOverflow) }) return ( <div - class={styles["message-lsp"]} + class={styles["message-error"]} data-expanded={expanded() || local.expand === true} {...rest} > - <CodeBlock - lang="ansi" - code={local.text} - onRendered={checkOverflow} - ref={(el) => (preEl = el)} - /> + <div data-section="content" ref={(el) => (preEl = el)}> + {local.children} + </div> {((!local.expand && overflowed()) || expanded()) && ( <button type="button" @@ -512,6 +534,7 @@ export default function Share(props: { info: SessionInfo messages: Record<string, SessionMessage> }) { + let hasScrolled = false const id = props.id const anchorId = createMemo<string | null>(() => { @@ -586,8 +609,9 @@ export default function Share(props: { const [, messageID] = splits setStore("messages", messageID, reconcile(d.content)) - if (messageID === anchorId()) { + if (!hasScrolled && messageID === anchorId()) { scrollToAnchor(window.location.hash.slice(1)) + hasScrolled = true } } } catch (error) { @@ -1241,12 +1265,9 @@ export default function Share(props: { <Switch> <Match when={hasError()}> <div data-part-tool-result> - <TextPart - expand - text={toolData()?.result} - data-size="sm" - data-color="dimmed" - /> + <ErrorPart> + {formatErrorString(toolData()?.result)} + </ErrorPart> </div> </Match> <Match when={preview()}> @@ -1339,19 +1360,14 @@ export default function Share(props: { <b>{filePath()}</b> </div> <Show when={diagnostics().length > 0}> - <LspPart - text={diagnostics().join("\n\n")} - /> + <ErrorPart>{diagnostics()}</ErrorPart> </Show> <Switch> <Match when={hasError()}> <div data-part-tool-result> - <TextPart - expand - text={toolData()?.result} - data-size="sm" - data-color="dimmed" - /> + <ErrorPart> + {formatErrorString(toolData()?.result)} + </ErrorPart> </div> </Match> <Match when={content()}> @@ -1429,12 +1445,9 @@ export default function Share(props: { <Switch> <Match when={hasError()}> <div data-part-tool-result> - <TextPart - expand - data-size="sm" - data-color="dimmed" - text={message()} - /> + <ErrorPart> + {formatErrorString(message())} + </ErrorPart> </div> </Match> <Match when={diff()}> @@ -1448,9 +1461,7 @@ export default function Share(props: { </Match> </Switch> <Show when={diagnostics().length > 0}> - <LspPart - text={diagnostics().join("\n\n")} - /> + <ErrorPart>{diagnostics()}</ErrorPart> </Show> </div> <ToolFooter time={toolData()?.duration || 0} /> @@ -1601,12 +1612,9 @@ export default function Share(props: { <Switch> <Match when={hasError()}> <div data-part-tool-result> - <TextPart - expand - text={toolData()?.result} - data-size="sm" - data-color="dimmed" - /> + <ErrorPart> + {formatErrorString(toolData()?.result)} + </ErrorPart> </div> </Match> <Match when={toolData()?.result}> diff --git a/packages/web/src/components/share.module.css b/packages/web/src/components/share.module.css index bcac00544..b216dbaf0 100644 --- a/packages/web/src/components/share.module.css +++ b/packages/web/src/components/share.module.css @@ -421,7 +421,7 @@ } } -.message-lsp { +.message-error { background-color: var(--sl-color-bg-surface); padding: 0.5rem calc(0.5rem + 3px); border-radius: 0.25rem; @@ -432,24 +432,47 @@ align-self: flex-start; max-width: var(--md-tool-width); - padding: 0.5rem calc(0.5rem + 3px); - - pre { - --shiki-dark-bg: var(--sl-color-bg-surface) !important; - background-color: var(--sl-color-bg-surface) !important; - line-height: 1.4; + [data-section="content"] { + p { + margin-bottom: 0.5rem; + line-height: 1.5; font-size: 0.75rem; white-space: pre-wrap; word-break: break-word; + + &:last-child { + margin-bottom: 0; + } + + span { + margin-right: 0.25rem; + &:last-child { + margin-right: 0; + } + } + span[data-color="red"] { + color: var(--sl-color-red); + } + span[data-color="dimmed"] { + color: var(--sl-color-text-dimmed); + } + span[data-marker="label"] { + text-transform: uppercase; + letter-spacing: -0.5px; + } + span[data-separator] { + margin-right: 0.375rem; + } } + } &[data-expanded="true"] { - pre { + [data-section="content"] { display: block; } } &[data-expanded="false"] { - pre { + [data-section="content"] { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 7; |
