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.
- checksums.yaml +4 -4
- data/.claude/skills/plutonium/SKILL.md +85 -102
- data/.claude/skills/plutonium-app/SKILL.md +572 -0
- data/.claude/skills/plutonium-auth/SKILL.md +163 -300
- data/.claude/skills/plutonium-behavior/SKILL.md +838 -0
- data/.claude/skills/plutonium-resource/SKILL.md +1176 -0
- data/.claude/skills/plutonium-tenancy/SKILL.md +655 -0
- data/.claude/skills/plutonium-testing/SKILL.md +6 -5
- data/.claude/skills/plutonium-ui/SKILL.md +900 -0
- data/CHANGELOG.md +27 -2
- data/Rakefile +2 -1
- data/app/assets/plutonium.css +1 -11
- data/app/assets/plutonium.js +1009 -1214
- data/app/assets/plutonium.js.map +3 -3
- data/app/assets/plutonium.min.js +52 -51
- data/app/assets/plutonium.min.js.map +3 -3
- data/docs/.vitepress/config.ts +37 -27
- data/docs/getting-started/index.md +22 -29
- data/docs/getting-started/installation.md +37 -80
- data/docs/getting-started/tutorial/index.md +4 -5
- data/docs/guides/adding-resources.md +66 -377
- data/docs/guides/authentication.md +94 -463
- data/docs/guides/authorization.md +124 -370
- data/docs/guides/creating-packages.md +94 -296
- data/docs/guides/custom-actions.md +121 -441
- data/docs/guides/index.md +22 -42
- data/docs/guides/multi-tenancy.md +116 -187
- data/docs/guides/nested-resources.md +103 -431
- data/docs/guides/search-filtering.md +123 -240
- data/docs/guides/testing.md +5 -4
- data/docs/guides/theming.md +157 -407
- data/docs/guides/troubleshooting.md +5 -3
- data/docs/guides/user-invites.md +106 -425
- data/docs/guides/user-profile.md +76 -243
- data/docs/index.md +1 -1
- data/docs/reference/app/generators.md +517 -0
- data/docs/reference/app/index.md +158 -0
- data/docs/reference/app/packages.md +146 -0
- data/docs/reference/app/portals.md +377 -0
- data/docs/reference/auth/accounts.md +230 -0
- data/docs/reference/auth/index.md +88 -0
- data/docs/reference/auth/profile.md +185 -0
- data/docs/reference/behavior/controllers.md +395 -0
- data/docs/reference/behavior/index.md +22 -0
- data/docs/reference/behavior/interactions.md +341 -0
- data/docs/reference/behavior/policies.md +417 -0
- data/docs/reference/index.md +56 -49
- data/docs/reference/resource/actions.md +423 -0
- data/docs/reference/resource/definition.md +508 -0
- data/docs/reference/resource/index.md +50 -0
- data/docs/reference/resource/model.md +348 -0
- data/docs/reference/resource/query.md +305 -0
- data/docs/reference/tenancy/entity-scoping.md +361 -0
- data/docs/reference/tenancy/index.md +36 -0
- data/docs/reference/tenancy/invites.md +393 -0
- data/docs/reference/tenancy/nested-resources.md +267 -0
- data/docs/reference/testing/index.md +287 -0
- data/docs/reference/ui/assets.md +400 -0
- data/docs/reference/ui/components.md +165 -0
- data/docs/reference/ui/displays.md +104 -0
- data/docs/reference/ui/forms.md +284 -0
- data/docs/reference/ui/index.md +30 -0
- data/docs/reference/ui/layouts.md +106 -0
- data/docs/reference/ui/pages.md +189 -0
- data/docs/reference/ui/tables.md +117 -0
- data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
- data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
- data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
- data/gemfiles/rails_7.gemfile.lock +1 -1
- data/gemfiles/rails_8.0.gemfile.lock +1 -1
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/generators/pu/core/update/update_generator.rb +0 -20
- data/lib/generators/pu/invites/install_generator.rb +1 -0
- data/lib/plutonium/definition/base.rb +1 -1
- data/lib/plutonium/definition/{views.rb → index_views.rb} +21 -20
- data/lib/plutonium/helpers/turbo_helper.rb +11 -0
- data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
- data/lib/plutonium/resource/controller.rb +1 -0
- data/lib/plutonium/resource/controllers/crud_actions.rb +19 -1
- data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
- data/lib/plutonium/resource/policy.rb +7 -0
- data/lib/plutonium/routing/mapper_extensions.rb +15 -0
- data/lib/plutonium/ui/component/methods.rb +4 -0
- data/lib/plutonium/ui/form/base.rb +6 -2
- data/lib/plutonium/ui/form/components/json.rb +58 -0
- data/lib/plutonium/ui/form/components/resource_select.rb +62 -8
- data/lib/plutonium/ui/form/components/secure_association.rb +98 -22
- data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
- data/lib/plutonium/ui/form/resource.rb +0 -4
- data/lib/plutonium/ui/grid/resource.rb +1 -1
- data/lib/plutonium/ui/layout/base.rb +1 -0
- data/lib/plutonium/ui/page/base.rb +0 -7
- data/lib/plutonium/ui/page/index.rb +4 -4
- data/lib/plutonium/ui/table/resource.rb +1 -1
- data/lib/plutonium/version.rb +1 -1
- data/lib/plutonium.rb +8 -0
- data/lib/tasks/release.rake +15 -1
- data/package.json +10 -10
- data/src/css/slim_select.css +4 -0
- data/src/js/controllers/slim_select_controller.js +61 -0
- data/src/js/turbo/turbo_actions.js +33 -0
- data/yarn.lock +553 -543
- metadata +44 -33
- data/.claude/skills/plutonium-assets/SKILL.md +0 -512
- data/.claude/skills/plutonium-controller/SKILL.md +0 -396
- data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
- data/.claude/skills/plutonium-definition/SKILL.md +0 -1223
- data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
- data/.claude/skills/plutonium-forms/SKILL.md +0 -465
- data/.claude/skills/plutonium-installation/SKILL.md +0 -331
- data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
- data/.claude/skills/plutonium-invites/SKILL.md +0 -408
- data/.claude/skills/plutonium-model/SKILL.md +0 -440
- data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
- data/.claude/skills/plutonium-package/SKILL.md +0 -198
- data/.claude/skills/plutonium-policy/SKILL.md +0 -456
- data/.claude/skills/plutonium-portal/SKILL.md +0 -410
- data/.claude/skills/plutonium-views/SKILL.md +0 -651
- data/docs/reference/assets/index.md +0 -496
- data/docs/reference/controller/index.md +0 -412
- data/docs/reference/definition/actions.md +0 -462
- data/docs/reference/definition/fields.md +0 -383
- data/docs/reference/definition/index.md +0 -326
- data/docs/reference/definition/query.md +0 -351
- data/docs/reference/generators/index.md +0 -648
- data/docs/reference/interaction/index.md +0 -449
- data/docs/reference/model/features.md +0 -248
- data/docs/reference/model/index.md +0 -218
- data/docs/reference/policy/index.md +0 -456
- data/docs/reference/portal/index.md +0 -379
- data/docs/reference/views/forms.md +0 -411
- data/docs/reference/views/index.md +0 -544
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: plutonium
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.51.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stefan Froelich
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-05-
|
|
10
|
+
date: 2026-05-14 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: zeitwerk
|
|
@@ -427,23 +427,13 @@ extensions: []
|
|
|
427
427
|
extra_rdoc_files: []
|
|
428
428
|
files:
|
|
429
429
|
- "# Plutonium: The pre-alpha demo.md"
|
|
430
|
-
- ".claude/skills/plutonium-
|
|
430
|
+
- ".claude/skills/plutonium-app/SKILL.md"
|
|
431
431
|
- ".claude/skills/plutonium-auth/SKILL.md"
|
|
432
|
-
- ".claude/skills/plutonium-
|
|
433
|
-
- ".claude/skills/plutonium-
|
|
434
|
-
- ".claude/skills/plutonium-
|
|
435
|
-
- ".claude/skills/plutonium-entity-scoping/SKILL.md"
|
|
436
|
-
- ".claude/skills/plutonium-forms/SKILL.md"
|
|
437
|
-
- ".claude/skills/plutonium-installation/SKILL.md"
|
|
438
|
-
- ".claude/skills/plutonium-interaction/SKILL.md"
|
|
439
|
-
- ".claude/skills/plutonium-invites/SKILL.md"
|
|
440
|
-
- ".claude/skills/plutonium-model/SKILL.md"
|
|
441
|
-
- ".claude/skills/plutonium-nested-resources/SKILL.md"
|
|
442
|
-
- ".claude/skills/plutonium-package/SKILL.md"
|
|
443
|
-
- ".claude/skills/plutonium-policy/SKILL.md"
|
|
444
|
-
- ".claude/skills/plutonium-portal/SKILL.md"
|
|
432
|
+
- ".claude/skills/plutonium-behavior/SKILL.md"
|
|
433
|
+
- ".claude/skills/plutonium-resource/SKILL.md"
|
|
434
|
+
- ".claude/skills/plutonium-tenancy/SKILL.md"
|
|
445
435
|
- ".claude/skills/plutonium-testing/SKILL.md"
|
|
446
|
-
- ".claude/skills/plutonium-
|
|
436
|
+
- ".claude/skills/plutonium-ui/SKILL.md"
|
|
447
437
|
- ".claude/skills/plutonium/SKILL.md"
|
|
448
438
|
- ".cliff.toml"
|
|
449
439
|
- ".node-version"
|
|
@@ -593,21 +583,36 @@ files:
|
|
|
593
583
|
- docs/public/tutorial/plutonium-posts-detail-customized.png
|
|
594
584
|
- docs/public/tutorial/plutonium-posts-detail.png
|
|
595
585
|
- docs/public/tutorial/plutonium-publish-post.png
|
|
596
|
-
- docs/reference/
|
|
597
|
-
- docs/reference/
|
|
598
|
-
- docs/reference/
|
|
599
|
-
- docs/reference/
|
|
600
|
-
- docs/reference/
|
|
601
|
-
- docs/reference/
|
|
602
|
-
- docs/reference/
|
|
586
|
+
- docs/reference/app/generators.md
|
|
587
|
+
- docs/reference/app/index.md
|
|
588
|
+
- docs/reference/app/packages.md
|
|
589
|
+
- docs/reference/app/portals.md
|
|
590
|
+
- docs/reference/auth/accounts.md
|
|
591
|
+
- docs/reference/auth/index.md
|
|
592
|
+
- docs/reference/auth/profile.md
|
|
593
|
+
- docs/reference/behavior/controllers.md
|
|
594
|
+
- docs/reference/behavior/index.md
|
|
595
|
+
- docs/reference/behavior/interactions.md
|
|
596
|
+
- docs/reference/behavior/policies.md
|
|
603
597
|
- docs/reference/index.md
|
|
604
|
-
- docs/reference/
|
|
605
|
-
- docs/reference/
|
|
606
|
-
- docs/reference/
|
|
607
|
-
- docs/reference/
|
|
608
|
-
- docs/reference/
|
|
609
|
-
- docs/reference/
|
|
610
|
-
- docs/reference/
|
|
598
|
+
- docs/reference/resource/actions.md
|
|
599
|
+
- docs/reference/resource/definition.md
|
|
600
|
+
- docs/reference/resource/index.md
|
|
601
|
+
- docs/reference/resource/model.md
|
|
602
|
+
- docs/reference/resource/query.md
|
|
603
|
+
- docs/reference/tenancy/entity-scoping.md
|
|
604
|
+
- docs/reference/tenancy/index.md
|
|
605
|
+
- docs/reference/tenancy/invites.md
|
|
606
|
+
- docs/reference/tenancy/nested-resources.md
|
|
607
|
+
- docs/reference/testing/index.md
|
|
608
|
+
- docs/reference/ui/assets.md
|
|
609
|
+
- docs/reference/ui/components.md
|
|
610
|
+
- docs/reference/ui/displays.md
|
|
611
|
+
- docs/reference/ui/forms.md
|
|
612
|
+
- docs/reference/ui/index.md
|
|
613
|
+
- docs/reference/ui/layouts.md
|
|
614
|
+
- docs/reference/ui/pages.md
|
|
615
|
+
- docs/reference/ui/tables.md
|
|
611
616
|
- docs/superpowers/plans/2026-04-08-plutonium-skills-overhaul.md
|
|
612
617
|
- docs/superpowers/plans/2026-04-14-plutonium-testing.md
|
|
613
618
|
- docs/superpowers/plans/2026-04-14-plutonium-testing.md.tasks.json
|
|
@@ -618,6 +623,9 @@ files:
|
|
|
618
623
|
- docs/superpowers/specs/2026-04-08-plutonium-skills-overhaul-design.md
|
|
619
624
|
- docs/superpowers/specs/2026-04-14-plutonium-testing-design.md
|
|
620
625
|
- docs/superpowers/specs/2026-05-07-ui-layout-overhaul-design.md
|
|
626
|
+
- docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md
|
|
627
|
+
- docs/superpowers/specs/2026-05-12-skill-compaction-design.md
|
|
628
|
+
- docs/superpowers/specs/2026-05-13-docs-restructure-design.md
|
|
621
629
|
- esbuild.config.js
|
|
622
630
|
- exe/pug
|
|
623
631
|
- gemfiles/rails_7.gemfile
|
|
@@ -912,6 +920,7 @@ files:
|
|
|
912
920
|
- lib/plutonium/definition/base.rb
|
|
913
921
|
- lib/plutonium/definition/config_attr.rb
|
|
914
922
|
- lib/plutonium/definition/defineable_props.rb
|
|
923
|
+
- lib/plutonium/definition/index_views.rb
|
|
915
924
|
- lib/plutonium/definition/inheritable_config_attr.rb
|
|
916
925
|
- lib/plutonium/definition/metadata.rb
|
|
917
926
|
- lib/plutonium/definition/nested_inputs.rb
|
|
@@ -919,7 +928,6 @@ files:
|
|
|
919
928
|
- lib/plutonium/definition/scoping.rb
|
|
920
929
|
- lib/plutonium/definition/search.rb
|
|
921
930
|
- lib/plutonium/definition/sorting.rb
|
|
922
|
-
- lib/plutonium/definition/views.rb
|
|
923
931
|
- lib/plutonium/engine.rb
|
|
924
932
|
- lib/plutonium/engine/validator.rb
|
|
925
933
|
- lib/plutonium/helpers.rb
|
|
@@ -983,6 +991,7 @@ files:
|
|
|
983
991
|
- lib/plutonium/resource/controllers/interactive_actions.rb
|
|
984
992
|
- lib/plutonium/resource/controllers/presentable.rb
|
|
985
993
|
- lib/plutonium/resource/controllers/queryable.rb
|
|
994
|
+
- lib/plutonium/resource/controllers/typeahead.rb
|
|
986
995
|
- lib/plutonium/resource/definition.rb
|
|
987
996
|
- lib/plutonium/resource/interaction.rb
|
|
988
997
|
- lib/plutonium/resource/policy.rb
|
|
@@ -1039,6 +1048,7 @@ files:
|
|
|
1039
1048
|
- lib/plutonium/ui/form/components/flatpickr.rb
|
|
1040
1049
|
- lib/plutonium/ui/form/components/hidden_wrapper.rb
|
|
1041
1050
|
- lib/plutonium/ui/form/components/intl_tel_input.rb
|
|
1051
|
+
- lib/plutonium/ui/form/components/json.rb
|
|
1042
1052
|
- lib/plutonium/ui/form/components/key_value_store.rb
|
|
1043
1053
|
- lib/plutonium/ui/form/components/resource_select.rb
|
|
1044
1054
|
- lib/plutonium/ui/form/components/secure_association.rb
|
|
@@ -1046,6 +1056,7 @@ files:
|
|
|
1046
1056
|
- lib/plutonium/ui/form/components/sticky_footer.rb
|
|
1047
1057
|
- lib/plutonium/ui/form/components/uppy.rb
|
|
1048
1058
|
- lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb
|
|
1059
|
+
- lib/plutonium/ui/form/concerns/typeahead_attributes.rb
|
|
1049
1060
|
- lib/plutonium/ui/form/interaction.rb
|
|
1050
1061
|
- lib/plutonium/ui/form/options/inferred_types.rb
|
|
1051
1062
|
- lib/plutonium/ui/form/query.rb
|
|
@@ -1172,7 +1183,7 @@ metadata:
|
|
|
1172
1183
|
homepage_uri: https://radioactive-labs.github.io/plutonium-core/
|
|
1173
1184
|
source_code_uri: https://github.com/radioactive-labs/plutonium-core
|
|
1174
1185
|
post_install_message: |
|
|
1175
|
-
⚠️ Plutonium 0.
|
|
1186
|
+
⚠️ Plutonium 0.51.0 — breaking change
|
|
1176
1187
|
|
|
1177
1188
|
Entity-scoped URL helpers and path params have been renamed from
|
|
1178
1189
|
`<entity>_scope_*` to `<entity>_scoped_*`.
|
|
@@ -1,512 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: plutonium-assets
|
|
3
|
-
description: Use BEFORE configuring Tailwind, registering a Stimulus controller, or editing design tokens / theming in a Plutonium app. Also when running pu:core:assets or editing tailwind.config.js. Covers the full frontend toolchain.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Plutonium Assets, Stimulus & Theming
|
|
7
|
-
|
|
8
|
-
## 🚨 Critical (read first)
|
|
9
|
-
- **Use the generator.** `pu:core:assets` wires Tailwind, imports Plutonium CSS, registers Stimulus controllers, and updates the Plutonium config. Never hand-roll this.
|
|
10
|
-
- **Always register Stimulus controllers.** `registerControllers(application)` is required — Plutonium's controllers (color-mode, form, slim-select, flatpickr, easymde, etc.) are dead without it. Custom controllers must also be explicitly registered.
|
|
11
|
-
- **Use `plutoniumTailwindConfig.merge`** when overriding theme keys. Plain object merge drops Plutonium's defaults.
|
|
12
|
-
- **Prefer `.pu-*` classes and CSS tokens** over hardcoded `gray-*/dark:gray-*` pairs — they switch with dark mode automatically.
|
|
13
|
-
- **Related skills:** `plutonium-views` (layout customization), `plutonium-forms` (form theming), `plutonium-installation` (initial setup).
|
|
14
|
-
|
|
15
|
-
Plutonium uses TailwindCSS 4 for styling with a customizable theme system for components, and ships its own Stimulus controllers and CSS design token system.
|
|
16
|
-
|
|
17
|
-
## Contents
|
|
18
|
-
- [Asset configuration](#asset-configuration)
|
|
19
|
-
- [TailwindCSS configuration](#tailwindcss-configuration)
|
|
20
|
-
- [CSS imports](#css-imports)
|
|
21
|
-
- [Phlexi component themes](#phlexi-component-themes)
|
|
22
|
-
- [Stimulus controllers](#stimulus-controllers)
|
|
23
|
-
- [Design tokens and theming](#design-tokens-and-theming)
|
|
24
|
-
- [Component classes (`.pu-*`)](#component-classes)
|
|
25
|
-
- [Gotchas](#gotchas)
|
|
26
|
-
|
|
27
|
-
## Asset configuration
|
|
28
|
-
|
|
29
|
-
```ruby
|
|
30
|
-
# config/initializers/plutonium.rb
|
|
31
|
-
Plutonium.configure do |config|
|
|
32
|
-
config.load_defaults 1.0
|
|
33
|
-
|
|
34
|
-
config.assets.stylesheet = "application" # Your CSS file
|
|
35
|
-
config.assets.script = "application" # Your JS file
|
|
36
|
-
config.assets.logo = "my_logo.png"
|
|
37
|
-
config.assets.favicon = "my_favicon.ico"
|
|
38
|
-
end
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Run the assets generator to set up your own TailwindCSS build:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
rails generate pu:core:assets
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
This:
|
|
48
|
-
1. Installs required npm packages (`@radioactive-labs/plutonium`, TailwindCSS plugins)
|
|
49
|
-
2. Creates `tailwind.config.js` that extends Plutonium's config
|
|
50
|
-
3. Imports Plutonium CSS into your `application.tailwind.css`
|
|
51
|
-
4. Registers Plutonium's Stimulus controllers
|
|
52
|
-
5. Updates Plutonium config to use your assets
|
|
53
|
-
|
|
54
|
-
## TailwindCSS configuration
|
|
55
|
-
|
|
56
|
-
### Generated Config
|
|
57
|
-
|
|
58
|
-
```javascript
|
|
59
|
-
// tailwind.config.js
|
|
60
|
-
const { execSync } = require('child_process');
|
|
61
|
-
const plutoniumGemPath = execSync("bundle show plutonium").toString().trim();
|
|
62
|
-
const plutoniumTailwindConfig = require(`${plutoniumGemPath}/tailwind.options.js`)
|
|
63
|
-
|
|
64
|
-
module.exports = {
|
|
65
|
-
darkMode: plutoniumTailwindConfig.darkMode,
|
|
66
|
-
plugins: [].concat(plutoniumTailwindConfig.plugins),
|
|
67
|
-
theme: plutoniumTailwindConfig.merge(
|
|
68
|
-
plutoniumTailwindConfig.theme,
|
|
69
|
-
{
|
|
70
|
-
// Your custom theme overrides
|
|
71
|
-
},
|
|
72
|
-
),
|
|
73
|
-
content: [
|
|
74
|
-
`${__dirname}/app/**/*.{erb,haml,html,slim,rb}`,
|
|
75
|
-
`${__dirname}/app/javascript/**/*.js`,
|
|
76
|
-
`${__dirname}/packages/**/app/**/*.{erb,haml,html,slim,rb}`,
|
|
77
|
-
].concat(plutoniumTailwindConfig.content),
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Customizing Colors
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
theme: plutoniumTailwindConfig.merge(
|
|
85
|
-
plutoniumTailwindConfig.theme,
|
|
86
|
-
{
|
|
87
|
-
extend: {
|
|
88
|
-
colors: {
|
|
89
|
-
primary: {
|
|
90
|
-
50: '#eff6ff', 500: '#3b82f6', 900: '#1e3a8a',
|
|
91
|
-
// ...
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
),
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Default Color Palette
|
|
100
|
-
|
|
101
|
-
| Color | Usage |
|
|
102
|
-
|-------|-------|
|
|
103
|
-
| `primary` | Primary brand color (turquoise by default) |
|
|
104
|
-
| `secondary` | Secondary color (navy by default) |
|
|
105
|
-
| `success` | Success states (green) |
|
|
106
|
-
| `info` | Informational states (blue) |
|
|
107
|
-
| `warning` | Warning states (amber) |
|
|
108
|
-
| `danger` | Error/danger states (red) |
|
|
109
|
-
| `accent` | Accent highlights (coral pink) |
|
|
110
|
-
|
|
111
|
-
### Dark Mode
|
|
112
|
-
|
|
113
|
-
Plutonium uses `selector` strategy for dark mode. Toggle by adding/removing `dark` class on `<html>`. Plutonium includes a color mode selector component that handles this automatically.
|
|
114
|
-
|
|
115
|
-
## CSS imports
|
|
116
|
-
|
|
117
|
-
```css
|
|
118
|
-
/* app/assets/stylesheets/application.tailwind.css */
|
|
119
|
-
@import "gem:plutonium/src/css/plutonium.css";
|
|
120
|
-
|
|
121
|
-
@import "tailwindcss";
|
|
122
|
-
@config '../../../tailwind.config.js';
|
|
123
|
-
|
|
124
|
-
/* Your custom styles */
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Plutonium CSS includes: core utility classes, EasyMDE (markdown editor) styles, Slim Select styles, International telephone input styles, Flatpickr (date picker) styles.
|
|
128
|
-
|
|
129
|
-
## Phlexi component themes
|
|
130
|
-
|
|
131
|
-
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.
|
|
132
|
-
|
|
133
|
-
### Form Theme
|
|
134
|
-
|
|
135
|
-
```ruby
|
|
136
|
-
class PostDefinition < ResourceDefinition
|
|
137
|
-
class Form < Form
|
|
138
|
-
class Theme < Plutonium::UI::Form::Theme
|
|
139
|
-
def self.theme
|
|
140
|
-
super.merge({
|
|
141
|
-
base: "bg-white dark:bg-gray-800 shadow-md rounded-lg p-6",
|
|
142
|
-
fields_wrapper: "grid grid-cols-2 gap-6",
|
|
143
|
-
actions_wrapper: "flex justify-end mt-6 space-x-2",
|
|
144
|
-
label: "block mb-2 text-base font-bold",
|
|
145
|
-
invalid_label: "text-red-700 dark:text-red-500",
|
|
146
|
-
input: "w-full p-2 border rounded-md shadow-sm",
|
|
147
|
-
invalid_input: "bg-red-50 border-red-500 text-red-900",
|
|
148
|
-
hint: "mt-2 text-sm text-gray-500",
|
|
149
|
-
error: "mt-2 text-sm text-red-600",
|
|
150
|
-
button: "px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700",
|
|
151
|
-
})
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Display Theme
|
|
159
|
-
|
|
160
|
-
```ruby
|
|
161
|
-
class PostDefinition < ResourceDefinition
|
|
162
|
-
class Display < Display
|
|
163
|
-
class Theme < Plutonium::UI::Display::Theme
|
|
164
|
-
def self.theme
|
|
165
|
-
super.merge({
|
|
166
|
-
fields_wrapper: "grid grid-cols-3 gap-8",
|
|
167
|
-
label: "text-sm font-bold text-gray-500 mb-1",
|
|
168
|
-
string: "text-lg text-gray-900 dark:text-white",
|
|
169
|
-
link: "text-primary-600 hover:underline",
|
|
170
|
-
markdown: "prose dark:prose-invert max-w-none",
|
|
171
|
-
})
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### Table Theme
|
|
179
|
-
|
|
180
|
-
```ruby
|
|
181
|
-
class PostDefinition < ResourceDefinition
|
|
182
|
-
class Table < Table
|
|
183
|
-
class Theme < Plutonium::UI::Table::Theme
|
|
184
|
-
def self.theme
|
|
185
|
-
super.merge({
|
|
186
|
-
wrapper: "overflow-x-auto shadow-md rounded-lg",
|
|
187
|
-
base: "w-full text-sm text-gray-500",
|
|
188
|
-
header: "text-xs uppercase bg-gray-100 dark:bg-gray-700",
|
|
189
|
-
header_cell: "px-6 py-3",
|
|
190
|
-
body_row: "bg-white border-b dark:bg-gray-800",
|
|
191
|
-
body_cell: "px-6 py-4",
|
|
192
|
-
})
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### Theme Keys Reference
|
|
200
|
-
|
|
201
|
-
**Form theme keys:** `base`, `fields_wrapper`, `actions_wrapper`, `wrapper`, `inner_wrapper`, `label`, `invalid_label`, `valid_label`, `neutral_label`, `input`, `invalid_input`, `valid_input`, `neutral_input`, `hint`, `error`, `button`, `checkbox`, `select`.
|
|
202
|
-
|
|
203
|
-
**Display theme keys:** `fields_wrapper`, `label`, `description`, `string`, `text`, `link`, `email`, `phone`, `markdown`, `json`.
|
|
204
|
-
|
|
205
|
-
**Table theme keys:** `wrapper`, `base`, `header`, `header_cell`, `body_row`, `body_cell`, `sort_icon`.
|
|
206
|
-
|
|
207
|
-
### Using `tokens` and `classes` helpers
|
|
208
|
-
|
|
209
|
-
```ruby
|
|
210
|
-
class MyComponent < Plutonium::UI::Component::Base
|
|
211
|
-
def initialize(active:)
|
|
212
|
-
@active = active
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def view_template
|
|
216
|
-
div(class: tokens(
|
|
217
|
-
"base-class",
|
|
218
|
-
active?: "bg-primary-500 text-white",
|
|
219
|
-
inactive?: "bg-gray-200 text-gray-700"
|
|
220
|
-
)) { "Content" }
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
private
|
|
224
|
-
|
|
225
|
-
def active? = @active
|
|
226
|
-
def inactive? = !@active
|
|
227
|
-
end
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
```ruby
|
|
231
|
-
div(**classes("p-4", "rounded", active?: "ring-2")) { }
|
|
232
|
-
# => <div class="p-4 rounded ring-2">
|
|
233
|
-
|
|
234
|
-
tokens(
|
|
235
|
-
"base",
|
|
236
|
-
condition?: { then: "if-true", else: "if-false" }
|
|
237
|
-
)
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
## Stimulus controllers
|
|
241
|
-
|
|
242
|
-
Register Plutonium's Stimulus controllers in your application:
|
|
243
|
-
|
|
244
|
-
```javascript
|
|
245
|
-
// app/javascript/controllers/index.js
|
|
246
|
-
import { application } from "./application"
|
|
247
|
-
|
|
248
|
-
import { registerControllers } from "@radioactive-labs/plutonium"
|
|
249
|
-
registerControllers(application)
|
|
250
|
-
|
|
251
|
-
// Your custom controllers...
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
### Available controllers
|
|
255
|
-
|
|
256
|
-
- `color-mode` - Dark/light mode toggle
|
|
257
|
-
- `form` - Form handling (pre-submit, etc.)
|
|
258
|
-
- `nested-resource-form-fields` - Nested form management
|
|
259
|
-
- `slim-select` - Enhanced select boxes
|
|
260
|
-
- `flatpickr` - Date/time pickers
|
|
261
|
-
- `easymde` - Markdown editor
|
|
262
|
-
- Various UI controllers
|
|
263
|
-
|
|
264
|
-
### Custom Stimulus controllers
|
|
265
|
-
|
|
266
|
-
```javascript
|
|
267
|
-
// app/javascript/controllers/custom_controller.js
|
|
268
|
-
import { Controller } from "@hotwired/stimulus"
|
|
269
|
-
|
|
270
|
-
export default class extends Controller {
|
|
271
|
-
connect() {
|
|
272
|
-
console.log("Custom controller connected")
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Register:
|
|
278
|
-
|
|
279
|
-
```javascript
|
|
280
|
-
import CustomController from "./custom_controller"
|
|
281
|
-
application.register("custom", CustomController)
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Typography
|
|
285
|
-
|
|
286
|
-
Plutonium uses Lato by default. Override:
|
|
287
|
-
|
|
288
|
-
```ruby
|
|
289
|
-
class MyLayout < Plutonium::UI::Layout::ResourceLayout
|
|
290
|
-
def render_fonts
|
|
291
|
-
link(rel: "preconnect", href: "https://fonts.googleapis.com")
|
|
292
|
-
link(href: "https://fonts.googleapis.com/css2?family=Inter&display=swap", rel: "stylesheet")
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
```javascript
|
|
298
|
-
theme: {
|
|
299
|
-
fontFamily: {
|
|
300
|
-
'body': ['Inter', 'sans-serif'],
|
|
301
|
-
'sans': ['Inter', 'sans-serif'],
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
## Design tokens and theming
|
|
307
|
-
|
|
308
|
-
Plutonium uses a comprehensive CSS design token system for consistent, themeable UI components — CSS custom properties and reusable component classes that automatically support light and dark modes. Tokens are defined in `src/css/tokens.css`.
|
|
309
|
-
|
|
310
|
-
### Surface & background colors
|
|
311
|
-
|
|
312
|
-
```css
|
|
313
|
-
/* Light */
|
|
314
|
-
--pu-body: #f8fafc;
|
|
315
|
-
--pu-surface: #ffffff;
|
|
316
|
-
--pu-surface-alt: #f1f5f9;
|
|
317
|
-
--pu-surface-raised: #ffffff;
|
|
318
|
-
--pu-surface-overlay: rgba(255, 255, 255, 0.95);
|
|
319
|
-
|
|
320
|
-
/* Dark (.dark class) */
|
|
321
|
-
--pu-body: #0f172a;
|
|
322
|
-
--pu-surface: #1e293b;
|
|
323
|
-
--pu-surface-alt: #0f172a;
|
|
324
|
-
--pu-surface-raised: #334155;
|
|
325
|
-
--pu-surface-overlay: rgba(30, 41, 59, 0.95);
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### Text colors
|
|
329
|
-
|
|
330
|
-
```css
|
|
331
|
-
/* Light */
|
|
332
|
-
--pu-text: #0f172a;
|
|
333
|
-
--pu-text-muted: #64748b;
|
|
334
|
-
--pu-text-subtle: #94a3b8;
|
|
335
|
-
|
|
336
|
-
/* Dark */
|
|
337
|
-
--pu-text: #f8fafc;
|
|
338
|
-
--pu-text-muted: #94a3b8;
|
|
339
|
-
--pu-text-subtle: #64748b;
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
### Border colors
|
|
343
|
-
|
|
344
|
-
```css
|
|
345
|
-
--pu-border: #e2e8f0;
|
|
346
|
-
--pu-border-muted: #f1f5f9;
|
|
347
|
-
--pu-border-strong: #cbd5e1;
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
### Form tokens
|
|
351
|
-
|
|
352
|
-
```css
|
|
353
|
-
--pu-input-bg: #ffffff;
|
|
354
|
-
--pu-input-border: #e2e8f0;
|
|
355
|
-
--pu-input-focus-ring: theme(colors.primary.500);
|
|
356
|
-
--pu-input-placeholder: #94a3b8;
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
### Card tokens
|
|
360
|
-
|
|
361
|
-
```css
|
|
362
|
-
--pu-card-bg: #ffffff;
|
|
363
|
-
--pu-card-border: #e2e8f0;
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
### Shadows
|
|
367
|
-
|
|
368
|
-
```css
|
|
369
|
-
--pu-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.03), 0 1px 3px 0 rgb(0 0 0 / 0.05);
|
|
370
|
-
--pu-shadow-md: 0 2px 4px -1px rgb(0 0 0 / 0.04), 0 4px 6px -1px rgb(0 0 0 / 0.06);
|
|
371
|
-
--pu-shadow-lg: 0 4px 6px -2px rgb(0 0 0 / 0.03), 0 10px 15px -3px rgb(0 0 0 / 0.08);
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
### Radius, spacing, transitions
|
|
375
|
-
|
|
376
|
-
```css
|
|
377
|
-
--pu-radius-sm: 0.375rem;
|
|
378
|
-
--pu-radius-md: 0.5rem;
|
|
379
|
-
--pu-radius-lg: 0.75rem;
|
|
380
|
-
--pu-radius-xl: 1rem;
|
|
381
|
-
--pu-radius-full: 9999px;
|
|
382
|
-
|
|
383
|
-
--pu-space-xs: 0.25rem;
|
|
384
|
-
--pu-space-sm: 0.5rem;
|
|
385
|
-
--pu-space-md: 1rem;
|
|
386
|
-
--pu-space-lg: 1.5rem;
|
|
387
|
-
--pu-space-xl: 2rem;
|
|
388
|
-
|
|
389
|
-
--pu-transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
390
|
-
--pu-transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
391
|
-
--pu-transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### Customizing tokens
|
|
395
|
-
|
|
396
|
-
```css
|
|
397
|
-
/* app/assets/stylesheets/application.tailwind.css */
|
|
398
|
-
@import "gem:plutonium/src/css/plutonium.css";
|
|
399
|
-
@import "tailwindcss";
|
|
400
|
-
|
|
401
|
-
:root {
|
|
402
|
-
--pu-surface: #fafafa;
|
|
403
|
-
--pu-border: #d1d5db;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
.dark {
|
|
407
|
-
--pu-surface: #111827;
|
|
408
|
-
--pu-border: #374151;
|
|
409
|
-
}
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
## Component classes
|
|
413
|
-
|
|
414
|
-
Component classes are defined in `src/css/components.css` for ready-to-use styled components.
|
|
415
|
-
|
|
416
|
-
### Buttons
|
|
417
|
-
|
|
418
|
-
```
|
|
419
|
-
.pu-btn /* Base */
|
|
420
|
-
.pu-btn-md / .pu-btn-sm / .pu-btn-xs
|
|
421
|
-
.pu-btn-primary / -secondary / -danger / -success / -warning / -info / -accent
|
|
422
|
-
.pu-btn-ghost / -outline
|
|
423
|
-
.pu-btn-soft-primary / -soft-danger / ...
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
```erb
|
|
427
|
-
<%= form.submit "Save", class: "pu-btn pu-btn-md pu-btn-primary" %>
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
### Inputs & labels
|
|
431
|
-
|
|
432
|
-
```
|
|
433
|
-
.pu-input / .pu-input-invalid / .pu-input-valid
|
|
434
|
-
.pu-label / .pu-label-required
|
|
435
|
-
.pu-hint / .pu-error
|
|
436
|
-
.pu-checkbox
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
### Cards, panels, tables, toolbar, empty state
|
|
440
|
-
|
|
441
|
-
```
|
|
442
|
-
.pu-card / .pu-card-body
|
|
443
|
-
.pu-panel-header / .pu-panel-title / .pu-panel-description
|
|
444
|
-
.pu-table-wrapper / .pu-table / .pu-table-header / .pu-table-header-cell /
|
|
445
|
-
.pu-table-body-row / .pu-table-body-row-selected / .pu-table-body-cell / .pu-selection-cell
|
|
446
|
-
.pu-toolbar / .pu-toolbar-text / .pu-toolbar-actions
|
|
447
|
-
.pu-empty-state / .pu-empty-state-icon / .pu-empty-state-title / .pu-empty-state-description
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### Ruby component class constants
|
|
451
|
-
|
|
452
|
-
The `Plutonium::UI::ComponentClasses` module (in `lib/plutonium/ui/component_classes.rb`) provides Ruby constants for consistent class usage:
|
|
453
|
-
|
|
454
|
-
```ruby
|
|
455
|
-
ComponentClasses::Button.classes(variant: :primary, size: :default, soft: false)
|
|
456
|
-
# => "pu-btn pu-btn-md pu-btn-primary"
|
|
457
|
-
|
|
458
|
-
ComponentClasses::Form::INPUT # "pu-input"
|
|
459
|
-
ComponentClasses::Form::LABEL # "pu-label"
|
|
460
|
-
ComponentClasses::Table::WRAPPER # "pu-table-wrapper"
|
|
461
|
-
ComponentClasses::Card::BASE # "pu-card"
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
### Using tokens in templates
|
|
465
|
-
|
|
466
|
-
```erb
|
|
467
|
-
<h1 class="text-[var(--pu-text)]">Title</h1>
|
|
468
|
-
<p class="text-[var(--pu-text-muted)]">Description</p>
|
|
469
|
-
|
|
470
|
-
<div class="bg-[var(--pu-surface)] border border-[var(--pu-border)] rounded-[var(--pu-radius-lg)]">
|
|
471
|
-
Content
|
|
472
|
-
</div>
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
```ruby
|
|
476
|
-
class MyComponent < Plutonium::UI::Component::Base
|
|
477
|
-
def view_template
|
|
478
|
-
div(class: "bg-[var(--pu-surface)] border border-[var(--pu-border)] rounded-[var(--pu-radius-lg)]",
|
|
479
|
-
style: "box-shadow: var(--pu-shadow-md)") {
|
|
480
|
-
h2(class: "text-lg font-semibold text-[var(--pu-text)]") { "Title" }
|
|
481
|
-
p(class: "text-[var(--pu-text-muted)]") { "Description" }
|
|
482
|
-
}
|
|
483
|
-
end
|
|
484
|
-
end
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
### Migration from hardcoded classes
|
|
488
|
-
|
|
489
|
-
| Old | New |
|
|
490
|
-
|-----|-----|
|
|
491
|
-
| `text-gray-900 dark:text-white` | `text-[var(--pu-text)]` |
|
|
492
|
-
| `text-gray-500 dark:text-gray-400` | `text-[var(--pu-text-muted)]` |
|
|
493
|
-
| `bg-gray-50 dark:bg-gray-700` | `bg-[var(--pu-surface)]` |
|
|
494
|
-
| `border-gray-300 dark:border-gray-600` | `border-[var(--pu-border)]` |
|
|
495
|
-
| long input class | `pu-input` |
|
|
496
|
-
| `block mb-2 text-sm font-semibold ...` | `pu-label` |
|
|
497
|
-
| `text-red-600 dark:text-red-400` | `pu-error` |
|
|
498
|
-
| long button class | `pu-btn pu-btn-md pu-btn-primary` |
|
|
499
|
-
|
|
500
|
-
## Gotchas
|
|
501
|
-
|
|
502
|
-
- **Always register Stimulus controllers** — Plutonium controllers won't work without `registerControllers(application)`. Custom controllers must also be registered.
|
|
503
|
-
- **Use `plutoniumTailwindConfig.merge`** when overriding theme — plain object merge drops Plutonium's defaults.
|
|
504
|
-
- **Dark mode uses `selector`**, not `class`. Toggle via `document.documentElement.classList.toggle('dark')`.
|
|
505
|
-
- **Tokens are CSS variables**, not Tailwind keys — use `bg-[var(--pu-surface)]`, not `bg-pu-surface`.
|
|
506
|
-
- **Prefer `.pu-*` component classes and tokens** over hardcoded `gray-*/dark:gray-*` pairs — they switch automatically with dark mode.
|
|
507
|
-
|
|
508
|
-
## Related skills
|
|
509
|
-
|
|
510
|
-
- `plutonium-views` - Layout customization
|
|
511
|
-
- `plutonium-forms` - Form theming and custom inputs
|
|
512
|
-
- `plutonium-installation` - Initial setup
|