Component api design
Skill segunadebayo/design-eng-skills/skills/component-api-design
Agent skills for design engineers: state machine design, component API design, engineering writing, changeset writing.
npx -y skills add segunadebayo/design-eng-skills --skill component-api-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 12 days oldThe repository was created 12 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when designing or reviewing a component's public API. Naming, props, compound component structure, CSS custom properties, and data-attributes.
SKILL.md
4.5 KB, as published. Nobody here has run it
Component API Design
A general guide to designing a component's public API, grounded in how real, widely-used component libraries actually name and structure things. Use GLOSSARY.md's terms exactly. Two topics get their own dedicated guide, since they're the two most load-bearing conventions here: CONTROLLED-UNCONTROLLED.md and CALLBACKS.md. See SOURCES.md for what all of this is grounded in.
1. Name the anatomy first
Write down the parts before any code: trigger, content, item, positioner. Group by shared prefix (item, itemText, itemIndicator) and shared suffix (itemTrigger, closeTrigger, both end in Trigger). Decide whether anatomy is a declared, schema-generated artifact (worth it once you have a whole library of components) or left implicit in JSX (fine for one self-contained component). See METHODOLOGY.md.
2. Decide what Root renders
A structural component (an accordion, a select) renders a real DOM wrapper at Root. An overlay or portal component (a dialog) has content living elsewhere in the tree, so Root is a pure state provider with no DOM output. See METHODOLOGY.md.
3. Design the compound export shape
Land on Namespace.Part (Dialog.Root, Dialog.Trigger). Export each part under its own qualified name too, then re-export the set under a namespace object, so both Dialog.Trigger and DialogTrigger work. See METHODOLOGY.md.
4. Design every stateful prop as a controlled/uncontrolled triad
value/defaultValue/onValueChange, every time, no exceptions. Full guide, the shape, why defaultValue matters, single source of truth per mode, partial control, in CONTROLLED-UNCONTROLLED.md.
5. Design the callback payload shape
Bare positional value or a details object, decide once for the whole surface and hold it everywhere. Full guide, naming, firing rules, granularity, cancellation, async, ordering, in CALLBACKS.md.
6. Pick one polymorphism mechanism
Clone-based (simple, structural-clone-only, single child) or render-function-based (state-aware, function-capable, needs an escape hatch for polymorphism under SSR). Don't mix the two. Write down the consumer contract (forward the ref, spread the props) wherever a caller will actually see it. See METHODOLOGY.md.
7. Design data-attributes for every meaningful state
Decide the addressing scheme (bespoke per-component, a generic scope-and-part system, or a single component-identity key) and enum vs. boolean-per-state on purpose. Render every boolean as present-when-true, absent-when-false, never the strings "true"/"false". See METHODOLOGY.md.
8. Design CSS custom properties for measured values
Fully-qualified names avoid collisions when composing several components on one page. Generic shared names are DRY when many components need the same positioning primitive. See METHODOLOGY.md.
9. If pre-styled, design a variant vocabulary
Name the axes (variant, size) and a closed set of values on each. Mirror the active variant onto the DOM as its own data-attribute. Always accept and merge a consumer className last. See METHODOLOGY.md.
10. Decide escape hatches on purpose
An ids override prop, a Root/Provider split, an imperative handle. Each solves one specific, real problem. Don't add one before you have the concrete case. See METHODOLOGY.md.
11. Write the governing philosophy down
One sentence, stated once, that resolves every close naming call the rest of this process leaves open. See METHODOLOGY.md.