Contributing Guide
This package is a publishable, reusable UI component library. Contributions should preserve portability, API stability, and enterprise readiness.
Scope And Guardrails
- Keep components presentational and data-source agnostic.
- Do not couple core components to host app routing, auth, state containers, or backend contracts.
- Keep public APIs domain-neutral and backward compatible by default.
- For authorization behavior, use injectable checks through
accessRequirementsandresolveAccess.
AI-First Operating Model
The repository uses a dual-context model:
- Baseline context: human-readable docs in
README.md, this file, and.github/copilot-instructions.md. - Structured context: machine-readable contracts under
ai/contracts. - Required rule: structured context under
ai/contractsmust be present and consulted for all AI-assisted component work.
Contract Workflow
- Read
ai/contracts/index.jsonbefore editing a component. - Read the component contract file in
ai/contracts/components. - Keep implementation, public types, and tests aligned with contract states.
- Update contract and tests together when behavior changes.
Component Documentation Workflow
For every new public component:
- Add a dedicated consumer doc page at
docs/components/<component>.md. - Add the component link to
docs/components/README.md. - Ensure the doc includes: purpose, import path, key props, access-control notes (if supported), accessibility notes, and at least one usage example.
- Keep docs aligned with the component’s public types and AI contract.
Input Contract Snapshot
- Access behavior:
- Missing
accessRequirementsor missingresolveAccess: input remains visible and editable unless explicitly disabled. - No view permission: component returns
null. - View allowed and edit denied: input renders disabled.
- Explicit
disabledprop always keeps input disabled.
- Missing
- Accessibility:
aria-invalid="true"whenerrorexists.- Label is associated via
htmlForand inputid.
- Interaction:
- Input stops keydown propagation.
- Consumer
onKeyDownstill executes after propagation is stopped.
Quality Gates
Run these before merge or release:
pnpm lint
pnpm tsc --noEmit
pnpm test
pnpm buildTesting Strategy
- Use
pnpm testas the default verification path for component behavior, public prop handling, access-control branches, and rendering assertions. - Use
pnpm test:ctonly for browser-dependent interaction coverage. In this repository, Playwright CT exists to validate cases that benefit from a real browser runtime, not to duplicate Vitest coverage. - Avoid adding Playwright tests for simple render checks, prop forwarding, static class assertions, or branches already covered in Vitest unless there is evidence that
happy-domis insufficient. - When adding new Playwright coverage, prefer interactive primitives and integration-heavy components such as tables, dialogs, menus, popovers, focus-managed widgets, or other surfaces with real browser event or layout sensitivity.