[READ-ONLY] Mirror of https://github.com/lukebennett88/luke-ui. ui.lukebennett.dev
luke-ui docs PUBLIC_API.md
7.6 kB

Public API #

How to decide what @luke-ui/react makes public, and how public composition props are named. Luke UI is pre-1.0, so prefer a clean breaking change to a compatibility alias. The per-export decisions from #711, with their evidence, are in research/711-public-api-audit.md.

What is public #

Every subpath in the package exports map is public, and so is every symbol it exports, documented or not. There is no root @luke-ui/react entrypoint.

Each module in src/exports/ names its exports. Do not use export *, because it publishes whatever the source module happens to export.

Generated class names, Vanilla Extract types, and any DOM structure or state attribute that a guide does not document are private.

Subpath Holds
@luke-ui/react/<component> A high-level component, its props type, and the companion exports it needs
@luke-ui/react/primitives/<name> Parts for composing a variant of a component
@luke-ui/react/theme breakpoints, defineTheme, ThemeInput, rootClassName, ThemeContrastError, ThemeGenerationError, vars
@luke-ui/react/themes/* Bundled theme and themeClassName, until #715 moves them
@luke-ui/react/utils Helpers for composing Luke UI output with other props
@luke-ui/react/provider The application Provider
stylesheet.css, spritesheet.svg, themes/*/stylesheet.css Static assets

There is no @luke-ui/react/styles subpath. Layout utilities stay package-internal. Consumers use Box and the other layout components.

What earns an export #

A high-level component and its props type are the default public surface. Any other export needs a consumer use that the high-level component does not already cover. Internal reuse, implementation structure, and symmetry with another component are not reasons to export something.

High-level components do not need matching APIs. Decide each prop on what consumers of that component need, not on what a sibling component or React Aria exposes.

Export Public when
Primitive An app can compose a variant of a component from it. Every primitive entrypoint has a docs page.
Recipe An app would style an element it owns without the component, and the recipe works on that element alone. A recipe that needs the component's private anatomy, internal hooks, or undocumented state attributes stays private.
Utility Consumers need it to combine Luke UI output with their own props.

Export a public recipe from the entrypoint of the component or primitive that owns it. Export the matching *RecipeVariants type only when the recipe has selectable variants. Do not export an empty variants type for naming symmetry. STYLING.md covers recipe authoring.

Composition props #

CONVENTIONS.md owns element choice: elementType, renderRoot, render<Part>, and React Aria's render.

IDs and refs #

Unprefixed id, className, style, and ref target the component's own root element. A prop for a descendant names it, such as inputId, inputRef, triggerId, or triggerRef. This is the ownership convention from the #714 decision record.

slot #

React Aria's slot lets a React Aria parent configure a child through context. Keep slot on a high-level component only when a React Aria parent defines a named slot that component can fill. Button and IconButton keep it for slots such as slot="close" in a React Aria Dialog. Checkbox keeps it for slot="selection" in a GridList or Table. Text and its typography compositions keep it for named text slots, including slot={null} to opt out of surrounding slotted text context. Other high-level components omit it. Primitives keep the slot of the React Aria component they wrap.

Controlled state #

Use React Aria's names for controlled and uncontrolled pairs, such as value, defaultValue, and onChange, or isOpen, defaultOpen, and onOpenChange. Do not add a parallel API. A change event can exist without its controlled pair when React Aria offers only the event, as onOpenChange does on ComboboxField.

Defaults #

A default value is part of the public contract, so changing one is a breaking change. Document it with @default, as DOCUMENTATION.md describes.

State attributes #

A state attribute is public only when a guide documents it, as the Select primitive guide documents data-open on SelectIndicator. Other attributes that React Aria or Luke UI set can change without a migration path.

Owned elsewhere #

Topic Owner
Form field names, parts, and semantics #714 decision record
Icons and Provider #712
Theme authoring and bundled-theme subpaths #715
Token taxonomy #716
Global stylesheet and cascade layers #717