代码提及

悬停文本时高亮相应的代码。

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.

悬停提及内容

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 || ""}
/>
),
}

我们还需要为 data-hover 属性的每个值 添加一些 CSS。

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;
}

您可以根据需要修改 CSS。

如果您需要更复杂的行为,可以在 HoverContainer 组件中添加 React Context Provider 来存储当前的悬停状态。然后,您可以在 Line 组件中使用 useContext 钩子来检查当前行是否是被悬停的行。