EXSA Component Library — 68 Components, 20 Themes
Component Library
Browse 68 components with live demos across 7 categories. Every component is token-driven — swap the theme or skin and every demo restyles instantly. All components use --color-link, --color-bg, --surface-shadow-md and 89 other CSS custom properties. Try the live theme × skin lab on skins.php, open a demo, inspect the source — zero build step, just CSS.
Hero Banner
Full-bleed header with image/video background and centered text overlay. Detects <header> as a direct child of <body> (outside <main>) containing a <figure> with media. Requires dist/components/hero.css (included in exsa.bundle.css). Gradient overlay uses --hero-overlay; height via --hero-height (default 60vh). Classless <button> elements invert to white automatically.
Accordion
Pure CSS expandable sections using hidden <input type="checkbox"> and the :checked pseudo-class. Zero JavaScript. Active label uses --color-link. Add .accordion--sm for compact variant.
--color-link for the active label, --color-bg-secondary for hover states and borders, --border-radius for the container corners.:checked pseudo-class to toggle the panel height. Same pattern as our Toggle Switch component..accordion block inside .accordion__panel-inner. Each nested accordion gets its own independent checkbox IDs. Works up to any depth.Kanban Board
Drag-and-drop board with columns and cards. Pointer-based dragging works with mouse and touch (touch-action: pan-y keeps vertical page scroll alive). Behavior: js/kanban.js. Fires exsa:kanban-drop / exsa:kanban-add events on the board.
Product Card
Store product tile for layouts/store.css .shop__grid product grids. Pair with badge.css for the corner badge colors.


Drawer
Slide-out panel triggered by a hidden checkbox. Includes backdrop overlay. Supports left variant with .drawer--left. Uses --color-bg and --color-overlay tokens. Pure CSS — no JavaScript required for the toggle.
Modal Window
Accessible dialog overlay with backdrop click-to-close, Escape key dismissal, and focus trapping. Structure: .modal__header (title + close button), .modal__body (content), .modal__footer (action buttons). Three footer button variants: primary, default, danger. Open via data-modal-open="id" on a trigger button; the modal uses a matching id. Requires ~48 lines of JavaScript. Uses --box-shadow and --border-radius from theme tokens.
Pricing Table
Responsive pricing grid with featured plan highlight. Uses --color-link for the featured border and button, --box-shadow for hover lift, and --border-radius for cards and buttons.
- 5 projects
- 1 GB storage
- Basic analytics
- Priority support
- Custom domain
- 50 projects
- 10 GB storage
- Advanced analytics
- Priority support
- Custom domain
- Unlimited projects
- 100 GB storage
- Real-time analytics
- 24/7 phone support
- Custom domain + SSL
RTL Direction
EXSA fully supports right-to-left (RTL) layouts. Simply set dir="rtl" on the <html> element — all components flip automatically using CSS logical properties (inline-start, inline-end). The button below is a convenience toggle to preview RTL on this page; it persists your choice in localStorage.
Topbar / Navbar
Fixed top navigation bar with scroll shadow. Always solid --color-bg with a subtle shadow on scroll. Left section for brand + nav, right section for actions + avatar. Hamburger menu on mobile. The one at the very top of this page is a live example.
Scroll the page to see the topbar turn solid with a blur backdrop. Resize to mobile to try the hamburger menu.
Sidebar Navigation
Vertical navigation sidebar with SVG icons, collapsible sub-menus, and active state highlighting. Token-driven via --color-bg, --color-bg-secondary, --color-text, and --color-link.
Command Palette
Ctrl+K modal search built on modal.css. Behavior: js/command-palette.js — filters items live, arrow keys navigate, Enter selects. Press Ctrl+K anywhere on this page to open it.
Notifications
Bell dropdown built on dropdown.css — the toggle reuses js/dropdown.js, so no extra behavior file. Unread items, timestamps, mark-all-read, and a footer link.
Tree
Nested file tree — pure CSS, zero JS. Expand/collapse comes free from native <details>, so it's keyboard-accessible by default. .tree--lines adds the connecting lines.
src4
exsa.css
components
- card.css
- modal.css
Back to Top
Floating button that appears after scrolling 300px. Smooth-scrolls to top on click. Uses --color-link for background. Fixed position, always visible in the bottom-right corner.
Scroll down to see the button appear in the bottom-right corner. Click it to scroll back up.
Breadcrumbs
Path navigation showing the user's location in a site hierarchy. Wrap in <nav aria-label="breadcrumb"> for accessibility. Separators are inline / characters via .breadcrumbs__sep — swap for > or → if preferred. Active page uses .breadcrumbs__current styled with --color-text-secondary; links use --color-link. Pure CSS, no JavaScript.
Pagination
Page navigation using a styled list. Active page uses --color-link. Disabled state uses reduced opacity. Add .pagination--sm for compact variant. Borders use --color-bg-secondary.
Stepper
Multi-step progress indicator with active and completed states. Connecting lines fill with --color-link when done. Supports horizontal and vertical (.stepper--vertical) layouts.
Timeline
Vertical timeline with dot markers and cards. Active item fills the dot with --color-link. The vertical line uses --color-bg-secondary. Add .timeline--sm for compact variant.
Project Kickoff
Initial architecture defined. Token system designed with 82 tokens powering all 9 layers.
First 8 Components
Slideshow, progress bars, toggle, tabs, charts, toast, tooltip, and breadcrumbs — all pure CSS.
23 Components Complete
Extended to 23 components across 6 categories. Theme engine supports 5 presets with live switching.
Export Engine v1
Selective CSS export: cherry-pick components, bundle with base framework + chosen theme. One download.
Tooltip
Pure CSS hover tooltip using ::after and ::before pseudo-elements. Arrow created with border trick. Text color uses --color-text, background inverts it to --color-bg.
Hover over this phrase to see the tooltip. Works on hover and keyboard focus.
Avatar
Squircle-masked user avatars with a proportional status dot (20% of size). Sizes (fluid — vw-clamped, scale down on small screens): --xs 24–40 · default 32–56 · --sm 40–80 · --lg 64–160 · --xl 96–320. Status variants: --online, --away, --busy, --offline. Fallback shows initials on a token-colored squircle when no image. Grouped avatars overlap with a background ring.







Badge
Small inline labels for status, counts, and categories. Five color variants, plus dot and count shapes. Primary variant uses --color-link; default uses --color-bg-secondary.
Card
Versatile content container with image, body, and footer slots. .card--hoverable lifts on hover using --box-shadow. .card--horizontal places image beside content — collapses to vertical on narrow containers. Add .card--horizontal-reverse to flip the image to the right. All colors reference theme tokens.
Design Tokens
82 design tokens drive every component. Change one theme file to restyle the entire library.
Export Engine
Select components, pick a theme, download a single CSS file. No build tools needed.
No Image Card
Cards work without images too. Add a rating between the title and text for review-style cards. The body fills the full width.
Horizontal — image beside content
Horizontal Card
Image sits on the left, content flows on the right. Body is vertically centered for balanced reading. Collapses to stacked on narrow containers.
Horizontal Reversed
FlexibleSame layout, image on the right. Add .card--horizontal-reverse to flip the direction. Title, badge, and star rating share one row — divider separates metadata from body text. Works with all card variants.
Table
Responsive data table with striped rows, hover states, and status badges. Add .tbl--striped, .tbl--bordered, .tbl--sm, or .tbl--responsive for card fallback on mobile. Uses --color-bg-secondary for borders and stripes.
| Project | Owner | Status | Updated |
|---|---|---|---|
| Token Engine | Ana | Active | 2h ago |
| Export CLI | Ben | Review | 5h ago |
| Theme Builder | Chen | Active | 1d ago |
| Legacy Docs | Dana | Archived | 12d ago |
| CDN Setup | Eli | Active | 3d ago |
Data List
Key-value metadata display using semantic <dl>, <dt>, <dd> elements. Horizontal by default, stack vertically with .data-list--vertical. Add .data-list--bordered for a card wrapper or .data-list--striped for alternating row backgrounds. Three sizes: --sm, default, --lg.
- Name
- Sam Intelco
- sam@intelco.com
- Company
- intelco
- Status
- Active
- Repository
- github.com/exsa/framework
- Version
- v1.0.0-rc.1
- License
- MIT
Separator
Horizontal (<hr>) or vertical (<span>) divider line. Three sizes: .sep--sm, default, .sep--lg. Vertical via .sep--vertical — use align-self:center in flex parents to keep it centered. Line color uses --color-text at low opacity — visible on any background. Common in navbars, toolbars, sidebar sections, and between content blocks.
HORIZONTAL
Tight spacing
Default spacing
Loose spacing
After lg separator
VERTICAL (in a toolbar)
Code Block
Syntax-highlighted code block with a copy-to-clipboard button. The .code-block__header shows a language label; the copy button sits beside it. Clicking the button copies the <code> content and shows a green "Copied!" checkmark for 2 seconds. Omit the header with .code-block--no-header — the copy button overlays the top-right corner of the code area. Add .code-block--sm for a compact variant with smaller padding and font. Uses --color-bg-secondary for the background, --color-link for hover, and --color-success for the copied state. Requires ~86 lines of JavaScript for the clipboard API.
<div class="card card--hoverable">
<img class="card__image" src="cover.jpg" alt="">
<div class="card__body">
<h4 class="card__title">Design Tokens</h4>
<p class="card__text">82 design tokens drive every component.</p>
</div>
<div class="card__footer">
<span class="badge badge--primary">v2.4</span>
</div>
</div>
/* EXSA theme token reference */
:root {
--color-bg: #fff;
--color-bg-secondary: #e9e9e9;
--color-text: #000;
--color-link: #118bee;
--color-success: #16a34a;
--color-danger: #dc2626;
--border-radius: 5px;
--box-shadow: 2px 2px 10px;
}
.btn { display: inline-flex; align-items: center; gap: .4em; }
.btn--primary { background: var(--color-link); color: #fff; }
Activity Feed
Grouped timeline feed (today / yesterday) with dot colors: --danger, --warning, --muted (default success). Pure CSS; pair with avatar.css for richer rows.
Empty State
Icon + title + CTA placeholder for blank lists and tables. .empty-state--bordered adds the card border; .empty-state--sm is the compact variant.
No projects yet
Create your first project to get started.
No results
Try a different search term.
Lightbox Gallery
Thumbnail grid with click-to-expand fullscreen overlay. Click any thumbnail to open the lightbox; use prev/next arrow buttons or left/right keyboard keys to navigate. An image counter ("3 / 6") shows current position. Close via the × button, Escape key, or clicking the dark backdrop. Uses --color-link for the hover border on thumbnails and --border-radius for thumbnail corners. Requires ~63 lines of JavaScript. Complements the Video Gallery component.






Music Player
Music playback UI with two-part structure: a .media-display for album art + play overlay, and a .media-bar for transport controls (prev/play/next), time readout, and volume. Set data-duration (in seconds) on the .music-player wrapper to display total time. Requires ~34 lines of JavaScript for play/pause toggle and time tracking. Colors use --color-link for the play button and --color-text for time labels.
Video Gallery
Responsive grid of video cards with thumbnail previews, play button overlay, and duration badges. Set the YouTube embed URL via data-video on each .video-gallery__card. Click any card to open it in a fullscreen modal player with the embedded video. Each card shows a thumbnail, play icon overlay, duration badge, title, and metadata line. Requires ~54 lines of JavaScript for the modal player. Colors use --color-link for the play icon, --color-bg-secondary for duration badges, and --border-radius for cards.
8:58
Homemade Burger
1:28
Ricotta Ravioli
5:59
Pancakes
7:18
Pesto Pasta
4:06
Homemade Gelato
7:52
Eggs On Toast
Slideshow
Accessible image carousel with ARIA role="region" and aria-roledescription="carousel". Auto-advances every 4.2 seconds (5s after manual navigation). Each slide supports an optional <figcaption>. Prev/next arrow buttons and dot navigation are generated by JavaScript (~39 lines). Active dot uses --color-link; container corners use --border-radius. Wrap multiple slideshows by giving each a unique id.
Carousel
Web component carousel with scroll-snap. Add attributes to enable features: pagination (dots), navigation (prev/next arrows), autoplay + loop, mouse-dragging (drag to slide), slides-per-page="N", autoplay-interval (ms), orientation="vertical". CSS props: --slide-gap, --scroll-hint (peek), --aspect-ratio. Example below shows vertical orientation.





Donut Chart
Pure CSS donut chart using the clip-rect technique. Up to 4 slices, each controlled by a CSS variable: --s1 through --s4 (set as degrees, e.g. 90deg). Slice colors use --color-link, --color-secondary, and --color-bg-secondary. Center displays a value and label via .donut__center-val and .donut__center-label. Pair with .donut-legend for labeled items with percentages. Zero JavaScript.
iOS
21%
Mac
48%
Linux
9%
Bar Chart
Horizontal bar chart built from stacked .bar-row elements. Each row has a .bar-row__label (left), a .bar-row__track with a .bar-row__fill bar, and a .bar-row__val (right). Set bar width via the CSS variable --bar-w (0–100%) on the fill element. Bar color is set via inline background — use --color-link, --color-secondary, or any token. Track background uses --color-bg-secondary. Pure CSS, no JavaScript.
Progress Bars
Progress indicator with icon, label, percentage readout, and gradient-filled track. Set fill width with --fill-pct (0–100%) and color with --fill-clr on the .progress-item__fill element. The fill renders as a gradient from the chosen color to a lighter tint. Each .progress-item contains a head row (.progress-item__head) with optional icon, label, and percentage, plus a track. Uses --color-bg-secondary for the empty track. Pure CSS — no JavaScript needed.
Range Slider
Custom styled <input type="range"> with live value display. Thumb uses --color-link fill with white border. Track uses --color-bg-secondary. Add .range--sm for compact variant.
Calendar
Month grid + event chips rendered from data attributes. Behavior: js/calendar.js — builds the grid, month navigation, today highlight, and fires exsa:day-select / exsa:event-click / exsa:month-change.
Chart
SVG line / area / bar / sparkline from data attributes — zero third-party dependencies. Behavior: js/chart.js generates the SVG; CSS styles it. Types via class (.chart--line/area/bar/sparkline) or data-chart-type.
KPI Card
Big number + delta (+ sparkline/progress) for dashboards. .kpi__delta--up/--down color the trend; .kpi-grid lays cards out responsively. Standalone — works with or without card.css.
Checkbox
Custom checkbox with a CSS-drawn checkmark. Checked state fills the box with --color-link; the check draws in with a scale animation (a rotated border ::after — no SVG, no JavaScript). Add the disabled attribute to the hidden <input> for a muted, non-interactive state. Label goes after .checkbox__box inside the <label> wrapper. Pure CSS using :checked on the hidden input. Group checkboxes by sharing a common context in a <fieldset>.
Color Picker
Styled wrapper around the native <input type="color">. Click the swatch to open the OS color picker. Hex value displays below. Three sizes: default, .color-picker--sm, .color-picker--lg.
Advanced Color Picker
HSL + Alpha color picker with canvas saturation/lightness field, hue/light/alpha sliders, and hex input. Click the swatch trigger to open the dropdown panel. Uses --color-link, --color-bg, --border-radius, and --box-shadow tokens. Requires ~133 lines of JavaScript.
Date Picker
Interactive calendar popup with month navigation, today highlight, and click-to-select dates. Click the input to open. Adapted from GeeksForGeeks. Uses --color-link, --color-bg-secondary, and --border-radius tokens.
Dropdown Menu
Click-to-toggle floating menu with items, shortcuts, separators, labels, and danger actions. Solid (default) and soft variants via .dropdown--soft. Compact size via .dropdown--sm. Uses --box-shadow and --border-radius from theme tokens.
Form Validation
Input error and success states with icon indicators and helper text. Uses semantic --color-danger and --color-success tokens with focus-ring shadows. Add .input--error, .input--success, or .form-helper--error to any input.
Form Required
Automatic required-field feedback — zero JavaScript. Required labels get a danger-colored asterisk via label:has(+ :required)::after, and any form containing a :user-invalid field gets a danger border via :has(). Works on any page with the exsa body class. Pair with form-validation.css for per-field error states.
The red asterisks next to Full name and Email are added automatically from the required attribute — no extra markup. Submit empty, or type an invalid email and blur, and the form border turns danger red automatically.
Icon Button
Now part of buttons.css. Use .btn .btn--icon for circular icon-only buttons, or .btn .btn--radius-full for pill-shaped icon+label combos. Combine with .btn--surface, .btn--ghost, or .btn--outline for styling.
Input Group
Label + icon/addon + input combined into one visual unit with a shared focus ring. Two adornment types: .input-group__icon for leading SVG icons (mail, search, user) and .input-group__addon for text prefixes like "https://". The focus ring uses --color-link blended semi-transparently. The wrap border uses --color-bg-secondary. Optional .input-group__label sits above the wrap. Works with type="email", type="text", type="search", and type="password".
Loading Button
Built-in loading state via .btn--loading. Text hides, spinner appears centered — works on all variants. Outline/ghost/soft/surface variants get a link-colored spinner. No extra markup needed.
Password Input
Password field with inline show/hide toggle. Focus ring uses --color-link. Toggle button reveals the plain-text value by swapping input type. Requires ~24 lines of JavaScript.
Popover
Click-triggered floating card for rich content — forms, text, media, or actions. Arrow points to the trigger. Four sizes: --sm, default, --lg, --xl. Align with .popover--align-start or .popover--align-end. Closes on outside click or Escape.

Notifications
You have 3 unread messages and 1 pending invite.
Radio Button
Styled radio button group. Each <label class="radio"> wraps a hidden <input type="radio">, a .radio__circle (outer ring + inner dot), and a .radio__label. All inputs in a group share the same name attribute for mutual exclusion. Checked state fills the inner dot with --color-link; the outer ring uses --color-bg-secondary. Add the disabled attribute to the input for a muted, non-interactive option. Pure CSS — no JavaScript required.
Rating Stars
Interactive 5-star rating. Click to set, hover to preview. Uses CSS direction trick for right-to-left fill. Requires ~27 lines of JavaScript for click handling.
Styled Select
Custom <select> wrapper with chevron icon, focus ring, and size variants. Uses --color-link for focus and --color-text-secondary for the chevron. Add .select--sm or .select--lg for compact/large variants.
Tabs
Tabbed interface for switching between content panels. Click a .tabs__tab to show its matching panel — linked by matching the tab's data-panel value to a panel's id prefixed with panel-. Active tab gets a bottom border in --color-link. Requires ~41 lines of JavaScript to toggle panels. Optional modifiers: .tabs--vertical for side tabs, .tabs--full for equal-width tabs filling the container. Panels use .tabs__panel--active to control visibility.
Tab components use --color-link for the active indicator line. The border and text colors follow the active theme from the CSS custom properties token file.
82 design tokens drive every visual aspect. Change one theme file and all components — tabs, toggles, spinners, everything — update simultaneously.
Add exsa.css alongside a theme. Pick your components. Zero configuration. All 68 Components ready to use.
Toggle Switch
Pure CSS toggle switch built on a hidden <input type="checkbox"> with the :checked pseudo-class. Active (on) state fills the track with --color-link and slides the thumb knob to the right. Add .toggle--sm for a compact 32px-wide variant. Add the disabled attribute to the input for a muted, non-interactive state. Label text goes after the track inside the <label> wrapper. Zero JavaScript.
Buttons
Button system with 9 variants, 4 sizes, and built-in loading. Theme-aware: uses --color-link, --color-success, --color-danger, --color-warning tokens. Works on both <button> and <a> elements. Mods: .btn--xs, .btn--sm, .btn--lg, .btn--icon, .btn--block, .btn--loading, .btn--high-contrast, .btn--radius-full, .btn--radius-none, and disabled.
Panel Resizer
Drag handle for resizable panels. Horizontal (ew-resize) and vertical (ns-resize) variants. Drag the ⋮ grip to resize the parent panel. Uses --color-bg and --color-bg-secondary tokens.
Tags Input
Chips + type-to-add with suggestions. Behavior: js/tags-input.js — creates the text field, filters suggestions, caps at data-tags-max, and writes the hidden input (data-tags-name). Fires exsa:tags-change.
Transfer List
Two-panel list picker with search and move controls. Behavior: js/transfer.js — click selects, double-click / Enter moves, action buttons data-action add/remove/add-all/remove-all. Fires exsa:transfer-change.
- Editor
- Viewer
- Admin
Upload Dropzone
Dropzone + file list with progress bars. Behavior: js/upload.js — with data-upload-url it uploads via XHR with live progress; without it, progress is simulated (demo mode). Fires exsa:upload-add / -done / -error / -remove.
Alert / Notice
Contextual feedback messages with four color variants, three styles (soft, outline, surface), and three sizes. Soft is the default tinted-background style. Outline uses a colored border with transparent background. Surface is card-like. Info variant uses --color-link; others use fixed semantic colors.
Default tinted style. Uses --color-link at 10% opacity for background.
Transparent background, colored border. Good for minimal UIs.
Card-like with subtle shadow. Neutral, works with any theme.
Compact alert--sm size for tight spaces.
Large alert--lg size. Build failed — check your theme file for missing variables.
Cookie Consent Bar
Fixed cookie consent banner that slides up from the bottom on first visit. Dismissal is stored in localStorage so it won't reappear after accepting or dismissing. Add .cookie-bar--top to pin it to the top of the viewport instead of the bottom. Accept button uses --color-link; the bar background uses --color-bg. Requires ~23 lines of JavaScript for show/hide and localStorage persistence.
Skeleton Loader
Shimmer placeholder for loading states. Pure CSS animation sliding a gradient across the element via background-position. The shimmer shifts between --color-bg-secondary and a lighter tint. Shape modifiers on .skeleton__line: --circle (round avatar, 40px), --h2 (thick heading, 60% height), --medium (half-width line), --short (quarter-width line), --btn (pill-shaped button). Compose realistic page skeletons by combining shapes inside a .skeleton wrapper. Zero JavaScript — pure CSS animation.
Spinner
CSS-only loading spinner using the border technique: a full circle with a transparent portion creates the spinning arc. The colored arc uses --color-link, the inactive track uses --color-bg-secondary. Three sizes: .spinner--sm (20px), default (36px), .spinner--lg (52px). Use inline within buttons or text, or center it in a container with flex/grid. To override the arc color, set border-top-color inline. Pure CSS animation via @keyframes spin — zero JavaScript.
Toast Notifications
Temporary notification that appears in the bottom-right corner and auto-dismisses after 3.5 seconds. Three semantic variants: .toast--success (green), .toast--error (red), .toast--info (neutral). Each toast contains an icon, message, and optional close button. Toasts stack vertically and slide in/out with a CSS transition. Requires a #toast-container element on the page and ~31 lines of JavaScript to create and remove toasts. Uses --border-radius and --box-shadow from the theme.
Confirm Action
Are you sure you want to proceed? This modal uses --color-bg, --box-shadow, and --border-radius tokens from the active theme.
Settings Panel
This panel slides in from the right using pure CSS. The toggle is a hidden checkbox — click the backdrop or close button to dismiss.
It reads --color-bg for its background, --color-bg-secondary for borders, and uses box-shadow for depth.