How destyler/destyler works
Purpose and Entry Points
Destyler is a TypeScript monorepo for unstyled, accessible web UI primitives. It exposes framework adapters for Vue, React, Solid, Svelte, Lit, and vanilla DOM while keeping component interaction logic framework-neutral. Public package entry points are typically packages/components/*/index.ts and packages/frameworks/*/index.ts; workspace orchestration begins at package.json and pnpm-workspace.yaml.
Headless Component Architecture
Each component package follows a uniform state-machine architecture: anatomy defines semantic parts, a machine owns state/transitions, connect projects machine state into framework-usable APIs/props, and DOM/props/type layers define boundaries.
• packages/components/dialog/src/machine.ts
• packages/components/dialog/src/connect.ts
• packages/components/dialog/src/anatomy.ts
This pattern is replicated across interactive primitives such as combobox, calendar, slider, popover, tree, tour, and toast. Consumers render markup and apply returned props; Destyler does not impose production styling.
State-Machine Runtime
packages/xstate is the core interaction runtime/wrapper layer used by component machines. It provides machine creation, proxying, transition utilities, delayed events, guard helpers, and prop merging.
• packages/xstate/src/machine.ts
• packages/xstate/src/create-proxy.ts
• packages/xstate/src/transition-utils.ts
Primary control flow: user/browser event → component machine transition → state snapshot/context update → connect.ts generates part props/state → framework renderer updates DOM. This separates interaction semantics from rendering implementation.
Framework Integration Boundary
Framework packages adapt actor/machine lifecycle and normalize cross-framework DOM props. They are the key boundary between headless component APIs and each renderer.
• packages/frameworks/vue/src/composition/machine.ts
• packages/frameworks/react/src/hooks/use-machine.ts
• packages/frameworks/lit/src/controllers/machine-controller.ts
The adapters support Vue composition APIs, React hooks, Solid hooks, Svelte rune-oriented hooks, Lit controllers/directives, and imperative vanilla helpers. Portal implementations in framework packages handle overlay rendering where required.
Shared Browser Behaviors and Domain Utilities
Reusable packages provide the browser-level behavior that machines compose: focus, dismissal, geometry, placement, DOM querying, collections, dates, colors, files, and accessibility isolation.
• packages/shareds/dismissable/src/dismissable-layer.ts
• packages/shareds/focus-trap/src/focus-trap.ts
• packages/shareds/popper/src/get-placement.ts
Specialized components additionally own domain parsing/collection logic—for example packages/components/select/src/collection.ts, packages/components/calendar/src/parse.ts, and packages/components/tour/src/utils/step.ts. These are internal implementation boundaries rather than renderer concerns.
Rendering Assets, Examples, and Documentation
The shared workspace supplies reusable demo controls, visualizers, and optional component CSS, distinct from unstyled runtime packages.
• shared/src/index.ts
• shared/src/styles/components/dialog.css
• shared/src/vue/components/Layout.vue
Each component contains framework-specific examples, snippets, Storybook stories, and MDX docs. The Astro documentation site consumes documentation data and framework-specific previews.
• document/src/content.config.ts
• document/src/components/FrameworkLayout.astro
• packages/docs/src/data.ts
Build, Validation, and Delivery
The repository runs on Node.js with pnpm workspaces, TypeScript, tsdown package builds, Vitest configurations, Astro documentation, and Storybook integration. CI/release automation is GitHub Actions-based.
• vitest.config.ts
• scripts/publish.ts
• .github/workflows/release.yml
Publishing is npm-oriented, as indicated by package metadata and release scripts; documentation is deployed through scripts/deploy.ts. No application backend or external runtime service is represented in the tree.
Components 22
Headless components
Framework-neutral interactive primitives.
- Component anatomy · Defines named parts for each primitive.
packages/components/dialog/src/anatomy.ts - Component machine · Representative dialog interaction machine pattern.
packages/components/dialog/src/machine.ts - Connect projection · Projects snapshots into part state and props.
packages/components/dialog/src/connect.ts - Domain internals · Component-specific collection, date, and tour logic.
packages/components/select/src/collection.ts - XState machine runtime · Creates and runs component machines.
packages/xstate/src/machine.ts - Actor proxying
packages/xstate/src/create-proxy.ts - Transition utilities · Guards, delayed events, transitions, and prop merging.
packages/xstate/src/transition-utils.ts
Framework adapters
Renderer lifecycle and prop normalization.
- Vue adapter
packages/frameworks/vue/src/composition/machine.ts - React adapter
packages/frameworks/react/src/hooks/use-machine.ts - Lit adapter
packages/frameworks/lit/src/controllers/machine-controller.ts - Other renderer adapters · Hooks and imperative APIs cover the remaining supported renderers.
Browser behaviors
Reusable DOM interaction utilities.
- Dismissable layers
packages/shareds/dismissable/src/dismissable-layer.ts - Focus trapping
packages/shareds/focus-trap/src/focus-trap.ts - Placement engine
packages/shareds/popper/src/get-placement.ts
Docs and examples
Documentation, previews, and optional demo styling.
- Shared demo UI
shared/src/index.ts - Component docs data
packages/docs/src/data.ts - Astro documentation site · Renders docs and framework-specific previews.
document/src/components/FrameworkLayout.astro
Build and delivery
Workspace validation, publishing, and deployment.
- pnpm workspace
package.json - Vitest validation
vitest.config.ts - npm publishing
scripts/publish.ts - Release CI
.github/workflows/release.yml
Other components
- Consumer DOM · Consumers render parts and apply returned props; no production styling is imposed.
Connections 24
- pnpm workspace → Component machine: builds workspace packages
- pnpm workspace → Vitest validation: runs validation
- Component anatomy → Component machine: names semantic parts
- Domain internals → Component machine: supplies domain logic
- XState machine runtime → Component machine: runs
- Actor proxying → Component machine: proxies actor state
- Transition utilities → Component machine: supplies transitions
- Dismissable layers → Component machine: composed behavior
- Focus trapping → Component machine: composed behavior
- Placement engine → Component machine: supplies placement
- Component machine → Connect projection: snapshot and context
- Component anatomy → Connect projection: part contract
- Connect projection → Vue adapter: headless props and state
- Connect projection → React adapter: headless props and state
- Connect projection → Lit adapter: headless props and state
- Connect projection → Other renderer adapters: headless props and state
- Vue adapter → Consumer DOM: updates DOM
- React adapter → Consumer DOM: updates DOM
- Lit adapter → Consumer DOM: updates DOM
- Other renderer adapters → Consumer DOM: updates DOM
- Shared demo UI → Astro documentation site: demo controls and styles
- Component docs data → Astro documentation site: documentation content
- Connect projection → Component docs data: documented component APIs
- Release CI → npm publishing: triggers release