Neon Pilot Download

Design System

Neon Pilot's design system lives in packages/ui and is published as @neon-pilot/ui.

Extension authors should normally import through the public SDK surface:

import { Field, TextInput, ToolbarButton } from '@neon-pilot/extensions/ui';

This applies to sibling first-party extension repositories too, such as ../neon-pilot-extensions. Those extensions should not copy local Field, TextInput, Select, Pill, notice, progress, or panel classes when the SDK component exists. Build the extension after replacement with its repo script, for example pnpm build system-video-probe from ../neon-pilot-extensions.

The desktop app may import from local compatibility paths such as packages/desktop/ui/src/components/ui, but reusable components should be implemented in packages/ui first and re-exported through @neon-pilot/extensions/ui.

Agent Workflow

  1. Search packages/ui/README.md and Storybook before writing local UI.
  2. Use shared primitives for buttons, fields, switches, notices, page shells, empty states, and status indicators.
  3. If a needed reusable component is missing, add it to packages/ui, add a story, add tests when behavior is non-trivial, and re-export it through the extension SDK.
  4. Replace local copies in app and extension code when the new component is compatible.
  5. Keep extension-specific workflow logic inside the extension; keep generic chrome and controls in the design system.

For dynamic or generated settings UIs, avoid local input/select/button class constants. Compose the shared primitives directly. Use Field for simple controls, and use FieldLabel plus FieldHint in a neutral wrapper for composite controls that contain buttons.

Always use the most user-friendly input method available. Prefer constrained controls over free-form text whenever the value space is known: Select or InlineSelect instead of a typed string, Switch or SettingToggleRow instead of a boolean text field, SegmentedControl or tabs instead of magic mode names, swatches instead of hex-only color fields, and resource pickers instead of path text boxes. Prefer explicit key/value or structured row editors for individual settings and records over a Textarea containing JSON. Use raw JSON editing only for genuinely large, deeply nested, import/export, or expert-only payloads, and pair it with validation and clear errors.

User-reachable UI actions should be command-backed when they may need a shortcut, command-palette entry, hardware trigger, or automation hook. Add or reuse an extension/app command for meaningful page actions, toolbar actions, navigation, and workflow operations instead of leaving behavior trapped inside an anonymous button handler.

When auditing an extension or app surface, search first for repeated local recipes such as rounded-md border border-border-subtle, bg-elevated p-, ui-toolbar-button, local BUTTON_CLASS constants, details/summary, and hand-written empty/error/loading text. Most of those should collapse into an existing primitive.

Commands

Run the component package build:

pnpm --dir packages/ui run build

Run component tests:

pnpm --dir packages/ui run test

Start Storybook:

pnpm --dir packages/ui run storybook

Build Storybook:

CI=true pnpm --dir packages/ui run build:storybook

Current Foundation

The shared package includes:

Host-backed extension components are also exposed through public SDK subpaths when they need app-owned data or behavior:

Prefer package primitives for generic chrome. Use host-backed components only when the component depends on desktop/app state, workspace files, transcript rendering, activity-tree behavior, or native context menus.

Extraction Priorities

Extract in small tranches and migrate real usage each time:

  1. Forms and feedback: fields, inputs, switches, notices.
  2. Overlays: confirmation dialogs and richer positioned menu behavior.
  3. Layout: settings sections, cards, page headers, richer search/filter bars.
  4. Data display: sortable columns, richer table states, and nested table actions.
  5. Host-owned app patterns: file trees, activity trees, chat/transcript surfaces, diff/artifact views.

Each tranche should include documentation, Storybook coverage, and at least one app or extension replacement so the component is proven against production usage.

Migration Map

Recent Production Examples

Use these as reference implementations when migrating similar surfaces:

Agent Checklist

Before introducing local UI markup in an app page or extension:

  1. Check packages/ui/README.md for a matching primitive and inspect packages/ui/src/stories/Primitives.stories.tsx for composition examples.
  2. Prefer SDK imports from @neon-pilot/extensions/ui for extension code and @neon-pilot/extensions/settings for Settings extension code.
  3. Choose the friendliest control before defaulting to text: dropdowns, toggles, segmented controls, pickers, key/value editors, and structured rows should replace raw inputs or JSON textareas whenever practical.
  4. Back meaningful user actions with commands so they can be discovered, automated, and hot-keyed.
  5. Keep domain behavior local, but move generic chrome, spacing, state color, empty/error/loading presentation, and modal/list/table shells to shared primitives.
  6. When adding a new primitive, update packages/ui/src/index.ts, packages/desktop/ui/src/extensions/ui.ts or settings exports if extensions need it, packages/ui/README.md, Storybook, and tests where behavior is non-trivial.
  7. Validate the actual touched surface: build the package or extension, run pnpm run check:extensions:static for extension boundary work, and perform browser/app QA when user-visible UI changes.