feat(messages): code blocks get a Wrap toggle next to Copy (#131)
Verified upstream first: the Copy chip (with a 'Copied' state) already exists on every code block. Added the missing half: a Wrap chip that switches long lines to pre-wrap (default stays no-wrap + horizontal scroll); the choice is remembered for the session, not persisted. Markdown/HTML output, layout widths and the syntax theme are untouched. Verified headless: scrollWidth 1016 → 612 px with wrapping on, 'Copied' state on copy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -333,13 +333,10 @@ const extractTextFromChildren = (nodes: ChildNode[]): string => {
|
||||
return text;
|
||||
};
|
||||
|
||||
export function CodeBlock({
|
||||
children,
|
||||
opts,
|
||||
}: {
|
||||
children: ChildNode[];
|
||||
opts: HTMLReactParserOptions;
|
||||
}) {
|
||||
export // Session memory for the code-block Wrap toggle (#131).
|
||||
const codeWrapPreference = { value: false };
|
||||
|
||||
function CodeBlock({ children, opts }: { children: ChildNode[]; opts: HTMLReactParserOptions }) {
|
||||
const code = children[0];
|
||||
const attribs = code instanceof Element && code.name === 'code' ? code.attribs : undefined;
|
||||
const languageClass = attribs?.class;
|
||||
@@ -357,6 +354,13 @@ export function CodeBlock({
|
||||
|
||||
const [expanded, setExpand] = useState(false);
|
||||
const [copied, setCopied] = useTimeoutToggle();
|
||||
// [Gitea #131] Line-wrap toggle for long lines; the choice is remembered for
|
||||
// the session (module-level), not persisted.
|
||||
const [wrap, setWrap] = useState(codeWrapPreference.value);
|
||||
const toggleWrap = () => {
|
||||
codeWrapPreference.value = !wrap;
|
||||
setWrap(!wrap);
|
||||
};
|
||||
|
||||
const handleCopy = () => {
|
||||
copyToClipboard(extractTextFromChildren(children));
|
||||
@@ -376,6 +380,16 @@ export function CodeBlock({
|
||||
</Text>
|
||||
</Box>
|
||||
<Box shrink="No" gap="200">
|
||||
<Chip
|
||||
variant={wrap ? 'Primary' : 'Surface'}
|
||||
fill="None"
|
||||
radii="Pill"
|
||||
onClick={toggleWrap}
|
||||
aria-pressed={wrap}
|
||||
title={wrap ? 'Scroll long lines instead of wrapping' : 'Wrap long lines'}
|
||||
>
|
||||
<Text size="B300">Wrap</Text>
|
||||
</Chip>
|
||||
<Chip
|
||||
variant={copied ? 'Success' : 'Surface'}
|
||||
fill="None"
|
||||
@@ -410,7 +424,11 @@ export function CodeBlock({
|
||||
visibility="Hover"
|
||||
hideTrack
|
||||
>
|
||||
<div id="code-block-content" className={css.CodeBlockInternal}>
|
||||
<div
|
||||
id="code-block-content"
|
||||
className={css.CodeBlockInternal}
|
||||
style={wrap ? { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' } : undefined}
|
||||
>
|
||||
{domToReact(children as unknown as DOMNode[], opts)}
|
||||
</div>
|
||||
</Scroll>
|
||||
|
||||
Reference in New Issue
Block a user