Open Windsooon opened 4 weeks ago
One way is to change the Scrollycoding component to accept a Block instead of a CodeBlock, then you can render anything inside the sticky part.
<Scrollycoding>
## !!steps A Game of Thrones
A Game of Thrones is the first book in the A Song of Ice and Fire series by George R.R. Martin. Set in a world where seasons last for years, it introduces a complex plot and a wide cast of characters, ranging from noble families vying for the Iron Throne to the supernatural threats in the North.
### !sticker
<CodeWithTooltips>
...
</CodeWithTooltips>
## !!steps ...
...
@pomber Thank you for your reply, I try several ways in the past few days but still couldn't figure it out:
I create a Schema like this:
const Schema = Block.extend({
steps: z.array(
Block.extend({
sticker: Block.extend({
code: CodeBlock,
tooltips: z.array(Block).optional(),
})
})),
})
And the MDX looks like:
<Scrollycoding>
## !!steps A Game of Thrones
A Game of Thrones is the first book in the A Song of Ice and Fire series by George R.R. Martin. Set in a world where seasons last for years, it introduces a complex plot and a wide cast of characters, ranging from noble families vying for the Iron Throne to the supernatural threats in the North.
The Fellowship of the Ring
### !sticker
<CodeWithTooltips>
~~~js !code
// !tooltip[/lorem/] description
function lorem(ipsum, dolor = 1) {
const sit = ipsum == null ? 0 : ipsum.sit
dolor = sit - amet(dolor)
// !tooltip[/consectetur/] inspect
return sit ? consectetur(ipsum) : []
}
~~~
## !!tooltips description
### Hello world
Lorem ipsum **dolor** sit amet `consectetur`.
</CodeWithTooltips>
</Scrollycoding>
I still got the error from const {steps} = parseProps(props, Schema)
Error: at
## !!steps A Game of Thrones
### !sticker
Error for `code`: Required
{
"expected": "object",
"received": "undefined"
}
I don't know why the Schema didn't work.
I created a Schema:
const Schema = Block.extend({
steps: z.array(
Block.extend({
sticker: Block
})),
})
const ToolSchema = Block.extend({
code: CodeBlock,
tooltips: z.array(Block).optional(),
})
And try to access code and tooltips using
export function Scrollycoding(props: unknown) {
const { steps } = parseProps(props, Schema)
return (
<SelectionProvider className="flex gap-4">
<div className="flex-1 mt-32 mb-[90vh] ml-2 prose min-w-60">
{steps.map((step, i) => (
<Selectable
key={i}
index={i}
selectOn={["click", "scroll"]}
className="border-l-4 data-[selected=true]:border-blue-400 px-5 py-2 mb-24 rounded bg-card"
>
<h2 className="mt-4 text-xl">{step.title}</h2>
<div>{step.children}</div>
</Selectable>
))}
</div>
<div className="w-1/2 bg-card">
<div className="top-16 sticky overflow-auto">
<Selection
from={steps.map((step) => (
<CodeWithTooltips props={step.sticker} />
))}
/>
</div>
</div>
</SelectionProvider>
)
}
async function CodeWithTooltips(props: unknown) {
const { code, tooltips = [] } = parseProps(props, ToolSchema)
const highlighted = await highlight(code, "github-from-css")
highlighted.annotations = highlighted.annotations.map((a) => {
const tooltip = tooltips.find((t) => t.title === a.query)
if (!tooltip) return a
return {
...a,
data: { ...a.data, children: tooltip.children },
}
})
return <Pre code={highlighted} handlers={[tooltip]} />
}
I still got
Error: at root
Error for `code`: Required
{
"expected": "object",
"received": "undefined"
}
I wonder which part I missed, Thank you.
In your first way, make the sticker a bare Block
:
const Schema = Block.extend({
steps: z.array(Block.extend({sticker: Block})),
})
and then you render the children
:
<Selection
from={steps.map((step) => (
step.sticker.children
))}
/>
Thank you so much. It works well!
I also found that token-transitions.tsx
would add display: "inline-block"
export const tokenTransitions: AnnotationHandler = {
name: "token-transitions",
PreWithRef: SmoothPre,
Token: (props) => (
<InnerToken merge={props} style={{ display: "inline-block" }} />
),
}
so the tooltip classunderline decoration-dashed
didn't work as expected. I solved it by adding an extra style
export const tooltip: AnnotationHandler = {
name: "tooltip",
Inline: ({ children, annotation }) => {
const { query, data } = annotation
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger
className="underline decoration-dashed"
style={{ borderBottom: "1px dashed black" }} // Add border and padding
>
{children}
</TooltipTrigger>
<TooltipContent align="start">
{data?.children || query}
</TooltipContent>
</Tooltip>
</TooltipProvider>
)
},
}
@pomber Do you think we should add an demo for using nested tag? I can create a PR using my current example if needed.
I'm trying to use Tag
<CodeWithTooltips>
inside<Scrollycoding>
like this:Error: at
!!steps A Game of Thrones
Error for
code
: Required { "expected": "object", "received": "undefined" }async function Code({ codeblock, tooltips }: { codeblock: RawCode; tooltips?: Block[] }) { console.log(tooltips); const highlighted = await highlight(codeblock, "github-from-css") highlighted.annotations = highlighted.annotations.map((a) => { const tooltip = tooltips.find((t) => t.title === a.query); if (!tooltip) return a; return { ...a, data: { ...a.data, children: tooltip.children },
}) return ( <Pre code={highlighted} handlers={[tooltip, tokenTransitions, wordWrap]} className="min-h-[40rem]" /> ) }