@stimulus-plumbers/controllers
v0.4.16
Published
Stimulus controllers following WCAG standards
Maintainers
Readme
@stimulus-plumbers/controllers
Accessible Stimulus controllers following WCAG 2.1+ standards.
For a plain-JS / non-Rails setup, see docs/guide.md.
Requirements
- Node.js >= 22
@hotwired/stimulus^2.0 or ^3.0 (peer dependency)
Installation
npm install @stimulus-plumbers/controllersSetup
Register the controllers you need with your Stimulus application:
import { Application } from '@hotwired/stimulus'
import {
InputComboboxController,
InputFormatterController,
InputClearableController,
InputRevealableController,
ComboboxDateController,
ComboboxTimeController,
ComboboxDropdownController,
CalendarMonthController,
CalendarMonthSelectorController,
CalendarYearController,
CalendarYearSelectorController,
CalendarDecadeController,
CalendarDecadeSelectorController,
ChecklistController,
ModalController,
PopoverController,
ProgressController,
DismisserController,
FlipperController,
ClipboardController,
PannerController,
PasswordStrengthController,
ReorderableController,
TimelineController,
VisibilityController,
} from '@stimulus-plumbers/controllers'
const application = Application.start()
application.register('input-combobox', InputComboboxController)
application.register('input-formatter', InputFormatterController)
application.register('input-clearable', InputClearableController)
application.register('input-revealable', InputRevealableController)
application.register('combobox-date', ComboboxDateController)
application.register('combobox-time', ComboboxTimeController)
application.register('combobox-dropdown', ComboboxDropdownController)
application.register('calendar-month', CalendarMonthController)
application.register('calendar-month-selector', CalendarMonthSelectorController)
application.register('calendar-year', CalendarYearController)
application.register('calendar-year-selector', CalendarYearSelectorController)
application.register('calendar-decade', CalendarDecadeController)
application.register('calendar-decade-selector', CalendarDecadeSelectorController)
application.register('checklist', ChecklistController)
application.register('modal', ModalController)
application.register('popover', PopoverController)
application.register('progress', ProgressController)
application.register('dismisser', DismisserController)
application.register('flipper', FlipperController)
application.register('clipboard', ClipboardController)
application.register('panner', PannerController)
application.register('password-strength', PasswordStrengthController)
application.register('reorderable', ReorderableController)
application.register('timeline', TimelineController)
application.register('visibility', VisibilityController)Controllers
| Controller | Description | Docs |
|-----------|-------------|------|
| input-combobox | Wrapper: trigger, popover, hidden value | docs/component/combobox.md |
| input-formatter | Formats and displays values | docs/component/input-formatter.md |
| input-clearable | Input with clear button | docs/component/input-clearable.md |
| input-revealable | Obscured input with reveal toggle | docs/component/input-revealable.md |
| combobox-date | Calendar grid date picker | docs/component/combobox.md |
| combobox-time | Drum/scroll-wheel time picker | docs/component/combobox.md |
| combobox-dropdown | Listbox with fuzzy filter or server fetch | docs/component/combobox.md |
| calendar-month | Calendar month grid — renders days, handles clicks, dispatches selection events | docs/component/calendar.md |
| calendar-month-selector | SSR/Turbo thin selector for server-rendered month grids | docs/component/calendar.md |
| calendar-year | Calendar year grid — renders month buttons, dispatches selection events | docs/component/calendar.md |
| calendar-year-selector | SSR/Turbo thin selector for server-rendered year grids | docs/component/calendar.md |
| calendar-decade | Calendar decade grid — renders year buttons, dispatches selection events | docs/component/calendar.md |
| calendar-decade-selector | SSR/Turbo thin selector for server-rendered decade grids | docs/component/calendar.md |
| checklist | Master "select all" toggle for native checkbox items | docs/component/checklist.md |
| modal | Native <dialog> or custom overlay | docs/component/modal.md |
| popover | Show/hide content with optional remote load | docs/component/popover.md |
| progress | Value-driven progress bar/segmented/ring/meter | docs/component/progress.md |
| dismisser | Click-outside dismissal | docs/component/dismisser.md |
| flipper | Floating element positioning | docs/component/flipper.md |
| clipboard | Copy-to-clipboard and paste interception | docs/component/clipboard.md |
| panner | Keeps content element within viewport on resize | docs/component/panner.md |
| password-strength | Live password meter and requirements checklist | docs/component/password-strength.md |
| reorderable | Drag (pointer) or keyboard (Alt+Arrow) reordering for a vertical list | docs/component/reorderable.md |
| timeline | Manages expandable timeline event items with keyboard navigation | docs/component/timeline.md |
| visibility | Show/hide a content element, kept within viewport, with click-outside dismissal | docs/component/visibility.md |
Utilities
| Export | Description | Docs |
|--------|-------------|------|
| setExpanded, setHidden, announce, generateId, ensureId, connectTriggerToTarget | ARIA state helpers | docs/utility/accessibility.md |
| FocusTrap, getFocusableElements, focusFirst | Focus management | docs/utility/accessibility.md |
| RovingTabIndex, ListboxNavigation, isActivationKey, isArrowKey | Keyboard interaction | docs/utility/accessibility.md |
| Requestor | Fetch wrapper with lifecycle events | docs/utility/requestor.md |
| fuzzyMatcher, filterOptions | Option filtering for comboboxes | docs/utility/researcher.md |
| Formatter, FORMATTER_TYPES | Input formatter plumber (attach to a controller; used by input-formatter) | docs/plumber/formatter.md |
| CharacterCells, attachCharacterCells | Character-cell display plumber (attach to a controller; used by input-formatter) | docs/plumber/character-cells.md |
| PasswordStrength, attachPasswordStrength, STRENGTH_TYPES | Password strength scoring plumber | docs/plumber/password_strength.md |
Method naming convention
Controllers follow a consistent naming pattern:
| Pattern | Parameter | Role | Example |
|---------|-----------|------|---------|
| x(value) | raw value | Programmatic API — pure logic, callable directly | select('us'), format('4242…'), filter('query') |
| onX(event) | DOM event | Event adapter — extracts payload, calls programmatic API | onSelect(event), onChange(event), onPaste(event), onInput(event) |
| past() | — | Plumber callback — called by plumber after async operation completes | shown(), dismissed(), flipped(), contentLoaded() |
Wire event adapters via data-action; call programmatic APIs directly from other controllers or outlets.
Development
npm install
npm test # run all tests (Vitest)
node --run test:ui # Vitest UI
node --run test:coverage # coverage report
node --run lint # ESLint
node --run format:write # Prettier (write)
node --run build # build dist/License
MIT © Ryan Chang
