Skip to content

Commit 8a25c34

Browse files
committed
Add BlocksToContext component
1 parent 421c1f6 commit 8a25c34

File tree

3 files changed

+120
-4
lines changed

3 files changed

+120
-4
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use client"
2+
import {
3+
Tooltip,
4+
TooltipContent,
5+
TooltipProvider,
6+
TooltipTrigger,
7+
} from "@/components/ui/tooltip"
8+
9+
import React from "react"
10+
11+
const BlocksContext = React.createContext<any>(null)
12+
13+
export function BlocksToContext({
14+
children,
15+
...rest
16+
}: {
17+
children: React.ReactNode
18+
rest: any
19+
}) {
20+
return (
21+
<BlocksContext.Provider value={rest}>{children}</BlocksContext.Provider>
22+
)
23+
}
24+
25+
export function useBlocksContext(name: string) {
26+
return React.useContext(BlocksContext)[name]
27+
}
28+
29+
export function WithTooltip({
30+
children,
31+
name,
32+
}: {
33+
children: React.ReactNode
34+
name: string
35+
}) {
36+
const block = useBlocksContext(name)
37+
const className = block.isCode
38+
? "p-0 [&>*]:my-0 border-none overflow-auto rounded-none"
39+
: ""
40+
return (
41+
<TooltipProvider>
42+
<Tooltip>
43+
<TooltipTrigger className="underline decoration-dotted underline-offset-4 cursor-help">
44+
{children}
45+
</TooltipTrigger>
46+
<TooltipContent className={className}>{block?.children}</TooltipContent>
47+
</Tooltip>
48+
</TooltipProvider>
49+
)
50+
}

apps/web/content/blog/build-time-components.mdx

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ authors: [pomber]
66
draft: true
77
---
88

9-
import { Demo, Chain } from "./build-time-components"
9+
import {
10+
Demo,
11+
Chain,
12+
BlocksToContext,
13+
WithTooltip,
14+
} from "./build-time-components"
1015

1116
In content-driven websites, it's common to have content that needs some transformation or refinement before being rendered. For example, a blog written in Markdown might need syntax highlighting for code blocks.
1217

@@ -220,9 +225,69 @@ Now let's go back to our problem: we want to show the open graph image of the li
220225

221226
If you didn't know anything about the build process, your first thought might be to fetch the image on the client-side when the link is rendered. So let's start with that.
222227

223-
Let's assume we already have a _`async function scrape(url)`_ that given a URL it fetches the HTML, finds the open graph image tag, and returns the `content` attribute, which is the URL of the image we want.
228+
<BlocksToContext>
224229

225-
We also have a _`function LinkWithCard({ href, children, image })`_ that renders a link with a hover card that shows the image (I'm using [shadcn's Hover Card](https://ui.shadcn.com/docs/components/hover-card)).
230+
Let's assume we already have a <WithTooltip name="one">_`async function scrape(url)`_</WithTooltip> that given a URL it fetches the HTML, finds the open graph image tag, and returns the `content` attribute, which is the URL of the image we want.
231+
232+
We also have a <WithTooltip name="two">_`function LinkWithCard({ href, children, image })`_</WithTooltip> that renders a link with a hover card that shows the image (I'm using [shadcn's Hover Card](https://ui.shadcn.com/docs/components/hover-card)).
233+
234+
## !one
235+
236+
!isCode true
237+
238+
```jsx scraper.js
239+
function LinkWithCard({
240+
href,
241+
children,
242+
image,
243+
}: {
244+
href: string
245+
children: React.ReactNode
246+
image: string
247+
}) {
248+
return (
249+
<HoverCard openDelay={200} closeDelay={100}>
250+
<HoverCardTrigger
251+
className="text-zinc-900 decoration-zinc-700"
252+
href={href}
253+
>
254+
{children}
255+
<img src={image} alt={href} className="hidden" fetchPriority="low" />
256+
</HoverCardTrigger>
257+
<HoverCardContent className="p-0 overflow-hidden [&>*]:m-0">
258+
<img src={image} alt={href} />
259+
</HoverCardContent>
260+
</HoverCard>
261+
)
262+
}
263+
```
264+
265+
## !two
266+
267+
!isCode true
268+
269+
```jsx card.jsx
270+
// !link[/(http.*?$)/] https://ui.shadcn.com/docs/components/hover-card
271+
// from https://ui.shadcn.com/docs/components/hover-card
272+
import {
273+
HoverCard,
274+
HoverCardContent,
275+
HoverCardTrigger,
276+
} from "@/components/ui/hover-card"
277+
278+
export function LinkWithCard({ href, children, image }) {
279+
return (
280+
<HoverCard openDelay={200} closeDelay={100}>
281+
<HoverCardTrigger href={href}>{children}</HoverCardTrigger>
282+
<HoverCardContent className="p-0">
283+
<img src={image} alt={href} />
284+
</HoverCardContent>
285+
</HoverCard>
286+
)
287+
}
288+
```
289+
290+
</BlocksToContext>
226291

227292
A component that solves this client-side would look like this:
228293

apps/web/content/blog/build-time-components.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import {
55
} from "@/components/ui/hover-card"
66
import { Block, CodeBlock, parseProps } from "codehike/blocks"
77
import { z } from "zod"
8-
import { Code } from "../../components/code"
8+
import { Code } from "@/components/code"
99
import { Fragment } from "react"
10+
export { BlocksToContext, WithTooltip } from "@/components/blocks-to-context"
1011

1112
export function Chain(props: unknown) {
1213
const { intro, steps, outro } = parseProps(

0 commit comments

Comments
 (0)