A Button with variants that accepts every native button prop
onClick, type, disabled and aria-label were never declared in ButtonProps; they come from ComponentProps<"button"> and reach the real button through ...rest. The disabled button ignores the click, so deleted never logs. ghost is a type error (shown in the comment), but the preview strips types, so it still renders with a made-up class.
Describe a component's props with a type or interface: optional props with ?, unions of string literals for variants, ReactNode for anything renderable, and ComponentProps<"button"> to accept every native prop of an HTML element.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 5 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write an Alert component with tone: "info" | "error" (required), an optional title?: string, and children. Render one of each tone.
Write a TextField that accepts every native <input> prop plus a required label: string, and renders a <label> wrapping the text and the input.
Explain it without notes
When would you choose type and when interface for props?
What is ReactNode, and why is it usually better than JSX.Element for children?
How do you build a Button that accepts all native <button> props plus a variant? What about ref in React 19?
What goes wrong when your prop has the same name as a native prop, and how do you fix it?
Preview
Console
Nothing logged yet.Expected console output
Save: btn btn-primary btn-md
saved
Cancel: btn btn-secondary btn-sm
cancelled
Delete: btn btn-danger btn-md (disabled)
Ghost: btn btn-ghost btn-md extra