plutonium 0.50.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +85 -102
  3. data/.claude/skills/plutonium-app/SKILL.md +572 -0
  4. data/.claude/skills/plutonium-auth/SKILL.md +163 -300
  5. data/.claude/skills/plutonium-behavior/SKILL.md +838 -0
  6. data/.claude/skills/plutonium-resource/SKILL.md +1176 -0
  7. data/.claude/skills/plutonium-tenancy/SKILL.md +655 -0
  8. data/.claude/skills/plutonium-testing/SKILL.md +6 -5
  9. data/.claude/skills/plutonium-ui/SKILL.md +900 -0
  10. data/CHANGELOG.md +27 -2
  11. data/Rakefile +2 -1
  12. data/app/assets/plutonium.css +1 -11
  13. data/app/assets/plutonium.js +1009 -1214
  14. data/app/assets/plutonium.js.map +3 -3
  15. data/app/assets/plutonium.min.js +52 -51
  16. data/app/assets/plutonium.min.js.map +3 -3
  17. data/docs/.vitepress/config.ts +37 -27
  18. data/docs/getting-started/index.md +22 -29
  19. data/docs/getting-started/installation.md +37 -80
  20. data/docs/getting-started/tutorial/index.md +4 -5
  21. data/docs/guides/adding-resources.md +66 -377
  22. data/docs/guides/authentication.md +94 -463
  23. data/docs/guides/authorization.md +124 -370
  24. data/docs/guides/creating-packages.md +94 -296
  25. data/docs/guides/custom-actions.md +121 -441
  26. data/docs/guides/index.md +22 -42
  27. data/docs/guides/multi-tenancy.md +116 -187
  28. data/docs/guides/nested-resources.md +103 -431
  29. data/docs/guides/search-filtering.md +123 -240
  30. data/docs/guides/testing.md +5 -4
  31. data/docs/guides/theming.md +157 -407
  32. data/docs/guides/troubleshooting.md +5 -3
  33. data/docs/guides/user-invites.md +106 -425
  34. data/docs/guides/user-profile.md +76 -243
  35. data/docs/index.md +1 -1
  36. data/docs/reference/app/generators.md +517 -0
  37. data/docs/reference/app/index.md +158 -0
  38. data/docs/reference/app/packages.md +146 -0
  39. data/docs/reference/app/portals.md +377 -0
  40. data/docs/reference/auth/accounts.md +230 -0
  41. data/docs/reference/auth/index.md +88 -0
  42. data/docs/reference/auth/profile.md +185 -0
  43. data/docs/reference/behavior/controllers.md +395 -0
  44. data/docs/reference/behavior/index.md +22 -0
  45. data/docs/reference/behavior/interactions.md +341 -0
  46. data/docs/reference/behavior/policies.md +417 -0
  47. data/docs/reference/index.md +56 -49
  48. data/docs/reference/resource/actions.md +423 -0
  49. data/docs/reference/resource/definition.md +508 -0
  50. data/docs/reference/resource/index.md +50 -0
  51. data/docs/reference/resource/model.md +348 -0
  52. data/docs/reference/resource/query.md +305 -0
  53. data/docs/reference/tenancy/entity-scoping.md +361 -0
  54. data/docs/reference/tenancy/index.md +36 -0
  55. data/docs/reference/tenancy/invites.md +393 -0
  56. data/docs/reference/tenancy/nested-resources.md +267 -0
  57. data/docs/reference/testing/index.md +287 -0
  58. data/docs/reference/ui/assets.md +400 -0
  59. data/docs/reference/ui/components.md +165 -0
  60. data/docs/reference/ui/displays.md +104 -0
  61. data/docs/reference/ui/forms.md +284 -0
  62. data/docs/reference/ui/index.md +30 -0
  63. data/docs/reference/ui/layouts.md +106 -0
  64. data/docs/reference/ui/pages.md +189 -0
  65. data/docs/reference/ui/tables.md +117 -0
  66. data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
  67. data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
  68. data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
  69. data/gemfiles/rails_7.gemfile.lock +1 -1
  70. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  71. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  72. data/lib/generators/pu/core/update/update_generator.rb +0 -20
  73. data/lib/generators/pu/invites/install_generator.rb +1 -0
  74. data/lib/plutonium/definition/base.rb +1 -1
  75. data/lib/plutonium/definition/{views.rb → index_views.rb} +21 -20
  76. data/lib/plutonium/helpers/turbo_helper.rb +11 -0
  77. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
  78. data/lib/plutonium/resource/controller.rb +1 -0
  79. data/lib/plutonium/resource/controllers/crud_actions.rb +19 -1
  80. data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
  81. data/lib/plutonium/resource/policy.rb +7 -0
  82. data/lib/plutonium/routing/mapper_extensions.rb +15 -0
  83. data/lib/plutonium/ui/component/methods.rb +4 -0
  84. data/lib/plutonium/ui/form/base.rb +6 -2
  85. data/lib/plutonium/ui/form/components/json.rb +58 -0
  86. data/lib/plutonium/ui/form/components/resource_select.rb +62 -8
  87. data/lib/plutonium/ui/form/components/secure_association.rb +98 -22
  88. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
  89. data/lib/plutonium/ui/form/resource.rb +0 -4
  90. data/lib/plutonium/ui/grid/resource.rb +1 -1
  91. data/lib/plutonium/ui/layout/base.rb +1 -0
  92. data/lib/plutonium/ui/page/base.rb +0 -7
  93. data/lib/plutonium/ui/page/index.rb +4 -4
  94. data/lib/plutonium/ui/table/resource.rb +1 -1
  95. data/lib/plutonium/version.rb +1 -1
  96. data/lib/plutonium.rb +8 -0
  97. data/lib/tasks/release.rake +15 -1
  98. data/package.json +10 -10
  99. data/src/css/slim_select.css +4 -0
  100. data/src/js/controllers/slim_select_controller.js +61 -0
  101. data/src/js/turbo/turbo_actions.js +33 -0
  102. data/yarn.lock +553 -543
  103. metadata +44 -33
  104. data/.claude/skills/plutonium-assets/SKILL.md +0 -512
  105. data/.claude/skills/plutonium-controller/SKILL.md +0 -396
  106. data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
  107. data/.claude/skills/plutonium-definition/SKILL.md +0 -1223
  108. data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
  109. data/.claude/skills/plutonium-forms/SKILL.md +0 -465
  110. data/.claude/skills/plutonium-installation/SKILL.md +0 -331
  111. data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
  112. data/.claude/skills/plutonium-invites/SKILL.md +0 -408
  113. data/.claude/skills/plutonium-model/SKILL.md +0 -440
  114. data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
  115. data/.claude/skills/plutonium-package/SKILL.md +0 -198
  116. data/.claude/skills/plutonium-policy/SKILL.md +0 -456
  117. data/.claude/skills/plutonium-portal/SKILL.md +0 -410
  118. data/.claude/skills/plutonium-views/SKILL.md +0 -651
  119. data/docs/reference/assets/index.md +0 -496
  120. data/docs/reference/controller/index.md +0 -412
  121. data/docs/reference/definition/actions.md +0 -462
  122. data/docs/reference/definition/fields.md +0 -383
  123. data/docs/reference/definition/index.md +0 -326
  124. data/docs/reference/definition/query.md +0 -351
  125. data/docs/reference/generators/index.md +0 -648
  126. data/docs/reference/interaction/index.md +0 -449
  127. data/docs/reference/model/features.md +0 -248
  128. data/docs/reference/model/index.md +0 -218
  129. data/docs/reference/policy/index.md +0 -456
  130. data/docs/reference/portal/index.md +0 -379
  131. data/docs/reference/views/forms.md +0 -411
  132. data/docs/reference/views/index.md +0 -544
@@ -1,440 +1,184 @@
1
1
  # Theming
2
2
 
3
- This guide covers customizing colors, styles, and branding.
3
+ Customize colors, styles, dark mode, and branding.
4
4
 
5
- ## Overview
5
+ ## Goal
6
6
 
7
- Plutonium uses TailwindCSS 4 with a design token system for consistent styling. Customization happens through:
7
+ Adapt Plutonium's defaults to match your brand: primary color, fonts, logo, dark mode behavior, optionally per-component theming.
8
8
 
9
- - **Design Tokens** - CSS custom properties for colors, spacing, shadows
10
- - **Component Classes** - Pre-built `.pu-*` classes for buttons, inputs, tables
11
- - **Tailwind Configuration** - Extend colors and design tokens
12
- - **Component Themes** - Override form, table, and display styling
9
+ ## How theming layers stack
13
10
 
14
- ## Design Token System
11
+ | Layer | What to edit | When to use |
12
+ |---|---|---|
13
+ | **Asset config** | `Plutonium.configure` | Logo / favicon / asset file paths |
14
+ | **CSS tokens** | `--pu-*` variables in your CSS | Colors that should auto-switch with dark mode |
15
+ | **Tailwind theme** | `tailwind.config.js` | Brand color palettes, custom fonts |
16
+ | **`.pu-*` classes** | Use in markup | Pre-styled buttons / inputs / cards |
17
+ | **Phlexi component themes** | Per-resource `Theme` class | Override Form/Display/Table per resource |
15
18
 
16
- Plutonium uses CSS custom properties (design tokens) for theming. These tokens automatically adapt to light and dark modes.
19
+ ## 🚨 Critical
17
20
 
18
- ### Available Tokens
21
+ - **Always register Stimulus controllers** — `registerControllers(application)`. Without it, the entire interactive layer is dead.
22
+ - **Use `plutoniumTailwindConfig.merge`** when overriding Tailwind theme — plain object spread drops Plutonium's defaults.
23
+ - **Tokens are CSS variables, not Tailwind keys** — `bg-[var(--pu-surface)]`, NOT `bg-pu-surface`.
24
+ - **Dark mode is `selector`, not `class`** — toggle by adding/removing `dark` on `<html>`.
25
+ - **Prefer `.pu-*` classes and `var(--pu-*)` tokens** over hardcoded `gray-X/dark:gray-Y` pairs — they switch with dark mode automatically.
19
26
 
20
- #### Surface Colors
27
+ ## Step 1: Run the assets generator
21
28
 
22
- ```css
23
- --pu-body /* Page background */
24
- --pu-surface /* Card/panel backgrounds */
25
- --pu-surface-alt /* Alternate surface (headers, sidebars) */
26
- --pu-surface-raised /* Elevated surfaces */
27
- --pu-surface-overlay /* Modal/dropdown overlays */
28
- ```
29
-
30
- #### Border Colors
31
-
32
- ```css
33
- --pu-border /* Default borders */
34
- --pu-border-muted /* Subtle borders */
35
- --pu-border-strong /* Emphasized borders */
36
- ```
37
-
38
- #### Text Colors
39
-
40
- ```css
41
- --pu-text /* Primary text */
42
- --pu-text-muted /* Secondary text */
43
- --pu-text-subtle /* Tertiary/placeholder text */
44
- ```
45
-
46
- #### Table Tokens
47
-
48
- ```css
49
- --pu-table-header-bg /* Header background */
50
- --pu-table-header-text /* Header text color */
51
- --pu-table-row-bg /* Row background */
52
- --pu-table-row-hover /* Row hover state */
53
- --pu-table-row-selected /* Selected row */
54
- --pu-table-border /* Row borders */
29
+ ```bash
30
+ rails generate pu:core:assets
55
31
  ```
56
32
 
57
- #### Form Tokens
33
+ This installs npm packages, creates `tailwind.config.js`, imports Plutonium CSS, registers Stimulus controllers, and points `Plutonium.configure` at your asset files. Run once per app.
58
34
 
59
- ```css
60
- --pu-input-bg /* Input background */
61
- --pu-input-border /* Input border */
62
- --pu-input-focus-ring /* Focus ring color */
63
- --pu-input-placeholder /* Placeholder text */
64
- ```
65
-
66
- #### Card Tokens
35
+ ## Step 2: Asset configuration
67
36
 
68
- ```css
69
- --pu-card-bg /* Card background */
70
- --pu-card-border /* Card border */
71
- ```
72
-
73
- #### Shadow System
37
+ ```ruby
38
+ # config/initializers/plutonium.rb
39
+ Plutonium.configure do |config|
40
+ config.load_defaults 1.0
74
41
 
75
- ```css
76
- --pu-shadow-sm /* Subtle shadow */
77
- --pu-shadow-md /* Medium shadow */
78
- --pu-shadow-lg /* Large shadow */
42
+ config.assets.stylesheet = "application"
43
+ config.assets.script = "application"
44
+ config.assets.logo = "my_logo.png"
45
+ config.assets.favicon = "my_favicon.ico"
46
+ end
79
47
  ```
80
48
 
81
- #### Spacing Scale
82
-
83
- ```css
84
- --pu-space-xs /* 0.25rem */
85
- --pu-space-sm /* 0.5rem */
86
- --pu-space-md /* 1rem */
87
- --pu-space-lg /* 1.5rem */
88
- --pu-space-xl /* 2rem */
89
- ```
49
+ Logo / favicon resolved from `app/assets/images/`.
90
50
 
91
- #### Border Radius
51
+ ## Step 3: Customize colors via Tailwind
92
52
 
93
- ```css
94
- --pu-radius-sm /* 0.375rem */
95
- --pu-radius-md /* 0.5rem */
96
- --pu-radius-lg /* 0.75rem */
97
- --pu-radius-xl /* 1rem */
98
- --pu-radius-full /* 9999px */
53
+ ```javascript
54
+ // tailwind.config.js
55
+ theme: plutoniumTailwindConfig.merge(plutoniumTailwindConfig.theme, {
56
+ extend: {
57
+ colors: {
58
+ primary: { 50: '#eff6ff', 500: '#3b82f6', 900: '#1e3a8a' },
59
+ secondary: { 50: '#f3f4f6', 500: '#6b7280', 900: '#111827' },
60
+ },
61
+ },
62
+ })
99
63
  ```
100
64
 
101
- #### Transitions
65
+ ### Default palette
102
66
 
103
- ```css
104
- --pu-transition-fast /* 150ms */
105
- --pu-transition-normal /* 200ms */
106
- --pu-transition-slow /* 300ms */
107
- ```
108
-
109
- ### Overriding Tokens
67
+ | Color | Use |
68
+ |---|---|
69
+ | `primary` | Brand primary (turquoise default) |
70
+ | `secondary` | Brand secondary (navy default) |
71
+ | `success` | Success states (green) |
72
+ | `info` | Informational (blue) |
73
+ | `warning` | Warning (amber) |
74
+ | `danger` | Error (red) |
75
+ | `accent` | Highlight (coral pink) |
110
76
 
111
- Override tokens in your CSS to customize the theme:
77
+ ## Step 4: Customize design tokens (dark-mode-aware)
112
78
 
113
79
  ```css
114
- /* app/assets/stylesheets/application.css */
115
- @import "tailwindcss";
80
+ /* app/assets/stylesheets/application.tailwind.css */
116
81
  @import "gem:plutonium/src/css/plutonium.css";
82
+ @import "tailwindcss";
117
83
 
118
- /* Light mode overrides */
119
84
  :root {
120
85
  --pu-surface: #fafafa;
121
- --pu-border: #d4d4d4;
122
- --pu-input-focus-ring: #6366f1;
86
+ --pu-border: #d1d5db;
123
87
  }
124
88
 
125
- /* Dark mode overrides */
126
89
  .dark {
127
- --pu-surface: #18181b;
128
- --pu-border: #3f3f46;
90
+ --pu-surface: #111827;
91
+ --pu-border: #374151;
129
92
  }
130
93
  ```
131
94
 
132
- ## Component Classes
133
-
134
- Plutonium provides pre-built component classes for common UI elements.
135
-
136
- ### Buttons
137
-
138
- ```html
139
- <!-- Sizes -->
140
- <button class="pu-btn pu-btn-md pu-btn-primary">Medium</button>
141
- <button class="pu-btn pu-btn-sm pu-btn-primary">Small</button>
142
- <button class="pu-btn pu-btn-xs pu-btn-primary">Extra Small</button>
143
-
144
- <!-- Solid variants -->
145
- <button class="pu-btn pu-btn-md pu-btn-primary">Primary</button>
146
- <button class="pu-btn pu-btn-md pu-btn-secondary">Secondary</button>
147
- <button class="pu-btn pu-btn-md pu-btn-success">Success</button>
148
- <button class="pu-btn pu-btn-md pu-btn-danger">Danger</button>
149
- <button class="pu-btn pu-btn-md pu-btn-warning">Warning</button>
150
- <button class="pu-btn pu-btn-md pu-btn-info">Info</button>
151
- <button class="pu-btn pu-btn-md pu-btn-accent">Accent</button>
152
-
153
- <!-- Soft variants (tinted backgrounds) -->
154
- <button class="pu-btn pu-btn-md pu-btn-soft-primary">Soft Primary</button>
155
- <button class="pu-btn pu-btn-md pu-btn-soft-secondary">Soft Secondary</button>
156
- <button class="pu-btn pu-btn-md pu-btn-soft-success">Soft Success</button>
157
- <button class="pu-btn pu-btn-md pu-btn-soft-danger">Soft Danger</button>
158
- <button class="pu-btn pu-btn-md pu-btn-soft-warning">Soft Warning</button>
159
- <button class="pu-btn pu-btn-md pu-btn-soft-info">Soft Info</button>
160
- <button class="pu-btn pu-btn-md pu-btn-soft-accent">Soft Accent</button>
161
-
162
- <!-- Other styles -->
163
- <button class="pu-btn pu-btn-md pu-btn-ghost">Ghost</button>
164
- <button class="pu-btn pu-btn-md pu-btn-outline">Outline</button>
165
- ```
166
-
167
- ### Form Inputs
168
-
169
- ```html
170
- <label class="pu-label">Email</label>
171
- <input type="email" class="pu-input" placeholder="you@example.com">
172
- <p class="pu-hint">We'll never share your email.</p>
173
-
174
- <!-- Validation states -->
175
- <input type="text" class="pu-input pu-input-invalid">
176
- <p class="pu-error">This field is required.</p>
177
-
178
- <input type="text" class="pu-input pu-input-valid">
179
- ```
180
-
181
- ### Checkboxes
95
+ Tokens auto-switch when the user toggles dark mode. See [Reference › UI › Assets › Design tokens](/reference/ui/assets#design-tokens) for the full token catalog.
182
96
 
183
- ```html
184
- <input type="checkbox" class="pu-checkbox">
185
- ```
186
-
187
- ### Cards
188
-
189
- ```html
190
- <div class="pu-card">
191
- <div class="pu-card-body">
192
- Card content here
193
- </div>
194
- </div>
195
- ```
97
+ ## Using tokens in your code
196
98
 
197
- ### Tables
198
-
199
- ```html
200
- <div class="pu-table-wrapper">
201
- <table class="pu-table">
202
- <thead class="pu-table-header">
203
- <tr>
204
- <th class="pu-table-header-cell">Name</th>
205
- </tr>
206
- </thead>
207
- <tbody>
208
- <tr class="pu-table-body-row">
209
- <td class="pu-table-body-cell">John</td>
210
- </tr>
211
- </tbody>
212
- </table>
213
- </div>
214
- ```
215
-
216
- ### Empty States
99
+ ```erb
100
+ <h1 class="text-[var(--pu-text)]">Title</h1>
101
+ <p class="text-[var(--pu-text-muted)]">Description</p>
217
102
 
218
- ```html
219
- <div class="pu-empty-state">
220
- <svg class="pu-empty-state-icon">...</svg>
221
- <h3 class="pu-empty-state-title">No items found</h3>
222
- <p class="pu-empty-state-description">Get started by creating a new item.</p>
103
+ <div class="bg-[var(--pu-surface)] border border-[var(--pu-border)] rounded-[var(--pu-radius-lg)]">
104
+ Content
223
105
  </div>
224
106
  ```
225
107
 
226
- ## Setup Custom Assets
227
-
228
- Run the assets generator to set up your own TailwindCSS build:
229
-
230
- ```bash
231
- rails generate pu:core:assets
232
- ```
233
-
234
- This:
235
- 1. Installs required npm packages (`@radioactive-labs/plutonium`, TailwindCSS plugins)
236
- 2. Creates `tailwind.config.js` that extends Plutonium's config
237
- 3. Imports Plutonium CSS into your `application.tailwind.css`
238
- 4. Registers Plutonium's Stimulus controllers
239
- 5. Updates Plutonium config to use your assets
240
-
241
- ## Asset Configuration
242
-
243
- Configure assets in the initializer:
244
-
245
108
  ```ruby
246
- # config/initializers/plutonium.rb
247
- Plutonium.configure do |config|
248
- config.load_defaults 1.0
249
-
250
- config.assets.stylesheet = "application" # Your CSS file
251
- config.assets.script = "application" # Your JS file
252
- config.assets.logo = "my_logo.png" # Logo image
253
- config.assets.favicon = "my_favicon.ico" # Favicon
109
+ class MyComponent < Plutonium::UI::Component::Base
110
+ def view_template
111
+ div(
112
+ class: "bg-[var(--pu-surface)] border border-[var(--pu-border)] rounded-[var(--pu-radius-lg)]",
113
+ style: "box-shadow: var(--pu-shadow-md)"
114
+ ) do
115
+ h2(class: "text-lg font-semibold text-[var(--pu-text)]") { "Title" }
116
+ p(class: "text-[var(--pu-text-muted)]") { "Description" }
117
+ end
118
+ end
254
119
  end
255
120
  ```
256
121
 
257
- ## TailwindCSS Configuration
122
+ ## Use `.pu-*` component classes
258
123
 
259
- ### Generated Config
124
+ Pre-styled ready-to-use components:
260
125
 
261
- ```javascript
262
- // tailwind.config.js
263
- const { execSync } = require('child_process');
264
- const plutoniumGemPath = execSync("bundle show plutonium").toString().trim();
265
- const plutoniumTailwindConfig = require(`${plutoniumGemPath}/tailwind.options.js`)
266
-
267
- module.exports = {
268
- darkMode: plutoniumTailwindConfig.darkMode,
269
- plugins: [
270
- // Add your plugins here
271
- ].concat(plutoniumTailwindConfig.plugins),
272
- theme: plutoniumTailwindConfig.merge(
273
- plutoniumTailwindConfig.theme,
274
- {
275
- // Your custom theme overrides
276
- },
277
- ),
278
- content: [
279
- `${__dirname}/app/**/*.{erb,haml,html,slim,rb}`,
280
- `${__dirname}/app/javascript/**/*.js`,
281
- `${__dirname}/packages/**/app/**/*.{erb,haml,html,slim,rb}`,
282
- ].concat(plutoniumTailwindConfig.content),
283
- }
126
+ ```erb
127
+ <%= form.submit "Save", class: "pu-btn pu-btn-md pu-btn-primary" %>
284
128
  ```
285
129
 
286
- ### Customizing Colors
130
+ | Family | Classes |
131
+ |---|---|
132
+ | Buttons | `.pu-btn`, `.pu-btn-md/-sm/-xs`, `.pu-btn-primary/-secondary/-danger/-success/-warning/-info/-accent`, `.pu-btn-ghost/-outline`, `.pu-btn-soft-*` |
133
+ | Inputs | `.pu-input/-invalid/-valid`, `.pu-label/-required`, `.pu-hint`, `.pu-error`, `.pu-checkbox` |
134
+ | Cards | `.pu-card`, `.pu-card-body`, `.pu-panel-header`, `.pu-panel-title`, `.pu-panel-description` |
135
+ | Tables | `.pu-table-wrapper`, `.pu-table`, `-header`, `-header-cell`, `-body-row`, `-body-row-selected`, `-body-cell`, `.pu-selection-cell` |
136
+ | Toolbars / empty states | `.pu-toolbar`, `-text`, `-actions`; `.pu-empty-state`, `-icon`, `-title`, `-description` |
287
137
 
288
- Override Plutonium's color palette:
138
+ Full catalog: [Reference › UI › Assets › Component classes](/reference/ui/assets#component-classes-pu-).
289
139
 
290
- ```javascript
291
- // tailwind.config.js
292
- theme: plutoniumTailwindConfig.merge(
293
- plutoniumTailwindConfig.theme,
294
- {
295
- extend: {
296
- colors: {
297
- primary: {
298
- 50: '#eff6ff',
299
- 100: '#dbeafe',
300
- 200: '#bfdbfe',
301
- 300: '#93c5fd',
302
- 400: '#60a5fa',
303
- 500: '#3b82f6', // Your brand color
304
- 600: '#2563eb',
305
- 700: '#1d4ed8',
306
- 800: '#1e40af',
307
- 900: '#1e3a8a',
308
- 950: '#172554',
309
- },
310
- },
311
- },
312
- },
313
- ),
314
- ```
315
-
316
- ### Semantic Colors
317
-
318
- Plutonium includes these semantic colors:
319
-
320
- | Color | Usage |
321
- |-------|-------|
322
- | `primary` | Primary brand color |
323
- | `secondary` | Secondary color |
324
- | `success` | Success states (green) |
325
- | `info` | Informational states (blue) |
326
- | `warning` | Warning states (amber) |
327
- | `danger` | Error/danger states (red) |
328
- | `accent` | Accent highlights |
329
-
330
- ## CSS Imports
331
-
332
- ### Application Stylesheet
333
-
334
- ```css
335
- /* app/assets/stylesheets/application.tailwind.css */
336
- @import "gem:plutonium/src/css/plutonium.css";
337
-
338
- @import "tailwindcss";
339
- @config '../../../tailwind.config.js';
140
+ ## Migrating from hardcoded classes
340
141
 
341
- /* Your custom styles and token overrides */
342
- ```
343
-
344
- ## Component Themes
142
+ | Old | New |
143
+ |---|---|
144
+ | `text-gray-900 dark:text-white` | `text-[var(--pu-text)]` |
145
+ | `text-gray-500 dark:text-gray-400` | `text-[var(--pu-text-muted)]` |
146
+ | `bg-gray-50 dark:bg-gray-700` | `bg-[var(--pu-surface)]` |
147
+ | `border-gray-300 dark:border-gray-600` | `border-[var(--pu-border)]` |
148
+ | Long input class chain | `pu-input` |
149
+ | Long button class chain | `pu-btn pu-btn-md pu-btn-primary` |
345
150
 
346
- Plutonium components use a theme system. Override themes by defining nested Theme classes in your definitions.
151
+ ## Per-resource theming (Phlexi themes)
347
152
 
348
- ### Form Theme
153
+ Override Form/Display/Table appearance per resource via a nested `Theme` class:
349
154
 
350
155
  ```ruby
351
156
  class PostDefinition < ResourceDefinition
352
157
  class Form < Form
353
158
  class Theme < Plutonium::UI::Form::Theme
354
159
  def self.theme
355
- super.merge({
356
- base: "pu-card my-4 p-8 space-y-8",
357
- fields_wrapper: "grid grid-cols-2 gap-6",
160
+ super.merge(
161
+ base: "bg-[var(--pu-card-bg)] shadow-md rounded-lg p-6",
162
+ fields_wrapper: "grid grid-cols-2 gap-6",
358
163
  actions_wrapper: "flex justify-end mt-6 space-x-2",
359
- label: "pu-label",
360
- input: "pu-input",
361
- hint: "pu-hint",
362
- error: "pu-error",
363
- button: "pu-btn pu-btn-md pu-btn-primary",
364
- })
164
+ input: "pu-input",
165
+ button: "pu-btn pu-btn-md pu-btn-primary"
166
+ )
365
167
  end
366
168
  end
367
169
  end
368
170
  end
369
171
  ```
370
172
 
371
- ### Display Theme
173
+ ::: warning Always `super.merge(...)`
174
+ Don't replace the theme wholesale — Plutonium's defaults handle invalid states, focus rings, and dark mode. `super.merge` keeps them.
175
+ :::
372
176
 
373
- ```ruby
374
- class PostDefinition < ResourceDefinition
375
- class Display < Display
376
- class Theme < Plutonium::UI::Display::Theme
377
- def self.theme
378
- super.merge({
379
- fields_wrapper: "grid grid-cols-3 gap-8",
380
- label: "text-sm font-bold text-[var(--pu-text-muted)] mb-1",
381
- string: "text-lg text-[var(--pu-text)]",
382
- link: "text-primary-600 hover:underline",
383
- })
384
- end
385
- end
386
- end
387
- end
388
- ```
177
+ Full theme key catalog: [Reference › UI › Assets › Phlexi component themes](/reference/ui/assets#phlexi-component-themes).
389
178
 
390
- ### Table Theme
179
+ ## Typography
391
180
 
392
- ```ruby
393
- class PostDefinition < ResourceDefinition
394
- class Table < Table
395
- class Theme < Plutonium::UI::Table::Theme
396
- def self.theme
397
- super.merge({
398
- wrapper: "pu-table-wrapper",
399
- base: "pu-table",
400
- header: "pu-table-header",
401
- header_cell: "pu-table-header-cell",
402
- body_row: "pu-table-body-row",
403
- body_cell: "pu-table-body-cell",
404
- })
405
- end
406
- end
407
- end
408
- end
409
- ```
410
-
411
- ## Branding
412
-
413
- ### Application Name
414
-
415
- ```ruby
416
- # config/initializers/plutonium.rb
417
- Plutonium.application_name = "My Application"
418
- ```
419
-
420
- ### Custom Logo
421
-
422
- Override the logo in your layout:
423
-
424
- ```ruby
425
- # packages/admin_portal/app/views/layouts/admin_portal/application.rb
426
- module AdminPortal
427
- class ApplicationLayout < Plutonium::UI::Layout::Application
428
- def render_logo
429
- img(src: helpers.asset_path("logo.svg"), alt: "My App", class: "h-8")
430
- end
431
- end
432
- end
433
- ```
434
-
435
- ### Custom Fonts
436
-
437
- Override in your layout:
181
+ Default font: Lato. Override via the layout:
438
182
 
439
183
  ```ruby
440
184
  class MyLayout < Plutonium::UI::Layout::ResourceLayout
@@ -445,73 +189,79 @@ class MyLayout < Plutonium::UI::Layout::ResourceLayout
445
189
  end
446
190
  ```
447
191
 
448
- Update Tailwind config:
192
+ Then configure Tailwind to use it:
449
193
 
450
194
  ```javascript
451
- theme: {
195
+ theme: plutoniumTailwindConfig.merge(plutoniumTailwindConfig.theme, {
452
196
  fontFamily: {
453
- 'body': ['Inter', 'sans-serif'],
454
- 'sans': ['Inter', 'sans-serif'],
197
+ body: ['Inter', 'sans-serif'],
198
+ sans: ['Inter', 'sans-serif']
455
199
  }
456
- }
200
+ })
457
201
  ```
458
202
 
459
- ## Dark Mode
203
+ ## Dark mode
204
+
205
+ `selector` strategy. The bundled `color-mode` Stimulus controller handles toggling; Plutonium ships a switcher in the topbar.
460
206
 
461
- Plutonium uses `selector` strategy for dark mode. Toggle by adding/removing the `dark` class on `<html>`:
207
+ Manual toggle:
462
208
 
463
209
  ```javascript
464
- document.documentElement.classList.toggle('dark');
210
+ document.documentElement.classList.toggle('dark')
465
211
  ```
466
212
 
467
- Plutonium includes a color mode selector component that handles this automatically.
468
-
469
- Design tokens automatically adapt to dark mode - override the `.dark` selector in your CSS to customize dark mode colors.
213
+ If you've overridden tokens via `:root` and `.dark`, both modes Just Work.
470
214
 
471
- ## Stimulus Controllers
215
+ ## Per-portal chrome — eject the shell
472
216
 
473
- Register Plutonium's Stimulus controllers in your application:
474
-
475
- ```javascript
476
- // app/javascript/controllers/index.js
477
- import { application } from "./application"
478
-
479
- import { registerControllers } from "@radioactive-labs/plutonium"
480
- registerControllers(application)
217
+ For per-portal headers/sidebars:
481
218
 
482
- // Your custom controllers...
219
+ ```bash
220
+ rails generate pu:eject:shell --dest=admin_portal
483
221
  ```
484
222
 
485
- ### Available Controllers
223
+ Copies `_resource_header.html.erb` and `_resource_sidebar.html.erb` into the portal's `app/views/plutonium/`. Edit directly.
486
224
 
487
- - `color-mode` - Dark/light mode toggle
488
- - `form` - Form handling
489
- - `nested-resource-form-fields` - Nested form management
490
- - `slim-select` - Enhanced select boxes
491
- - `flatpickr` - Date/time pickers
492
- - `easymde` - Markdown editor
225
+ ```bash
226
+ rails generate pu:eject:layout
227
+ ```
493
228
 
494
- ### Custom Controllers
229
+ Copies `layouts/resource.html.erb` for layout-level edits.
495
230
 
496
- ```javascript
497
- // app/javascript/controllers/custom_controller.js
498
- import { Controller } from "@hotwired/stimulus"
231
+ ## Shell config
499
232
 
500
- export default class extends Controller {
501
- connect() {
502
- console.log("Connected")
503
- }
504
- }
233
+ ```ruby
234
+ Plutonium.configure do |config|
235
+ config.shell = :modern # default — topbar + icon rail
236
+ # config.shell = :classic # legacy header + sidebar (only when upgrading)
237
+ end
505
238
  ```
506
239
 
507
- Register in your index:
240
+ ## Stimulus
508
241
 
509
242
  ```javascript
243
+ // app/javascript/controllers/index.js
244
+ import { application } from "./application"
245
+ import { registerControllers } from "@radioactive-labs/plutonium"
246
+
247
+ registerControllers(application) // ← mandatory
248
+
249
+ // Your custom controllers...
510
250
  import CustomController from "./custom_controller"
511
251
  application.register("custom", CustomController)
512
252
  ```
513
253
 
254
+ Bundled controllers: `color-mode`, `form` (pre-submit), `nested-resource-form-fields`, `slim-select`, `flatpickr`, `easymde`.
255
+
256
+ ## Common issues
257
+
258
+ - **Stimulus controllers silently fail** — if `registerControllers(application)` isn't called, the entire UI's interactive layer is dead (color-mode toggle, slim-select, flatpickr, easymde, pre-submit). No error — just no behavior.
259
+ - **`plutoniumTailwindConfig.merge` is mandatory** — plain spread drops defaults silently.
260
+ - **Tokens not switching in dark mode** — you used `bg-pu-surface` instead of `bg-[var(--pu-surface)]`. Tokens are CSS variables, not Tailwind keys.
261
+ - **`.pu-btn` styles not applying** — check that Plutonium CSS is imported BEFORE Tailwind: `@import "gem:plutonium/src/css/plutonium.css";` then `@import "tailwindcss";`.
262
+
514
263
  ## Related
515
264
 
516
- - [Custom Actions](./custom-actions)
517
- - [Creating Packages](./creating-packages)
265
+ - [Reference › UI › Assets](/reference/ui/assets) — full Tailwind / Stimulus / design tokens / component classes surface
266
+ - [Reference › UI › Layouts](/reference/ui/layouts) — shell, eject, ResourceLayout
267
+ - [Reference › UI › Forms › Theming](/reference/ui/forms#theming) — Form theme keys
@@ -77,6 +77,8 @@ If you encounter an issue not covered here, please [open an issue](https://githu
77
77
 
78
78
  ## Related
79
79
 
80
- - [Nested Resources Guide](./nested-resources)
81
- - [Adding Resources Guide](./adding-resources)
82
- - [Rails Inflections Documentation](https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html)
80
+ - [Nested resources](./nested-resources)
81
+ - [Adding resources](./adding-resources)
82
+ - [Reference Behavior › Controllers](/reference/behavior/controllers) — `controller_for`, `resource_url_for`, `current_parent`
83
+ - [Reference › Tenancy › Nested resources](/reference/tenancy/nested-resources) — nested URL generation
84
+ - [Rails Inflections](https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html)