diff --git a/src/app/components/editor/Elements.tsx b/src/app/components/editor/Elements.tsx
index a7438ecd..6a6659b9 100644
--- a/src/app/components/editor/Elements.tsx
+++ b/src/app/components/editor/Elements.tsx
@@ -162,7 +162,7 @@ export function RenderElement({ attributes, element, children }: RenderElementPr
visibility="Hover"
hideTrack
>
-
{children}
+ {children}
);
diff --git a/src/app/plugins/react-custom-html-parser.tsx b/src/app/plugins/react-custom-html-parser.tsx
index 057b0dff..f0cf9609 100644
--- a/src/app/plugins/react-custom-html-parser.tsx
+++ b/src/app/plugins/react-custom-html-parser.tsx
@@ -4,6 +4,8 @@ import React, {
ReactEventHandler,
Suspense,
lazy,
+ useCallback,
+ useMemo,
useState,
} from 'react';
import {
@@ -202,45 +204,103 @@ export const highlightText = (
);
});
-export function CodeBlock(children: ChildNode[], opts: HTMLReactParserOptions) {
- const [copied, setCopied] = useState(false);
- const [collapsed, setCollapsed] = useState(false);
-
- //HANDLECOPY FUNCTION HERE?
- const handleCopyClick = () => {
- //const codeText = extractTextFromChildren(children); // IDK HOW THIS SHOULD BE DONE
- //copyToClipboard(codeText);
-
- setCopied(true);
- };
+type CodeBlockControlsProps = {
+ copied: boolean;
+ onCopy: () => void;
+ collapsible: boolean;
+ collapsed: boolean;
+ onToggle: () => void;
+};
+function CodeBlockControls({
+ copied,
+ onCopy,
+ collapsible,
+ collapsed,
+ onToggle,
+}: CodeBlockControlsProps) {
return (
- // Probably need a better copy icon
- <>
-
+ // Needs a better copy icon
+
+
+
+
+ {collapsible && (
{
- handleCopyClick();
- }}
- >
-
-
- {
- setCollapsed(!collapsed);
- }}
+ onClick={onToggle}
+ aria-expanded={!collapsed}
+ aria-controls="code-block-content"
+ aria-label={collapsed ? 'Show Full Code Block' : 'Show Code Block Preview'}
+ style={collapsed ? { visibility: 'visible' } : {}}
>
-
-
- {domToReact(children, opts)}
+ )}
+
+ );
+}
+
+export function CodeBlock(children: ChildNode[], opts: HTMLReactParserOptions) {
+ const LINE_LIMIT = 14;
+
+ const extractTextFromChildren = useCallback((nodes: ChildNode[]): string => {
+ let text = '';
+
+ nodes.forEach((node) => {
+ if (node.type === 'text') {
+ text += node.data;
+ } else if (node instanceof Element && node.children) {
+ text += extractTextFromChildren(node.children);
+ }
+ });
+
+ return text;
+ }, []);
+
+ const [copied, setCopied] = useState(false);
+ const collapsible = useMemo(
+ () => extractTextFromChildren(children).split('\n').length > LINE_LIMIT,
+ [children, extractTextFromChildren]
+ );
+ const [collapsed, setCollapsed] = useState(collapsible);
+
+ const handleCopy = useCallback(() => {
+ copyToClipboard(extractTextFromChildren(children));
+ setCopied(true);
+ }, [children, extractTextFromChildren]);
+
+ const toggleCollapse = useCallback(() => {
+ setCollapsed((prev) => !prev);
+ }, []);
+
+ return (
+ <>
+
+
+
+ {domToReact(children, opts)}
+
>
);
@@ -321,8 +381,7 @@ export const getReactCustomHtmlParser = (
if (name === 'pre') {
return (
- //SHOULD ALL OF THIS BE IN A renderCodeBlock function? not text, but one layr down
-
+
{CodeBlock(children, opts)}
);
diff --git a/src/app/styles/CustomHtml.css.ts b/src/app/styles/CustomHtml.css.ts
index 95cb6dc5..e5e74b61 100644
--- a/src/app/styles/CustomHtml.css.ts
+++ b/src/app/styles/CustomHtml.css.ts
@@ -85,6 +85,7 @@ export const CodeBlock = style([
MarginSpaced,
{
fontStyle: 'normal',
+ position: 'relative',
},
]);
export const CodeBlockInternal = recipe({
@@ -98,8 +99,7 @@ export const CodeBlockInternal = recipe({
variants: {
collapsed: {
true: {
- maxHeight: config.space.S700, // should controls (collapse) be visible when collapsed? - yes, what's the best way to do this?
- overflow: 'hidden', // collapse should also only be visible if the doc has more than 1 line
+ maxHeight: `calc(${config.size.ModalDrawerWidth} - ${config.lineHeight.T400} / 2)`,
},
},
},
@@ -108,10 +108,10 @@ export const CodeBlockControls = style({
position: 'absolute',
top: config.space.S200,
right: config.space.S200,
- display: 'none',
+ visibility: 'hidden',
selectors: {
[`${CodeBlock}:hover &`]: {
- display: 'inline',
+ visibility: 'visible',
},
},
});