plutonium 0.50.0 → 0.52.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 +574 -0
- data/.claude/skills/plutonium-auth/SKILL.md +167 -302
- 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 +674 -0
- data/.claude/skills/plutonium-testing/SKILL.md +9 -6
- data/.claude/skills/plutonium-ui/SKILL.md +900 -0
- data/CHANGELOG.md +44 -2
- data/Rakefile +2 -1
- data/app/assets/plutonium.css +1 -11
- data/app/assets/plutonium.js +1010 -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 +38 -29
- data/docs/.vitepress/theme/components/HomeAudienceSplit.vue +53 -0
- data/docs/.vitepress/theme/components/HomeCta.vue +108 -0
- data/docs/.vitepress/theme/components/HomeHero.vue +70 -0
- data/docs/.vitepress/theme/components/HomeInTheBox.vue +74 -0
- data/docs/.vitepress/theme/components/HomePillars.vue +42 -0
- data/docs/.vitepress/theme/components/HomeStopWriting.vue +49 -0
- data/docs/.vitepress/theme/components/HomeWalkthrough.vue +111 -0
- data/docs/.vitepress/theme/components/SectionLanding.vue +115 -0
- data/docs/.vitepress/theme/custom.css +144 -0
- data/docs/.vitepress/theme/index.ts +58 -1
- data/docs/getting-started/index.md +33 -57
- data/docs/getting-started/installation.md +37 -80
- data/docs/getting-started/tutorial/02-first-resource.md +17 -8
- data/docs/getting-started/tutorial/03-authentication.md +31 -23
- data/docs/getting-started/tutorial/05-custom-actions.md +9 -4
- data/docs/getting-started/tutorial/06-nested-resources.md +7 -1
- data/docs/getting-started/tutorial/07-author-portal.md +8 -0
- data/docs/getting-started/tutorial/08-customizing-ui.md +4 -0
- data/docs/getting-started/tutorial/index.md +4 -5
- data/docs/guides/adding-resources.md +66 -377
- data/docs/guides/authentication.md +98 -462
- data/docs/guides/authorization.md +124 -370
- data/docs/guides/creating-packages.md +93 -298
- data/docs/guides/custom-actions.md +126 -441
- data/docs/guides/customizing-ui.md +258 -0
- data/docs/guides/index.md +49 -52
- data/docs/guides/multi-tenancy.md +123 -186
- data/docs/guides/nested-resources.md +137 -396
- data/docs/guides/search-filtering.md +127 -238
- data/docs/guides/testing.md +10 -5
- data/docs/guides/theming.md +168 -405
- data/docs/guides/troubleshooting.md +5 -3
- data/docs/guides/user-invites.md +112 -425
- data/docs/guides/user-profile.md +82 -241
- data/docs/index.md +10 -219
- data/docs/public/asciinema/home-scaffold.cast +305 -0
- data/docs/public/images/guides/custom-actions-bulk.png +0 -0
- data/docs/public/images/guides/multi-tenancy-dashboard.png +0 -0
- data/docs/public/images/guides/multi-tenancy-welcome.png +0 -0
- data/docs/public/images/guides/nested-inputs.png +0 -0
- data/docs/public/images/guides/nested-resources-tab.png +0 -0
- data/docs/public/images/guides/search-filtering-index.png +0 -0
- data/docs/public/images/guides/search-filtering-panel.png +0 -0
- data/docs/public/images/guides/theming-after.png +0 -0
- data/docs/public/images/guides/theming-before.png +0 -0
- data/docs/public/images/guides/user-invites-landing.png +0 -0
- data/docs/public/images/guides/user-profile-edit.png +0 -0
- data/docs/public/images/guides/user-profile-show.png +0 -0
- data/docs/public/images/home-index.png +0 -0
- data/docs/public/images/home-new.png +0 -0
- data/docs/public/images/home-show.png +0 -0
- data/docs/public/images/tutorial/02-empty-index.png +0 -0
- data/docs/public/images/tutorial/02-index-with-posts.png +0 -0
- data/docs/public/images/tutorial/02-new-form-modal.png +0 -0
- data/docs/public/images/tutorial/02-new-form.png +0 -0
- data/docs/public/images/tutorial/03-create-account.png +0 -0
- data/docs/public/images/tutorial/03-login.png +0 -0
- data/docs/public/images/tutorial/04-admin-index.png +0 -0
- data/docs/public/images/tutorial/05-actions-menu.png +0 -0
- data/docs/public/images/tutorial/05-row-actions.png +0 -0
- data/docs/public/images/tutorial/06-comments-tab.png +0 -0
- data/docs/public/images/tutorial/06-post-with-comments.png +0 -0
- data/docs/public/images/tutorial/07-author-dashboard.png +0 -0
- data/docs/public/images/tutorial/07-author-portal.png +0 -0
- data/docs/public/images/tutorial/08-customized-index.png +0 -0
- 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 +229 -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 +67 -48
- 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 +368 -0
- data/docs/reference/tenancy/index.md +36 -0
- data/docs/reference/tenancy/invites.md +400 -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 +121 -0
- data/docs/superpowers/plans/2026-05-15-public-pages-overhaul.md +1648 -0
- data/docs/superpowers/plans/2026-05-15-public-pages-overhaul.md.tasks.json +109 -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/docs/superpowers/specs/2026-05-15-public-pages-overhaul-design.md +263 -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/assets/assets_generator.rb +10 -0
- data/lib/generators/pu/core/update/update_generator.rb +0 -20
- data/lib/generators/pu/invites/install_generator.rb +45 -0
- data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/user_invitations_controller.rb.tt +1 -0
- data/lib/generators/pu/profile/conn_generator.rb +2 -2
- data/lib/generators/pu/res/conn/conn_generator.rb +33 -6
- data/lib/generators/pu/res/model/templates/model.rb.tt +4 -0
- data/lib/generators/pu/rodauth/account_generator.rb +2 -1
- data/lib/generators/pu/rodauth/admin_generator.rb +0 -2
- data/lib/generators/pu/rodauth/migration_generator.rb +0 -2
- data/lib/generators/pu/rodauth/views_generator.rb +0 -2
- data/lib/generators/pu/saas/membership/USAGE +4 -1
- data/lib/generators/pu/saas/setup_generator.rb +16 -4
- data/lib/generators/pu/saas/welcome/templates/app/controllers/welcome_controller.rb.tt +1 -1
- 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 +30 -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 +23 -5
- data/lib/plutonium/resource/controllers/interactive_actions.rb +3 -3
- 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 +5 -0
- data/lib/plutonium/ui/form/base.rb +23 -3
- 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 +103 -22
- data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
- data/lib/plutonium/ui/form/interaction.rb +1 -1
- data/lib/plutonium/ui/form/resource.rb +0 -4
- data/lib/plutonium/ui/form/theme.rb +1 -1
- 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/edit.rb +1 -1
- data/lib/plutonium/ui/page/index.rb +4 -4
- data/lib/plutonium/ui/page/new.rb +1 -1
- data/lib/plutonium/ui/table/components/filter_form.rb +12 -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 +13 -10
- data/src/css/slim_select.css +4 -0
- data/src/js/controllers/form_controller.js +5 -4
- data/src/js/controllers/slim_select_controller.js +61 -0
- data/src/js/turbo/turbo_actions.js +33 -0
- data/yarn.lock +661 -544
- metadata +86 -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
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Customizing the UI
|
|
2
|
+
|
|
3
|
+
Plutonium's UI is built on Phlex, Tailwind 4, and Stimulus. Almost everything you see — pages, forms, displays, tables, components, layouts, even the design tokens — is open for override. This guide is the map. Each section shows the smallest useful example for one kind of customization, then points to the reference for the full surface.
|
|
4
|
+
|
|
5
|
+
When you're not sure where to start, read this top to bottom. When you know what you need, jump to the right section and follow the link to reference.
|
|
6
|
+
|
|
7
|
+
## The override pattern
|
|
8
|
+
|
|
9
|
+
Customization in Plutonium is overrides via **nested classes inside the definition**, never replacement of the root class. The pattern looks the same everywhere:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
class PostDefinition < ResourceDefinition
|
|
13
|
+
class ShowPage < ShowPage; end # override show page
|
|
14
|
+
class Form < Form; end # override form
|
|
15
|
+
class Table < Table; end # override index table
|
|
16
|
+
class Display < Display; end # override show display
|
|
17
|
+
end
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Each nested class inherits from Plutonium's defaults and lets you override only the methods you care about. Don't reimplement the whole layer — use the render hooks below.
|
|
21
|
+
|
|
22
|
+
→ See [Reference › UI › Pages](/reference/ui/pages) for the full hook list.
|
|
23
|
+
|
|
24
|
+
## Adding chrome to a page
|
|
25
|
+
|
|
26
|
+
Most page customization is "I want to add something before/after this section." Use the render hooks; don't override `view_template`.
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
class PostDefinition < ResourceDefinition
|
|
30
|
+
class ShowPage < ShowPage
|
|
31
|
+
def render_before_content
|
|
32
|
+
div(class: "pu-card pu-card-body") do
|
|
33
|
+
plain "This post has #{object.comments.count} comments"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Hooks exist around the header, breadcrumbs, page header, toolbar, content, and footer — pick the one closest to where you want the thing to appear.
|
|
41
|
+
|
|
42
|
+
→ See [Reference › UI › Pages](/reference/ui/pages) › Page hooks.
|
|
43
|
+
|
|
44
|
+
## Customizing a form layout
|
|
45
|
+
|
|
46
|
+
The default form renders every permitted field in a single grid. To group fields into sections or columns, override `form_template`:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
class Form < Form
|
|
50
|
+
def form_template
|
|
51
|
+
section("Basic") do
|
|
52
|
+
render_resource_field :title
|
|
53
|
+
render_resource_field :slug
|
|
54
|
+
end
|
|
55
|
+
section("Publishing") do
|
|
56
|
+
render_resource_field :published_at
|
|
57
|
+
render_resource_field :category
|
|
58
|
+
end
|
|
59
|
+
render_actions # REQUIRED — without this, no submit button
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def section(title, &)
|
|
65
|
+
div(class: "mb-8") do
|
|
66
|
+
h3(class: "text-lg font-semibold mb-4 text-[var(--pu-text)]") { title }
|
|
67
|
+
fields_wrapper(&)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
→ See [Reference › UI › Forms](/reference/ui/forms) for `render_resource_field`, field tags (`flatpickr_tag`, `easymde_tag`, `uppy_tag`, etc.), and Phlexi themes.
|
|
74
|
+
|
|
75
|
+
## Customizing a display
|
|
76
|
+
|
|
77
|
+
The show page renders a `Display` for the record. Override `display_template` to add hero blocks, group fields, or interleave custom panels:
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
class Display < Display
|
|
81
|
+
def display_template
|
|
82
|
+
div(class: "pu-card pu-card-body mb-4") do
|
|
83
|
+
h1 { object.title }
|
|
84
|
+
p(class: "text-[var(--pu-text-muted)]") { object.excerpt }
|
|
85
|
+
end
|
|
86
|
+
Block { fields_wrapper { render_fields } }
|
|
87
|
+
render_associations if present_associations?
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
→ See [Reference › UI › Displays](/reference/ui/displays).
|
|
93
|
+
|
|
94
|
+
## Replacing a table with a grid
|
|
95
|
+
|
|
96
|
+
By default the index page renders a `Table`. To use cards instead, override `view_template` on the nested `Table`:
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
class Table < Table
|
|
100
|
+
def view_template
|
|
101
|
+
render_toolbar
|
|
102
|
+
render_scopes_pills
|
|
103
|
+
if collection.empty?
|
|
104
|
+
render_empty_card
|
|
105
|
+
else
|
|
106
|
+
div(class: "grid grid-cols-3 gap-4") do
|
|
107
|
+
collection.each { |post| render PostCardComponent.new(post:) }
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
render_footer
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
→ See [Reference › UI › Tables](/reference/ui/tables).
|
|
116
|
+
|
|
117
|
+
## Writing a custom Phlex component
|
|
118
|
+
|
|
119
|
+
When you need a piece of UI that's reused across pages, write a Phlex component. Inherit from `Plutonium::UI::Component::Base` and you get the component kit (`PageHeader`, `Panel`, `Block`), resource URL helpers, and a `helpers` proxy for Rails helpers.
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
class PostCardComponent < Plutonium::UI::Component::Base
|
|
123
|
+
def initialize(post:) = @post = post
|
|
124
|
+
|
|
125
|
+
def view_template
|
|
126
|
+
div(class: "pu-card pu-card-body") do
|
|
127
|
+
h3(class: "font-bold text-[var(--pu-text)]") { @post.title }
|
|
128
|
+
p(class: "text-[var(--pu-text-muted)] mt-2") { @post.excerpt }
|
|
129
|
+
a(href: resource_url_for(@post), class: "pu-btn pu-btn-sm pu-btn-ghost") { "Read more" }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use it directly in a page, or wire it as a field in the definition:
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
display :card, as: PostCardComponent
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
→ See [Reference › UI › Components](/reference/ui/components).
|
|
142
|
+
|
|
143
|
+
## Phlexi themes (recolor without rewriting)
|
|
144
|
+
|
|
145
|
+
If all you want is to recolor or restyle the form/display/table, write a `Theme` class instead of overriding the template. Always `super.merge(...)` — never replace wholesale:
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
class Form < Form
|
|
149
|
+
class Theme < Plutonium::UI::Form::Theme
|
|
150
|
+
def self.theme
|
|
151
|
+
super.merge(
|
|
152
|
+
base: "bg-[var(--pu-card-bg)] shadow-md rounded-lg p-6",
|
|
153
|
+
fields_wrapper: "grid grid-cols-2 gap-6",
|
|
154
|
+
label: "block mb-2 text-base font-bold",
|
|
155
|
+
)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
→ See [Reference › UI › Forms](/reference/ui/forms) › Theme keys, [Reference › UI › Displays](/reference/ui/displays) › Theme, [Reference › UI › Tables](/reference/ui/tables) › Theme.
|
|
162
|
+
|
|
163
|
+
## Modals and slideovers
|
|
164
|
+
|
|
165
|
+
By default `:new` and `:edit` render in a slideover panel. Switch to a centered modal or a full standalone page from the definition:
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
class PostDefinition < ResourceDefinition
|
|
169
|
+
modal :slideover # default — slide-in from the right
|
|
170
|
+
# modal :centered # centered dialog
|
|
171
|
+
# modal false # full standalone page
|
|
172
|
+
end
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
→ See [Reference › Resource › Actions](/reference/resource/actions) for per-action `modal:` options on interactive actions.
|
|
176
|
+
|
|
177
|
+
## Layouts and the shell
|
|
178
|
+
|
|
179
|
+
The layout is the chrome around every resource page — topbar, sidebar, flash region, scripts. Two ways to customize it:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Per-portal: eject the shell partials and edit them directly
|
|
183
|
+
rails generate pu:eject:shell --dest=admin_portal
|
|
184
|
+
# Or eject the whole layout
|
|
185
|
+
rails generate pu:eject:layout
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
For programmatic overrides, subclass `Plutonium::UI::Layout::ResourceLayout` and use its render hooks (`render_before_main`, `render_body_scripts`, etc.).
|
|
189
|
+
|
|
190
|
+
→ See [Reference › UI › Layouts](/reference/ui/layouts) and [Theming](/guides/theming) for design tokens.
|
|
191
|
+
|
|
192
|
+
## Tailwind, Stimulus, and assets
|
|
193
|
+
|
|
194
|
+
Plutonium ships with a Tailwind config, design tokens, and a set of Stimulus controllers. To plug into them in your app:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
rails generate pu:core:assets
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
This installs the npm packages, creates a `tailwind.config.js` that extends Plutonium's defaults via `plutoniumTailwindConfig.merge`, imports Plutonium's CSS, and registers its Stimulus controllers. After that, you can:
|
|
201
|
+
|
|
202
|
+
- Extend the palette under `theme.extend.colors` (always inside `plutoniumTailwindConfig.merge` — a plain spread drops Plutonium's defaults).
|
|
203
|
+
- Use `.pu-btn`, `.pu-card`, `.pu-input`, `.pu-table`, etc. instead of hand-rolling Tailwind chains.
|
|
204
|
+
- Reference design tokens directly: `bg-[var(--pu-surface)]`, `text-[var(--pu-text-muted)]`, `border-[var(--pu-border)]`. These auto-switch with dark mode.
|
|
205
|
+
- Register your own Stimulus controllers alongside Plutonium's — `registerControllers(application)` is mandatory or the entire interactive layer is dead.
|
|
206
|
+
|
|
207
|
+
→ See [Reference › UI › Assets](/reference/ui/assets) for the full toolchain, the `.pu-*` class catalog, and design-token reference.
|
|
208
|
+
|
|
209
|
+
## ERB views (escape hatch)
|
|
210
|
+
|
|
211
|
+
When the Phlex page class is the wrong tool — you want to keep an existing ERB layout, you're integrating with a designer's HTML, or you just want to surround the generated page with custom markup — drop an ERB view at the controller path:
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
app/views/posts/show.html.erb
|
|
215
|
+
packages/admin_portal/app/views/admin_portal/posts/show.html.erb
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The default page renders the Phlex page class in one line:
|
|
219
|
+
|
|
220
|
+
```erb
|
|
221
|
+
<%= render current_definition.show_page_class.new %>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Keep that line and wrap it to add chrome without giving up the generated page:
|
|
225
|
+
|
|
226
|
+
```erb
|
|
227
|
+
<div class="announcement-banner">Special announcement</div>
|
|
228
|
+
<%= render current_definition.show_page_class.new %>
|
|
229
|
+
<%= render partial: "related" %>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Or replace the line entirely for full control. ERB views always win over the Phlex page class when both exist for the same action — reach for this only when Phlex hooks + overrides genuinely can't do the job.
|
|
233
|
+
|
|
234
|
+
## When to reach for what
|
|
235
|
+
|
|
236
|
+
| You want to… | Use |
|
|
237
|
+
|---|---|
|
|
238
|
+
| Add a banner above the show page | Page hook (`render_before_content`) |
|
|
239
|
+
| Group form fields into sections | Custom `form_template` |
|
|
240
|
+
| Render the index as cards | Custom `Table#view_template` |
|
|
241
|
+
| Reuse a UI block across pages | Custom Phlex component |
|
|
242
|
+
| Recolor without changing structure | Phlexi `Theme` class |
|
|
243
|
+
| Swap the topbar or sidebar | `pu:eject:shell` or custom layout class |
|
|
244
|
+
| Change brand color or radius | Design tokens — see [Theming](/guides/theming) |
|
|
245
|
+
| Add a custom JS interaction | Stimulus controller registered alongside Plutonium's |
|
|
246
|
+
|
|
247
|
+
## Gotchas
|
|
248
|
+
|
|
249
|
+
- **Don't override `view_template` in pages** when a render hook fits — you lose breadcrumbs, header, and DynaFrame (turbo-frame) behavior.
|
|
250
|
+
- **`render_actions` is mandatory** when you write a custom `form_template` — otherwise the form has no submit button.
|
|
251
|
+
- **Always `registerControllers(application)`** in `app/javascript/controllers/index.js`. Without it, every Plutonium-shipped Stimulus controller is dead (color mode, slim-select, flatpickr, easymde, form pre-submit).
|
|
252
|
+
- **Use `plutoniumTailwindConfig.merge`** when extending the Tailwind theme. A plain object spread drops Plutonium's defaults.
|
|
253
|
+
- **Prefer `.pu-*` classes and `var(--pu-*)` tokens** over hardcoded `gray-X/dark:gray-Y` pairs — they switch with dark mode automatically.
|
|
254
|
+
|
|
255
|
+
## Related
|
|
256
|
+
|
|
257
|
+
- [Theming](/guides/theming) — design tokens, brand colors.
|
|
258
|
+
- [Reference › UI](/reference/ui/) — the full surface area for every override above.
|
data/docs/guides/index.md
CHANGED
|
@@ -1,52 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
## Looking for Reference Docs?
|
|
51
|
-
|
|
52
|
-
For complete API documentation, see the [Reference](/reference/) section.
|
|
1
|
+
---
|
|
2
|
+
layout: page
|
|
3
|
+
sidebar: false
|
|
4
|
+
aside: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<SectionLanding
|
|
8
|
+
eyebrow="Guides"
|
|
9
|
+
title="How to do the things Plutonium apps do."
|
|
10
|
+
lede="Task-oriented walkthroughs for the parts of the framework you reach for most."
|
|
11
|
+
mode="categorized"
|
|
12
|
+
:rail="[
|
|
13
|
+
{ group: 'Setup & Resources', items: [
|
|
14
|
+
{ name: 'Adding resources', link: '/plutonium-core/guides/adding-resources' },
|
|
15
|
+
{ name: 'Creating packages', link: '/plutonium-core/guides/creating-packages' },
|
|
16
|
+
]},
|
|
17
|
+
{ group: 'Auth', items: [
|
|
18
|
+
{ name: 'Authentication', link: '/plutonium-core/guides/authentication' },
|
|
19
|
+
{ name: 'Authorization', link: '/plutonium-core/guides/authorization' },
|
|
20
|
+
{ name: 'User profile', link: '/plutonium-core/guides/user-profile' },
|
|
21
|
+
{ name: 'User invites', link: '/plutonium-core/guides/user-invites' },
|
|
22
|
+
]},
|
|
23
|
+
{ group: 'Features', items: [
|
|
24
|
+
{ name: 'Custom actions', link: '/plutonium-core/guides/custom-actions' },
|
|
25
|
+
{ name: 'Nested resources', link: '/plutonium-core/guides/nested-resources' },
|
|
26
|
+
{ name: 'Multi-tenancy', link: '/plutonium-core/guides/multi-tenancy' },
|
|
27
|
+
{ name: 'Search & filtering', link: '/plutonium-core/guides/search-filtering' },
|
|
28
|
+
]},
|
|
29
|
+
{ group: 'Customization', items: [
|
|
30
|
+
{ name: 'Customizing the UI', desc: 'A map of the override surface — pages, forms, displays, tables, components, layouts.', link: '/plutonium-core/guides/customizing-ui' },
|
|
31
|
+
{ name: 'Theming', desc: 'Design tokens and brand colors.', link: '/plutonium-core/guides/theming' },
|
|
32
|
+
]},
|
|
33
|
+
{ group: 'Quality', items: [
|
|
34
|
+
{ name: 'Testing', link: '/plutonium-core/guides/testing' },
|
|
35
|
+
{ name: 'Troubleshooting', link: '/plutonium-core/guides/troubleshooting' },
|
|
36
|
+
]},
|
|
37
|
+
]"
|
|
38
|
+
:sidebar="[
|
|
39
|
+
{ heading: 'New to Plutonium?', items: [
|
|
40
|
+
{ label: 'Start with the tutorial', href: '/plutonium-core/getting-started/tutorial/' },
|
|
41
|
+
]},
|
|
42
|
+
{ heading: 'Looking for APIs?', items: [
|
|
43
|
+
{ label: 'Browse the reference', href: '/plutonium-core/reference/' },
|
|
44
|
+
]},
|
|
45
|
+
{ heading: 'Need help?', items: [
|
|
46
|
+
{ label: 'GitHub Discussions', href: 'https://github.com/radioactive-labs/plutonium-core/discussions' },
|
|
47
|
+
]},
|
|
48
|
+
]"
|
|
49
|
+
/>
|