RapidRailsUI · Rails UI components

Ship the feature.
Not the button.

Every Rails team rebuilds the same UI from scratch — buttons, modals, dropdowns, tables. Hours per sprint on work that already exists. RapidRailsUI ends that cycle. 30+ tested, documented components. One line where you used to write fifteen.

Open the component library

Live components

These are rendering
live in Rails.

Not screenshots. Not mockups. Every button, dropdown, and accordion below is a live rui_button, rui_dropdown, and rui_accordion call rendering in this Rails view right now.

rui_button — variants, live

What you write vs what Rails renders

# You write — 1 line
<%= rui_button(text: "Solid primary", variant: :solid, color: :primary) %>

# Rails generates — 25+ Tailwind classes, dark mode, focus rings, disabled states
<button type="button"
  class="relative inline-flex items-center justify-center gap-2
         font-medium transition-colors cursor-pointer whitespace-nowrap
         h-10 ps-4 pe-4 text-sm rounded-md
         focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2
         disabled:pointer-events-none disabled:opacity-60
         bg-zinc-600 hover:bg-zinc-700 focus-visible:ring-zinc-600
         border-zinc-900 text-white
         dark:bg-zinc-700 dark:hover:bg-zinc-600 dark:text-white">
  Solid primary
</button>

rui_dropdown — slot-based menus, live

What you write vs what you'd build manually

# You write — slots compose the menu declaratively
<%= rui_dropdown(text: "Actions", variant: :solid, color: :primary) do |dropdown| %>
  <% dropdown.with_item(text: "Edit post", href: "#", icon: :edit) %>
  <% dropdown.with_item(text: "Duplicate", href: "#", icon: :copy) %>
  <% dropdown.with_divider %>
  <% dropdown.with_item(text: "Delete", href: "#", danger: true) %>
<% end %>

# Without RUI — 50+ lines: button, Stimulus controller, menu container,
# positioned panel, transition classes, keyboard navigation, click-outside
# dismiss, focus trapping, ARIA attributes, dark mode variants...

rui_accordion — collapsible sections, live

30+ production-ready components covering forms, display, and interaction patterns.

Buttons Dropdowns Dialogs Tables

Every interactive component ships with a Stimulus controller. Turbo Frames and Streams work out of the box.

Every component accepts class: to extend or override styles. RapidCascade variables let you theme globally.

What you write vs what you'd build manually

# You write — nested components compose naturally
<%= rui_accordion(variant: :bordered, color: :primary) do |accordion| %>
  <% accordion.with_item(title: "Question?", icon: :package, expanded: true) do %>
    <%= rui_badge(text: "Tag", color: :primary, size: :sm) %>
    <%= rui_button(text: "Action", variant: :outline, size: :sm) %>
  <% end %>
<% end %>

# Without RUI — details/summary or div+button+JS wiring,
# transition animations, ARIA expanded states, exclusive open
# logic, icon rotation, keyboard support, dark mode...

The math

One component.
The difference compounds.

A button. A badge. A dialog. Each looks small — until you multiply by every view in your app.

With RapidRailsUI

<%= rui_button(
  text: "Approve",
  variant: :solid,
  color: :success
) %>

<%= rui_badge(
  text: "Live",
  color: :success
) %>

2 lines

button + badge

~25 tokens

for AI to generate both

Without RapidRailsUI

<button type="button"
  class="relative inline-flex items-center
    justify-center gap-2 font-medium
    transition-colors cursor-pointer
    whitespace-nowrap h-10 ps-4 pe-4
    text-sm rounded-md
    focus-visible:outline-none
    focus-visible:ring-2 focus-visible:ring-offset-2
    disabled:pointer-events-none disabled:opacity-60
    bg-green-600 hover:bg-green-700
    focus-visible:ring-green-600 text-white
    dark:bg-green-700 dark:hover:bg-green-600">
  Approve
</button>
<span class="inline-flex items-center
  px-2.5 py-0.5 rounded-full text-xs
  font-medium bg-green-100 text-green-800
  border border-green-200">Live</span>

22 lines

button + badge

~180 tokens

for AI to generate both

RapidRailsUI
Without RUI

A button in your view

1 line

15–20 lines of HTML + classes

A badge / status

1 line

5–8 lines per colour variant

A dialog / modal

1 line

40+ lines + JS Stimulus wiring

A data table

1 line

30+ lines of HTML

AI tokens — one button

~15 tokens

~100 tokens (real class string)

Design refresh

Edit component source

Touch every partial that uses it

Dark mode

Automatic (built in)

Duplicate every class with dark:

Test coverage

Included in the gem

Write yourself

Accessibility

focus-visible, aria built in

Remember to add yourself

New dev gets productive

Read the docs

Learn your project's conventions

What changes

One install.
Three promises.

01

Save time

Stop rebuilding UI primitives every sprint. Every component you reach for is already built, tested, and documented. The sprint starts on the feature — not the scaffolding.

Building a button from scratch: 2–4 hours. Using rui_button: seconds.

02

Save money

Developer time is your most expensive resource. Every hour rebuilding a modal instead of shipping a feature costs twice — once to build, again at the next redesign.

The exact savings depend on your team. The direction is always the same.

03

Save AI tokens

When your AI pair programmer writes rui_button(...) instead of 22 lines of raw HTML, you use roughly 7× fewer tokens per component.

~15 tokens (RUI) vs ~100 tokens (raw HTML). Verified against actual button output.

Token economics

Your AI writes better code when it has less to guess.

A named, typed component is a contract. AI tools read rui_button(variant: :solid, color: :success) and know exactly what to generate. No hallucinated classes. No forgotten dark mode variants. No missed focus states.

Schema endpoint at /api/schema

AI agents query every component's variants and parameters before generating code.

llms.txt — machine-readable map

A concise index of every helper, parameter, and variant. Fits in any context window.

Closed variant set — no guessing

:solid, :outline, :ghost. Enumerated. The API is the specification.

Tokens to generate one button (approximate)

rui_button(text: "X", variant: :solid, color: :primary) ~15 tokens
Equivalent raw HTML with all classes ~100 tokens

The full button class string (25 Tailwind classes) + markup = ~100 tokens. The rui_button helper call = ~15. Across hundreds of components, this accumulates.

GET /api/schema → button

{
  "helper": "rui_button",
  "variants": ["solid", "outline", "ghost", "soft"],
  "colors":   ["primary", "danger", "success", "warning"],
  "sizes":    ["sm", "md", "lg"]
}

# AI reads this before generating. Correct output, first try.
32 components

Everything your Rails app needs.

Forms

  • Input
  • Textarea
  • Select
  • Checkbox
  • "Radio
  • Button"
  • Date
  • Combobox
  • Upload
  • Editable

Display

  • Button
  • Link
  • Badge
  • Icon
  • Text
  • Avatar
  • Image
  • Table
  • Pagination

Interaction

  • Dialog
  • Dropdown
  • Accordion
  • Alert
  • Tooltip
  • Popover
  • Clipboard
  • "Live
  • Search"
  • Steps

Production proof

We use it every day.
So do our customers.

Every app below runs RapidRailsUI in production. Including the site you're reading right now.

See the docs

RapidRails UI

Composable UI components for Rails..

FixOurHood

Civic reporting service in Toronto, Canada.

Ship It

Launch accountability for indie makers.

Rapidfy

Build Rails Apps, and Websites with AI.

Get started

Your backlog
is waiting.

Schedule a 30-minute call. We'll review your stack and show you exactly where RapidRailsUI fits.

RapidRails.