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.

Design System Astro React Svelte CSS Modules Design Tokens Islands Architecture
Read the full notes
Skip demo, jump to notes
DEMO.EXE

This 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

Astro
React
Svelte
TypeScript
jQuery (retired)

Checkboxes & Radio

Preferred contact method

Tags

default primary muted default sm primary sm muted sm

Tabs

Content for the first tab. Switch tabs to see the panels swap.

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.
- Claude Shannon

Lists

Unordered List

  • First item in the list
  • Second item with more content
  • Third item

Ordered List

  1. Step one
  2. Step two
  3. 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

example.ts typescript
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

Languages I work in
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

Chameleon themes
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.

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

It's Jimmy

Small, non-zoomable image with caption.

Placeholder Image

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.

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