Use compact success signals when the interface needs calm confirmation without turning the row into a new surface.
Primitives
These examples stay inside shipped package classes. No demo helper layer is added on top.
Try primitives in the Playground when you want to test raw HTML snippets quickly, preview the same shipped CSS, icons, and JavaScript in an isolated HTML-only surface.
Primitive boundaries
Tables stay single-surface: wb-table-wrap owns the border and radius, any toolbar inside it stays a control row, and the table header remains a band instead of a second card. Text casing is content-defined throughout the system; hierarchy comes from weight, spacing, and color rather than automatic uppercase transforms so metadata stays quiet but clear.
| Need | Reach for | Why |
|---|---|---|
| Primary actions and status | wb-btn, wb-badge, wb-status-pill, wb-action-group | Use these when the page needs clear actions, compact signals, and row-level controls. |
| Grouped information and data display | wb-card, wb-stat, wb-list, wb-callout, wb-table | Cards, stats, lists, and callouts are surfaces. Tables remain primitives. Choose by UI role, not by folder location. |
| Orientation and section switching | wb-tabs, wb-pagination, pattern wb-breadcrumb | Use these when the page needs context or section changes, but keep breadcrumb secondary to the page title. |
| Temporary or layered interaction | wb-modal, wb-dropdown, wb-drawer, wb-accordion, wb-toast | Use these when the page needs temporary surfaces and explicit behavior hooks instead of hidden helper logic. Use wb-modal for structured dialogs, content-first viewer work, and cookie-consent preference centers. |
Actions and signals
Keep warnings concise so they act like state signals rather than full explanatory callouts.
Use danger states for destructive or high-risk conditions that need immediate recognition.
Active marks the current state without introducing extra helper markup.
Pending stays compact so data rows can surface progress without becoming mini dashboards.
Forms
Fields use a three-slot contract: label, control, and wb-field-meta. Keep hints and errors inside the shared meta area so multi-column wb-form-row layouts stay aligned even when sibling fields carry different assistive content. Do not place wb-field-hint or wb-field-error directly under wb-field. In stacked forms, empty meta rows are usually unnecessary.
| Field | Contract example |
|---|---|
| Project name | Hint: Use a short internal name. |
| Environment | Options: Production, Staging, Local. |
| Owner email | Hint: Enter a valid email address. |
| Region | Options: Frankfurt, London, Virginia. Hint: Used for billing and data residency. Error: This region is not available on the current plan. |
| Description | Placeholder: https:// |
| Admin password | Hint: Use the shipped input-group toggle instead of adding page-local password JS. |
| Enable analytics | Options: Private, Public, Maintenance mode. |
Surfaces and display contracts
Stats
Alerts
Recommended markup
<div class="wb-alert wb-alert-info">
<h3 class="wb-alert-title">Title</h3>
<p>Content...</p>
</div>
<div class="wb-alert wb-alert-info">
<p>Content only...</p>
</div>
Legacy wrapper markup still renders, but direct semantic headings and paragraphs are now the recommended pattern.
Users
| Name | Role | Status | Actions |
|---|---|---|---|
| Alice Brown | Owner | Active | Open |
| Marco Chen | Editor | Pending | Open |
Open in Playground when you want to combine these primitives into a real snippet before wiring them into a full page. Use td.wb-text-end directly when an action cell only needs end alignment.
Editorial body copy
wb-rich-text is the CSS-only primitive for sanitized editorial body copy after safe Markdown-like content has already been rendered to HTML. Keep headings, buttons, media, tables, layout composition, and raw HTML handling outside this primitive.
Readable body copy
Use this primitive for longer editorial copy where paragraphs, strong emphasis, tone shifts, inline code, and links should stay readable without leaking typography rules into the global page.
The readable modifier keeps the body-copy contract explicit, but width now comes from the parent card, shell, or content column instead of the primitive itself.
- Supports safe unordered lists.
- Keeps spacing predictable inside one scoped primitive.
- Render sanitized content first.
- Apply
wb-rich-textto the output wrapper.
Rich text is a body-copy contract, not a page builder. Compose headings, media blocks, tables, and actions with their own shipped primitives and patterns.
Rhythm variants
| Variant | Guidance |
|---|---|
| wb-rich-text wb-rich-text-compact | Compact rhythm fits denser panels, side notes, and shorter editorial summaries. Paragraph spacing tightens while list and quote behavior stays scoped to the same primitive. |
| wb-rich-text wb-rich-text-loose | Loose rhythm gives longer reading surfaces more air. Use it when the page wants calmer editorial pacing, not when you need a new layout wrapper or width rule. |
Pagination and context navigation
Use wb-pagination for page-based result sets. Keep it semantic: a nav landmark, an ordered list, a passive current-page marker with aria-current="page", and a passive disabled previous/next state when navigation is unavailable. Do not reuse it for breadcrumb hierarchy or content footer previous-next links.
Default rhythm
- Previous
- 1
- 2
- 3
- ...
- 12
- Next
Page 1 of 12
Current and disabled states are passive spans, not fake disabled links.
Compact table footer
- Previous
- 9
- 10
- 11
- Next
Use the compact variant only when the standard rhythm is too large for a dense table or narrow control row.
Interaction shells
Keep lightweight reveal-and-expand patterns close to the page, and reserve wb-modal for true top-layer dialog, viewer, or cookie-preference work.
Dropdown, popover, and tabs
Open. Duplicate. Archive.
Popover note
Use popover for small contextual panels that should not become full dropdown menus or modals.
Tabs switch between matched panels by data-wb-tab and panel id.
<button class="wb-tabs-btn" data-wb-tab="panel-id">Tab</button>
<div class="wb-tabs-panel" id="panel-id">...</div>
Accordion and drawer flows
Primitive questions
What counts as a primitive?
What does not count?
Modal: dialog and media viewer
Use wb-modal for two jobs: explicit decisions and content-first viewing.
Dialog modal
Use it when the user needs to confirm, cancel, continue, or make a focused decision above the page.
Media viewer modal
Use the same modal primitive for images and content previews. Both thumbnails below open one shared viewer modal.
- Workspace dashboard with charts and analytics cards.
- Product planning session around a shared table with laptops and notes.
Primitive modal
Use wb-modal when the interaction is a real dialog with explicit structure, decisions, or footer actions.
1 / 2
Overview dashboard
Use wb-modal in a content-first mode for gallery viewing instead of inventing a separate public overlay or lightbox primitive.
Primitive checklist
| Checklist | Guidance |
|---|---|
| Use shipped classes | Do not invent presentation-only names. |
| Use tokens indirectly | Stay inside package primitives and patterns when possible. |
| Use data hooks for behavior | Let shipped JavaScript handle overlays and interaction state. |