Skip to content

Folio component catalog ​

Live variants and states. Buttons, forms and feedback update local state only. Use keyboard Tab to inspect focus. Search the sample table for an empty state; open the native dialog and press Escape.

Atoms

Button

Pressed 0 times

Icon button / Button group

Badge / Status / Tag

NeutralSuccessWarningDangerInfoOutline

Avatar / Avatar group

JDAMNS
NSJD+4
NS

Input / Label / Helper

Default with helper text.Type to preview the invalid state.

Textarea / Select

Checkbox / Radio

Switch / Slider

On

Progress / Spinner / Skeleton

Loading state

Text / Amount / Separator

$128,450.80

Body text for decisions and context.

Secondary content stays readable.
tabular-nums · 123456

Validation and risk use semantic color.

Molecules

Alert

success Sample feedback. No account action.
warning Sample feedback. No account action.
danger Sample feedback. No account action.
info Sample feedback. No account action.

Card / KPI

Available balance
$128,450.80

↗ 12.8% vs. last month

3 sample accounts

Tabs

Overview sample content. Keyboard-focusable native buttons.

Accordion / Details

Billing details

Example monthly plan. No purchase.

Payment methods

No card is connected in this demo.

Workspace permissions

Illustrative member roles.

Dialog / Drawer

Close with Escape or the close control. No outside action.

Review local change

This is a native modal preview.

Menu / Popover / Tooltip

Search / Table / Empty state

CompanyStatusAmount
NorthstarCompleted$4,200
AtlasPending$1,800
PineFailed$750
FieldCompleted$3,100

Pagination / Breadcrumb / Stepper

  1. Details
  2. Review
  3. Complete

Toast / Notification / List item

NS
NorthstarMonthly report ready
New
JD
JordanApproved a sample payment
2h ago

Charts

Line / Area / Sparkline

Trend colors identify a series, not approval.

Bar / Stack / Distribution

Payroll 74% · Operations 18% · Growth 8%

Donut / Progress ring

78%

Cash-flow comparison

Received$86,250
Spent$64,820
Fictitious values. No connected data.

Layouts

Sidebar / Header / Navigation

Workspace

Overview

Form / Validation / Action footer

Workspace details

Native modal drawer with Escape and focus containment.

Catalog coverage ​

Button, icon button, button group, badge, status, tag, avatar, avatar group, label, input, helper/error, textarea, select, checkbox, radio, switch, slider, progress, spinner, skeleton, amount/text, separator, alert, card/KPI, tabs, details/accordion, dialog, drawer, menu/popover, tooltip, search, table/empty state, pagination, breadcrumb, stepper, toast, notification/list item, charts and app/form layouts.

Menus are lightweight illustrative patterns. Dialogs and drawers use native modal focus containment and Escape. A production application should add its own menu keyboard navigation and routing. No live preview sends or purchases anything.

Extended variants

Local, keyboard-focusable examples. File selection stays in this page; nothing is uploaded.

Buttons: variants and outline

Buttons: sizes and disabled

Buttons: full width and shapes

Buttons: active, icons, counters and loading

Button groups: sizes, toolbar and vertical

Button groups: checks, radio and dropdown

Badges: variants, pill, square, dot and positioned

successwarningdangerinfoPillSquareOnline

Alerts: variants, actions, icon and dismissible

ⓘ Report ready

Your fictitious report is available.

⚠ Review needed
✓ Complete
! Local error sample

Cards: header, footer, image and horizontal

Monthly report

Card body with a generated CSS illustration.

Updated today
Team reportHorizontal layout

Cards: highlighted, list and grid groups

Highlighted card

Use emphasis for a decision, not every surface.

Grid 1
Grid 2
List group 1
List group 2

Forms: sizes, textarea and file

No file selected

Forms: validation, input groups and floating labels

Helper text.

Select, checks, radio, switches and range

Navigation: tabs, vertical and panes

Overview content

Pagination, breadcrumbs, steps and keys

  1. Details
  2. Review
  3. Done

Search ⌘ K · Close Esc

Modal, offcanvas, popover and tooltip

Popover details

Local context. Native disclosure.

Progress, spinners and placeholders

Loading example
Placeholder text

List groups: active, disabled and actions

Tables: basic, striped, hover, border, compact and states

StatusAmount
NorthstarSuccess$4,200
AtlasWarning$1,800
PineDanger$750
Striped, hover, bordered, compact and dark-header variants combined here. Status remains textual.

Accordion and collapse

Extended accordion

Native keyboard disclosure.

Carousel

Manual navigation only. No automatic timer.

Avatars, stacks and toast

NSJDAM
NSJD+2

Language select and navbar

English selected. Demo selection, not whole-site translation.

Date picker and choice cards

Hover card, notifications and error/retry

Northstar profileNorthstarSample workspace · 4 members
NS
Report readyNotification from local demo
Could not load the fictitious report.

Message, attachment and close control

Jordan

The draft report is ready for review.

Local message sample, not sent.

⌕ report.pdf · sample attachment

Navigation menu, sidebar, footer and scrollspy

Summary

Anchor navigation keeps the section visible.

Details

Second sample section.

Active section: Summary. Native anchors and observed scroll position.

Extended modal

Extended offcanvas

Native modal focus and Escape.

Extended coverage checklist ​

These patterns match the Felix/Lumen extended catalog, with Folio tokens. Base patterns appear in the live catalog above; extended variants follow it.

  • Buttons: variants
  • Buttons: outline
  • Buttons: sizes
  • Buttons: disabled
  • Buttons: block and full width
  • Buttons: shapes
  • Buttons: active and toggle
  • Buttons: with icons and counters
  • Buttons: loading
  • Button groups: basic and sizes
  • Button groups: toolbar and vertical
  • Button groups: checkbox and radio style
  • Button groups: with dropdown
  • Badges: variants
  • Badges: pill, square, dot and in buttons
  • Badges: positioned on a button
  • Alerts: variants
  • Alerts: with heading and actions
  • Alerts: dismissible and with icon
  • Cards: basic, header and footer
  • Cards: with image, horizontal and highlighted
  • Cards: list and grid groups
  • Forms: text inputs
  • Forms: sizes, textarea and file
  • Forms: validation
  • Forms: input groups
  • Forms: floating labels and layout
  • Select: variants
  • Checks and radios
  • Switches
  • Range
  • Nav and tabs
  • Nav: vertical and tab panes
  • Pagination
  • Breadcrumbs
  • Dropdowns
  • Modals
  • Tooltips
  • Popovers
  • Progress
  • Spinners
  • List groups
  • Tables: basic, striped and hover
  • Tables: bordered, small, dark header and states
  • Accordion
  • Collapse
  • Toasts
  • Offcanvas
  • Carousel
  • Avatars and stacks
  • Placeholders and skeletons
  • Steps and keyboard keys
  • Language select
  • Navbar

Complete family reference ​

Usage, copyable markup and keyboard notes for the same 43 core families as the other systems, using Folio tokens.

folio / UI library

Every component, in context.

43 families · Live previews · Usage · Markup · Keyboard notes

Buttons

Primary is for one leading action per surface. Secondary is for peer actions. Destructive uses semantic red, never the brand gradient.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><button class="l-btn l-primary" @click="showToast('Primary action selected')">Primary action</button><button class="l-btn l-secondary" @click="showToast('Secondary action selected')">Secondary</button><button class="l-btn l-quiet" @click="showToast('Quiet action selected')">Quiet</button><button class="l-btn l-danger" @click="openNative('modal',$event)">Delete...</button><button class="l-btn l-secondary" disabled>Disabled</button></div>

Button group

Button group chooses one mode; the adjacent dropdown holds secondary actions.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><div class="l-segment" aria-label="Display mode"><button v-for="item in ['Design','Code','Preview']" :key="item" :aria-pressed="choice===item" :class="{'is-active':choice===item}" @click="choice=item">{{ item }}</button></div></div>

Pagination

Lustro foundation ↗

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><a href="/lustro">Lustro foundation ↗</a><nav class="l-pages" aria-label="Example pages"><button @click="page=Math.max(1,page-1)" :disabled="page===1">Previous</button><span>Page {{page}} / 3</span><button @click="page=Math.min(3,page+1)" :disabled="page===3">Next</button></nav></div>

Alerts

Alerts occupy the page and stay until dismissed. Notifications need a clear source, severity and next action. Do not use color alone to explain the state.

Saved

Your changes are up to date.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><div v-if="alertOpen" class="l-alert l-alert-warn" role="alert"><div><strong>Needs attention</strong><p>Two checks are waiting for a review.</p></div><button class="l-icon-btn" aria-label="Dismiss notification" @click="alertOpen=false">×</button></div><button v-else class="l-btn l-secondary" @click="alertOpen=true">Show notification again</button><div class="l-alert l-alert-success"><div><strong>Saved</strong><p>Your changes are up to date.</p></div></div></div>

Toasts

A toast confirms a short-lived result; it must never be the only place for an error that needs fixing. Trigger several in quick succession: each one stays visible independently until dismissed or its six-second timer ends. Color, a label and a message communicate the variant together.

For production, keep independent IDs and timers so a new arrival never overwrites an earlier one. Render the stack in a portal above app content, cap its height and let it scroll on small screens. Keep errors that need user action inline too; the toast is only a short announcement. Respect reduced-motion when animating entry and exit.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><button class="l-btn l-primary" @click="showToast('Changes saved', 'success')">Show toast</button><button class="l-btn l-secondary" @click="showToast('Secondary action queued', 'info')">Show secondary toast</button><button class="l-btn l-secondary" @click="showToast('Review before continuing', 'warn')">Show warning</button><button class="l-btn l-secondary" @click="showToast('Could not save changes', 'error')">Show error</button></div>
<div class="l-toast-stack" aria-label="Toast notifications"><div v-for="item in toasts" :key="item.id" class="l-toast" :class="'l-toast-' + item.type" :role="item.type === 'error' ? 'alert' : 'status'"><span class="l-dot" :class="'l-dot-' + item.type" aria-hidden="true"></span><span class="l-toast-copy"><strong>{{ { success: 'Success', info: 'Info', warn: 'Warning', error: 'Error' }[item.type] }}</strong><span>{{ item.message }}</span></span><button class="l-icon-btn" :aria-label="'Dismiss ' + item.type + ' toast: ' + item.message" @click="dismissToast(item.id)">×</button></div></div>
<p>For production, keep independent IDs and timers so a new arrival never overwrites an earlier one. Render the stack in a portal above app content, cap its height and let it scroll on small screens. Keep errors that need user action inline too; the toast is only a short announcement. Respect reduced-motion when animating entry and exit.</p>

Badge

DraftReadyRunningBlocked

Use a short label with text, not a color alone. The grouped demo below includes four states.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><span class="l-badge">Draft</span><span class="l-badge l-badge-success">Ready</span><span class="l-badge l-badge-warn">Running</span><span class="l-badge l-badge-error">Blocked</span></div>
<p>Use a short label with text, not a color alone. The grouped demo below includes four states.</p>

Progress

68%

Progress has a value and a max; use an indeterminate loader only when no useful estimate exists.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><label class="l-field-label" for="sample-progress">Upload progress · 68%</label><progress id="sample-progress" max="100" value="68">68%</progress></div>
<p>Progress has a value and a max; use an indeterminate loader only when no useful estimate exists.</p>

Spinners/Loaders

Name the loading region for assistive technology.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><span class="l-spinner" role="status" aria-label="Loading"></span></div>
<p>Name the loading region for assistive technology.</p>

Placeholders

Loading summary...

Skeletons reserve space while content loads; do not leave them in a permanent empty state.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><div class="l-skeleton" aria-hidden="true"></div><p>Loading summary...</p></div>
<p>Skeletons reserve space while content loads; do not leave them in a permanent empty state.</p>

Card

Use a compact summary with a clear title, metadata and the next action; keep card links and nested buttons separate.

PROJECT · REPO A

Review changes

The latest request is waiting for your review.

Needs review
TASK · 024

Ready to ship

Checks completed. The next step is a merge.

Ready

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-grid"><article class="l-card"><span class="l-eyebrow">PROJECT · REPO A</span><h3>Review changes</h3><p>The latest request is waiting for your review.</p><div class="l-card-foot"><span class="l-badge l-badge-warn">Needs review</span><button class="l-btn l-secondary" @click="showToast('Card action selected')">Open</button></div></article><article class="l-card"><span class="l-eyebrow">TASK · 024</span><h3>Ready to ship</h3><p>Checks completed. The next step is a merge.</p><div class="l-card-foot"><span class="l-badge l-badge-success">Ready</span><button class="l-btn l-secondary" @click="showToast('Card action selected')">Details</button></div></article></div>

Accordion

Use the shared color, type and spacing tokens.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><div v-for="item in ['Tokens','Behavior','Accessibility']" :key="item" class="l-accordion"><button :aria-expanded="accordion===item" @click="accordion=accordion===item?'':item">{{item}} <span>{{accordion===item?'−':'+'}}</span></button><p v-if="accordion===item">{{item==='Tokens'?'Use the shared color, type and spacing tokens.':item==='Behavior'?'Keep transitions short and tied to a state change.':'Use labels, visible focus and reduced-motion fallbacks.'}}</p></div></div>

List group

  • 01 · Surface tokensDocs
  • 02 · Component statesReady

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><ul class="l-list"><li><span>01 · Surface tokens</span><span class="l-badge">Docs</span></li><li><span>02 · Component states</span><span class="l-badge l-badge-success">Ready</span></li></ul></div>

Tables

ComponentStatusOwner
ButtonsReadyDesign
NotificationsReviewProduct
GraphsExampleMotion
No results

Try a different search or clear your filters.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><div class="l-table-scroll"><table class="l-table"><thead><tr><th scope="col">Component</th><th scope="col">Status</th><th scope="col">Owner</th></tr></thead><tbody><tr><td>Buttons</td><td><span class="l-badge l-badge-success">Ready</span></td><td>Design</td></tr><tr><td>Notifications</td><td><span class="l-badge l-badge-warn">Review</span></td><td>Product</td></tr><tr><td>Graphs</td><td><span class="l-badge">Example</span></td><td>Motion</td></tr></tbody></table></div><div class="l-empty"><strong>No results</strong><p>Try a different search or clear your filters.</p><button class="l-btn l-secondary" @click="search=''">Clear filters</button></div></div>

Forms

Use descriptive labels, not only placeholders.
Density

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><label class="l-field-label" for="sample-search">Search components</label><input id="sample-search" type="search" v-model="search" placeholder="Search by name"><small>{{search?`Searching for “${search}”`:'Use descriptive labels, not only placeholders.'}}</small><label class="l-field-label" for="sample-select">Category</label><select id="sample-select"><option>All components</option><option>Actions</option><option>Feedback</option><option>Content</option></select><label class="l-field-label" for="sample-notes">Notes</label><textarea id="sample-notes" rows="2" placeholder="Optional notes"></textarea><label class="l-check"><input type="checkbox" checked> Send updates</label><fieldset><legend>Density</legend><label class="l-check"><input type="radio" name="density" checked> Comfortable</label><label class="l-check"><input type="radio" name="density"> Compact</label></fieldset><label class="l-switch"><input type="checkbox" checked><span aria-hidden="true"></span> Enable notifications</label></div>

Tooltips

Optional help appears on hover and keyboard focus. Required instructions stay visible.

Changes apply to this workspace.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><span class="kit-tooltip"><button class="l-btn l-secondary" aria-describedby="kit-tip">Focus or hover for help</button><span id="kit-tip" role="tooltip">Changes apply to this workspace.</span></span></div>

Popovers

The adjacent disclosure stays open for longer text.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><details class="l-dropdown"><summary>More information</summary><div class="l-menu l-popover">This content stays visible until you close the panel.</div></details></div>

Close button

Use an accessible name and a hit area large enough to tap. The toast is an illustration, not a destructive action.

Close a dismissible panel

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><button class="l-close" aria-label="Close sample panel" @click="showToast('Sample panel closed')">×</button><span>Close a dismissible panel</span></div>

Collapse

For one block of secondary detail, prefer native disclosure. Accordion above coordinates several blocks.

Show delivery details

Open with Enter or Space without losing context.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><details class="l-collapse"><summary>Show delivery details</summary><p>Open with Enter or Space without losing context.</p></details></div>

Offcanvas

Drawer / sheet / offcanvas: contextual details beside the current view. Native modal behavior includes Escape and focus containment.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><button class="l-btn l-secondary" @click="openNative('sheet',$event)">Open side panel</button></div>

Scrollspy

Select a section to bring it into view; the active state is also exposed as text.

Inicio

Section inicio selected.

This is a section-selection preview, not automatic scroll tracking. Production scrollspy should use IntersectionObserver to update aria-current.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><nav class="l-spy-nav" aria-label="Example sections"><button v-for="item in ['Home','Details','Summary']" :key="item" :aria-current="menuSection===item?'location':undefined" @click="menuSection=item">{{item}}</button></nav><div class="l-card" aria-live="polite"><strong>{{menuSection}}</strong><p>Section {{menuSection.toLowerCase()}} selected.</p></div></div>
<p>This is a section-selection preview, not automatic scroll tracking. Production scrollspy should use IntersectionObserver to update aria-current.</p>

Notifications

A persistent inbox for events that need attention, distinct from short-lived toasts.

Notifications2 unread
  • Unread · Dana requested a project review4 minutes ago
  • Unread · Budget approved1 hour ago

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><div class="l-actions"><strong>Notifications</strong><span class="l-badge">{{notificationsRead?0:2}} unread</span><button class="l-btn l-secondary" @click="notificationsRead=!notificationsRead">{{notificationsRead?'Reset unread':'Mark all read'}}</button></div><ul class="l-list"><li><span>{{notificationsRead?'Read':'Unread'}} · Dana requested a project review</span><small>4 minutes ago</small></li><li><span>{{notificationsRead?'Read':'Unread'}} · Budget approved</span><small>1 hour ago</small></li></ul></div>

Attachment and file upload

Native file selection, filename and size. This preview never uploads a file.

No file selectedLocal selection only. Production: validate type and size on the server.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><label>Attach a PDF or text file<input type="file" accept=".pdf,.txt" @change="selectFile"></label><span class="l-badge">{{pickedFile}}</span><small>Local selection only. Production: validate type and size on the server.</small></div>

Date picker

Use locale-aware native date input for a single date; see Calendar for richer scheduling.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><label>Due date<input type="date" value="2026-10-15"></label><label>Date and time<input type="datetime-local"></label></div>

Choice card

A larger radio target for options with descriptions. Arrow keys move between native radios.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-grid"><label class="l-card"><input type="radio" name="delivery" checked> <strong>Weekly summary</strong><p>A weekly overview of your workspace.</p></label><label class="l-card"><input type="radio" name="delivery"> <strong>Daily summary</strong><p>Updates at the end of each day.</p></label></div>

Stepper

Show a finite workflow. Production steps must not bypass required validation.

  1. 1. Details
  2. 2. Review
  3. 3. Done

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><ol class="l-actions"><li v-for="(s,i) in ['Details','Review','Done']" :aria-current="step===i+1?'step':undefined" :class="{'l-badge':step===i+1}">{{i+1}}. {{s}}</li></ol><div class="l-actions"><button class="l-btn l-secondary" :disabled="step===1" @click="step--">Back</button><button class="l-btn l-secondary" :disabled="step===3" @click="step++">Continue</button></div></div>

Hover card

Optional rich context. Native disclosure also makes the information available without a mouse.

Dana Lee · Coach details
Dana Lee

Lead coach · 12 classes this month

Available

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><details><summary>Dana Lee · Coach details</summary><article class="l-card"><strong>Dana Lee</strong><p>Lead coach · 12 classes this month</p><span class="l-badge l-badge-success">Available</span></article></details></div>

Message

Keep sender and time with the content. Incoming, outgoing and system states have different roles.

Dana · 10:42

Ready for review.

You · 10:43

I will check the task list.

System · Review requested

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo"><article class="kit-bubble"><strong>Dana · 10:42</strong><p>Ready for review.</p></article><article class="kit-bubble outgoing"><strong>You · 10:43</strong><p>I will check the task list.</p></article><small>System · Review requested</small></div>

Range slider

For approximate numeric settings; always show the current value. Arrow keys adjust the native slider.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><label>Volume<input type="range" min="0" max="100" v-model="volume"><output>{{volume}}%</output></label></div>

Input group

Combine a field with units or a related action while retaining a visible label.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><label>Budget (USD)<div class="l-actions"><span>$</span><input type="number" min="0" value="1200"><button class="l-btn l-secondary" @click="showToast('Demo budget updated','success')">Apply</button></div></label></div>

Validation and field states

Validate after interaction, preserve entered values, and connect errors to the field.

Use a short unique name

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><form @submit.prevent="formSent=true" novalidate><label>Project name<input v-model="formName" required :aria-invalid="formSent&&!formName.trim()" aria-describedby="kit-validation"></label><small id="kit-validation" role="status">{{formSent?(formName.trim()?'Demo saved':'Enter a project name'):'Use a short unique name'}}</small><label>Read-only reference<input value="PRJ-042" readonly></label><label>Disabled field<input value="Managed by workspace" disabled></label><button class="l-btn l-secondary" type="submit">Validate demo</button></form></div>

Error and retry

Explain the failure, keep context, and offer recovery. This retry is local simulation.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo" :role="failed?'alert':'status'"><strong>{{failed?'Could not load projects':'Demo projects loaded'}}</strong><p>{{failed?'Your previous changes are safe. Try again.':'Connection restored (simulation).'}}</p><button class="l-btn l-secondary" @click="failed=!failed">{{failed?'Try again':'Reset error'}}</button></div>

Empty state

Explain why there is no content and offer one useful next action.

No projects yet

Create a project to start tracking work.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-empty"><strong>No projects yet</strong><p>Create a project to start tracking work.</p><button class="l-btn l-secondary" @click="showToast('Demo project created','success')">Create demo project</button></div>

Select and suggestions

Use select for a fixed set. Datalist is browser-native suggestions, not a full custom combobox.

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><label>Priority<select><option>Normal</option><option>High</option><option>Low</option></select></label><label>Owner suggestions<input list="kit-owners" placeholder="Type a name"></label><datalist id="kit-owners"><option value="Dana Lee"/><option value="Marcos Silva"/></datalist></div>

Checkbox, radio and switch

Choose many values with checkboxes, one with radios, and immediate on/off settings with a switch.

Plan

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-form"><label><input type="checkbox" checked> Email updates</label><label><input type="checkbox" disabled> Managed option (disabled)</label><fieldset><legend>Plan</legend><label><input type="radio" name="kit-plan" checked> Personal</label><label><input type="radio" name="kit-plan"> Team</label></fieldset><label class="l-switch"><input type="checkbox" role="switch" checked><span aria-hidden="true"></span> Automatic reminders</label></div>

Avatar

Initials fallback and text status. Noninteractive avatars do not need a tab stop.

DLMSAvailable

Keyboard: Tab to interactive controls. Enter activates buttons and links; Space toggles native choices. Disabled controls cannot be activated. Use Escape to close modal surfaces.

Copy implementation markup
<div class="l-demo l-actions"><span class="l-avatar" role="img" aria-label="Dana Lee">DL</span><span class="l-avatar" role="img" aria-label="Marcos Silva">MS</span><span>Available</span></div>

Archive project?

This is a local demo. No project is changed.

Project details

Dana Lee · Launch checklist