Code Mentions

Add a language picker when you need to switch between languages in a code block.

content.mdx
<HoverContainer>
The [base case](hover:one) returns 1.
```cpp
int factorial(int n) {
if (n == 0) {
// !hover one
return 1;
} else {
// !hover two
return n * factorial(n - 1);
}
}
```
The [recursive case](hover:two) multiplies something.
</HoverContainer>

The base case returns 1.

int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}

The recursive case multiplies something.

Hover the mentions

Implementation

code.tsx
import {
AnnotationHandler,
InnerLine,
Pre,
RawCode,
highlight,
} from "codehike/code"
import React from "react"
import Content from "./content.mdx"
import "./styles.css"
export default function Page() {
return <Content components={{ HoverContainer, a: Link, Code }} />
}
function HoverContainer(props: { children: React.ReactNode }) {
return <div className="hover-container">{props.children}</div>
}
function Link(props: { href?: string; children?: React.ReactNode }) {
if (props.href?.startsWith("hover:")) {
const hover = props.href.slice("hover:".length)
return (
<span
className=""
data-hover={hover}
>
{props.children}
</span>
)
} else {
return <a {...props} />
}
}
async function Code({ codeblock }: { codeblock: RawCode }) {
const highlighted = await highlight(codeblock, "github-dark")
return <Pre code={highlighted} handlers={[hover]} />
}
const hover: AnnotationHandler = {
name: "hover",
onlyIfAnnotated: true,
Line: ({ annotation, ...props }) => (
<InnerLine
merge={props}
className=""
data-line={annotation?.query || ""}
/>
),
}

We also need to add some CSS for each value of the data-hover attribute.

styles.css
.hover-container:has([data-hover="one"]:hover)
[data-line]:not([data-line="one"]),
.hover-container:has([data-hover="two"]:hover)
[data-line]:not([data-line="two"]) {
opacity: 0.5;
}

You can change the CSS to fit your needs.

If you need a more complex behavior, you could add a React Context Provider to the HoverContainer component and use it to store the current hover state. Then, you can use the useContext hook in the Line component to check if the current line is the one being hovered over.