4.8 KiB
Builder Conventions
Naming and file placement conventions required by the api-docs-builder at site/scripts/api-docs-builder/.
File Locations
| File | Path | Purpose |
|---|---|---|
| Core | packages/core/src/core/ui/{name}/{name}-core.ts |
Props, State, defaultProps |
| Data attrs | packages/core/src/core/ui/{name}/{name}-data-attrs.ts |
Data attribute definitions |
| CSS vars | packages/core/src/core/ui/{name}/{name}-css-vars.ts |
CSS custom property definitions (optional) |
| HTML element | packages/html/src/ui/{name}/{name}-element.ts |
Custom element with static tagName |
| React parts | packages/react/src/ui/{name}/index.parts.ts |
Multi-part detection (optional) |
Naming Requirements
The builder derives PascalCase from kebab-case using kebabCase from es-toolkit. All interfaces and exports must follow this pattern:
| Convention | Example (play-button) |
|---|---|
| Props interface | PlayButtonProps |
| State interface | PlayButtonState |
| Core class | PlayButtonCore |
| Data attrs export | PlayButtonDataAttrs |
| CSS vars export | PlayButtonCSSVars |
| HTML element class | PlayButtonElement |
| HTML tag name | static tagName = 'media-play-button' |
NAME_OVERRIDES
When kebab-to-pascal conversion doesn't produce the correct name, add an override in site/src/utils/api-reference-overrides.ts (the shared map the builder imports and the reference pages invert for slug lookup):
export const NAME_OVERRIDES: Record<string, string> = {
'pip-button': 'PiPButton',
'airplay-button': 'AirPlayButton',
};
Use overrides only when the standard conversion fails (e.g., acronyms like PiP). Prefer aligning component naming with the standard conversion when possible.
The same map covers media elements whose PascalCase name doesn't kebab-case to their element tag name (e.g. 'hlsjs-video': 'HlsJsVideo'). It is keyed by the generated-reference file slug regardless of component vs. media.
Multi-Part Components
Detection: Presence of packages/react/src/ui/{name}/index.parts.ts.
Non-local re-export filtering: Only exports with source paths starting with ./ are treated as parts. Re-exports from other directories (e.g., ../slider/index.parts) are filtered out. This prevents domain variant components (TimeSlider, VolumeSlider) from inheriting base component parts.
Single-part fallback: When filtering leaves only one part (typically Root), the component uses single-part mode — the remaining part's props/state/data-attrs are promoted to the top level, not nested under parts.
Primary part identification: The part whose React source file instantiates the component's Core class (matches new \w+Core\(). The primary part receives the shared core props/state/data-attrs/css-vars.
Non-primary parts: Each gets its own element file at {name}-{part}-element.ts. Element class must be {Name}{Part}Element (e.g., TimeGroupElement).
Framework-divergent parts: All parts get platforms.react. Parts with a matching HTML element file also get platforms.html. The renderer filters parts by framework — React-only parts are hidden in HTML docs.
Part descriptions: Extracted from JSDoc on the React component export:
/** Displays a formatted time value. */
export const Value = ...;
JSDoc Extraction
- Data attribute descriptions: From JSDoc comments on each property in the data-attrs export object
- Part descriptions: From JSDoc on React component exports in their
.tsxfiles - Prop/state descriptions: From JSDoc on interface properties in the core file
Util JSDoc
Util exports (hooks, controllers, factories, selectors) have their own JSDoc conventions for @param, @label, and @public tags. See references/util-conventions.md → "JSDoc Conventions".
Common Failures
The builder fails silently for many issues — data just won't appear in the JSON:
| Symptom | Cause |
|---|---|
| No JSON generated | Core file missing or Props interface not found |
| Empty props | Interface not named {PascalCase}Props |
| Empty state | Interface not named {PascalCase}State |
| No data attributes | File missing or export not named {PascalCase}DataAttrs |
| No CSS vars | File missing or export not named {PascalCase}CSSVars |
| No HTML tag | Element file missing or no static tagName |
| No part descriptions | Missing JSDoc on React component exports |
| Wrong PascalCase | Need a NAME_OVERRIDES entry |
Validation
# Generate JSON
pnpm -F site api-docs
# Check component output
cat site/src/content/generated-component-reference/{name}.json
# Check util output
cat site/src/content/generated-util-reference/{slug}.json
# Verify schema
# The builder validates against ComponentReferenceSchema / UtilReferenceSchema before writing.
# Schema errors are logged as errors and cause exit code 1.