EXSA Component Library — 49 Components, 17 Themes
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.Drawer
Slide-out panel triggered by a hidden checkbox. Includes backdrop overlay. Supports left variant with .drawer--left. Uses --box-shadow and --color-bg 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 ~20 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
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.
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 12 CSS custom properties powering all 4 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
User profile images with status indicators. Five sizes from --xs to --xl. Supports rounded-square variant and grouped avatars. Fallback shows initials when no image. Uses --color-bg-secondary for fallback background.
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. All colors reference theme tokens.
Design Tokens
12 CSS custom properties 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. The body fills the full width. Great for text-only content like changelog entries or notifications.
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
- 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-bg-secondary. Common in navbars, toolbars, sidebar sections, and between content blocks.
HORIZONTAL
Tight spacing
Default spacing
Loose spacing
After lg separator
VERTICAL (in a toolbar)
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 ~25 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 ~20 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 ~20 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.
Homemade Burger
Ricotta Ravioli
Pancakes
Pesto Pasta
Homemade Gelato
Eggs On Toast
Slideshow
Accessible image carousel with ARIA role="region" and aria-roledescription="carousel". Auto-advances every 5 seconds — pauses on hover via .slideshow--paused. Each slide supports an optional <figcaption>. Prev/next arrow buttons and dot navigation are generated by JavaScript (~30 lines). Active dot uses --color-link; container corners use --border-radius. Wrap multiple slideshows by giving each a unique id.
Donut Chart
Pure CSS donut chart using the clip-rect technique. Up to 4 slices, each controlled by a CSS variable: --slice1 through --slice4 (set as percentages, e.g. 21%). Slice colors are set inline via background on each .donut__slice .fill. 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.
Checkbox
Custom checkbox with animated SVG checkmark. Checked state fills the box with --color-link; the check icon draws in with a stroke animation. 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 — no JavaScript. 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.
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-error and --color-success tokens with focus-ring shadows. Add .input--error, .input--success, or .form-helper--error to any input.
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 ~8 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 ~10 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 ~15 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.
12 CSS custom properties drive every visual aspect. Change one theme file and all components — tabs, toggles, spinners, everything — update simultaneously.
Add components.css alongside style.css. Pick a theme. Zero configuration. All 12 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 36px-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.
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 ~10 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 (16px), default (24px), .spinner--lg (36px). 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 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 ~15 lines of JavaScript to create and remove toasts. Uses --border-radius and --box-shadow from the theme.