A syntax-highlighted code block component with copy functionality and language detection
npm install @choice-ui/code-blockA flexible and feature-rich code block component with syntax highlighting, copy functionality, expand/collapse features, and comprehensive language support.
- šØ Syntax Highlighting: Powered by Shiki for accurate, VS Code-quality highlighting
- š Auto Theme Detection: Automatically adapts to system/app theme (light/dark)
- š Copy to Clipboard: One-click code copying with visual feedback
- š Expand/Collapse: Smart truncation for long code with expand controls
- šļø Language Icons: Automatic language detection with custom icons
- š i18n Support: Customizable labels and tooltips
- š Line Count Display: Shows total lines in header
- šÆ Compound Component: Flexible composition with Header, Content, and Footer
The CodeBlock component is part of the @choice-ui/react package.
``bash`
pnpm add @choice-ui/react
`tsx
import { CodeBlock } from "@choice-ui/react"
function App() {
const code = function hello() {
console.log('Hello, World!')
}
return (
)
}
`
`tsx`
filename="App.tsx"
>
Main container component that provides context to child components.
#### Props
| Prop | Type | Default | Description |
| --------------------- | ----------------------------- | -------- | -------------------------------------------- |
| language | string | "code" | Programming language for syntax highlighting |filename
| | string | - | Filename to display in header |lineThreshold
| | number | 20 | Line count threshold for showing footer |expandable
| | boolean | true | Enable expand/collapse functionality |defaultExpanded
| | boolean | true | Initial expanded state |defaultCodeExpanded
| | boolean | false | Initial code expansion state (for long code) |onExpandChange
| | (expanded: boolean) => void | - | Callback when expand state changes |onCodeExpandChange
| | (expanded: boolean) => void | - | Callback when code expansion changes |className
| | string | - | Additional CSS classes |
Displays filename, language icon, line count, and action buttons.
#### Props
| Prop | Type | Default | Description |
| --------------- | --------- | ------- | ---------------------------------------------- |
| showLineCount | boolean | true | Show line count indicator |i18n
| | object | - | Custom labels (copy, copied, expand, collapse) |className
| | string | - | Additional CSS classes |
#### i18n Object
`tsx`
{
copy: "Copy",
copied: "Copied",
expand: "Expand",
collapse: "Collapse"
}
Renders the syntax-highlighted code content.
#### Props
| Prop | Type | Default | Description |
| ---------------- | --------- | ------------ | ---------------------------- |
| code | string | required | Code content to display |withScrollArea
| | boolean | true | Enable scroll area container |className
| | string | - | Additional CSS classes |
Shows expand/collapse controls when code exceeds line threshold.
#### Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ---------------------- |
| className | string | - | Additional CSS classes |
The component automatically detects and applies syntax highlighting for numerous languages:
- JavaScript (js, jsx)
- TypeScript (ts, tsx, d.ts)
- HTML
- CSS, SCSS, Sass, Less
- JSON
- XML
- Python
- Java
- C, C++
- Go
- Rust
- PHP
- Ruby
- Node.js
- Markdown (md, mdx)
- YAML (yaml, yml)
- Shell (bash, sh, zsh)
- Plain text (text, txt)
And many more through Shiki's comprehensive language support.
The component displays language-specific icons in the header. Icons are automatically selected based on:
1. Filename extension: filename="App.tsx" ā TypeScript iconlanguage="python"
2. Language prop: ā Python icon
3. Fallback: Default code icon for unsupported languages
Currently supported icons:
- JavaScript/JSX
- TypeScript/TSX
- And more (extensible icon system)
`tsx`
filename="example.py"
defaultExpanded={false}
>
`tsx`
lineThreshold={10} // Show footer after 10 lines
>
`tsx`
`tsx`
filename="App.tsx"
>
copy: "å¤å¶",
copied: "å·²å¤å¶",
expand: "å±å¼",
collapse: "ęå ",
}}
/>
`tsx`
expandable={false}
>
The component automatically detects theme changes from:
- .dark class on elementdata-theme="dark"
- attribute on element
Theme switching is handled automatically using MutationObserver, providing seamless dark/light mode transitions.
- Syntax Highlighting Cache: Highlighted code is cached to improve performance
- Lazy Rendering: Uses React's memo for optimized re-renders
- Efficient Updates: Only re-highlights when code, language, or theme changes
- Semantic HTML structure
- Keyboard navigation support
- Copy button with visual feedback
- Expand/collapse controls with proper ARIA labels
1. Always specify language: Provides better syntax highlighting
`tsx`
2. Use filename for context: Helps users understand the code context
`tsx`
3. Set appropriate line threshold: Balance between space and usability
`tsx`
4. Provide i18n labels: For non-English applications
`tsx`
See the Storybook stories for comprehensive examples including:
- Different programming languages
- Long code with scrolling
- Expand/collapse functionality
- Custom themes and i18n
- Language-specific icons
- Shiki: Syntax highlighting engine
- React: UI framework
- Tailwind CSS: Styling via tailwind-variants
``
code-block/
āāā code-block.tsx # Main container component
āāā index.ts # Public exports
āāā types.ts # TypeScript definitions
āāā hooks/
ā āāā use-code-block.ts # Main logic hook
ā āāā use-theme.ts # Theme detection hook
ā āāā use-line-count.ts # Line counting hook
ā āāā use-scroll-detection.ts # Scroll state hook
āāā components/
ā āāā code-block-header.tsx # Header subcomponent
ā āāā code-block-content.tsx # Content subcomponent
ā āāā code-block-footer.tsx # Footer subcomponent
ā āāā code-block-code.tsx # Code renderer
āāā utils/
āāā language-icon-map.tsx # Icon mappings
āāā extract-code.ts # Code extraction utilities
When adding new language icons:
1. Add SVG to utils/language-icon-map.tsxlanguageIconMap`
2. Map language identifiers in
3. Update this README with the new language
Part of the ChoiceForm Design System.