Install LocoMotion for Rails

LocoMotion is both a set of guides for building Ruby on Rails applications as well as a Component library that you can install into an existing Rails application.

This guide walks you through installing the Component library.

1. Gem Installation

Add the following to your Gemfile and run bundle install.

# Gemfile
gem "loco_motion-rails", "~> 0.5.2", require: "loco_motion"

Or if you want the latest and greatest:

# Gemfile
gem "loco_motion", github: "profoundry-us/loco_motion", branch: "main", require: "loco_motion"

2. Javascript Installation

Next, some of the components require Javascript. Install the library with your package manager of choice.

npm

npm i -D @profoundry-us/loco_motion@latest

Yarn

yarn add -D @profoundry-us/loco_motion@latest

Now, import and register the relevant controllers in your controllers/index.js file.

# app/javascript/controllers/index.js

import { Application } from "@hotwired/stimulus"
const application = Application.start()

// Import LocoMotion controllers
import { CountdownController, ThemeController, CallyInputController } from "@profoundry-us/loco_motion"

application.register("loco-countdown", CountdownController)
application.register("loco-theme", ThemeController)
application.register("loco-cally-input", CallyInputController)
Cally Javascript Setup

Note that there is an extra step if you want to use the Cally Calendar or CallyInput components.


See the CallyInput Docs for more information.

3. TailwindCSS Installation

LocoMotion uses Tailwind 4, which configures plugins directly in your CSS file rather than in tailwind.config.js.

3a. CSS Setup

Add the following to your application.tailwind.css (or equivalent):

/* application.tailwind.css */

/* Import the base Tailwind theme */
@import 'tailwindcss';

/* Include DaisyUI via @plugin directive */
@plugin 'daisyui' {
  themes: light --default, dark --prefersdark;
}

/* Custom variant to reduce selector specificity for component defaults */
@custom-variant where (:where(&));

/* Custom dark: variant for System-based & DaisyUI ThemeController dark mode */
@custom-variant dark (@media (prefers-color-scheme: dark), :root:has(input.theme-controller[value=dark]:checked) &);

/* Point to tailwind.config.js for content scan paths */
@config "../tailwind.config.js";

3b. Content Path Setup

Next, create or update your tailwind.config.js to tell Tailwind where to scan for class names. In Tailwind 4 this file handles only content paths — plugins belong in your CSS file (see above).

// tailwind.config.js
const { execSync } = require('child_process');

// Get the path to the loco_motion gem
let locoBundlePath = execSync('bundle show loco_motion-rails').toString().trim();

module.exports = {
  content: [
    `${locoBundlePath}/app/components/**/*.{rb,js,html,haml}`,
    'app/components/**/*.{rb,js,html,haml}',
    'app/views/**/*.{rb,js,html,haml}',
  ]
}

If you want an even smaller bundle size, you can import just the components that you utilize. You will, however, need to update your tailwind.config.js file every time you add new components.

// tailwind.config.js
const { execSync } = require('child_process');

// Get the path to the loco_motion gem
let locoBundlePath = execSync('bundle show loco_motion-rails').toString().trim();

module.exports = {
  content: [
    `${locoBundlePath}/app/components/hero/*.{rb,js,html,haml}`,
    `${locoBundlePath}/app/components/daisy/actions/button_component.{rb,haml}`,
    `${locoBundlePath}/app/components/daisy/data_display/countdown_component.{rb,haml}`,
    `${locoBundlePath}/app/components/daisy/data_display/countdown_controller.js`,
    /* And so on and so forth */
    'app/components/**/*.{rb,js,html,haml}',
    'app/views/**/*.{rb,js,html,haml}',
  ]

4. Try it out!

You're ready to start using the components! 🥳

Hop into one of your views and show the world what you can build.

Preview
Task completed!

Loading endless possibilities...

Code
= daisy_button("Done!", html: { onclick: "alert('Go you!')" })

= daisy_badge(css: "badge-success") do
  = hero_icon("check-circle")
  Task completed!

= daisy_alert(icon: "information-circle", css: "alert-info alert-soft") do
  Where will you go from here?

%p.flex.flex-col.gap-1.text-primary
  Loading endless possibilities...
  = daisy_progress(css: "w-100 progress-primary")
Made with by Profoundry .
Copyright © 2023-2026 Profoundry LLC.
All rights reserved.