@kushagradhawan/kookie-blocks 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,65 +1,396 @@
1
- import React, { type ReactNode } from "react";
2
- import { Card, Flex } from "@kushagradhawan/kookie-ui";
3
- import { SyntaxHighlighter } from "./SyntaxHighlighter";
4
- import { CopyButton } from "./CopyButton";
5
- import { LanguageBadge } from "./LanguageBadge";
6
- import { PreviewSection } from "./PreviewSection";
1
+ import React, { useState, useRef, useEffect, useCallback, memo, type ReactNode } from "react";
2
+ import { Box, Card, Flex, Button, Code, Theme } from "@kushagradhawan/kookie-ui";
3
+ import { HugeiconsIcon } from "@hugeicons/react";
4
+ import { Copy01Icon, Tick01Icon, ArrowDown01Icon } from "@hugeicons/core-free-icons";
5
+ import { codeToHtml } from "shiki";
7
6
  import type { CodeBlockProps } from "./types";
8
7
 
9
- function extractLanguageFromChildren(children?: ReactNode): string {
10
- if (!children) return "text";
11
-
12
- // Try to extract language from pre > code className
13
- if (typeof children === "object" && children !== null && "props" in children) {
14
- const childProps = (children as any).props;
15
-
16
- // If children is a <pre><code className="language-xxx">
17
- if (childProps?.children && typeof childProps.children === "object") {
18
- const codeProps = (childProps.children as any).props;
19
- const className = codeProps?.className || "";
20
- const match = className.match(/language-([\w-]+)/i);
21
- if (match) return match[1];
22
- }
8
+ const COLLAPSED_HEIGHT = 360;
9
+ const DEFAULT_LIGHT_THEME = "one-light";
10
+ const DEFAULT_DARK_THEME = "one-dark-pro";
11
+
12
+ // ============================================
13
+ // Preview Section
14
+ // ============================================
15
+
16
+ interface PreviewSectionProps {
17
+ children: ReactNode;
18
+ background?: "none" | "dots" | string;
19
+ backgroundProps?: {
20
+ dotSize?: number;
21
+ color?: string;
22
+ backgroundColor?: string;
23
+ height?: string;
24
+ width?: string;
25
+ radius?: string;
26
+ };
27
+ }
28
+
29
+ function PreviewSection({ children, background = "none", backgroundProps = {} }: PreviewSectionProps) {
30
+ const { dotSize = 24, color = "var(--gray-10)", backgroundColor = "var(--gray-2)", height, width = "100%", radius = "3" } = backgroundProps;
23
31
 
24
- // Direct className on children
25
- const className = childProps?.className || "";
26
- const match = className.match(/language-([\w-]+)/i);
27
- if (match) return match[1];
32
+ if (background === "none") {
33
+ return (
34
+ <Card size="1" variant="soft">
35
+ <Flex justify="center" align="center" py="4">
36
+ <Theme fontFamily="sans">{children}</Theme>
37
+ </Flex>
38
+ </Card>
39
+ );
28
40
  }
29
41
 
30
- return "text";
42
+ if (background === "dots") {
43
+ const dotsStyle: React.CSSProperties = {
44
+ backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1px)`,
45
+ borderRadius: `var(--radius-${radius})`,
46
+ backgroundSize: `${dotSize}px ${dotSize}px`,
47
+ backgroundPosition: "center",
48
+ backgroundColor,
49
+ width,
50
+ ...(height && { height }),
51
+ };
52
+
53
+ return (
54
+ <Card size="1" variant="soft">
55
+ <Flex justify="center" align="center" py="4" style={dotsStyle}>
56
+ <Theme fontFamily="sans">{children}</Theme>
57
+ </Flex>
58
+ </Card>
59
+ );
60
+ }
61
+
62
+ const imageStyle: React.CSSProperties = {
63
+ backgroundImage: `url(${background})`,
64
+ backgroundSize: "cover",
65
+ backgroundPosition: "center",
66
+ backgroundRepeat: "no-repeat",
67
+ borderRadius: `var(--radius-${radius})`,
68
+ width,
69
+ ...(height && { height }),
70
+ };
71
+
72
+ return (
73
+ <Card size="1" variant="soft">
74
+ <Flex justify="center" align="center" py="4" style={imageStyle}>
75
+ <Theme fontFamily="sans">{children}</Theme>
76
+ </Flex>
77
+ </Card>
78
+ );
31
79
  }
32
80
 
33
- function extractCodeFromChildren(children?: ReactNode): string {
34
- if (!children) return "";
81
+ // ============================================
82
+ // Code Section (for runtime highlighting)
83
+ // ============================================
35
84
 
36
- // Try to extract text from pre > code structure
37
- if (typeof children === "object" && children !== null && "props" in children) {
38
- const childProps = (children as any).props;
85
+ interface CodeSectionProps {
86
+ code: string;
87
+ language: string;
88
+ showCopy?: boolean;
89
+ showLanguage?: boolean;
90
+ lightTheme?: string;
91
+ darkTheme?: string;
92
+ }
39
93
 
40
- // If children is <pre><code>...</code></pre>
41
- if (childProps?.children && typeof childProps.children === "object") {
42
- const codeProps = (childProps.children as any).props;
43
- const codeChildren = codeProps?.children;
94
+ const CodeSection = memo(function CodeSection({
95
+ code,
96
+ language,
97
+ showCopy = true,
98
+ showLanguage = true,
99
+ lightTheme = DEFAULT_LIGHT_THEME,
100
+ darkTheme = DEFAULT_DARK_THEME,
101
+ }: CodeSectionProps) {
102
+ const [highlighted, setHighlighted] = useState<string | null>(null);
103
+ const [isExpanded, setIsExpanded] = useState(false);
104
+ const [contentHeight, setContentHeight] = useState(COLLAPSED_HEIGHT);
105
+ const [copied, setCopied] = useState(false);
106
+ const contentRef = useRef<HTMLDivElement>(null);
107
+ const resetTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
44
108
 
45
- if (typeof codeChildren === "string") {
46
- return codeChildren;
47
- }
109
+ const shouldShowToggle = contentHeight > COLLAPSED_HEIGHT;
110
+
111
+ useEffect(() => {
112
+ let cancelled = false;
113
+ codeToHtml(code, {
114
+ lang: language,
115
+ themes: { light: lightTheme, dark: darkTheme },
116
+ defaultColor: false,
117
+ })
118
+ .then((html) => {
119
+ if (!cancelled) setHighlighted(html);
120
+ })
121
+ .catch(() => {
122
+ if (!cancelled) setHighlighted(null);
123
+ });
124
+ return () => {
125
+ cancelled = true;
126
+ };
127
+ }, [code, language, lightTheme, darkTheme]);
128
+
129
+ useEffect(() => {
130
+ if (contentRef.current) {
131
+ setContentHeight(contentRef.current.scrollHeight);
48
132
  }
133
+ }, [highlighted]);
134
+
135
+ useEffect(() => {
136
+ return () => {
137
+ if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);
138
+ };
139
+ }, []);
49
140
 
50
- // Direct text content
51
- if (typeof childProps?.children === "string") {
52
- return childProps.children;
141
+ const handleCopy = useCallback(async () => {
142
+ if (!code.trim()) return;
143
+ try {
144
+ await navigator.clipboard.writeText(code);
145
+ setCopied(true);
146
+ if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);
147
+ resetTimeoutRef.current = setTimeout(() => setCopied(false), 2000);
148
+ } catch {
149
+ // Silently fail
53
150
  }
54
- }
151
+ }, [code]);
55
152
 
56
- if (typeof children === "string") {
57
- return children;
58
- }
153
+ const displayLanguage = language === "text" ? "plaintext" : language;
154
+
155
+ const handleToggle = useCallback(() => {
156
+ setIsExpanded((prev) => !prev);
157
+ }, []);
158
+
159
+ const contentStyle: React.CSSProperties = {
160
+ maxHeight: isExpanded ? `${contentHeight}px` : `${COLLAPSED_HEIGHT}px`,
161
+ };
162
+
163
+ const chevronStyle: React.CSSProperties = {
164
+ transform: isExpanded ? "rotate(180deg)" : "rotate(0deg)",
165
+ };
166
+
167
+ return (
168
+ <Box position="relative">
169
+ <Card size="1" variant="soft">
170
+ <Flex direction="column" gap="3">
171
+ <Flex gap="2" justify="between" align="start">
172
+ {showLanguage && (
173
+ <Code size="1" color="gray" highContrast>
174
+ {displayLanguage}
175
+ </Code>
176
+ )}
177
+ <Flex align="center" gap="2" className="code-action-buttons">
178
+ {shouldShowToggle && (
179
+ <Button
180
+ size="2"
181
+ variant="ghost"
182
+ color="gray"
183
+ onClick={handleToggle}
184
+ tooltip={isExpanded ? "Collapse" : "Expand"}
185
+ aria-label={isExpanded ? "Collapse code" : "Expand code"}
186
+ >
187
+ <HugeiconsIcon icon={ArrowDown01Icon} style={chevronStyle} className="code-chevron" />
188
+ </Button>
189
+ )}
190
+ {showCopy && (
191
+ <Button
192
+ size="2"
193
+ variant="ghost"
194
+ color="gray"
195
+ onClick={handleCopy}
196
+ tooltip={copied ? "Copied!" : "Copy"}
197
+ aria-label={copied ? "Copied!" : "Copy code"}
198
+ >
199
+ <HugeiconsIcon icon={copied ? Tick01Icon : Copy01Icon} /> Copy
200
+ </Button>
201
+ )}
202
+ </Flex>
203
+ </Flex>
204
+
205
+ <Box ref={contentRef} style={contentStyle} className="code-content">
206
+ {highlighted ? (
207
+ <Box className="code-block-content" width="100%" style={{ minWidth: 0 }} dangerouslySetInnerHTML={{ __html: highlighted }} />
208
+ ) : (
209
+ <pre className="code-block-content">
210
+ <Code size="3">{code}</Code>
211
+ </pre>
212
+ )}
213
+ </Box>
214
+
215
+ {shouldShowToggle && !isExpanded && <Box className="code-scroll-shadow visible" />}
216
+ </Flex>
217
+ </Card>
218
+ </Box>
219
+ );
220
+ });
221
+
222
+ // ============================================
223
+ // Children Code Section (for pre-highlighted MDX)
224
+ // ============================================
225
+
226
+ interface ChildrenCodeSectionProps {
227
+ children: ReactNode;
228
+ showCopy?: boolean;
229
+ showLanguage?: boolean;
230
+ }
59
231
 
60
- return "";
232
+ function extractCodeFromChildren(children?: ReactNode): string {
233
+ const extractText = (node: any): string => {
234
+ if (typeof node === "string") return node;
235
+ if (typeof node === "number") return String(node);
236
+ if (!node) return "";
237
+ if (Array.isArray(node)) return node.map(extractText).join("");
238
+ if (typeof node === "object" && "props" in node) {
239
+ const props = node.props;
240
+ if (props?.children) return extractText(props.children);
241
+ }
242
+ return "";
243
+ };
244
+ return extractText(children);
61
245
  }
62
246
 
247
+ function extractLanguageFromChildren(children?: ReactNode): string {
248
+ const findLanguage = (node: any): string | null => {
249
+ if (!node) return null;
250
+ if (typeof node === "object" && "props" in node) {
251
+ const props = node.props;
252
+ const className = props?.className || props?.class || "";
253
+ if (typeof className === "string") {
254
+ const match = className.match(/language-([\w-]+)/i);
255
+ if (match) return match[1];
256
+ }
257
+ if (props?.children) {
258
+ if (Array.isArray(props.children)) {
259
+ for (const child of props.children) {
260
+ const lang = findLanguage(child);
261
+ if (lang) return lang;
262
+ }
263
+ } else {
264
+ return findLanguage(props.children);
265
+ }
266
+ }
267
+ }
268
+ return null;
269
+ };
270
+ return findLanguage(children) || "text";
271
+ }
272
+
273
+ function formatLanguageLabel(lang: string): string {
274
+ const aliasMap: Record<string, string> = {
275
+ tsx: "TSX",
276
+ ts: "TS",
277
+ jsx: "JSX",
278
+ js: "JS",
279
+ javascript: "JS",
280
+ typescript: "TS",
281
+ css: "CSS",
282
+ html: "HTML",
283
+ json: "JSON",
284
+ bash: "SH",
285
+ sh: "SH",
286
+ shell: "SH",
287
+ text: "plaintext",
288
+ };
289
+ return aliasMap[lang.toLowerCase()] || lang.toLowerCase();
290
+ }
291
+
292
+ const ChildrenCodeSection = memo(function ChildrenCodeSection({ children, showCopy = true, showLanguage = true }: ChildrenCodeSectionProps) {
293
+ const [isExpanded, setIsExpanded] = useState(false);
294
+ const [contentHeight, setContentHeight] = useState(COLLAPSED_HEIGHT);
295
+ const [copied, setCopied] = useState(false);
296
+ const contentRef = useRef<HTMLDivElement>(null);
297
+ const resetTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
298
+
299
+ const code = extractCodeFromChildren(children);
300
+ const language = extractLanguageFromChildren(children);
301
+ const displayLanguage = formatLanguageLabel(language);
302
+
303
+ const shouldShowToggle = contentHeight > COLLAPSED_HEIGHT;
304
+
305
+ useEffect(() => {
306
+ if (contentRef.current) {
307
+ setContentHeight(contentRef.current.scrollHeight);
308
+ }
309
+ }, [children]);
310
+
311
+ useEffect(() => {
312
+ return () => {
313
+ if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);
314
+ };
315
+ }, []);
316
+
317
+ const handleCopy = useCallback(async () => {
318
+ if (!code.trim()) return;
319
+ try {
320
+ await navigator.clipboard.writeText(code);
321
+ setCopied(true);
322
+ if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);
323
+ resetTimeoutRef.current = setTimeout(() => setCopied(false), 2000);
324
+ } catch {
325
+ // Silently fail
326
+ }
327
+ }, [code]);
328
+
329
+ const contentStyle: React.CSSProperties = {
330
+ maxHeight: isExpanded ? `${contentHeight}px` : `${COLLAPSED_HEIGHT}px`,
331
+ };
332
+
333
+ const handleToggle = useCallback(() => {
334
+ setIsExpanded((prev) => !prev);
335
+ }, []);
336
+
337
+ const chevronStyle: React.CSSProperties = {
338
+ transform: isExpanded ? "rotate(180deg)" : "rotate(0deg)",
339
+ };
340
+
341
+ return (
342
+ <Box position="relative">
343
+ <Card size="1" variant="soft">
344
+ <Flex direction="column" gap="3">
345
+ <Flex gap="2" justify="between" align="start">
346
+ {showLanguage && (
347
+ <Code size="1" color="gray" highContrast>
348
+ {displayLanguage}
349
+ </Code>
350
+ )}
351
+ <Flex align="center" gap="2" className="code-action-buttons">
352
+ {shouldShowToggle && (
353
+ <Button
354
+ size="2"
355
+ variant="ghost"
356
+ color="gray"
357
+ onClick={handleToggle}
358
+ tooltip={isExpanded ? "Collapse" : "Expand"}
359
+ aria-label={isExpanded ? "Collapse code" : "Expand code"}
360
+ >
361
+ <HugeiconsIcon icon={ArrowDown01Icon} style={chevronStyle} className="code-chevron" />
362
+ </Button>
363
+ )}
364
+ {showCopy && (
365
+ <Button
366
+ size="2"
367
+ variant="ghost"
368
+ color="gray"
369
+ onClick={handleCopy}
370
+ tooltip={copied ? "Copied!" : "Copy"}
371
+ aria-label={copied ? "Copied!" : "Copy code"}
372
+ >
373
+ <HugeiconsIcon icon={copied ? Tick01Icon : Copy01Icon} /> Copy
374
+ </Button>
375
+ )}
376
+ </Flex>
377
+ </Flex>
378
+
379
+ <Box ref={contentRef} style={contentStyle} className="code-content">
380
+ <div className="code-block-content">{children}</div>
381
+ </Box>
382
+
383
+ {shouldShowToggle && !isExpanded && <Box className="code-scroll-shadow visible" />}
384
+ </Flex>
385
+ </Card>
386
+ </Box>
387
+ );
388
+ });
389
+
390
+ // ============================================
391
+ // Main CodeBlock Component
392
+ // ============================================
393
+
63
394
  export function CodeBlock({
64
395
  children,
65
396
  code,
@@ -72,48 +403,28 @@ export function CodeBlock({
72
403
  background,
73
404
  backgroundProps,
74
405
  }: CodeBlockProps) {
75
- // Determine the code and language to display
76
- let displayCode = code;
77
- let displayLanguage = language;
78
-
79
- // If children are provided (pre-highlighted from MDX), extract code and language
80
- if (children && !code) {
81
- displayCode = extractCodeFromChildren(children);
82
- displayLanguage = language || extractLanguageFromChildren(children);
83
- }
84
-
85
- // Default language
86
- if (!displayLanguage) {
87
- displayLanguage = "text";
88
- }
89
-
90
- // If no code to display, render nothing
91
- if (!displayCode && !children) {
92
- return null;
93
- }
406
+ const hasCode = code || (children && React.Children.count(children) > 0);
407
+ const displayLanguage = language || extractLanguageFromChildren(children) || "text";
94
408
 
95
409
  return (
96
- <Flex direction="column" className="code-block-wrapper" style={{ minWidth: 0 }} my="2">
97
- {preview && (
98
- <PreviewSection background={background} backgroundProps={backgroundProps}>
99
- {preview}
100
- </PreviewSection>
101
- )}
102
-
103
- <Card size="2" variant="soft">
104
- <Flex gap="2" direction="column">
105
- <Flex align="start" justify="between">
106
- {showLanguage && <LanguageBadge language={displayLanguage} />}
107
- {showCopy && displayCode && <CopyButton code={displayCode} />}
108
- </Flex>
410
+ <Box className="docs-code-block" mt="6" mb="8">
411
+ <Flex direction="column" gap="2">
412
+ {preview && (
413
+ <PreviewSection background={background} backgroundProps={backgroundProps}>
414
+ {preview}
415
+ </PreviewSection>
416
+ )}
109
417
 
110
- {/* If we have runtime code, use SyntaxHighlighter */}
111
- {code && <SyntaxHighlighter code={code} language={displayLanguage} lightTheme={lightTheme} darkTheme={darkTheme} />}
418
+ {code && (
419
+ <CodeSection code={code} language={displayLanguage} showCopy={showCopy} showLanguage={showLanguage} lightTheme={lightTheme} darkTheme={darkTheme} />
420
+ )}
112
421
 
113
- {/* If we have pre-highlighted children from MDX, render them */}
114
- {children && !code && <div className="code-block-content">{children}</div>}
115
- </Flex>
116
- </Card>
117
- </Flex>
422
+ {children && !code && (
423
+ <ChildrenCodeSection showCopy={showCopy} showLanguage={showLanguage}>
424
+ {children}
425
+ </ChildrenCodeSection>
426
+ )}
427
+ </Flex>
428
+ </Box>
118
429
  );
119
430
  }
@@ -15,7 +15,7 @@ interface PreviewSectionProps {
15
15
  }
16
16
 
17
17
  export function PreviewSection({ children, background = "none", backgroundProps = {} }: PreviewSectionProps) {
18
- const { dotSize = 24, color = "var(--gray-10)", backgroundColor = "var(--gray-2)", height = "300px", width = "100%", radius = "3" } = backgroundProps;
18
+ const { dotSize = 24, color = "var(--gray-10)", backgroundColor = "var(--gray-2)", height, width = "100%", radius = "3" } = backgroundProps;
19
19
 
20
20
  // Render with no background (default card styling)
21
21
  if (background === "none") {
@@ -36,8 +36,8 @@ export function PreviewSection({ children, background = "none", backgroundProps
36
36
  backgroundSize: `${dotSize}px ${dotSize}px`,
37
37
  backgroundPosition: "center",
38
38
  backgroundColor,
39
- height,
40
39
  width,
40
+ ...(height && { height }),
41
41
  };
42
42
 
43
43
  return (
@@ -56,8 +56,8 @@ export function PreviewSection({ children, background = "none", backgroundProps
56
56
  backgroundPosition: "center",
57
57
  backgroundRepeat: "no-repeat",
58
58
  borderRadius: `var(--radius-${radius})`,
59
- height,
60
59
  width,
60
+ ...(height && { height }),
61
61
  };
62
62
 
63
63
  return (
@@ -1,15 +1,19 @@
1
- /* Components CSS aggregator for Kookie Blocks (e.g., hero variants if styled). */
1
+ /* Components CSS aggregator for Kookie Blocks */
2
2
 
3
3
  /* ============================================
4
4
  Code Block Component Styles
5
5
  ============================================ */
6
6
 
7
- /* Code block wrapper - constrain width in flex containers */
8
- .code-block-wrapper {
9
- min-width: 0;
10
- max-width: 100%;
7
+ /* Main docs code block wrapper */
8
+ .docs-code-block {
11
9
  width: 100%;
10
+ }
11
+
12
+ /* Code content area - handles expand/collapse */
13
+ .code-content {
12
14
  overflow: hidden;
15
+ transition: max-height 0.3s ease-in-out;
16
+ position: relative;
13
17
  }
14
18
 
15
19
  /* Code block content (the pre part, below the header) */
@@ -52,14 +56,17 @@
52
56
  height: 0 !important;
53
57
  }
54
58
 
55
- .code-block-wrapper pre,
56
- .code-block-wrapper .code-block-content pre {
57
- overflow-x: visible; /* Let .code-block-content handle scrolling */
59
+ /* Pre elements inside code content */
60
+ .code-content pre,
61
+ .code-block-content pre {
62
+ overflow-x: visible;
58
63
  max-width: 100%;
59
64
  min-width: 0;
60
65
  margin: 0;
61
66
  width: 100%;
62
67
  box-sizing: border-box;
68
+ scrollbar-width: none;
69
+ -ms-overflow-style: none;
63
70
  }
64
71
 
65
72
  /* Ensure Shiki-generated pre elements fill width */
@@ -69,8 +76,8 @@
69
76
  }
70
77
 
71
78
  /* Code elements inside pre */
72
- .code-block-wrapper pre code,
73
- .code-block-wrapper .code-block-content pre code {
79
+ .code-content pre code,
80
+ .code-block-content pre code {
74
81
  font-family: var(--font-mono);
75
82
  font-size: var(--font-size-2);
76
83
  line-height: 1.75;
@@ -82,16 +89,16 @@
82
89
  }
83
90
 
84
91
  /* Shiki line spans */
85
- .code-block-wrapper pre code .line,
86
- .code-block-wrapper .code-block-content pre code .line {
92
+ .code-content pre code .line,
93
+ .code-block-content pre code .line {
87
94
  display: flex;
88
95
  align-items: center;
89
96
  gap: 0;
90
97
  }
91
98
 
92
99
  /* Line numbers */
93
- .code-block-wrapper pre code .line::before,
94
- .code-block-wrapper .code-block-content pre code .line::before {
100
+ .code-content pre code .line::before,
101
+ .code-block-content pre code .line::before {
95
102
  counter-increment: line;
96
103
  content: counter(line);
97
104
  display: inline-block;
@@ -104,8 +111,37 @@
104
111
  margin-right: var(--space-4);
105
112
  }
106
113
 
114
+ /* Scroll shadow overlay for collapsed state */
115
+ .code-scroll-shadow {
116
+ position: absolute;
117
+ bottom: 0;
118
+ left: 0;
119
+ right: 0;
120
+ height: 80px;
121
+ background: linear-gradient(to top, var(--color-panel-solid), transparent);
122
+ pointer-events: none;
123
+ opacity: 0;
124
+ transition: opacity 0.2s ease-in-out;
125
+ z-index: 1;
126
+ }
127
+
128
+ .code-scroll-shadow.visible {
129
+ opacity: 1;
130
+ }
131
+
132
+ /* Action buttons styling */
133
+ .code-action-buttons {
134
+ flex-shrink: 0;
135
+ }
136
+
137
+ /* Chevron rotation animation */
138
+ .code-chevron {
139
+ transition: transform 0.2s ease-in-out;
140
+ }
141
+
107
142
  /* Default to light theme for all tokens (codeToHtml with defaultColor: false) */
108
- .code-block-wrapper pre.shiki span {
143
+ .code-block-content pre.shiki span,
144
+ .code-content pre.shiki span {
109
145
  color: var(--shiki-light) !important;
110
146
  font-style: var(--shiki-light-font-style);
111
147
  font-weight: var(--shiki-light-font-weight);
@@ -113,9 +149,12 @@
113
149
  }
114
150
 
115
151
  /* Override with dark theme colors when inside a dark context */
116
- .dark .code-block-wrapper pre.shiki span,
117
- .dark-theme .code-block-wrapper pre.shiki span,
118
- [data-appearance="dark"] .code-block-wrapper pre.shiki span {
152
+ .dark .code-block-content pre.shiki span,
153
+ .dark-theme .code-block-content pre.shiki span,
154
+ [data-appearance="dark"] .code-block-content pre.shiki span,
155
+ .dark .code-content pre.shiki span,
156
+ .dark-theme .code-content pre.shiki span,
157
+ [data-appearance="dark"] .code-content pre.shiki span {
119
158
  color: var(--shiki-dark) !important;
120
159
  font-style: var(--shiki-dark-font-style);
121
160
  font-weight: var(--shiki-dark-font-weight);