From 0118aecde8a59dff0f03fd3202f873e8ba8e8f4d Mon Sep 17 00:00:00 2001 From: Priyanshu Thapliyal <114170980+Priyanshuthapliyal2005@users.noreply.github.com> Date: Thu, 11 Dec 2025 18:13:31 +0530 Subject: [PATCH] =?UTF-8?q?feat(code-block):=20add=20word=20wrap=20functio?= =?UTF-8?q?nality=20and=20controls=20to=20code=20bl=E2=80=A6=20(#39689)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(code-block): add word wrap functionality and controls to code blocks * feat(code-block): enhance layout of code block with improved line number display and structure * fix h-full issue * fix Prettier issue --------- Co-authored-by: Chris Chinchilla --- .../ui/CodeBlock/CodeBlock.client.tsx | 48 ++++++++++++++++- apps/docs/features/ui/CodeBlock/CodeBlock.tsx | 53 ++++++++++++------- apps/docs/styles/main.scss | 7 +++ 3 files changed, 87 insertions(+), 21 deletions(-) diff --git a/apps/docs/features/ui/CodeBlock/CodeBlock.client.tsx b/apps/docs/features/ui/CodeBlock/CodeBlock.client.tsx index 9b3ca95161f..a075ae9f2e0 100644 --- a/apps/docs/features/ui/CodeBlock/CodeBlock.client.tsx +++ b/apps/docs/features/ui/CodeBlock/CodeBlock.client.tsx @@ -1,10 +1,11 @@ 'use client' -import { Check, Copy } from 'lucide-react' -import { type MouseEvent, useCallback, useEffect, useState } from 'react' +import { Check, Copy, WrapText, ArrowRightFromLine } from 'lucide-react' +import { type MouseEvent, useCallback, useEffect, useState, useRef } from 'react' import { type ThemedToken } from 'shiki' import { type NodeHover } from 'twoslash' import { cn, copyToClipboard, Tooltip, TooltipContent, TooltipTrigger } from 'ui' +import { getFontStyle } from './CodeBlock.utils' export function AnnotatedSpan({ token, @@ -113,3 +114,46 @@ export function CodeCopyButton({ className, content }: { className?: string; con ) } + +export function CodeBlockControls({ content }: { content: string }) { + const [isWrapped, setIsWrapped] = useState(false) + const wrapperRef = useRef(null) + + const toggleWrap = useCallback(() => { + setIsWrapped((prev) => { + const newValue = !prev + // Find the parent code block and toggle the wrap data attribute + const codeBlock = wrapperRef.current?.closest('.shiki') + if (codeBlock) { + if (newValue) { + codeBlock.setAttribute('data-wrapped', 'true') + } else { + codeBlock.removeAttribute('data-wrapped') + } + } + return newValue + }) + }, []) + + return ( +
+ + + + + {isWrapped ? 'Disable word wrap' : 'Enable word wrap'} + + +
+ ) +} diff --git a/apps/docs/features/ui/CodeBlock/CodeBlock.tsx b/apps/docs/features/ui/CodeBlock/CodeBlock.tsx index 518171367c0..c79c416b9a6 100644 --- a/apps/docs/features/ui/CodeBlock/CodeBlock.tsx +++ b/apps/docs/features/ui/CodeBlock/CodeBlock.tsx @@ -1,9 +1,9 @@ -import { type PropsWithChildren } from 'react' +import { Fragment, type PropsWithChildren } from 'react' import { bundledLanguages, createHighlighter, type BundledLanguage, type ThemedToken } from 'shiki' import { createTwoslasher, type ExtraFiles, type NodeHover } from 'twoslash' import { cn } from 'ui' -import { AnnotatedSpan, CodeCopyButton } from './CodeBlock.client' +import { AnnotatedSpan, CodeBlockControls } from './CodeBlock.client' import { getFontStyle } from './CodeBlock.utils' import theme from './supabase-2.json' with { type: 'json' } import denoTypes from './types/lib.deno.d.ts.include' @@ -72,27 +72,42 @@ export async function CodeBlock({ )} >
-        
-          {lineNumbers && (
-            
- {tokens.map((_, idx) => ( -
- {idx + 1} -
+ + {lineNumbers ? ( + <> + {tokens.map((line, idx) => ( + +
+ {idx + 1} +
+
+ +
+
+ ))} + + ) : ( +
+ {tokens.map((line, idx) => ( + ))}
)} -
- {tokens.map((line, idx) => ( - - ))} -
- + ) } @@ -112,7 +127,7 @@ function CodeLine({ }) return ( - + {tokens.map((token) => twoslash?.has(token.offset) ? (