import React from "react"
import * as cn from "./CodeTutorialSteps.styles";
/**
* Props for the CodeTutorialSteps component
*/
export interface CodeTutorialStepsProps {
/** Steps to be rendered - one `CodeTutorialSteps.Step` per numbered step */
children: React.ReactNode;
/** Optional CSS class name to be applied to the tutorial container */
className?: string;
}
/**
* CodeTutorialSteps component that renders a numbered vertical stepper whose body is
* split in two: prose on the left and the code or callouts it produces on the right.
* Use it for programmatic quickstarts - for a plain sequence of instructions use `Steps`.
*
* @category Component
*/
export function CodeTutorialSteps({ children, className }: CodeTutorialStepsProps) {
const blocks: React.ReactNode[] = []
let items: React.ReactNode[] = []
let step = 0
// an `ol` may only contain `li`, so anything that is not a step ends the run
// instead of being smuggled into the list - `start` carries the numbering over
function flushItems() {
if (!items.length) {
return
}
blocks.push(
{items}
)
items = []
}
React.Children.forEach(children, (child, index) => {
if (React.isValidElement(child) && child.type === CodeTutorialSteps.Step) {
step++
items.push(React.cloneElement(
child as React.ReactElement,
{ key: `step-${index}`, step }
))
return
}
flushItems()
blocks.push({child})
})
flushItems()
return
{blocks}
}
/**
* Props for the CodeTutorialSteps.Step component
*/
export interface CodeTutorialStepProps {
/** Slots of the step - a `Title`, a `Body` and an optional `Aside` */
children: React.ReactNode;
/** Position of the step, 1-based. Injected by `CodeTutorialSteps` */
step?: number;
/** Optional CSS class name to be applied to the step */
className?: string;
}
/**
* A single step of a code tutorial. This component should be used as a child of
* the CodeTutorialSteps component.
*
* @category Component
*/
CodeTutorialSteps.Step = function CodeTutorialStep({ children, step, className }: CodeTutorialStepProps) {
return
{/* the `ol` already tells assistive tech which step this is - the badge repeats it visually */}
{step}
{children}
}
/**
* Heading of a step. Rendered as text rather than a heading element on purpose:
* a step sits under the page `h1` and would read as a level skip.
*
* @category Component
*/
CodeTutorialSteps.Title = function CodeTutorialStepTitle({ children }: { children: React.ReactNode }) {
return
{children}
}
/**
* Left column of a step - the explanation.
*
* @category Component
*/
CodeTutorialSteps.Body = function CodeTutorialStepBody({ children }: { children: React.ReactNode }) {
return
{children}
}
/**
* Right column of a step - the code blocks and callouts the explanation refers to.
*
* @category Component
*/
CodeTutorialSteps.Aside = function CodeTutorialStepAside({ children }: { children: React.ReactNode }) {
return
{children}
}