Files
go-otel/otel-ui/src/components/common/CodeBlock.tsx
T
mats 8f670dfa2f
Build and Publish / Metadata (push) Successful in 2s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 1m26s
better otel i think
2026-09-19 19:14:51 +02:00

49 lines
2.0 KiB
TypeScript

import { useEffect, useRef } from "react"
import { EditorState } from "@codemirror/state"
import { EditorView, lineNumbers } from "@codemirror/view"
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language"
import { javascript } from "@codemirror/lang-javascript"
import { tags as t } from "@lezer/highlight"
const highlight = HighlightStyle.define([
{ tag: [t.keyword, t.modifier, t.operatorKeyword], color: "var(--ds-accent)" },
{ tag: [t.propertyName], color: "var(--ds-accent)" },
{ tag: [t.string, t.regexp], color: "var(--ds-ok)" },
{ tag: [t.number, t.bool, t.null], color: "var(--ds-warn)" },
{ tag: [t.comment], color: "var(--ds-text-3)", fontStyle: "italic" },
])
const theme = EditorView.theme({
"&": { backgroundColor: "var(--ds-bg)", color: "var(--ds-text-2)", fontSize: "12px" },
".cm-content": { fontFamily: "var(--font-data, ui-monospace, monospace)", padding: "6px 0" },
".cm-gutters": { backgroundColor: "var(--ds-bg)", color: "var(--ds-text-3)", border: "none" },
".cm-scroller": { overflow: "auto", maxHeight: "360px" },
})
/**
* Read-only CodeMirror view. JSON is valid JavaScript, so the JS grammar
* highlights it; `lang="text"` skips highlighting for plain log lines.
*/
export const CodeBlock = ({ code, lang = "json", label }: { code: string; lang?: "json" | "text"; label: string }) => {
const host = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!host.current) return
const view = new EditorView({
parent: host.current,
state: EditorState.create({
doc: code,
extensions: [
EditorState.readOnly.of(true),
EditorView.editable.of(false),
EditorView.lineWrapping,
lineNumbers(),
theme,
...(lang === "json" ? [javascript(), syntaxHighlighting(highlight)] : []),
],
}),
})
return () => view.destroy()
}, [code, lang])
return <div ref={host} role="group" aria-label={label} className="overflow-hidden rounded-[10px] border border-ds-line" />
}