Component library
28 components covering forms, feedback, navigation, overlays, and data. Every component is plain HTML + a class — no framework, no runtime. Click "Code" on any demo to copy the markup.
Accordion
Collapsible sections. The chevron rotates 180° when the item opens.
data-theme="dark" on the html element.<div class="accordion"> <div class="accordion-item" data-state="open"> <button class="accordion-trigger">Question</button> <div class="accordion-content">Answer.</div> </div> </div>
Alert
Inline messages for validation, system feedback, and contextual notes. Composable with an icon and title.
<div class="alert alert-danger"> <svg class="alert-icon"></svg> <div class="alert-body"> <div class="alert-title">Connection lost</div> We're trying to reconnect. </div> </div>
Avatar
Initials fallback, image override, four sizes. Stack into a .avatar-group for team displays.
<span class="avatar">SC</span> <span class="avatar avatar-lg"><img src="/me.jpg"></span> <div class="avatar-group"> <span class="avatar">SC</span> <span class="avatar">TO</span> </div>
Banner
Full-width contextual banners for system-wide state. The pulsing .banner-dot signals an active condition.
<div class="banner banner-danger"> <span class="banner-dot"></span> <span>Dialing stopped</span> <span class="tag tag-danger">Hard stop</span> </div>
Breadcrumb
Hierarchical location indicator. Mark the current page with aria-current="page".
<nav class="breadcrumb"> <a class="breadcrumb-item" href="#">Workspace</a> <span class="breadcrumb-sep">/</span> <span class="breadcrumb-item" aria-current="page">Settings</span> </nav>
Button
Seven variants from primary confirmation to inline link. Three sizes via .btn-sm and .btn-lg. Add .btn-icon for a square icon-only button.
<button class="btn btn-primary">Apply changes</button> <button class="btn btn-secondary">Cancel</button> <button class="btn btn-outline">Outline</button> <button class="btn btn-ghost">Ghost</button> <button class="btn btn-brand">Continue</button> <button class="btn btn-danger">Delete</button> <button class="btn btn-link">Read more</button>
Sizes
<button class="btn btn-primary btn-sm">Small</button> <button class="btn btn-primary">Default</button> <button class="btn btn-primary btn-lg">Large</button>
States
Icon button
<button class="btn-icon"><svg ... /></button> <button class="btn-icon btn-icon-outline"><svg ... /></button> <button class="btn-icon btn-icon-outline btn-sm"><svg ... /></button>
Operational variants
Specialized buttons for control-panel UIs: a hard-stop and a compact rollback.
<button class="btn-stop">Stop all dialing <span class="tag tag-danger">Hard stop</span></button> <button class="btn-rollback">Rollback</button>
Button group
<div class="btn-group"> <button class="btn btn-sm active">Day</button> <button class="btn btn-sm">Week</button> <button class="btn btn-sm">Month</button> </div>
Card
The primary container. White surface, 1px border, 8px radius, 16px padding. Add .card-disabled for a locked state.
vs 22,184 last month
This will permanently delete the selected items. This action cannot be undone.
Controls are disabled while another operation is in progress.
<div class="card"> <div class="card-header"> <div class="card-title">Monthly active</div> <span class="tag tag-success">+12%</span> </div> <p class="card-desc">vs 22,184 last month</p> <div class="card-footer"> <button class="btn btn-ghost">Cancel</button> <button class="btn btn-danger btn-sm">Delete</button> </div> </div>
Checkbox
16px square, fills with the brand cobalt when checked. Pair with .field-check wrapper for inline labels.
<label class="field-check"> <input type="checkbox" class="checkbox"> <span class="field-check-label">Subscribe to updates</span> </label>
Command
Searchable action palette (⌘K). The list scrolls; groups are labeled with a small caps header.
<div class="command"> <div class="command-input-wrap"> <input class="command-input" placeholder="Search..."> <kbd>⌘K</kbd> </div> <div class="command-list"> <div class="command-group-label">Suggestions</div> <button class="menu-item">...</button> </div> </div>
Dialog
Centered modal with a blurred scrim. Use for confirmations, forms, and any flow that should block the rest of the page.
Accessibility: render with role="dialog" aria-modal="true" and point aria-labelledby at the title. On open, move focus into the dialog and trap Tab inside it; on close, return focus to the trigger and dismiss on Esc. The demo above does this.
<div class="dialog-overlay"></div> <div class="dialog"> <div class="dialog-header"> <div class="dialog-title">Delete this segment?</div> <p class="dialog-desc">This action can't be undone.</p> </div> <div class="dialog-body">...</div> <div class="dialog-footer"> <button class="btn btn-ghost">Cancel</button> <button class="btn btn-danger">Delete</button> </div> </div>
Dropdown Menu
List-of-actions menu. Supports icons, keyboard shortcuts, grouped sections, and a destructive variant.
<div class="menu"> <div class="menu-label">Account</div> <button class="menu-item"> <svg class="menu-item-icon"></svg> Profile <span class="menu-item-shortcut">⇧ ⌘ P</span> </button> <div class="menu-separator"></div> <button class="menu-item menu-item-danger">Sign out</button> </div>
Empty State
Centered placeholder for tables, search results, and feature onboarding. Always include an icon and a primary action.
<div class="empty-state"> <div class="empty-state-icon"><svg /></div> <div class="empty-state-title">No results found</div> <div class="empty-state-desc">Try adjusting your filters.</div> <div class="empty-state-actions"><button class="btn btn-primary btn-sm">New search</button></div> </div>
Input
32px tall, 6px radius. Full width by default; .input-sm (24px) for inline numeric fields, .input-lg (40px) for hero inputs. Pair with .label, .helper, and .field-error.
We'll never share your email.
<label class="label" for="email">Email</label> <input class="input" id="email" type="email" placeholder="you@example.com"> <p class="helper">We'll never share your email.</p> <!-- Sizes --> <input class="input input-sm" type="number"> <input class="input input-lg" type="search">
States
Please enter a valid email address.
Input group (addons)
<div class="input-group"> <span class="input-group-addon">https://</span> <input class="input" placeholder="example.com"> </div>
Pagination
<nav class="pagination"> <button class="pagination-item">1</button> <button class="pagination-item active">2</button> <span class="pagination-ellipsis">…</span> </nav>
Popover
Click-anchored floating panel. Use for rich content — forms, color pickers, inline editors.
<div class="popover"> <div class="popover-header">Quick settings</div> ... </div>
Progress
6px-tall bar with a brand cobalt fill by default. Use .progress-bar-danger or .progress-bar-warning for critical states.
<div class="progress"> <span class="progress-bar" style="width: 62%;"></span> </div>
Spinner
Radio
Single-selection variant. Same sizing and color treatment as Checkbox.
<label class="field-check"> <input type="radio" name="plan" class="radio"> <span class="field-check-label">Starter</span> </label>
Select
Native select with a custom chevron. Matches input height and focus styles.
<select class="select"> <option>United States</option> <option>United Kingdom</option> </select>
Sheet
Side-anchored drawer. Use for detail panels, filter sets, and contextual forms that should stay accessible alongside the main view.
Accessibility: same contract as the dialog — role="dialog" aria-modal="true", aria-labelledby on the title, focus moved in and trapped on open, returned to the trigger on close, Esc to dismiss.
<div class="sheet"> <div class="sheet-header">...</div> <div class="sheet-body">...</div> <div class="sheet-footer">...</div> </div>
Sidebar
The application sidebar. .sidebar is the full 240px form with labeled links and grouped sections. Add .sidebar--rail for the collapsed, icon-only rail at --sidebar-w (56px). Active state is .sidebar-link.active; icons use currentColor, so they inherit --text-tertiary and shift to --text-primary when active. A Shift-branded example lives at sidebar-rail.html.
<!-- Collapsed icon rail --> <aside class="sidebar sidebar--rail"> <div class="sidebar-header">…brand…</div> <div class="sidebar-group"> <a class="sidebar-link active"><svg class="sidebar-link-icon" /></a> <a class="sidebar-link"><svg class="sidebar-link-icon" /></a> </div> </aside>
Skeleton
Animated shimmer placeholder. Use any width/height — it inherits the rounded corner of its parent or you can set border-radius directly.
<div class="skeleton" style="height:10px; width:60%;"></div> <div class="skeleton" style="width:34px; height:34px; border-radius:var(--radius-full);"></div>
Slider
Range input with pill track and circular thumb. Pair with .slider-val for a display-font numeric readout.
<div class="slider-wrap"> <input type="range" class="slider" min="1.0" max="2.0" step="0.1" value="1.2"> <span class="slider-val">1.2</span> </div>
Status Chip
Pill-shaped semantic status indicators. Always pair with a .chip-dot that inherits the chip color.
<span class="chip chip-ok"> <span class="chip-dot"></span>Active </span>
Status dots
Switch
Toggle for boolean settings. Use when the state takes effect immediately; use Checkbox when paired with a form submission.
<label class="field-check"> <input type="checkbox" class="switch" checked> <span class="field-check-label">Email notifications</span> </label>
Table
Borderless by default — relies on light row dividers. Add .table-bordered for a card-wrapped variant.
| Name | Role | Status | Calls today | |
|---|---|---|---|---|
SCSasha Chen |
Senior Agent | Available | 84 | |
TOTobi Okafor |
Manager | On call | 62 | |
JLJamie Lee |
Agent | Away | 47 |
<table class="table"> <thead><tr> <th>Name</th> <th class="td-num">Calls</th> </tr></thead> <tbody><tr> <td class="td-primary">Sasha Chen</td> <td class="td-num td-primary">84</td> </tr></tbody> </table>
Tabs
Two variants: bottom-border tabs for primary navigation, pill tabs for filter/segment switching.
Overview content goes here. Switch tabs to see different panels.
<div class="tabs-list"> <button class="tab active">Overview</button> <button class="tab">Activity</button> </div> <div class="tab-panel">...</div>
Tag & Badge
Tags are loud: all-caps, semantic-colored fill. Badges are quiet: muted, used for metadata.
<span class="tag tag-danger">Hard stop</span> <span class="tag tag-success">Active</span> <span class="badge">rolled back</span>
Textarea
Multiline input, vertically resizable, with a 72px minimum height.
Markdown is supported.
<textarea class="textarea" placeholder="Add a note..."></textarea>
Toast
Transient feedback. Anchor to a corner (usually bottom-right) and stack.
<div class="toast"> <svg class="toast-icon"></svg> <div class="toast-body"> <div class="toast-title">Changes applied</div> <div class="toast-desc">Detail…</div> </div> </div>
Tooltip
Hovers show after a short delay. Always wrap in .tooltip-wrap for the auto-show behavior.
<div class="tooltip-wrap"> <button class="btn btn-outline">Hover me</button> <div class="tooltip" data-side="top">Tooltip text</div> </div>