Development Workflow

This guide is for contributors maintaining Boreal UI source, docs, generated prop metadata, and package output.

Architecture

Public components follow the base/core/next pattern:

src/components/ComponentName/
  ComponentName.types.ts
  ComponentNameBase.tsx
  core/ComponentName.tsx
  core/ComponentName.scss
  next/ComponentName.tsx
  next/ComponentName.module.scss
  server/ComponentName.tsx

Base components own shared behavior, ARIA wiring, keyboard handling, state, test IDs, and class composition. Core wrappers import global SCSS and pass string class maps. Next wrappers import SCSS Modules and include "use client" when the wrapper or base behavior uses client-only React behavior.

Add a server wrapper only when the component has useful static rendering behavior. Server wrappers must avoid "use client", hooks, browser APIs, and callback props. Reuse a hook-free base where possible; otherwise create a stripped static renderer. Add the entry to serverEntries in scripts/generateEntryPoints.cjs, update server stories and tests, and document any omitted or replacement props.

When a component has multiple public pieces, such as RadioButton and RadioGroup, keep each public prop interface documented and exported.

Updating a Public Component

When changing a public component, update the full surface:

  1. Type definitions in ComponentName.types.ts.
  2. Base behavior in ComponentNameBase.tsx.
  3. Core wrapper and global SCSS.
  4. Next wrapper and SCSS Module.
  5. Tests in __tests__.
  6. Stories, if the behavior is user-facing.
  7. Generated prop docs with npm run gen:docs.
  8. Public entry points or package exports, if the import surface changes.
  9. Server wrapper, tests, stories, and docs when the component has a server entry.

Use combineClassNames from src/utils/classNames.ts for class composition.

Generated Prop Docs

Generated docs live in src/generated-docs and are built from component .types.ts files.

npm run gen:docs

The generator emits one *PropDocs object per public component props interface with a matching core or next wrapper. This includes multi-component type files such as:

  • RadioButtonProps and RadioGroupProps
  • SelectProps and ThemeSelectProps

Do not hand-edit generated files except as a temporary diagnostic step. Update the source type JSDoc or generator instead, then regenerate.

Package Output

The package publishes:

  • dist/core for React consumers.
  • dist/next for Next.js consumers.
  • dist/next/server for Next.js React Server Component entries.
  • dist/docs and dist/types/generated-docs for the standalone docs package.
  • dist/types for TypeScript declarations.
  • docs for markdown API guides.
  • packages/cli/src for the setup CLI.

Build output is produced by:

npm run build

The build also patches Next client directives and produces the standalone documentation bundle.

Clean and refresh package folders

Before packaging or publishing, remove all generated package output and stage a completely fresh build:

npm run refresh:packages

This command:

  1. Removes root dist.
  2. Removes the generated dist directories under packages/core, packages/next, packages/types, and packages/docs.
  3. Runs the complete production build.
  4. Restages all five publishable package folders from the new output.

It deliberately preserves packages/cli/src, which is the CLI's publishable source rather than generated output. If cleaning or building fails, the command stops before staging so older package output cannot be mistaken for the current release.

Package staging skips manifest writes when the generated JSON is unchanged. On Windows it also retries short-lived EACCES, EBUSY, EPERM, and UNKNOWN write failures. If all retries fail, close any editor, npm process, antivirus scan, or sync client holding the reported manifest and run npm run stage:split-packages again.

Preview the exact cleanup targets without deleting anything:

npm run clean:package-builds:dry-run

To clean the generated directories without rebuilding:

npm run clean:package-builds

npm run pack:split uses this clean refresh automatically before creating the five npm tarballs.

Boreal UI publishes five scoped packages from this repository:

  • @boreal-ui/types
  • @boreal-ui/core
  • @boreal-ui/next
  • @boreal-ui/docs
  • @boreal-ui/cli

Documentation Checklist

Before merging public API changes:

  • JSDoc on public props explains the behavior and default where useful.
  • npm run gen:docs has been run.
  • docs/public-api-reference.md is updated when import paths, barrel exports, or standalone exports change.
  • docs/installation-and-imports.md is updated when setup or package entry points change.
  • docs/performance-and-async-behavior.md is updated when timer, polling, cleanup, selection-key, or rendering semantics change.
  • docs/server-components.md is updated when server entries or stripped behavior change.
  • docs/styling-and-theming.md is updated when style config, theme, color-scheme, or CSS variable APIs change.
  • docs/accessibility.md is updated when ARIA, keyboard, focus, or labeling behavior changes.
  • README.md is updated for user-facing capabilities, scripts, or package entry points.

Generated prop metadata should be exhaustive. Markdown docs should stay practical: document import paths, common usage, accessibility expectations, theming workflows, and maintenance rules rather than duplicating every prop table by hand.