Rails - JS Bundler
How to install RBUI within a Rails app that employs JS bundling.
Creating a Rails app
1
Generate a new Rails application
In case you don't have a Rails application set up yet, let's start by generating one. The demo uses esbuild, however feel free to change esbuild to use bun, webpack or rollup.js. Read more about JS bundlers in Rails here.
rails new CHANGE_TO_NAME_OF_APP --css=tailwind --javascript=esbuild
Once that is created, navigate to the app
cd CHANGE_TO_NAME_OF_APP
Install the gem
1
Install Phlex
Run the following in the terminal to install phlex for Rails
bundle add phlex-rails
After the gem is installed, run the generator to create necessary files.
bin/rails generate phlex:install
Refer to the Phlex installation guide for Rails for more information.
2
Install RBUI gem
Run the following in the terminal to install the RBUI Component Library
bundle add phlex_ui
3
Include RBUI module
Include RBUI module in your application_component.rb
file
class ApplicationComponent < Phlex::HTML include RBUI end
4
Next step, JS!
Let's make the components come to life by adding some JavaScript.
Install JS
1
Install package
Run the following in the terminal to install RBUI JS package
yarn add rbui-js
2
Import package
Import the package in your app/javascript/application.js
file
import 'rbui-js';
Install Styles
1
Install TailwindCSS
Most will already have TailwindCSS installed, however if you do not, first follow the TailwindCSS installation guide
2
Install Dependencies
Run the following in the terminal to install the dependencies
yarn add tailwindcss-animate
3
Update Tailwind Configuration
Add the following to your tailwind.config.js
file
// For importing tailwind styles from rbui gem const execSync = require('child_process').execSync; // Import rbui gem path (To make sure Tailwind loads classes used by rbui gem) const outputRBUI = execSync('bundle show phlex_ui', { encoding: 'utf-8' }); const rbui_path = outputRBUI.trim() + '/**/*.rb'; const defaultTheme = require('tailwindcss/defaultTheme') module.exports = { darkMode: ["class"], content: [ './app/views/**/*.{erb,haml,html,slim,rb}', './app/helpers/**/*.rb', './app/assets/stylesheets/**/*.css', './app/javascript/**/*.js', rbui_path ], theme: { container: { center: true, padding: "2rem", screens: { "2xl": "1400px", }, }, extend: { colors: { border: "hsl(var(--border))", input: "hsl(var(--input))", ring: "hsl(var(--ring))", background: "hsl(var(--background))", foreground: "hsl(var(--foreground))", primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))", }, secondary: { DEFAULT: "hsl(var(--secondary))", foreground: "hsl(var(--secondary-foreground))", }, destructive: { DEFAULT: "hsl(var(--destructive))", foreground: "hsl(var(--destructive-foreground))", }, muted: { DEFAULT: "hsl(var(--muted))", foreground: "hsl(var(--muted-foreground))", }, accent: { DEFAULT: "hsl(var(--accent))", foreground: "hsl(var(--accent-foreground))", }, popover: { DEFAULT: "hsl(var(--popover))", foreground: "hsl(var(--popover-foreground))", }, card: { DEFAULT: "hsl(var(--card))", foreground: "hsl(var(--card-foreground))", }, warning: { DEFAULT: "hsl(var(--warning))", foreground: "hsl(var(--warning-foreground))", }, success: { DEFAULT: "hsl(var(--success))", foreground: "hsl(var(--success-foreground))", }, }, borderRadius: { lg: `var(--radius)`, md: `calc(var(--radius) - 2px)`, sm: "calc(var(--radius) - 4px)", }, fontFamily: { sans: ["var(--font-sans)", ...defaultTheme.fontFamily.sans], }, }, }, # Not compatible with importmaps plugins: [ require("tailwindcss-animate"), ], }
4
Add CSS variables
Add the following to your app/assets/stylesheets/application.tailwind.css
file
@tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { --background: 0 0% 100%; --foreground: 240 10% 3.9%; --card: 0 0% 100%; --card-foreground: 240 10% 3.9%; --popover: 0 0% 100%; --popover-foreground: 240 10% 3.9%; --primary: 240 5.9% 10%; --primary-foreground: 0 0% 98%; --secondary: 240 4.8% 95.9%; --secondary-foreground: 240 5.9% 10%; --muted: 240 4.8% 95.9%; --muted-foreground: 240 3.8% 46.1%; --accent: 240 4.8% 95.9%; --accent-foreground: 240 5.9% 10%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 0 0% 98%; --border: 240 5.9% 90%; --input: 240 5.9% 90%; --ring: 240 5.9% 10%; --radius: 0.5rem; --warning: 38 92% 50%; --warning-foreground: 0 0% 100%; --success: 87 100% 37%; --success-foreground: 0 0% 100%; } .dark { --background: 240 10% 3.9%; --foreground: 0 0% 98%; --card: 240 10% 3.9%; --card-foreground: 0 0% 98%; --popover: 240 10% 3.9%; --popover-foreground: 0 0% 98%; --primary: 0 0% 98%; --primary-foreground: 240 5.9% 10%; --secondary: 240 3.7% 15.9%; --secondary-foreground: 0 0% 98%; --muted: 240 3.7% 15.9%; --muted-foreground: 240 5% 64.9%; --accent: 240 3.7% 15.9%; --accent-foreground: 0 0% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 0 0% 98%; --border: 240 3.7% 15.9%; --input: 240 3.7% 15.9%; --ring: 240 4.9% 83.9%; --warning: 38 92% 50%; --warning-foreground: 0 0% 100%; --success: 84 81% 44%; --success-foreground: 0 0% 100%; } } @layer base { * { @apply border-border; } body { @apply bg-background text-foreground; font-feature-settings: "rlig" 1, "calt" 1; } }