fix: auto-detect dark mode in CodeBlock component
- Add useDarkMode hook that watches for .dark class on html element - Remove hardcoded #24292e color override that broke dark mode syntax highlighting - CodeBlock now auto-detects theme and uses vscDarkPlus style in dark mode - Theme prop is now optional, only override when explicitly needed
This commit is contained in:
parent
a137afd65d
commit
1efb9b0003
2 changed files with 35 additions and 8 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { cn } from '@tpmjs/utils/cn';
|
||||
import { forwardRef, useState } from 'react';
|
||||
import { forwardRef, useEffect, useState } from 'react';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
// eslint-disable-next-line import/no-internal-modules -- react-syntax-highlighter requires deep import for styles
|
||||
import { prism, vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
|
|
@ -11,6 +11,33 @@ import {
|
|||
codeBlockCopyButtonVariants,
|
||||
} from './variants';
|
||||
|
||||
/**
|
||||
* Hook to detect if dark mode is active by checking for .dark class on html element
|
||||
*/
|
||||
function useDarkMode(): boolean {
|
||||
const [isDark, setIsDark] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Check initial state
|
||||
const checkDarkMode = () => {
|
||||
setIsDark(document.documentElement.classList.contains('dark'));
|
||||
};
|
||||
|
||||
checkDarkMode();
|
||||
|
||||
// Watch for class changes on html element
|
||||
const observer = new MutationObserver(checkDarkMode);
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class'],
|
||||
});
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
return isDark;
|
||||
}
|
||||
|
||||
/**
|
||||
* CodeBlock component
|
||||
*
|
||||
|
|
@ -35,11 +62,12 @@ import {
|
|||
* ```
|
||||
*/
|
||||
export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
|
||||
(
|
||||
{ className, code, language = 'text', size = 'md', showCopy = true, theme = 'light', ...props },
|
||||
ref
|
||||
) => {
|
||||
({ className, code, language = 'text', size = 'md', showCopy = true, theme, ...props }, ref) => {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const isDarkMode = useDarkMode();
|
||||
|
||||
// Use provided theme or auto-detect from system
|
||||
const effectiveTheme = theme ?? (isDarkMode ? 'dark' : 'light');
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
|
|
@ -71,7 +99,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
|
|||
<div className={codeBlockCodeVariants({ size })} data-language={normalizedLanguage}>
|
||||
<SyntaxHighlighter
|
||||
language={normalizedLanguage}
|
||||
style={theme === 'dark' ? vscDarkPlus : prism}
|
||||
style={effectiveTheme === 'dark' ? vscDarkPlus : prism}
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
|
|
@ -82,7 +110,6 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
|
|||
codeTagProps={{
|
||||
style: {
|
||||
fontFamily: 'inherit',
|
||||
color: '#24292e', // Darker text color for better contrast
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export interface CodeBlockProps extends Omit<HTMLAttributes<HTMLDivElement>, 'ch
|
|||
|
||||
/**
|
||||
* Color theme for syntax highlighting
|
||||
* @default 'light'
|
||||
* If not provided, auto-detects from .dark class on html element
|
||||
*/
|
||||
theme?: 'light' | 'dark';
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue