plutonium-assets
Plutonium asset setup - TailwindCSS configuration, Stimulus controllers, and Phlexi component themes
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Plutonium Assets & Setup
Plutonium uses TailwindCSS 4 for styling with a customizable theme system for components.
Note: For CSS design tokens (
--pu-*variables) and component classes (.pu-btn,.pu-input, etc.), see theplutonium-themingskill.
Asset Configuration
Configure assets in the initializer:
# config/initializers/plutonium.rb
Plutonium.configure do |config|
config.load_defaults 1.0
# Custom assets
config.assets.stylesheet = "application" # Your CSS file
config.assets.script = "application" # Your JS file
config.assets.logo = "my_logo.png" # Logo image
config.assets.favicon = "my_favicon.ico" # Favicon
end
Setup Custom Assets
Run the assets generator to set up your own TailwindCSS build:
rails generate pu:core:assets
This:
- Installs required npm packages (
@radioactive-labs/plutonium, TailwindCSS plugins) - Creates
tailwind.config.jsthat extends Plutonium's config - Imports Plutonium CSS into your
application.tailwind.css - Registers Plutonium's Stimulus controllers
- Updates Plutonium config to use your assets
TailwindCSS Configuration
Generated Config
// tailwind.config.js
const { execSync } = require('child_process');
const plutoniumGemPath = execSync("bundle show plutonium").toString().trim();
const plutoniumTailwindConfig = require(`${plutoniumGemPath}/tailwind.options.js`)
module.exports = {
darkMode: plutoniumTailwindConfig.darkMode,
plugins: [
// Add your plugins here
].concat(plutoniumTailwindConfig.plugins),
theme: plutoniumTailwindConfig.merge(
plutoniumTailwindConfig.theme,
{
// Your custom theme overrides
},
),
content: [
`${__dirname}/app/**/*.{erb,haml,html,slim,rb}`,
`${__dirname}/app/javascript/**/*.js`,
`${__dirname}/packages/**/app/**/*.{erb,haml,html,slim,rb}`,
].concat(plutoniumTailwindConfig.content),
}
Customizing Colors
Override Plutonium's color palette:
// tailwind.config.js
theme: plutoniumTailwindConfig.merge(
plutoniumTailwindConfig.theme,
{
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6', // Your brand color
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
950: '#172554',
},
secondary: {
// Your secondary palette
},
},
},
},
),
Default Color Palette
Plutonium includes these semantic colors:
| Color | Usage |
|---|---|
primary |
Primary brand color (turquoise by default) |
secondary |
Secondary color (navy by default) |
success |
Success states (green) |
info |
Informational states (blue) |
warning |
Warning states (amber) |
danger |
Error/danger states (red) |
accent |
Accent highlights (coral pink) |
Dark Mode
Plutonium uses selector strategy for dark mode:
darkMode: "selector"
Toggle dark mode by adding/removing the dark class on <html>:
// Toggle dark mode
document.documentElement.classList.toggle('dark');
Plutonium includes a color mode selector component that handles this automatically.
CSS Imports
Application Stylesheet
/* app/assets/stylesheets/application.tailwind.css */
@import "gem:plutonium/src/css/plutonium.css";
@import "tailwindcss";
@config '../../../tailwind.config.js';
/* Your custom styles */
What Plutonium CSS Includes
- Core utility classes
- EasyMDE (markdown editor) styles
- Slim Select styles
- International telephone input styles
- Flatpickr (date picker) styles
Component Themes (Phlexi)
Plutonium components use a theme system based on Phlexi for customizing Form, Display, and Table components. Each component type has a theme class with named style tokens.
Note: This is different from the CSS design token system (
.pu-*classes). For pre-built component classes, seeplutonium-theming.
Form Theme
class PostDefinition < ResourceDefinition
class Form < Form
class Theme < Plutonium::UI::Form::Theme
def self.theme
super.merge({
# Container
base: "bg-white dark:bg-gray-800 shadow-md rounded-lg p-6",
fields_wrapper: "grid grid-cols-2 gap-6",
actions_wrapper: "flex justify-end mt-6 space-x-2",
# Labels
label: "block mb-2 text-base font-bold",
invalid_label: "text-red-700 dark:text-red-500",
valid_label: "text-green-700 dark:text-green-500",
neutral_label: "text-gray-500 dark:text-gray-400",
# Inputs
input: "w-full p-2 border rounded-md shadow-sm",
invalid_input: "bg-red-50 border-red-500 text-red-900",
valid_input: "bg-green-50 border-green-500 text-green-900",
neutral_input: "border-gray-300 dark:border-gray-600",
# Hints & Errors
hint: "mt-2 text-sm text-gray-500",
error: "mt-2 text-sm text-red-600",
# Buttons
button: "px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700",
})
end
end
end
end
Display Theme
class PostDefinition < ResourceDefinition
class Display < Display
class Theme < Plutonium::UI::Display::Theme
def self.theme
super.merge({
fields_wrapper: "grid grid-cols-3 gap-8",
label: "text-sm font-bold text-gray-500 mb-1",
string: "text-lg text-gray-900 dark:text-white",
link: "text-primary-600 hover:underline",
markdown: "prose dark:prose-invert max-w-none",
})
end
end
end
end
Table Theme
class PostDefinition < ResourceDefinition
class Table < Table
class Theme < Plutonium::UI::Table::Theme
def self.theme
super.merge({
wrapper: "overflow-x-auto shadow-md rounded-lg",
base: "w-full text-sm text-gray-500",
header: "text-xs uppercase bg-gray-100 dark:bg-gray-700",
header_cell: "px-6 py-3",
body_row: "bg-white border-b dark:bg-gray-800",
body_cell: "px-6 py-4",
})
end
end
end
end
Theme Keys Reference
Form Theme Keys
| Key | Description |
|---|---|
base |
Form container |
fields_wrapper |
Grid wrapper for fields |
actions_wrapper |
Submit button container |
wrapper |
Individual field wrapper |
inner_wrapper |
Inner field wrapper |
label |
Label base styles |
invalid_label |
Label when field invalid |
valid_label |
Label when field valid |
neutral_label |
Label default state |
input |
Input base styles |
invalid_input |
Input when invalid |
valid_input |
Input when valid |
neutral_input |
Input default state |
hint |
Hint text |
error |
Error message |
button |
Submit button |
checkbox |
Checkbox input |
select |
Select dropdown |
Display Theme Keys
| Key | Description |
|---|---|
fields_wrapper |
Grid wrapper |
label |
Field label |
description |
Field description |
string |
String values |
text |
Text values |
link |
URL links |
email |
Email links |
phone |
Phone links |
markdown |
Markdown content |
json |
JSON display |
Table Theme Keys
| Key | Description |
|---|---|
wrapper |
Table container |
base |
Table element |
header |
Header row |
header_cell |
Header cell |
body_row |
Body row |
body_cell |
Body cell |
sort_icon |
Sort indicator |
Using Tokens in Components
The tokens Helper
Conditionally apply classes:
class MyComponent < Plutonium::UI::Component::Base
def initialize(active:)
@active = active
end
def view_template
div(class: tokens(
"base-class",
active?: "bg-primary-500 text-white",
inactive?: "bg-gray-200 text-gray-700"
)) {
"Content"
}
end
private
def active? = @active
def inactive? = !@active
end
The classes Helper
Returns a hash suitable for splatting:
div(**classes("p-4", "rounded", active?: "ring-2")) { }
# => <div class="p-4 rounded ring-2">
Conditional Tokens with Hash
tokens(
"base",
condition?: { then: "if-true", else: "if-false" }
)
Stimulus Controllers
Plutonium includes Stimulus controllers. Register them in your application:
// app/javascript/controllers/index.js
import { application } from "./application"
import { registerControllers } from "@radioactive-labs/plutonium"
registerControllers(application)
// Your custom controllers...
Available Controllers
-
color-mode- Dark/light mode toggle -
form- Form handling (pre-submit, etc.) -
nested-resource-form-fields- Nested form management -
slim-select- Enhanced select boxes -
flatpickr- Date/time pickers -
easymde- Markdown editor - Various UI controllers
Custom Stimulus Controllers
Add your own controllers alongside Plutonium's:
// app/javascript/controllers/custom_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
console.log("Custom controller connected")
}
}
Register in your index:
import CustomController from "./custom_controller"
application.register("custom", CustomController)
Typography
Plutonium uses Lato font by default. The layout loads it from Google Fonts.
Override in your layout:
class MyLayout < Plutonium::UI::Layout::ResourceLayout
def render_fonts
# Your custom fonts
link(rel: "preconnect", href: "https://fonts.googleapis.com")
link(href: "https://fonts.googleapis.com/css2?family=Inter&display=swap", rel: "stylesheet")
end
end
Update Tailwind config:
theme: {
fontFamily: {
'body': ['Inter', 'sans-serif'],
'sans': ['Inter', 'sans-serif'],
}
}
Related Skills
-
plutonium-theming- CSS design tokens and component classes (.pu-*) -
plutonium-views- Layout customization -
plutonium-forms- Form theming -
plutonium-installation- Initial setup
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!