53 / 122 · Structured output
Math
Rendered expressions with the working shown, one step at a time.
derivation
Installation
npx shadcn@latest add "@assistant-ui/elements-math-block"
Usage
import { MathBlock, Frac, Sup } from "@/components/elements/math-block";
<MathBlock label="derivation" steps={steps} visibleSteps={2} />Props
MathBlock
labelstringOptional eyebrow above the working.
steps*MathStep[]Each step is a node, so you compose expressions from the exported Frac, Sup, and Sub helpers rather than passing a string to parse.
visibleSteps*numberHow much of the derivation has been shown.
classNamestringExtra classes merged onto the root.
Frac
over*React.ReactNodeNumerator.
under*React.ReactNodeDenominator.
Source
math-block.tsx"use client";
import { cn } from "@/lib/utils";
import { mono, paper } from "./surfaces";
export interface MathStep {
expression: React.ReactNode;
note?: string;
}
export function MathBlock({
label,
steps,
visibleSteps,
className,
}: {
label?: string;
steps: readonly MathStep[];
visibleSteps: number;
className?: string;
}) {
return (
<div
className={cn(
paper,
"flex w-full max-w-sm flex-col gap-2.5 rounded-2xl p-4",
className,
)}
>
{label && <span className={cn(mono, "text-foreground/30")}>{label}</span>}
{steps.slice(0, visibleSteps).map((step, i) => (
<div
key={i}
className="fade-in slide-in-from-bottom-1 animate-in fill-mode-both flex flex-col gap-1 duration-300"
>
<span className="text-foreground/90 overflow-x-auto py-1 text-center font-serif text-[17px] leading-relaxed italic">
{step.expression}
</span>
{step.note && (
<span className={cn(mono, "text-foreground/30 text-center")}>
{step.note}
</span>
)}
</div>
))}
</div>
);
}
export function Frac({
over,
under,
}: {
over: React.ReactNode;
under: React.ReactNode;
}) {
return (
<span className="inline-flex flex-col items-center align-middle text-[0.85em] leading-tight">
<span className="px-1">{over}</span>
<span className="border-foreground/40 w-full border-t px-1">{under}</span>
</span>
);
}
export function Sup({ children }: { children: React.ReactNode }) {
return <sup className="text-[0.65em] not-italic">{children}</sup>;
}
export function Sub({ children }: { children: React.ReactNode }) {
return <sub className="text-[0.65em] not-italic">{children}</sub>;
}