railsui-stimulus
Rails UI includes railsui-stimulus, a library of JavaScript patterns we repeatedly use across themes and apps. It works independently of Rails UI and comes pre-installed with every theme.
The library includes 14 Stimulus controllers for common UI interactions:
Available Controllers
Clipboard
Copy content to the clipboard with visual feedback.
<div data-controller="railsui-clipboard">
<input type="text" value="Text to copy" data-railsui-clipboard-target="source" readonly>
<button data-action="click->railsui-clipboard#copy">
Copy
</button>
</div>
Count Up
Animate numbers counting up to a target value. Great for statistics and metrics.
<span data-controller="railsui-count-up"
data-railsui-count-up-target-value="1000"
data-railsui-count-up-duration-value="2000">
0
</span>
Combobox
Searchable dropdown combining an input field with selectable options.
<div data-controller="railsui-combobox">
<input type="text"
data-railsui-combobox-target="input"
data-action="input->railsui-combobox#filter focus->railsui-combobox#open"
placeholder="Search...">
<ul data-railsui-combobox-target="list" class="hidden">
<li data-action="click->railsui-combobox#select">Option 1</li>
<li data-action="click->railsui-combobox#select">Option 2</li>
<li data-action="click->railsui-combobox#select">Option 3</li>
</ul>
</div>
Date Range Picker
Select date ranges with an interactive calendar. Requires flatpickr.
<div data-controller="railsui-date-range-picker">
<input type="text"
data-railsui-date-range-picker-target="input"
placeholder="Select date range">
</div>
Dropdown
Collapsible menus that show/hide content when triggered.
<div data-controller="railsui-dropdown">
<button data-action="click->railsui-dropdown#toggle">
Open Menu
</button>
<div data-railsui-dropdown-target="menu" class="hidden">
<a href="#">Menu Item 1</a>
<a href="#">Menu Item 2</a>
<a href="#">Menu Item 3</a>
</div>
</div>
Modal
Display modal dialogs and overlay windows.
<div data-controller="railsui-modal">
<button data-action="click->railsui-modal#open">
Open Modal
</button>
<div data-railsui-modal-target="modal" class="hidden">
<div data-railsui-modal-target="overlay"
data-action="click->railsui-modal#close"></div>
<div data-railsui-modal-target="content">
<h2>Modal Title</h2>
<p>Modal content goes here.</p>
<button data-action="click->railsui-modal#close">Close</button>
</div>
</div>
</div>
Password Toggle
Toggle password field visibility between masked and plain text.
<div data-controller="railsui-password-toggle">
<input type="password"
data-railsui-password-toggle-target="input">
<button data-action="click->railsui-password-toggle#toggle">
Show/Hide
</button>
</div>
Range
Slider input with visual fill indicator.
<div data-controller="railsui-range">
<input type="range"
data-railsui-range-target="input"
data-action="input->railsui-range#update"
min="0" max="100" value="50">
<span data-railsui-range-target="value">50</span>
</div>
Read More
Expandable/collapsible text sections with truncated content.
<div data-controller="railsui-read-more">
<div data-railsui-read-more-target="content" class="line-clamp-3">
Long content that will be truncated initially...
</div>
<button data-action="click->railsui-read-more#toggle"
data-railsui-read-more-target="button">
Read more
</button>
</div>
Select All
Bulk selection for checkboxes or list items.
<div data-controller="railsui-select-all">
<label>
<input type="checkbox"
data-railsui-select-all-target="selectAll"
data-action="change->railsui-select-all#toggleAll">
Select All
</label>
<label>
<input type="checkbox"
data-railsui-select-all-target="checkbox"
data-action="change->railsui-select-all#updateSelectAll">
Item 1
</label>
<label>
<input type="checkbox"
data-railsui-select-all-target="checkbox"
data-action="change->railsui-select-all#updateSelectAll">
Item 2
</label>
</div>
Tabs
Tabbed navigation for organizing content into panels.
<div data-controller="railsui-tabs" data-railsui-tabs-active-class="active">
<div role="tablist">
<button data-railsui-tabs-target="tab"
data-action="click->railsui-tabs#select">Tab 1</button>
<button data-railsui-tabs-target="tab"
data-action="click->railsui-tabs#select">Tab 2</button>
</div>
<div data-railsui-tabs-target="panel">Content for Tab 1</div>
<div data-railsui-tabs-target="panel" class="hidden">Content for Tab 2</div>
</div>
Toast
Temporary notification messages that auto-dismiss.
<div data-controller="railsui-toast"
data-railsui-toast-delay-value="3000">
<div data-railsui-toast-target="toast">
<p>This message will auto-dismiss in 3 seconds.</p>
<button data-action="click->railsui-toast#dismiss">Dismiss</button>
</div>
</div>
Toggle
Basic toggle switches for boolean state management.
<div data-controller="railsui-toggle">
<button data-action="click->railsui-toggle#toggle">
Toggle Content
</button>
<div data-railsui-toggle-target="toggleable" class="hidden">
Hidden content that can be toggled.
</div>
</div>
Installation
Every Rails UI theme includes railsui-stimulus pre-configured. If you need to install it separately:
Importmap (nobuild)
<span data-controller="railsui-tooltip"
data-railsui-tooltip-content-value="Helpful tooltip text"
data-railsui-tooltip-placement-value="top">
Hover me
</span>
./bin/importmap pin railsui-stimulus
Then register the controllers in your JavaScript:
<span data-controller="railsui-tooltip"
data-railsui-tooltip-content-value="Helpful tooltip text"
data-railsui-tooltip-placement-value="top">
Hover me
</span>
./bin/importmap pin railsui-stimulus
// app/javascript/controllers/index.js
import { application } from "./application"
import { RailsuiClipboard, RailsuiDropdown, RailsuiModal, RailsuiTabs }
from "railsui-stimulus"
application.register("railsui-clipboard", RailsuiClipboard)
application.register("railsui-dropdown", RailsuiDropdown)
application.register("railsui-modal", RailsuiModal)
application.register("railsui-tabs", RailsuiTabs)
// ... register others as needed
NPM/Yarn (build mode)
<span data-controller="railsui-tooltip"
data-railsui-tooltip-content-value="Helpful tooltip text"
data-railsui-tooltip-placement-value="top">
Hover me
</span>
npm install railsui-stimulus
# or
yarn add railsui-stimulus
// app/javascript/controllers/index.js
import { application } from "./application"
import { RailsuiClipboard, RailsuiDropdown, RailsuiModal, RailsuiTabs }
from "railsui-stimulus"
application.register("railsui-clipboard", RailsuiClipboard)
application.register("railsui-dropdown", RailsuiDropdown)
application.register("railsui-modal", RailsuiModal)
application.register("railsui-tabs", RailsuiTabs)
// ... register others as needed
Turbo Compatibility
All controllers are designed to work seamlessly with Turbo. They properly clean up on disconnect and reinitialize when Turbo navigates to new pages or updates frames.
When using Turbo Frames or Turbo Streams, controllers automatically connect to new elements as they're added to the DOM.