new labs released: weekly ship meetup, strand ui component library (MIT Licensed), JOBINT search, trust code signing cli

Strand Design Language

Open Source
STRAND

Design tokens + UI components. Zero-runtime CSS. Ship faster.

Install

npm install @dillingerstaffing/strand @dillingerstaffing/strand-ui
npm install @dillingerstaffing/strand @dillingerstaffing/strand-vue
npm install @dillingerstaffing/strand @dillingerstaffing/strand-svelte
npm install @dillingerstaffing/strand @dillingerstaffing/strand-ui

Use CSS classes directly. HTML Reference

npm install @dillingerstaffing/strand @dillingerstaffing/strand-ui bulma

Then import @dillingerstaffing/strand/bulma/strand-bulma-compat.css after Bulma. Migration guide

Or run npx strand-ui init to auto-detect your framework. CDN also available.

Features

Components 34

Input, display, layout, navigation, feedback, surface, and animation. Every interaction state.

Runtime CSS 0

All tokens are CSS custom properties. No ThemeProvider. No CSS-in-JS. No runtime cost.

Accessibility AA

WCAG 2.2 AA. Every color pairing passes contrast. WAI-ARIA compliant. Reduced motion.

Bundle <50KB

Total gzipped. Static CSS. Tree-shakeable. Framework-agnostic tokens.

Patterns

What are you building?

Sign-up flow
FormField + Input + Button
Alerts and toasts
Saved
Your changes are live.
Alert + Toast
Navigation
Breadcrumb + Tabs
Live metrics
Revenue $94K
DataReadout
Content card
BETA Team roles

Invite teammates, assign roles, and keep permissions in sync across projects.

Card + Tag + Stack
Showcases

Strand UI Showcases

Showcases are graduating.

Check back soon.

Setup

Get running in three steps

1

Install

npm install @dillingerstaffing/strand @dillingerstaffing/strand-ui
2

Import CSS

@import '@dillingerstaffing/strand/css/reset.css';
@import '@dillingerstaffing/strand/css/tokens.css';
@import '@dillingerstaffing/strand/css/base.css';
@import '@dillingerstaffing/strand-ui/css/strand-ui.css';

Components are unstyled without these imports.

3

Use

import { Button, Card, Stack } from '@dillingerstaffing/strand-ui';

<Card variant="elevated">
  <Stack gap={4}>
    <Button>Get Started</Button>
  </Stack>
</Card>

Preact: Works natively, no configuration needed.

React: Alias preact in your bundler; see framework setup.

Vue 3: Use strand-vue; components register as native Vue SFCs.

Svelte: Use strand-svelte; components register as native Svelte components.

CSS Only: Use classes directly per HTML Reference.

Bulma: Load the Strand Bulma theme for visual cohesion.

Reference

Every component, rendered

Input

Button

Primary action trigger. 4 variants, 3 sizes, loading state.

Variants
Size
State
PropTypeDefault
variant"primary" | "secondary" | "ghost" | "danger""primary"
size"sm" | "md" | "lg""md"
loadingbooleanfalse
iconOnlybooleanfalse
fullWidthbooleanfalse
disabledbooleanfalse
<Button variant="primary" size="md">Submit</Button>

Input

Single-line text entry. 5 types, leading/trailing addons, error state.

PropTypeDefault
type"text" | "email" | "password" | "search" | "number""text"
errorbooleanfalse
leadingAddonReactNode-
trailingAddonReactNode-
disabledbooleanfalse
<Input type="email" placeholder="[email protected]" />

Textarea

Multi-line text entry. Auto-resize, character count, error state.

PropTypeDefault
autoResizebooleanfalse
showCountbooleanfalse
maxLengthnumber-
errorbooleanfalse
<Textarea autoResize placeholder="Message" />

Select

Option selection. Native select with custom styling and error state.

PropTypeDefault
optionsSelectOption[][]
valuestring-
errorbooleanfalse
placeholderstring-
<Select options={items} onChange={handleChange} />

Checkbox

Binary toggle for multiple selections. Supports indeterminate state.

PropTypeDefault
checkedbooleanfalse
indeterminatebooleanfalse
labelstring-
disabledbooleanfalse
<Checkbox checked={value} onChange={fn} label="Accept terms" />

Radio

Single selection from a set. Group with shared name attribute.

PropTypeDefault
checkedbooleanfalse
namestring-
valuestring-
labelstring-
<Radio name="plan" value="pro" label="Pro plan" />

Switch

Binary toggle for a single setting. On/off with inline label.

PropTypeDefault
checkedbooleanfalse
labelstring-
onChange(checked: boolean) => void-
<Switch checked={enabled} onChange={setEnabled} label="Notifications" />

Slider

Range value selection with single thumb.

PropTypeDefault
minnumber0
maxnumber100
stepnumber1
valuenumber50
<Slider min={0} max={100} value={vol} onChange={setVol} />

FormField

Wraps any input with label, hint text, error message, and required indicator.

As it appears on your ID.

PropTypeDefault
labelstring-
hintstring-
errorstring-
requiredbooleanfalse
<FormField label="Email" error={err} required>
  <Input type="email" />
</FormField>

Display

Card

Content container. Elevated, outlined, or interactive with hover lift.

Elevated
Outlined
Interactive (hover lifts)
PropTypeDefault
variant"elevated" | "outlined" | "interactive""elevated"
padding"none" | "sm" | "md" | "lg""md"
<Card variant="elevated" padding="lg">...</Card>

Badge

Status dot or count indicator. 5 status colors.

5 99+
PropTypeDefault
variant"dot" | "count""dot"
status"default" | "teal" | "blue" | "amber" | "red""default"
countnumber-
<Badge variant="count" status="red" count={notifications} />

Avatar

User or entity representation. Image, initials fallback. 4 sizes.

PropTypeDefault
srcstring-
initialsstring-
size"sm" | "md" | "lg" | "xl""md"
<Avatar src="/photo.jpg" alt="Jane" size="lg" />

Tag

Categorization label. Solid or outlined, removable, 5 status colors.

Default Teal Blue Amber Red Remove
PropTypeDefault
variant"solid" | "outlined""solid"
status"default" | "teal" | "blue" | "amber" | "red""default"
removablebooleanfalse
<Tag status="blue" removable onRemove={fn}>React</Tag>

Table

Tabular data display. Sortable headers, responsive horizontal scroll.

NameRoleStatus
Jane SmithEngineerActive
Alex ChenDesignerAway
PropTypeDefault
columnsTableColumn[]-
dataT[]-
onSort(key, direction) => void-
<Table columns={cols} data={rows} onSort={handleSort} />

DataReadout

Monospace instrument readout. Overline label + large value display.

Active Users 12,847
Uptime 99.97%
Latency 12ms
PropTypeDefault
labelstring-
valuestring | number-
size"sm" | "md" | "lg""md"
<DataReadout label="Revenue" value="$94,200" />

Layout

Stack

Flex layout primitive. Vertical or horizontal stacking with gap control.

PropTypeDefault
direction"vertical" | "horizontal""vertical"
gapnumber0
align"start" | "center" | "end" | "stretch""stretch"
wrapbooleanfalse
<Stack direction="horizontal" gap={4} align="center">...</Stack>

Grid

CSS grid layout primitive. Column count and gap control.

PropTypeDefault
columnsnumber1
gapnumber0
<Grid columns={3} gap={6}>...</Grid>

Container

Width constraint. 4 tiers: narrow (640px), default (768px), wide (1024px), full (1280px).

full 1280wide 1024default 768narrow 640
PropTypeDefault
size"narrow" | "default" | "wide" | "full""default"
<Container size="wide">...</Container>

Divider

Visual separator. Horizontal or vertical, with optional label.

PropTypeDefault
direction"horizontal" | "vertical""horizontal"
labelstring-
<Divider label="or" />

Section

Page section with consistent padding rhythm. Standard or hero variant.

Standard
Hero
PropTypeDefault
variant"standard" | "hero""standard"
background"primary" | "elevated" | "recessed""primary"
<Section variant="hero" background="elevated">...</Section>

Navigation

Tabs

Content switching. Full WAI-ARIA tabs with keyboard arrow navigation.

PropTypeDefault
tabsTabItem[]-
activeTabstring-
onChange(id: string) => void-
<Tabs tabs={items} activeTab={current} onChange={setTab} />

Breadcrumb

Hierarchical location indicator with custom separator.

PropTypeDefault
itemsBreadcrumbItem[]-
separatorstring"/"
<Breadcrumb items={[{ label: "Home", href: "/" }, { label: "Page" }]} />

Nav

Site or app navigation bar. Responsive hamburger collapse on mobile.

PropTypeDefault
logoReactNode-
itemsNavItem[]-
actionsReactNode-
<Nav logo={<Logo />} items={navItems}>
  <Button size="sm">Sign In</Button>
</Nav>

Feedback

Toast

Transient notification. 4 statuses. Auto-dismiss. Use with ToastProvider + useToast().

InfoNew version available.
CompleteProfile saved.
WarningLow storage.
ErrorSave failed.
PropTypeDefault
status"info" | "success" | "warning" | "error""info"
messagestring-
durationnumber (ms)5000
const { toast } = useToast();
toast({ message: "Saved!", status: "success" });

Alert

Persistent inline notification. 4 statuses, optional dismiss.

Info
You can sort columns by clicking the header.
Complete
Changes saved successfully.
PropTypeDefault
status"info" | "success" | "warning" | "error""info"
dismissiblebooleanfalse
onDismiss() => void-
<Alert status="success" dismissible onDismiss={fn}>Saved!</Alert>

Dialog

Modal overlay. Focus trap, escape-to-close, portal rendering, scroll lock.

PropTypeDefault
openbooleanfalse
onClose() => void-
titlestring-
closeOnEscapebooleantrue
<Dialog open={show} onClose={close} title="Confirm">
  Are you sure?
</Dialog>

Tooltip

Contextual hint on hover/focus. 4 positions, configurable delay.

Tooltip text
PropTypeDefault
contentstring-
position"top" | "right" | "bottom" | "left""top"
delaynumber (ms)200
<Tooltip content="More info" position="top">
  <Button>Hover me</Button>
</Tooltip>

Progress

Completion indicator. Bar or ring variant, determinate or indeterminate.

PropTypeDefault
variant"bar" | "ring""bar"
valuenumber (0-100)- (indeterminate)
size"sm" | "md" | "lg""md"
<Progress variant="ring" value={75} />

Spinner

Loading indicator. Thin ring animation with screen reader text.

Loading Loading Loading
PropTypeDefault
size"sm" | "md" | "lg""md"
<Spinner size="md" />

Skeleton

Content placeholder with shimmer animation. Text, rectangle, or circle.

PropTypeDefault
variant"text" | "rectangle" | "circle""text"
widthstring"100%"
heightstring"1em"
<Skeleton variant="text" width="200px" />
<Skeleton variant="circle" width="40px" height="40px" />

The Right Person. The Right Role.

Matches that last, by understanding what actually matters about a role, a team, and a person.