aeon-ui-engine
v1.0.3
Published
**Future-proof UI infrastructure for the web.**
Downloads
577
Readme
Aeon UI
Future-proof UI infrastructure for the web.
State is defined first. UI represents the totality of that definition.
Coding agents: read AGENTS.md first, then docs/INDEX.md. Human overview below.
Aeon UI models interactive behavior as executable statecharts, exposes production-ready headless compound components, and ships a styled layer powered by Panda CSS slot recipes aligned with @aeon-ui/core anatomy. Every primitive projects a full machine snapshot onto the DOM — structure, copy, and data-aeon-state stay in sync.
Packages
| Package | Purpose |
|---------|---------|
| @aeon-ui/core | Anatomy tokens, data-aeon-* attributes, machine helpers |
| @aeon-ui/primitives | XState machines (toggle, dialog, tabs, accordion, async, button lifecycle, field) |
| @aeon-ui/react | React headless bindings |
| @aeon-ui/panda | Design tokens, defineSlotRecipe styles, generated styled-system |
| @aeon-ui/ui | Styled components (aeonButton, aeonAccordion, …) |
| @aeon-ui/vue | Vue 3 headless adapter (v0.1: Switch + useAeonMachine) |
| @aeon-ui/solid | Solid headless adapter (v0.1: Switch + useAeonMachine) |
| @aeon-ui/svelte | Svelte headless adapter (v0.1: Switch + useAeonMachine) |
Catalog (React): Button, Switch, Checkbox, Dialog, Tabs, Accordion, Select, Combobox, Async, Field, Scroll, Menu, Popover, Tooltip, Toast, Separator, Progress, RadioGroup, Slider, PinInput — see COMPONENTS.md.
Quick start
The monorepo is published on npm as aeon-ui-engine (bundles all @aeon-ui/* workspace packages):
npm install aeon-ui-engine react react-dom xstate @xstate/reactImportant: @aeon-ui/react, @aeon-ui/ui, etc. are not separate npm packages yet. After installing the engine, wire Vite so those imports resolve:
import { aeonUiOptimizeDeps, aeonUiViteAliases } from 'aeon-ui-engine/vite'
export default defineConfig({
resolve: { alias: aeonUiViteAliases() },
optimizeDeps: aeonUiOptimizeDeps(),
})Full copy-paste setup (TypeScript paths, CSS imports): CONSUMER.md.
Open https://github.com/GenericCPU/aeon-ui for the repo. The marketing demo lives at https://aeon-ui.com — set VITE_SITE_ORIGIN to that origin in Vercel so Open Graph previews resolve the social image in apps/demo/public/ correctly.
After changing recipes or tokens in packages/panda:
pnpm codegenStyling (Panda CSS)
Recipes live in packages/panda/src/recipes/ and map to core anatomy parts (accordion, dialog, tabs, …). The styled layer applies them:
import { aeonAccordion } from '@aeon-ui/panda/styled-system/recipes'
const styles = aeonAccordion()
// styles.root, styles.itemTrigger, …Apps import generated CSS once, then runtime theme overrides (required for light/dark):
import '@aeon-ui/panda/styles.css'
import '@aeon-ui/panda/theme-runtime.css'
import '@aeon-ui/panda/scrollbars.css'
import '@aeon-ui/panda/chrome.css'Legacy --aeon-* CSS variables are still emitted on :root for landing layout and gradual migration.
Themes (light / dark × mood)
Edit packages/panda/src/theme/themes.config.ts — one entry per mood (default, signal, berry, slate, neon, …), each with light + dark palette fields. Run pnpm codegen in packages/panda to regenerate theme-runtime.css.
// themes.config.ts — add a mood
{
id: 'brand',
label: 'Brand',
description: 'Your product',
light: { bg: '#f5f5f5', surface: '#fff', border: '#ddd', text: '#111', muted: '#666', accent: '#3366ff' },
dark: { bg: '#0a0a0a', surface: '#141414', border: '#333', text: '#eee', muted: '#999', accent: '#6699ff' },
}Runtime API:
import { applyAeonTheme, AEON_THEMES } from '@aeon-ui/panda/themes'
applyAeonTheme('ocean', 'light')Built-in moods: Aeon, Signal, Dusk, Calm, Ocean, Ember, Frost, Dawn, Forest, Noir. The demo uses a custom Select (not the OS dropdown) plus a Light/Dark rail.
Focus policy: chrome.css shows focus rings only for keyboard (:focus-visible). Selected tabs, pressed buttons, and open selects use surface tint — not a focus “circle” on click.
Docs
| Doc | Purpose |
|-----|---------|
| AGENTS.md | LLM/agent entry — rules, workflows, naming |
| docs/INDEX.md | Full documentation map |
| docs/MACHINES.md | Machine vs prop vs useState (ground truth) |
| docs/LAYOUT_COORDINATES.md | Responsive play surfaces — normalized coordinate plane |
| docs/COMPONENT_CHECKLIST.md | Add or change a component (ordered steps) |
| COMPONENTS.md | What ships today vs planned |
| INTEGRATION.md | Headless, Panda, Tailwind |
| PUBLISHING.md | npm release checklist |
| FRAMEWORKS.md | React now; adapter contract |
| ACCESSIBILITY.md | Roles, focus, checklist |
Philosophy & state catalog
Read PHILOSOPHY.md and STATES.md — gaps traditional UI leaves implicit (empty vs idle, button pending/success, orthogonal field regions) and how Aeon models them.
UI = f(state). Define every stable condition in the chart; build UI that expresses the whole definition, not a fragment of it.
Async region (totality)
import { Async, Button } from '@aeon-ui/ui'
<Async.Root>
<Async.Track />
<Async.Readout>Ready when you are</Async.Readout>
<Async.Actions>
<Button.Root size="sm">Fetch</Button.Root>
</Async.Actions>
</Async.Root>Example
import { Dialog, Button, Switch } from '@aeon-ui/ui'
<Switch.Root defaultChecked>
<Switch.Control><Switch.Thumb /></Switch.Control>
<Switch.Label>Notifications</Switch.Label>
</Switch.Root>
<Dialog.Root>
<Dialog.Trigger><Button.Root>Open</Button.Root></Dialog.Trigger>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Title>Title</Dialog.Title>
<Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>Headless usage:
import { Dialog } from '@aeon-ui/react'License
MIT
