Next.js Discord

Discord Forum

Exclude HTML tag from MDX Code component

Answered
Paranoia posted this in #help-forum
Open in Discord
Hey! I created a MDX component to use with Velite. It's a copy button that's automatically beeing applied to every code component:
import CodeBlockWithCopy from "@/components/mdx/copy";

const components 
  code: CodeBlockWithCopy, // html tag: Component
};

interface MdxProps {
  code: string;
}

export function MDXContent({ code }: MdxProps) {
  const Component = useMDXComponent(code);
  return <Component components={components} />;
}

This works fine for code blocks (with three backticks) but doesnt with inlinecode (just a single backtick). The copy button is beeing added to the inline code as well and removes the default style from Tailwind Typography.
How can I exclude the inline code from my copy button component and keep the default tailwind typography styles and only add the button to code blocks?
[Heres all the code](https://github.com/paranoia8972/Blog)
Answered by Paranoia
I solved it after a lot of try and error. This is what I ended up with:
// src/components/mdx/mdx-components.tsx
const PreWithCodeBlock: React.FC<React.HTMLProps<HTMLPreElement>> = (props) => {
  const isCodeTag =
    React.Children.count(props.children) === 1 &&
    React.isValidElement(React.Children.toArray(props.children)[0]) &&
    (React.Children.toArray(props.children)[0] as React.ReactElement).type ===
      "code";

  if (isCodeTag) {
    const codeElement = React.Children.toArray(
      props.children,
    )[0] as React.ReactElement;
    return (
      <pre {...props}>
        <CodeBlockWithCopy {...codeElement.props} />
      </pre>
    );
  }

  return <pre {...props} />;
};

and
// src/components/mdx/mdx-components.tsx
const components = {
-  code: CodeBlockWithCopy,
+  pre: PreWithCodeBlock,
};
View full answer

2 Replies

I solved it after a lot of try and error. This is what I ended up with:
// src/components/mdx/mdx-components.tsx
const PreWithCodeBlock: React.FC<React.HTMLProps<HTMLPreElement>> = (props) => {
  const isCodeTag =
    React.Children.count(props.children) === 1 &&
    React.isValidElement(React.Children.toArray(props.children)[0]) &&
    (React.Children.toArray(props.children)[0] as React.ReactElement).type ===
      "code";

  if (isCodeTag) {
    const codeElement = React.Children.toArray(
      props.children,
    )[0] as React.ReactElement;
    return (
      <pre {...props}>
        <CodeBlockWithCopy {...codeElement.props} />
      </pre>
    );
  }

  return <pre {...props} />;
};

and
// src/components/mdx/mdx-components.tsx
const components = {
-  code: CodeBlockWithCopy,
+  pre: PreWithCodeBlock,
};
Answer
Thanks. Forgot it