Forms & inputs
Insurance workflows live and die on forms. Every input is built for clear labeling, obvious errors, and fast keyboard entry — from simple text fields to complex search, filter, and menu interactions.
Text input
The foundational field pattern. Every text input requires a visible <label> associated via for/id. Hint text clarifies the expected format; error text replaces the hint when validation fails.
<div class="ws-field">
<label class="ws-field__label" for="fname">Named insured</label>
<input class="ws-input" id="fname" type="text" placeholder="Acme Manufacturing Co." />
<span class="ws-field__hint">Legal entity name as it appears on the policy.</span>
</div>Validation states
Error messages are specific and instructive. Use aria-describedby to associate the error with the field for screen readers. Never clear an error message before the user has corrected their input.
<div class="ws-field is-error">
<label class="ws-field__label" for="ferr">Effective date</label>
<input class="ws-input" id="ferr" aria-describedby="ferr-error" />
<span class="ws-field__error" id="ferr-error">Enter a valid date in MM/DD/YYYY format.</span>
</div>Select & textarea
<select class="ws-select"><option>Property</option></select>
<textarea class="ws-textarea" placeholder="…"></textarea>Checkbox, radio & switch
<div class="ws-check-row">
<input class="ws-checkbox" type="checkbox" id="c1" />
<label for="c1">Label text</label>
</div>
<input class="ws-switch" type="checkbox" id="s1" />Search input
The search input extends the base text input with a leading search icon and an optional clear (×) button that appears when the field has a value. Use type="search" for native browser clear behaviour on mobile. Always include a visible label or aria-label.
<div class="ws-search-wrap">
<svg class="ws-search-icon">...</svg>
<input class="ws-input" type="search" placeholder="Search…" />
<button class="ws-search-clear" aria-label="Clear search">×</button>
</div>Filter bar
Filter bars combine chips and selects to narrow a data list. Active filter count appears on the "Filter" trigger so users know filters are applied even when the bar is collapsed. A "Clear all" link resets all filters simultaneously.
Expanded filter bar
<div class="ws-filter-bar">
<span class="ws-filter-bar__label">Filter by</span>
<button class="ws-chip is-active" aria-pressed="true">
<span class="ws-chip__dot"></span>General Liability
</button>
<!-- more chips -->
</div>Collapsed filter trigger
Dropdown menu
Dropdown menus surface a list of actions or options anchored to a trigger element. They support section labels, keyboard navigation (arrow keys, Enter, Escape), and a right-aligned variant. Use for "More actions" overflow menus, sort controls, and action groups.
Action dropdown
<div class="ws-dropdown is-open">
<button class="ws-btn ws-btn--secondary" aria-haspopup="true" aria-expanded="true">
Actions <svg>...chevron</svg>
</button>
<div class="ws-dropdown-menu">
<div class="ws-dropdown-section">Policy actions</div>
<button class="ws-dropdown-item">Add endorsement</button>
<div class="ws-dropdown-divider"></div>
<button class="ws-dropdown-item ws-dropdown-item--danger">Cancel policy</button>
</div>
</div>Kebab (⋯) context menu
Icon-only triggers use the three-dot (kebab) pattern. Always add aria-label="More options". Right-align the menu when the trigger is near the right edge of the screen.
<!-- Right-aligned context menu -->
<div class="ws-dropdown ws-dropdown--right is-open">
<button class="ws-btn ws-btn--icon" aria-label="More options">⋯</button>
<div class="ws-dropdown-menu">
<button class="ws-dropdown-item">View details</button>
<button class="ws-dropdown-item ws-dropdown-item--danger">Remove</button>
</div>
</div>| Part | Class | Notes |
|---|---|---|
| Container | .ws-dropdown | Add .is-open to show the menu |
| Menu surface | .ws-dropdown-menu | Positioned absolute, top + 4px from trigger |
| Menu item | .ws-dropdown-item | Use <button> for actions, <a> for navigation |
| Danger item | .ws-dropdown-item--danger | Red text, red hover background |
| Section label | .ws-dropdown-section | Non-interactive group heading |
| Divider | .ws-dropdown-divider | 1px horizontal rule between groups |
| Right-align | .ws-dropdown--right | Anchors menu to right edge of trigger |
Usage guidance
- Always pair a visible
<label>with every input — placeholder is never a substitute. - Use
aria-describedbyto link error messages and hints to their field. - Show filter count on the trigger when filters are applied and the bar is collapsed.
- Support keyboard navigation (arrow keys) in dropdown menus.
- Close dropdowns on Escape key and on outside click.
- Don't use placeholder text as the only label — it disappears once the user types.
- Don't nest dropdown menus more than one level deep.
- Don't put more than 10 items in a dropdown without a search filter inside it.
- Don't use a dropdown for navigation — use a navigation pattern instead.
Design tokens
| Token | Value | Usage |
|---|---|---|
--color-border-default | gray-300 | Default input border |
--color-border-focus | #319B42 | Input focus ring + border |
--color-text-secondary | gray-500 | Placeholder, hint, search icon |
--color-error | #DB3131 | Error state border + message text |
--shadow-200 | Medium shadow | Dropdown menu surface |
--radius-md | 8px | Dropdown menu corner radius |