This website's Component library!
This website's Component library!
The Chameleon UI primitives rendered side by side in Astro, React, and Svelte across six switchable visual themes - one stylesheet, one content source, three frameworks, identical pixels.
Read the full notesThis program is best experienced on a larger display. Rotate your device, or scroll sideways at your own risk.
Buttons
Links
This paragraph has a default link and an external link that opens in a new tab.
Hover, focus, and visited states are live - Retro renders visited links in classic purple.
Form Inputs
Select & Multiselect
Checkboxes & Radio
Tags
Tabs
Content for the first tab. Switch tabs to see the panels swap.
Inactive panels stay mounted but hidden, so state survives switching.
The framework switcher at the top of this page is this same atom with a storageKey.
Accordion
What is the Chameleon Engine?
A theme-morphing design system: one semantic component tree, radically different visual languages per theme.
Why native details/summary?
Zero hydration, keyboard support for free, and content that stays in the DOM - find-in-page still works.
Exclusive group, item one
These share a name, so opening one closes the other - native browser grouping, no JavaScript.
Exclusive group, item two
Same native grouping, seen from the other side.
Plain variant
The plain variant drops the raised surface and keeps a single divider.
Disabled accordion (locked shut)
If you can read this, the disabled state is broken.
Typography
Hero Heading
Section Heading
Third Level Heading
Subtle Heading
Fifth Level Heading
Sixth Level Heading
Lead text introduces a page or section with extra emphasis.
Body text with comfortable line height and measure. Inline code: pnpm astro build .
Small text, useful for captions or secondary information.
Caption text - italic, muted, for annotations.
Blockquotes
The fundamental problem of communication is that of reproducing at one point either exactly or approximately a message selected at another point.
Lists
Unordered List
- First item in the list
- Second item with more content
- Third item
Ordered List
- Step one
- Step two
- Step three
Inventory Grid
- Item A
- Item B
- Item C
- Item D
- Item E
- Item F
Inline List
- Astro
- React
- Svelte
- TypeScript
- CSS Modules
Checklist
- Accordion covered
- Table covered
- Modal covered
Code Block
function greet(name: string): string {
return `Hello, ${name}!`;
}
const message = greet("World");
console.log(message); one stylesheet per atom -> as many frameworks as you like
this single line is deliberately long enough to push past the content measure so horizontal overflow, scrolling and theme contrast stay easy to inspect without resizing anything The second block has no filename, no line numbers - the long line tests horizontal overflow across themes.
Table
Caption, sections, row headers, numeric cells
| Language | Role | Years |
|---|---|---|
| TypeScript | Everything user-facing | 8 |
| HTML & CSS | The actual product | 16 |
| C# | Past-life backends | 6 |
| Python | Scripts and tooling | 4 |
| Combined years of bugs | 34 | |
Live sorting, hover, active and selected rows
| Vibe | ||
|---|---|---|
| Terminal | Green on black | 29 |
| Retro | Windows 95 energy | 38 |
| Modern | Clean and soft | 41 |
| Rainbow | MySpace maximalism | 45 |
Sorting is progressively enhanced in this Astro panel. Mobile card layout belongs to the higher-level DataTable component, so this primitive demo stays a semantic table.
Cards
Default Card
This is the card body content.
Elevated Card
This card has a shadow elevation.
Outlined Card
This card has a thicker border.
Panel Card
Panel variant on the sunken surface, rendered as an article.
Interactive Card
Click this card to navigate.
Images
Small, non-zoomable image with caption.
Zoomable - click opens the shared modal with a higher-res source.
Zoomable - click opens the shared modal with a higher-res source.
Modal
Escape and the backdrop both dismiss. All sizes use the same shared registry.
Medium dialog
Default dialog size. Focus traps in on open and returns to the trigger on close.
Large dialog
Large max-width with scrolling body. Header and footer stay pinned.
Theme styling is worth inspecting: Retro chrome title bar, Terminal green glow, Rainbow candy shadows, Modern backdrop blur.
Full-width dialog
Stretches to 95vw for workspace-style dialogs.
Buttons
Links
This paragraph has a default link and an external link that opens in a new tab.
Hover, focus, and visited states are live - Retro renders visited links in classic purple.
Form Inputs
Select & Multiselect
Checkboxes & Radio
Tags
Tabs
Content for the first tab. Switch tabs to see the panels swap.
Inactive panels stay mounted but hidden, so state survives switching.
The framework switcher at the top of this page is this same atom with a storageKey.
Accordion
What is the Chameleon Engine?
A theme-morphing design system: one semantic component tree, radically different visual languages per theme.
Why native details/summary?
Zero hydration, keyboard support for free, and content that stays in the DOM - find-in-page still works.
Exclusive group, item one
These share a name, so opening one closes the other - native browser grouping, no JavaScript.
Exclusive group, item two
Same native grouping, seen from the other side.
Plain variant
The plain variant drops the raised surface and keeps a single divider.
Disabled accordion (locked shut)
If you can read this, the disabled state is broken.
Typography
Hero Heading
Section Heading
Third Level Heading
Subtle Heading
Fifth Level Heading
Sixth Level Heading
Lead text introduces a page or section with extra emphasis.
Body text with comfortable line height and measure. Inline code: pnpm astro build.
Small text, useful for captions or secondary information.
Caption text - italic, muted, for annotations.
Blockquotes
The fundamental problem of communication is that of reproducing at one point either exactly or approximately a message selected at another point.
Lists
Unordered List
- First item in the list
- Second item with more content
- Third item
Ordered List
- Step one
- Step two
- Step three
Inventory Grid
- Item A
- Item B
- Item C
- Item D
- Item E
- Item F
Inline List
- Astro
- React
- Svelte
- TypeScript
- CSS Modules
Checklist
- Accordion covered
- Table covered
- Modal covered
Code Block
function greet(name: string): string {
return `Hello, ${name}!`;
}
const message = greet("World");
console.log(message);one stylesheet per atom -> as many frameworks as you like
this single line is deliberately long enough to push past the content measure so horizontal overflow, scrolling and theme contrast stay easy to inspect without resizing anythingThe second block has no filename, no line numbers - the long line tests horizontal overflow across themes.
Table
Caption, sections, row headers, numeric cells
| Language | Role | Years |
|---|---|---|
| TypeScript | Everything user-facing | 8 |
| HTML & CSS | The actual product | 16 |
| C# | Past-life backends | 6 |
| Python | Scripts and tooling | 4 |
| Combined years of bugs | 34 | |
Live sorting, hover, active and selected rows
| Vibe | ||
|---|---|---|
| Terminal | Green on black | 29 |
| Retro | Windows 95 energy | 38 |
| Modern | Clean and soft | 41 |
| Rainbow | MySpace maximalism | 45 |
Sorting is live in React and Svelte. Astro renders the default sort statically.
Cards
Default Card
This is the card body content.
Elevated Card
This card has a shadow elevation.
Outlined Card
This card has a thicker border.
Panel Card
Panel variant on the sunken surface, rendered as an article.
Interactive Card
Click this card to navigate.
Images


Modal
Escape and the backdrop both dismiss. All sizes use the same shared registry.
Buttons
Links
This paragraph has a default link and an external link that opens in a new tab.
Hover, focus, and visited states are live - Retro renders visited links in classic purple.
Form Inputs
Select & Multiselect
Checkboxes & Radio
Tags
Tabs
Content for the first tab. Switch tabs to see the panels swap.
Inactive panels stay mounted but hidden, so state survives switching.
The framework switcher at the top of this page is this same atom with a storageKey.
Accordion
What is the Chameleon Engine?
A theme-morphing design system: one semantic component tree, radically different visual languages per theme.
Why native details/summary?
Zero hydration, keyboard support for free, and content that stays in the DOM - find-in-page still works.
Exclusive group, item one
These share a name, so opening one closes the other - native browser grouping, no JavaScript.
Exclusive group, item two
Same native grouping, seen from the other side.
Plain variant
The plain variant drops the raised surface and keeps a single divider.
Disabled accordion (locked shut)
If you can read this, the disabled state is broken.
Typography
Hero Heading
Section Heading
Third Level Heading
Subtle Heading
Fifth Level Heading
Sixth Level Heading
Lead text introduces a page or section with extra emphasis.
Body text with comfortable line height and measure. Inline code: pnpm astro build.
Small text, useful for captions or secondary information.
Caption text - italic, muted, for annotations.
Blockquotes
The fundamental problem of communication is that of reproducing at one point either exactly or approximately a message selected at another point.
Lists
Unordered List
- First item in the list
- Second item with more content
- Third item
Ordered List
- Step one
- Step two
- Step three
Inventory Grid
- Item A
- Item B
- Item C
- Item D
- Item E
- Item F
Inline List
- Astro
- React
- Svelte
- TypeScript
- CSS Modules
Checklist
- Accordion covered
- Table covered
- Modal covered
Code Block
function greet(name: string): string {
return `Hello, ${name}!`;
}
const message = greet("World");
console.log(message);one stylesheet per atom -> as many frameworks as you like
this single line is deliberately long enough to push past the content measure so horizontal overflow, scrolling and theme contrast stay easy to inspect without resizing anythingThe second block has no filename, no line numbers - the long line tests horizontal overflow across themes.
Table
Caption, sections, row headers, numeric cells
| Language | Role | Years |
|---|---|---|
| TypeScript | Everything user-facing | 8 |
| HTML & CSS | The actual product | 16 |
| C# | Past-life backends | 6 |
| Python | Scripts and tooling | 4 |
| Combined years of bugs | 34 | |
Live sorting, hover, active and selected rows
| Vibe | ||
|---|---|---|
| Terminal | Green on black | 29 |
| Retro | Windows 95 energy | 38 |
| Modern | Clean and soft | 41 |
| Rainbow | MySpace maximalism | 45 |
Sorting is live in React and Svelte. Astro renders the default sort statically.
Cards
Default Card
This is the card body content.
Card footer
Elevated Card
This card has a shadow elevation.
Outlined Card
This card has a thicker border.
Panel Card
Panel variant on the sunken surface, rendered as an article.
Interactive Card
Click this card to navigate.
Images
Modal
Escape and the backdrop both dismiss. All sizes use the same shared registry.
Medium dialog
Default dialog size. Focus traps in on open and returns to the trigger on close.
Large dialog
Large max-width with scrolling body. Header and footer stay pinned.
Theme styling is worth inspecting: Retro chrome title bar, Terminal green glow, Rainbow candy shadows, Modern backdrop blur.
Full-width dialog
Stretches to 95vw for workspace-style dialogs.
Overview
The Chameleon UI primitives presented as a live gallery, rendered with components written in three different frameworks. The tabs at the top of the stage switch the entire gallery between its Astro, React, and Svelte implementations: same components, same content, same appearance.
There are two switches to try here. The tabs compare framework implementations; the theme picker in the navigation changes the site's visual system. Pick any of the six themes and all three framework variants morph together, because they all read the same design tokens.
Why it matters
Most design systems fracture the moment a second framework enters the codebase: a React library here, a Svelte port there, each drifting at its own pace. The Chameleon Engine takes a different bet - one CSS module and one type contract per component, with thin framework wrappers around them. Visual drift between frameworks becomes impossible by construction rather than by discipline.
For a site built on Astro's islands architecture, this matters in practice: static pages compose Astro atoms with zero JavaScript, while interactive islands use the Svelte or React variants - without anyone maintaining three sources of styling truth.
Technical notes
Astro components are compiled away at build time, so 'switching frameworks' doesn't swap a runtime. All three panels are server-rendered up front and toggled with a few lines of vanilla JS; inspect the DOM and you'll find identical hashed CSS-module classes on each panel's buttons, cards, and inputs, because they are literally the same classes.
The Astro panel ships almost no JavaScript - the Accordion is native details/summary with zero hydration, and the Modal atom carries its own small open/close runtime plus a shared registry so dialogs from any framework answer to window.openModal. The React and Svelte panels hydrate as islands with client:idle - visibility-based hydration can't work here, since hidden tab panels never intersect the viewport.
The Table section shows the same split deliberately: the Astro primitives render sortable-header markup (real buttons, aria-sort) with no behavior, while the Svelte and React tabs wire those buttons to parent-owned sort state - the contract working as designed. Composition syntax is the one thing that legitimately differs: Astro and Svelte fill component zones with named slots, while the React variants map those zones to props and accept class rather than className, so markup stays portable between files.
What this proves
- One shared stylesheet and type contract per component across three frameworks
- Six switchable themes - one DOM and all three framework panels transform together
- Islands architecture in practice: static Astro HTML beside hydrated React and Svelte
- Compound primitives (Table) and registry-driven overlays (Modal) holding parity across frameworks
- Accessible disclosure, dialog, and sortable-table semantics built into the atoms
- Slot-to-prop interop contracts that keep markup portable between frameworks