# 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/scripts/api-docs-builder/src/index.ts`: ```ts const NAME_OVERRIDES: Record = { 'pip-button': 'PiPButton', }; ``` Use overrides only when the standard conversion fails (e.g., acronyms like PiP). Prefer aligning component naming with the standard conversion when possible. ## 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: ```tsx /** 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 `.tsx` files - **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 ```bash # 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. ```