plutonium 0.49.1 → 0.50.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-definition/SKILL.md +87 -2
- data/.claude/skills/plutonium-installation/SKILL.md +6 -0
- data/.claude/skills/plutonium-views/SKILL.md +59 -0
- data/CHANGELOG.md +12 -0
- data/app/assets/plutonium.css +2 -2
- data/app/assets/plutonium.js +369 -25
- data/app/assets/plutonium.js.map +4 -4
- data/app/assets/plutonium.min.js +45 -45
- data/app/assets/plutonium.min.js.map +4 -4
- data/app/views/plutonium/_resource_header.html.erb +4 -4
- data/app/views/plutonium/_resource_sidebar.html.erb +9 -9
- data/app/views/resource/_resource_grid.html.erb +1 -0
- data/config/brakeman.ignore +25 -2
- data/docs/reference/definition/actions.md +14 -1
- data/docs/reference/definition/index.md +58 -0
- data/docs/reference/views/index.md +43 -0
- data/docs/superpowers/plans/2026-05-07-ui-layout-overhaul.md +841 -0
- data/docs/superpowers/plans/2026-05-07-ui-layout-overhaul.md.tasks.json +103 -0
- data/docs/superpowers/specs/2026-05-07-ui-layout-overhaul-design.md +270 -0
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +1 -0
- data/lib/generators/pu/core/update/update_generator.rb +20 -0
- data/lib/generators/pu/lite/rails_pulse/rails_pulse_generator.rb +54 -5
- data/lib/plutonium/action/base.rb +44 -1
- data/lib/plutonium/action/interactive.rb +1 -1
- data/lib/plutonium/configuration.rb +4 -0
- data/lib/plutonium/definition/actions.rb +3 -0
- data/lib/plutonium/definition/base.rb +8 -0
- data/lib/plutonium/definition/metadata.rb +40 -0
- data/lib/plutonium/definition/views.rb +94 -0
- data/lib/plutonium/helpers/turbo_helper.rb +1 -1
- data/lib/plutonium/interaction/response/redirect.rb +1 -1
- data/lib/plutonium/query/base.rb +8 -0
- data/lib/plutonium/query/filters/association.rb +30 -8
- data/lib/plutonium/query/filters/boolean.rb +5 -0
- data/lib/plutonium/resource/controllers/presentable.rb +11 -2
- data/lib/plutonium/resource/definition.rb +42 -0
- data/lib/plutonium/resource/query_object.rb +64 -6
- data/lib/plutonium/testing/resource_definition.rb +2 -2
- data/lib/plutonium/ui/action_button.rb +4 -2
- data/lib/plutonium/ui/component/kit.rb +12 -0
- data/lib/plutonium/ui/display/base.rb +3 -1
- data/lib/plutonium/ui/display/resource.rb +109 -25
- data/lib/plutonium/ui/display/theme.rb +2 -1
- data/lib/plutonium/ui/dyna_frame/content.rb +8 -14
- data/lib/plutonium/ui/empty_card.rb +1 -1
- data/lib/plutonium/ui/form/base.rb +29 -1
- data/lib/plutonium/ui/form/components/hidden_wrapper.rb +25 -0
- data/lib/plutonium/ui/form/components/resource_select.rb +79 -1
- data/lib/plutonium/ui/form/components/secure_association.rb +7 -2
- data/lib/plutonium/ui/form/components/sticky_footer.rb +17 -0
- data/lib/plutonium/ui/form/resource.rb +48 -9
- data/lib/plutonium/ui/form/theme.rb +1 -1
- data/lib/plutonium/ui/frame_navigator_panel.rb +7 -4
- data/lib/plutonium/ui/grid/card.rb +235 -0
- data/lib/plutonium/ui/grid/resource.rb +149 -0
- data/lib/plutonium/ui/layout/base.rb +37 -1
- data/lib/plutonium/ui/layout/header.rb +1 -2
- data/lib/plutonium/ui/layout/icon_rail.rb +212 -0
- data/lib/plutonium/ui/layout/resource_layout.rb +10 -3
- data/lib/plutonium/ui/layout/sidebar.rb +12 -24
- data/lib/plutonium/ui/layout/topbar.rb +100 -0
- data/lib/plutonium/ui/modal/base.rb +109 -0
- data/lib/plutonium/ui/modal/centered.rb +21 -0
- data/lib/plutonium/ui/modal/slideover.rb +26 -0
- data/lib/plutonium/ui/page/base.rb +25 -6
- data/lib/plutonium/ui/page/edit.rb +13 -1
- data/lib/plutonium/ui/page/index.rb +40 -1
- data/lib/plutonium/ui/page/interactive_action.rb +8 -39
- data/lib/plutonium/ui/page/new.rb +13 -1
- data/lib/plutonium/ui/page/show.rb +8 -1
- data/lib/plutonium/ui/page_header.rb +8 -13
- data/lib/plutonium/ui/panel.rb +10 -19
- data/lib/plutonium/ui/sidebar_menu.rb +2 -25
- data/lib/plutonium/ui/tab_list.rb +29 -7
- data/lib/plutonium/ui/table/base.rb +106 -0
- data/lib/plutonium/ui/table/components/bulk_actions_toolbar.rb +12 -4
- data/lib/plutonium/ui/table/components/filter_form.rb +171 -0
- data/lib/plutonium/ui/table/components/filter_pills.rb +89 -0
- data/lib/plutonium/ui/table/components/row_actions_dropdown.rb +13 -12
- data/lib/plutonium/ui/table/components/scopes_pills.rb +67 -0
- data/lib/plutonium/ui/table/components/selection_column.rb +2 -11
- data/lib/plutonium/ui/table/components/toolbar.rb +104 -0
- data/lib/plutonium/ui/table/components/view_switcher.rb +81 -0
- data/lib/plutonium/ui/table/resource.rb +158 -89
- data/lib/plutonium/ui/table/theme.rb +14 -5
- data/lib/plutonium/version.rb +1 -1
- data/lib/plutonium.rb +6 -0
- data/package.json +1 -1
- data/src/css/components.css +304 -131
- data/src/css/tokens.css +101 -85
- data/src/js/controllers/autosubmit_controller.js +24 -0
- data/src/js/controllers/bulk_actions_controller.js +15 -16
- data/src/js/controllers/capture_url_controller.js +14 -0
- data/src/js/controllers/filter_panel_controller.js +77 -19
- data/src/js/controllers/frame_navigator_controller.js +34 -6
- data/src/js/controllers/icon_rail_controller.js +22 -0
- data/src/js/controllers/icon_rail_flyout_controller.js +128 -0
- data/src/js/controllers/register_controllers.js +16 -0
- data/src/js/controllers/resource_tab_list_controller.js +56 -3
- data/src/js/controllers/row_click_controller.js +21 -0
- data/src/js/controllers/table_column_menu_controller.js +43 -0
- data/src/js/controllers/table_header_controller.js +16 -0
- data/src/js/controllers/view_switcher_controller.js +29 -0
- metadata +31 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f93a96f45defbcd651a0c13ce62ca190dfb8fb83b7d0bca50d450f28c8ee6c0
|
|
4
|
+
data.tar.gz: ac996ab0486ae36f7cfda6f6a25d625c71560f4841e828c443f1cd906cd1af2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8f06360e34c7b43c797877a2555bbae11222f870e2bf82e4ec0a1ce8c0a4baf0a078cff1b65baf6159f8095345068cd1216fdcdf4d152354d46069a4d0480ad6
|
|
7
|
+
data.tar.gz: 663af09cc688359ef9fb41c3b4a76aa3061c9dc68b701586f03e6b09bce7b2d853b0afed60202d3b5ffa497e7b6c413b7e3c86207ac6bed9e26e1c4969400e76
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plutonium-definition
|
|
3
|
-
description: Use BEFORE editing a resource definition — adding fields, inputs, displays, columns, search, filters, scopes, custom actions, or bulk actions.
|
|
3
|
+
description: Use BEFORE editing a resource definition — adding fields, inputs, displays, columns, metadata, index views (table/grid), search, filters, scopes, custom actions, modal/slideover behavior, or bulk actions.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Plutonium Resource Definitions
|
|
@@ -582,9 +582,19 @@ class PostDefinition < ResourceDefinition
|
|
|
582
582
|
# true = always show
|
|
583
583
|
# false = always hide
|
|
584
584
|
submit_and_continue false
|
|
585
|
+
|
|
586
|
+
# How `:new` / `:edit` render. Default is :slideover.
|
|
587
|
+
# :slideover — slide-in panel from the right (default)
|
|
588
|
+
# :centered — centered dialog
|
|
589
|
+
# false — full standalone pages (no modal)
|
|
590
|
+
modal :centered
|
|
585
591
|
end
|
|
586
592
|
```
|
|
587
593
|
|
|
594
|
+
The `modal` setting only affects the framework-provided `:new` / `:edit`
|
|
595
|
+
actions. Custom actions render in their own dialog, controlled by the
|
|
596
|
+
per-action `modal:` option (`:centered` default, or `:slideover`).
|
|
597
|
+
|
|
588
598
|
## Page Customization
|
|
589
599
|
|
|
590
600
|
```ruby
|
|
@@ -617,6 +627,74 @@ class PostDefinition < ResourceDefinition
|
|
|
617
627
|
end
|
|
618
628
|
```
|
|
619
629
|
|
|
630
|
+
## Metadata Panel (Show Page)
|
|
631
|
+
|
|
632
|
+
The `metadata` DSL declares a list of fields rendered in the show page's
|
|
633
|
+
right-side aside as label/value rows. The main details card and the
|
|
634
|
+
metadata aside share the same field-rendering machinery, so labels and
|
|
635
|
+
formatting come from your existing `field` / `display` declarations.
|
|
636
|
+
|
|
637
|
+
```ruby
|
|
638
|
+
class PostDefinition < ResourceDefinition
|
|
639
|
+
metadata :author, :state, :created_at, :updated_at
|
|
640
|
+
end
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Behavior:
|
|
644
|
+
|
|
645
|
+
- **Opt-in.** No `metadata` call → the show page renders full-width with
|
|
646
|
+
no aside.
|
|
647
|
+
- **Policy-aware.** Metadata fields are intersected with the policy's
|
|
648
|
+
permitted attributes. Fields the user can't see disappear from the
|
|
649
|
+
panel; the panel auto-hides when nothing is permitted.
|
|
650
|
+
- **Deduplicated.** Fields listed in `metadata` are removed from the main
|
|
651
|
+
details card so the same value never appears twice.
|
|
652
|
+
- **Responsive.** Side-by-side at `lg+`, stacked single-column below.
|
|
653
|
+
|
|
654
|
+
Use it for chrome that's not the focus of the record — timestamps,
|
|
655
|
+
ownership, system flags — keeping the main card focused on the record's
|
|
656
|
+
substance.
|
|
657
|
+
|
|
658
|
+
## Index Views (Table & Grid)
|
|
659
|
+
|
|
660
|
+
Resources can opt into a card-based **Grid** view alongside the default
|
|
661
|
+
**Table** view. Users can switch between the two and the choice is
|
|
662
|
+
persisted per-resource via cookie.
|
|
663
|
+
|
|
664
|
+
```ruby
|
|
665
|
+
class UserDefinition < ResourceDefinition
|
|
666
|
+
views :table, :grid # enable both; user can switch
|
|
667
|
+
default_view :grid # initial view if no cookie
|
|
668
|
+
|
|
669
|
+
grid_fields(
|
|
670
|
+
image: :avatar, # ActiveStorage attachment, Shrine, or URL
|
|
671
|
+
header: :name, # falls back to record.to_label
|
|
672
|
+
subheader: :email,
|
|
673
|
+
body: :bio,
|
|
674
|
+
meta: [:role, :status], # rendered as small pills
|
|
675
|
+
footer: :last_seen_at # falls back to :created_at
|
|
676
|
+
)
|
|
677
|
+
|
|
678
|
+
grid_layout :media # :compact (default) or :media
|
|
679
|
+
grid_columns 3 # pin to 3 cols on lg+; default is 1/2/3/4 responsive
|
|
680
|
+
end
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
DSL surface:
|
|
684
|
+
|
|
685
|
+
| Method | Purpose |
|
|
686
|
+
|--------|---------|
|
|
687
|
+
| `views :table, :grid` | Which views are available. Default `[:table]`. |
|
|
688
|
+
| `default_view :grid` | Initial view when no cookie. Falls back to first view in `views`. |
|
|
689
|
+
| `grid_fields(...)` | Maps card slots to fields. **Implicitly enables `:grid`** if not already in `views`. |
|
|
690
|
+
| `grid_layout :media` | `:compact` (image left of content) or `:media` (full-width image on top). |
|
|
691
|
+
| `grid_columns 3` | Override responsive column count on lg+. |
|
|
692
|
+
|
|
693
|
+
Grid slots are all optional — `:image`, `:header`, `:subheader`, `:body`,
|
|
694
|
+
`:meta`, `:footer`. `:meta` accepts an array; the rest are single
|
|
695
|
+
fields. Slots that point at fields not permitted by the user's policy
|
|
696
|
+
collapse silently.
|
|
697
|
+
|
|
620
698
|
## Context in Blocks
|
|
621
699
|
|
|
622
700
|
Inside `condition` procs and `input` blocks:
|
|
@@ -941,9 +1019,16 @@ action :name,
|
|
|
941
1019
|
# Behavior
|
|
942
1020
|
confirmation: "Are you sure?",
|
|
943
1021
|
turbo_frame: "_top",
|
|
944
|
-
route_options: {action: :foo}
|
|
1022
|
+
route_options: {action: :foo},
|
|
1023
|
+
modal: :slideover # :centered (default) or :slideover —
|
|
1024
|
+
# how the action's interaction form renders
|
|
945
1025
|
```
|
|
946
1026
|
|
|
1027
|
+
**`Action#with(...)`** — actions are frozen value objects. To derive a
|
|
1028
|
+
variant (typically inside `customize_actions`) call
|
|
1029
|
+
`existing_action.with(turbo_frame: nil)` for a new copy with the
|
|
1030
|
+
overrides applied.
|
|
1031
|
+
|
|
947
1032
|
### Creating an Interaction
|
|
948
1033
|
|
|
949
1034
|
#### Basic Structure
|
|
@@ -211,6 +211,10 @@ rails generate pu:res:conn Post --dest=admin_portal
|
|
|
211
211
|
Plutonium.configure do |config|
|
|
212
212
|
config.load_defaults 1.0
|
|
213
213
|
|
|
214
|
+
# Page chrome. Default :modern (topbar + icon rail). Set :classic
|
|
215
|
+
# only when upgrading and you want to keep the legacy header + sidebar.
|
|
216
|
+
# config.shell = :classic
|
|
217
|
+
|
|
214
218
|
# Custom assets (optional)
|
|
215
219
|
# config.assets.stylesheet = "custom_stylesheet"
|
|
216
220
|
# config.assets.script = "custom_script"
|
|
@@ -311,6 +315,8 @@ For models that already exist in your app:
|
|
|
311
315
|
| `pu:res:scaffold NAME` | Create resource (model, policy, definition, controller) |
|
|
312
316
|
| `pu:res:conn NAME` | Connect resource to portal |
|
|
313
317
|
| `pu:eject:layout` | Eject layout files for customization |
|
|
318
|
+
| `pu:eject:shell` | Eject the topbar/sidebar partials so you can customize chrome per-portal |
|
|
319
|
+
| `pu:core:update` | Update the plutonium gem + npm package |
|
|
314
320
|
| `pu:skills:sync` | Sync Claude Code skills to project |
|
|
315
321
|
|
|
316
322
|
## Related Skills
|
|
@@ -425,6 +425,65 @@ class PostDefinition < ResourceDefinition
|
|
|
425
425
|
end
|
|
426
426
|
```
|
|
427
427
|
|
|
428
|
+
## Page Chrome (Shell)
|
|
429
|
+
|
|
430
|
+
`Plutonium.configuration.shell` controls the layout shipped above the
|
|
431
|
+
resource pages. Default is **`:modern`** (topbar + icon rail) — only
|
|
432
|
+
override to **`:classic`** (legacy header + sidebar) if you're upgrading
|
|
433
|
+
from a pre-`:modern` version and want to preserve the old chrome:
|
|
434
|
+
|
|
435
|
+
```ruby
|
|
436
|
+
Plutonium.configure do |config|
|
|
437
|
+
config.shell = :classic
|
|
438
|
+
end
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
To customize the shipped chrome per-portal, eject the templates:
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
rails generate pu:eject:shell --dest=admin_portal
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
This copies `_resource_header.html.erb` and `_resource_sidebar.html.erb`
|
|
448
|
+
into the portal's `app/views/plutonium/`. The eject is independent of
|
|
449
|
+
`shell` — you can run it on either.
|
|
450
|
+
|
|
451
|
+
## Modal & Slideover Forms
|
|
452
|
+
|
|
453
|
+
The framework's `:new` / `:edit` actions render inline inside a modal.
|
|
454
|
+
Choose the chrome per-resource via the `modal` DSL on the definition:
|
|
455
|
+
|
|
456
|
+
```ruby
|
|
457
|
+
class PostDefinition < ResourceDefinition
|
|
458
|
+
modal :slideover # default — slide-in panel from the right
|
|
459
|
+
# modal :centered # centered dialog
|
|
460
|
+
# modal false # full standalone page (no modal)
|
|
461
|
+
end
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Custom interactive actions render in their own dialog with their own
|
|
465
|
+
`modal:` option (`:centered` default, or `:slideover`).
|
|
466
|
+
|
|
467
|
+
### Detecting render context in components
|
|
468
|
+
|
|
469
|
+
Custom pages / forms can branch on render context:
|
|
470
|
+
|
|
471
|
+
| Helper | True when |
|
|
472
|
+
|--------|-----------|
|
|
473
|
+
| `in_frame?` | Request is targeting a turbo-frame |
|
|
474
|
+
| `in_modal?` | Request is rendering inside a modal/slideover |
|
|
475
|
+
|
|
476
|
+
Use them to pin action strips, omit nav chrome, or swap layouts.
|
|
477
|
+
|
|
478
|
+
## Tabs & URL Hash
|
|
479
|
+
|
|
480
|
+
Show pages with associations render the **Details** tab first followed
|
|
481
|
+
by one tab per permitted association. The active tab is reflected in
|
|
482
|
+
the URL hash (`#products`, `#refund-requests`) so the page deep-links and
|
|
483
|
+
the active state survives reloads / back navigation.
|
|
484
|
+
|
|
485
|
+
Tab rows scroll horizontally on narrow viewports — they don't wrap.
|
|
486
|
+
|
|
428
487
|
## Layout Customization
|
|
429
488
|
|
|
430
489
|
### Eject Layout
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [0.50.0] - 2026-05-11
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- *(ui)* UI layout overhaul: modern shell, slideovers, filters, Grid view (#52)
|
|
6
|
+
- *(css)* Style WebKit autofill on .pu-input variants
|
|
7
|
+
|
|
8
|
+
### 🐛 Bug Fixes
|
|
9
|
+
|
|
10
|
+
- *(ui/form)* Suppress label and chrome for hidden fields
|
|
11
|
+
- *(generators/rails_pulse)* Inject recurring tasks under env blocks
|
|
12
|
+
- *(bulk_actions)* Selection cells survive table re-renders
|
|
1
13
|
## [0.49.1] - 2026-05-06
|
|
2
14
|
|
|
3
15
|
### 🚀 Features
|