plutonium 0.34.1 → 0.35.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 +53 -0
- data/.claude/skills/{assets → plutonium-assets}/SKILL.md +13 -8
- data/.claude/skills/{connect-resource → plutonium-connect-resource}/SKILL.md +1 -1
- data/.claude/skills/{controller → plutonium-controller}/SKILL.md +27 -13
- data/.claude/skills/{create-resource → plutonium-create-resource}/SKILL.md +1 -1
- data/.claude/skills/{definition → plutonium-definition}/SKILL.md +10 -10
- data/.claude/skills/{definition-actions → plutonium-definition-actions}/SKILL.md +34 -9
- data/.claude/skills/{definition-fields → plutonium-definition-fields}/SKILL.md +38 -10
- data/.claude/skills/plutonium-definition-query/SKILL.md +356 -0
- data/.claude/skills/{forms → plutonium-forms}/SKILL.md +6 -6
- data/.claude/skills/{installation → plutonium-installation}/SKILL.md +9 -9
- data/.claude/skills/{interaction → plutonium-interaction}/SKILL.md +20 -19
- data/.claude/skills/{model → plutonium-model}/SKILL.md +3 -3
- data/.claude/skills/{model-features → plutonium-model-features}/SKILL.md +3 -3
- data/.claude/skills/{nested-resources → plutonium-nested-resources}/SKILL.md +5 -5
- data/.claude/skills/{package → plutonium-package}/SKILL.md +7 -8
- data/.claude/skills/{policy → plutonium-policy}/SKILL.md +26 -4
- data/.claude/skills/{portal → plutonium-portal}/SKILL.md +33 -31
- data/.claude/skills/{resource → plutonium-resource}/SKILL.md +27 -27
- data/.claude/skills/{rodauth → plutonium-rodauth}/SKILL.md +5 -5
- data/.claude/skills/plutonium-theming/SKILL.md +424 -0
- data/.claude/skills/{views → plutonium-views}/SKILL.md +7 -7
- data/CHANGELOG.md +52 -0
- data/CLAUDE.md +215 -0
- data/CONTRIBUTING.md +72 -18
- data/README.md +100 -19
- data/app/assets/plutonium.css +1 -11
- data/app/assets/plutonium.js +1685 -1146
- data/app/assets/plutonium.js.map +4 -4
- data/app/assets/plutonium.min.js +70 -70
- data/app/assets/plutonium.min.js.map +4 -4
- data/app/views/resource/interactive_bulk_action.html.erb +1 -5
- data/app/views/rodauth/_email_auth_request_form.html.erb +1 -1
- data/app/views/rodauth/_login_form.html.erb +15 -55
- data/app/views/rodauth/_login_form_footer.html.erb +2 -2
- data/app/views/rodauth/_password_visibility.html.erb +2 -8
- data/app/views/rodauth/add_recovery_codes.html.erb +2 -2
- data/app/views/rodauth/change_login.html.erb +36 -19
- data/app/views/rodauth/change_password.html.erb +34 -10
- data/app/views/rodauth/close_account.html.erb +12 -4
- data/app/views/rodauth/confirm_password.html.erb +19 -17
- data/app/views/rodauth/create_account.html.erb +30 -109
- data/app/views/rodauth/email_auth.html.erb +1 -1
- data/app/views/rodauth/logout.html.erb +4 -4
- data/app/views/rodauth/otp_auth.html.erb +13 -4
- data/app/views/rodauth/otp_disable.html.erb +12 -4
- data/app/views/rodauth/otp_setup.html.erb +29 -12
- data/app/views/rodauth/otp_unlock.html.erb +19 -10
- data/app/views/rodauth/otp_unlock_not_available.html.erb +7 -7
- data/app/views/rodauth/recovery_auth.html.erb +12 -4
- data/app/views/rodauth/recovery_codes.html.erb +12 -4
- data/app/views/rodauth/remember.html.erb +7 -7
- data/app/views/rodauth/reset_password.html.erb +23 -7
- data/app/views/rodauth/reset_password_request.html.erb +14 -10
- data/app/views/rodauth/sms_auth.html.erb +13 -4
- data/app/views/rodauth/sms_confirm.html.erb +13 -4
- data/app/views/rodauth/sms_disable.html.erb +12 -4
- data/app/views/rodauth/sms_request.html.erb +1 -1
- data/app/views/rodauth/sms_setup.html.erb +23 -7
- data/app/views/rodauth/two_factor_auth.html.erb +2 -2
- data/app/views/rodauth/two_factor_disable.html.erb +12 -4
- data/app/views/rodauth/two_factor_manage.html.erb +7 -7
- data/app/views/rodauth/unlock_account.html.erb +13 -5
- data/app/views/rodauth/unlock_account_request.html.erb +2 -2
- data/app/views/rodauth/verify_account.html.erb +25 -7
- data/app/views/rodauth/verify_account_resend.html.erb +14 -10
- data/app/views/rodauth/verify_login_change.html.erb +1 -1
- data/app/views/rodauth/webauthn_auth.html.erb +1 -1
- data/app/views/rodauth/webauthn_remove.html.erb +18 -8
- data/app/views/rodauth/webauthn_setup.html.erb +12 -4
- data/docs/.vitepress/config.ts +15 -26
- data/docs/.vitepress/theme/custom.css +388 -29
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/tutorial/02-first-resource.md +9 -0
- data/docs/getting-started/tutorial/06-nested-resources.md +2 -2
- data/docs/getting-started/tutorial/07-author-portal.md +191 -0
- data/docs/getting-started/tutorial/{07-customizing-ui.md → 08-customizing-ui.md} +7 -7
- data/docs/getting-started/tutorial/index.md +5 -2
- data/docs/guides/authorization.md +33 -0
- data/docs/guides/creating-packages.md +12 -16
- data/docs/guides/custom-actions.md +36 -0
- data/docs/guides/search-filtering.md +121 -42
- data/docs/guides/theming.md +232 -36
- data/docs/index.md +203 -57
- data/docs/public/og-image.png +0 -0
- data/docs/reference/controller/index.md +14 -16
- data/docs/reference/definition/actions.md +38 -3
- data/docs/reference/definition/fields.md +3 -3
- data/docs/reference/definition/index.md +2 -2
- data/docs/reference/generators/index.md +0 -1
- data/docs/reference/interaction/index.md +14 -10
- data/docs/reference/model/index.md +0 -1
- data/docs/reference/portal/index.md +13 -27
- 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/pkg/portal/portal_generator.rb +0 -2
- data/lib/generators/pu/pkg/portal/templates/app/views/package/dashboard/index.html.erb +28 -72
- data/lib/plutonium/action/interactive.rb +2 -2
- data/lib/plutonium/core/controller.rb +2 -1
- data/lib/plutonium/definition/actions.rb +2 -2
- data/lib/plutonium/lib/deep_freezer.rb +3 -7
- data/lib/plutonium/query/filter.rb +14 -0
- data/lib/plutonium/query/filters/association.rb +49 -0
- data/lib/plutonium/query/filters/boolean.rb +35 -0
- data/lib/plutonium/query/filters/date.rb +97 -0
- data/lib/plutonium/query/filters/date_range.rb +58 -0
- data/lib/plutonium/query/filters/select.rb +55 -0
- data/lib/plutonium/resource/controllers/crud_actions.rb +24 -6
- data/lib/plutonium/resource/controllers/interactive_actions.rb +76 -58
- data/lib/plutonium/resource/controllers/queryable.rb +4 -2
- data/lib/plutonium/resource/query_object.rb +1 -1
- data/lib/plutonium/ui/action_button.rb +23 -65
- data/lib/plutonium/ui/actions_dropdown.rb +103 -0
- data/lib/plutonium/ui/block.rb +1 -1
- data/lib/plutonium/ui/breadcrumbs.rb +12 -19
- data/lib/plutonium/ui/color_mode_selector.rb +1 -1
- data/lib/plutonium/ui/component/kit.rb +6 -0
- data/lib/plutonium/ui/component_classes.rb +102 -0
- data/lib/plutonium/ui/display/base.rb +15 -0
- data/lib/plutonium/ui/display/components/attachment.rb +6 -5
- data/lib/plutonium/ui/display/components/boolean.rb +23 -0
- data/lib/plutonium/ui/display/components/color.rb +23 -0
- data/lib/plutonium/ui/display/resource.rb +1 -1
- data/lib/plutonium/ui/display/theme.rb +29 -15
- data/lib/plutonium/ui/empty_card.rb +3 -3
- data/lib/plutonium/ui/form/base.rb +20 -0
- data/lib/plutonium/ui/form/components/key_value_store.rb +11 -11
- data/lib/plutonium/ui/form/components/resource_select.rb +31 -0
- data/lib/plutonium/ui/form/components/secure_association.rb +1 -2
- data/lib/plutonium/ui/form/components/uppy.rb +5 -4
- data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +4 -4
- data/lib/plutonium/ui/form/interaction.rb +17 -1
- data/lib/plutonium/ui/form/query.rb +133 -80
- data/lib/plutonium/ui/form/theme.rb +50 -35
- data/lib/plutonium/ui/frame_navigator_panel.rb +2 -2
- data/lib/plutonium/ui/layout/base.rb +1 -1
- data/lib/plutonium/ui/layout/header.rb +4 -7
- data/lib/plutonium/ui/layout/rodauth_layout.rb +7 -7
- data/lib/plutonium/ui/layout/sidebar.rb +1 -1
- data/lib/plutonium/ui/nav_grid_menu.rb +7 -6
- data/lib/plutonium/ui/nav_user.rb +9 -8
- data/lib/plutonium/ui/page/interactive_action.rb +5 -5
- data/lib/plutonium/ui/page_header.rb +29 -10
- data/lib/plutonium/ui/panel.rb +4 -4
- data/lib/plutonium/ui/sidebar_menu.rb +8 -8
- data/lib/plutonium/ui/skeleton_table.rb +7 -8
- data/lib/plutonium/ui/tab_list.rb +5 -5
- data/lib/plutonium/ui/table/base.rb +3 -0
- data/lib/plutonium/ui/table/components/attachment.rb +4 -3
- data/lib/plutonium/ui/table/components/bulk_actions_toolbar.rb +82 -0
- data/lib/plutonium/ui/table/components/pagy_info.rb +2 -2
- data/lib/plutonium/ui/table/components/pagy_pagination.rb +13 -8
- data/lib/plutonium/ui/table/components/row_actions_dropdown.rb +101 -0
- data/lib/plutonium/ui/table/components/scopes_bar.rb +2 -2
- data/lib/plutonium/ui/table/components/selection_column.rb +100 -0
- data/lib/plutonium/ui/table/display_theme.rb +6 -6
- data/lib/plutonium/ui/table/resource.rb +93 -52
- data/lib/plutonium/ui/table/theme.rb +28 -15
- data/lib/plutonium/version.rb +1 -1
- data/package.json +2 -2
- data/plutonium.gemspec +5 -4
- data/src/css/components.css +471 -0
- data/src/css/intl_tel_input.css +2 -2
- data/src/css/plutonium.css +2 -0
- data/src/css/tokens.css +149 -0
- data/src/js/controllers/bulk_actions_controller.js +109 -0
- data/src/js/controllers/filter_panel_controller.js +35 -0
- data/src/js/controllers/register_controllers.js +5 -1
- data/src/js/controllers/resource_drop_down_controller.js +25 -1
- data/src/js/controllers/slim_select_controller.js +6 -2
- data/src/js/turbo/turbo_actions.js +1 -1
- metadata +52 -39
- data/.claude/skills/definition-query/SKILL.md +0 -334
- data/docs/concepts/architecture.md +0 -226
- data/docs/concepts/auto-detection.md +0 -254
- data/docs/concepts/index.md +0 -61
- data/docs/concepts/packages-portals.md +0 -304
- data/docs/concepts/resources.md +0 -224
- data/docs/cookbook/blog.md +0 -411
- data/docs/cookbook/index.md +0 -289
- data/docs/cookbook/saas.md +0 -481
- data/docs/public/CLAUDE.md +0 -578
- data/lib/generators/pu/pkg/portal/templates/app/controllers/resource_controller.rb.tt +0 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: portal
|
|
2
|
+
name: plutonium-portal
|
|
3
3
|
description: Plutonium portals - web interfaces with authentication, entity scoping, and routes
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -244,35 +244,37 @@ end
|
|
|
244
244
|
|
|
245
245
|
## Controller Hierarchy
|
|
246
246
|
|
|
247
|
+
### Resource Controllers
|
|
248
|
+
|
|
249
|
+
Portal resource controllers inherit from the feature package's controller:
|
|
250
|
+
|
|
247
251
|
```
|
|
248
|
-
::
|
|
249
|
-
↓
|
|
250
|
-
::ResourceController (resource handling)
|
|
251
|
-
↓
|
|
252
|
-
DashboardPortal::ResourceController (portal base)
|
|
252
|
+
::PostsController (feature package controller)
|
|
253
253
|
↓
|
|
254
|
-
DashboardPortal::PostsController (
|
|
254
|
+
DashboardPortal::PostsController (portal-specific)
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
-
|
|
257
|
+
Controllers are auto-created if not defined. When accessing `DashboardPortal::PostsController`:
|
|
258
|
+
|
|
259
|
+
1. If file exists, use it
|
|
260
|
+
2. Otherwise, dynamically create inheriting from `::PostsController`
|
|
261
|
+
3. Include `DashboardPortal::Concerns::Controller`
|
|
262
|
+
|
|
263
|
+
### Non-Resource Controllers
|
|
264
|
+
|
|
265
|
+
For portal pages not tied to a resource (dashboard, settings, etc.), inherit from `PlutoniumController`:
|
|
258
266
|
|
|
259
267
|
```ruby
|
|
260
|
-
# packages/dashboard_portal/app/controllers/dashboard_portal/
|
|
268
|
+
# packages/dashboard_portal/app/controllers/dashboard_portal/dashboard_controller.rb
|
|
261
269
|
module DashboardPortal
|
|
262
|
-
class
|
|
263
|
-
|
|
270
|
+
class DashboardController < PlutoniumController
|
|
271
|
+
def index
|
|
272
|
+
# Dashboard home page
|
|
273
|
+
end
|
|
264
274
|
end
|
|
265
275
|
end
|
|
266
276
|
```
|
|
267
277
|
|
|
268
|
-
### Dynamic Controllers
|
|
269
|
-
|
|
270
|
-
Controllers are auto-created if not defined. When accessing `DashboardPortal::PostsController`:
|
|
271
|
-
|
|
272
|
-
1. If file exists, use it
|
|
273
|
-
2. Otherwise, dynamically create inheriting from `::PostsController`
|
|
274
|
-
3. Include `DashboardPortal::Concerns::Controller`
|
|
275
|
-
|
|
276
278
|
## Portal-Specific Overrides
|
|
277
279
|
|
|
278
280
|
### Override Definition
|
|
@@ -307,13 +309,13 @@ end
|
|
|
307
309
|
|
|
308
310
|
```ruby
|
|
309
311
|
# packages/dashboard_portal/app/controllers/dashboard_portal/posts_controller.rb
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
private
|
|
312
|
+
class DashboardPortal::PostsController < ::PostsController
|
|
313
|
+
include DashboardPortal::Concerns::Controller
|
|
313
314
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
private
|
|
316
|
+
|
|
317
|
+
def preferred_action_after_submit
|
|
318
|
+
"index"
|
|
317
319
|
end
|
|
318
320
|
end
|
|
319
321
|
```
|
|
@@ -392,9 +394,9 @@ Each portal can:
|
|
|
392
394
|
|
|
393
395
|
## Related Skills
|
|
394
396
|
|
|
395
|
-
- `package` - Package overview (features vs portals)
|
|
396
|
-
- `rodauth` - Authentication setup and configuration
|
|
397
|
-
- `connect-resource` - Connecting resources to portals
|
|
398
|
-
- `policy` - Portal-specific policies
|
|
399
|
-
- `definition` - Portal-specific definitions
|
|
400
|
-
- `controller` - Portal-specific controllers
|
|
397
|
+
- `plutonium-package` - Package overview (features vs portals)
|
|
398
|
+
- `plutonium-rodauth` - Authentication setup and configuration
|
|
399
|
+
- `plutonium-connect-resource` - Connecting resources to portals
|
|
400
|
+
- `plutonium-policy` - Portal-specific policies
|
|
401
|
+
- `plutonium-definition` - Portal-specific definitions
|
|
402
|
+
- `plutonium-controller` - Portal-specific controllers
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: resource
|
|
2
|
+
name: plutonium-resource
|
|
3
3
|
description: Overview of Plutonium resources - what they are and how the pieces fit together
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -49,7 +49,7 @@ This generates:
|
|
|
49
49
|
- `app/controllers/posts_controller.rb` - Controller (empty, inherits CRUD)
|
|
50
50
|
- Migration file
|
|
51
51
|
|
|
52
|
-
See `create-resource` skill for full generator options.
|
|
52
|
+
See `plutonium-create-resource` skill for full generator options.
|
|
53
53
|
|
|
54
54
|
### From Existing Models
|
|
55
55
|
|
|
@@ -99,7 +99,7 @@ This:
|
|
|
99
99
|
- Creates portal-specific controller
|
|
100
100
|
- Creates portal-specific policy with attribute permissions
|
|
101
101
|
|
|
102
|
-
See `connect-resource` skill for details.
|
|
102
|
+
See `plutonium-connect-resource` skill for details.
|
|
103
103
|
|
|
104
104
|
## Layer Responsibilities
|
|
105
105
|
|
|
@@ -122,14 +122,14 @@ The model handles:
|
|
|
122
122
|
- Business logic scopes
|
|
123
123
|
- Callbacks
|
|
124
124
|
|
|
125
|
-
**Skills:** `model`, `model-features`
|
|
125
|
+
**Skills:** `plutonium-model`, `plutonium-model-features`
|
|
126
126
|
|
|
127
127
|
### Definition (UI Layer)
|
|
128
128
|
|
|
129
129
|
```ruby
|
|
130
130
|
class PostDefinition < ResourceDefinition
|
|
131
131
|
# Override auto-detected field types
|
|
132
|
-
input :content, as: :
|
|
132
|
+
input :content, as: :markdown
|
|
133
133
|
|
|
134
134
|
# Add filters and scopes
|
|
135
135
|
filter :published, with: Plutonium::Query::Filters::Boolean
|
|
@@ -147,7 +147,7 @@ The definition handles:
|
|
|
147
147
|
- Search, filters, scopes, sorting
|
|
148
148
|
- Actions (interactive operations)
|
|
149
149
|
|
|
150
|
-
**Skills:** `definition`, `definition-fields`, `definition-actions`, `definition-query`
|
|
150
|
+
**Skills:** `plutonium-definition`, `plutonium-definition-fields`, `plutonium-definition-actions`, `plutonium-definition-query`
|
|
151
151
|
|
|
152
152
|
### Policy (Authorization Layer)
|
|
153
153
|
|
|
@@ -188,7 +188,7 @@ The policy handles:
|
|
|
188
188
|
- Resource scoping (what records user can see)
|
|
189
189
|
- Attribute permissions (read/write access per field)
|
|
190
190
|
|
|
191
|
-
**Skill:** `policy`
|
|
191
|
+
**Skill:** `plutonium-policy`
|
|
192
192
|
|
|
193
193
|
### Controller (Request Layer)
|
|
194
194
|
|
|
@@ -216,7 +216,7 @@ The controller handles:
|
|
|
216
216
|
- Custom parameter processing
|
|
217
217
|
- Non-standard authorization flows
|
|
218
218
|
|
|
219
|
-
**Skill:** `controller`
|
|
219
|
+
**Skill:** `plutonium-controller`
|
|
220
220
|
|
|
221
221
|
## Auto-Detection
|
|
222
222
|
|
|
@@ -260,22 +260,22 @@ end
|
|
|
260
260
|
|
|
261
261
|
## Related Skills
|
|
262
262
|
|
|
263
|
-
- `model` - Model structure and organization
|
|
264
|
-
- `model-features` - has_cents, associations, scopes, routes
|
|
265
|
-
- `definition` - Definition overview and structure
|
|
266
|
-
- `definition-fields` - Fields, inputs, displays, columns
|
|
267
|
-
- `definition-actions` - Actions and interactions
|
|
268
|
-
- `interaction` - Writing interaction classes
|
|
269
|
-
- `definition-query` - Search, filters, scopes, sorting
|
|
270
|
-
- `policy` - Authorization and permissions
|
|
271
|
-
- `controller` - Controller customization
|
|
272
|
-
- `views` - Custom pages, displays, tables using Phlex
|
|
273
|
-
- `forms` - Custom form templates and field builders
|
|
274
|
-
- `assets` - TailwindCSS and component theming
|
|
275
|
-
- `package` - Feature and portal packages
|
|
276
|
-
- `portal` - Portal configuration and entity scoping
|
|
277
|
-
- `nested-resources` - Parent/child routes and scoping
|
|
278
|
-
- `installation` - Setting up Plutonium
|
|
279
|
-
- `rodauth` - Authentication setup
|
|
280
|
-
- `create-resource` - Scaffold generator details
|
|
281
|
-
- `connect-resource` - Portal connection details
|
|
263
|
+
- `plutonium-model` - Model structure and organization
|
|
264
|
+
- `plutonium-model-features` - has_cents, associations, scopes, routes
|
|
265
|
+
- `plutonium-definition` - Definition overview and structure
|
|
266
|
+
- `plutonium-definition-fields` - Fields, inputs, displays, columns
|
|
267
|
+
- `plutonium-definition-actions` - Actions and interactions
|
|
268
|
+
- `plutonium-interaction` - Writing interaction classes
|
|
269
|
+
- `plutonium-definition-query` - Search, filters, scopes, sorting
|
|
270
|
+
- `plutonium-policy` - Authorization and permissions
|
|
271
|
+
- `plutonium-controller` - Controller customization
|
|
272
|
+
- `plutonium-views` - Custom pages, displays, tables using Phlex
|
|
273
|
+
- `plutonium-forms` - Custom form templates and field builders
|
|
274
|
+
- `plutonium-assets` - TailwindCSS and component theming
|
|
275
|
+
- `plutonium-package` - Feature and portal packages
|
|
276
|
+
- `plutonium-portal` - Portal configuration and entity scoping
|
|
277
|
+
- `plutonium-nested-resources` - Parent/child routes and scoping
|
|
278
|
+
- `plutonium-installation` - Setting up Plutonium
|
|
279
|
+
- `plutonium-rodauth` - Authentication setup
|
|
280
|
+
- `plutonium-create-resource` - Scaffold generator details
|
|
281
|
+
- `plutonium-connect-resource` - Portal connection details
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: rodauth
|
|
2
|
+
name: plutonium-rodauth
|
|
3
3
|
description: Plutonium Rodauth integration - authentication setup, account types, and configuration
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -165,7 +165,7 @@ Including `Plutonium::Auth::Rodauth(:name)` adds:
|
|
|
165
165
|
|--------|-------------|
|
|
166
166
|
| `current_user` | The authenticated account |
|
|
167
167
|
| `logout_url` | URL to logout |
|
|
168
|
-
| `rodauth` | Access to Rodauth instance |
|
|
168
|
+
| `plutonium-rodauth` | Access to Rodauth instance |
|
|
169
169
|
|
|
170
170
|
## Generated Files
|
|
171
171
|
|
|
@@ -447,6 +447,6 @@ User.create!(
|
|
|
447
447
|
|
|
448
448
|
## Related Skills
|
|
449
449
|
|
|
450
|
-
- `installation` - Initial Plutonium setup
|
|
451
|
-
- `portal` - Portal configuration
|
|
452
|
-
- `policy` - Authorization after authentication
|
|
450
|
+
- `plutonium-installation` - Initial Plutonium setup
|
|
451
|
+
- `plutonium-portal` - Portal configuration
|
|
452
|
+
- `plutonium-policy` - Authorization after authentication
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plutonium-theming
|
|
3
|
+
description: Plutonium design token system - CSS custom properties, component classes, and consistent styling patterns
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Plutonium Design Token System
|
|
7
|
+
|
|
8
|
+
Plutonium uses a comprehensive CSS design token system for consistent, themeable UI components. This system provides CSS custom properties and reusable component classes that automatically support light and dark modes.
|
|
9
|
+
|
|
10
|
+
## CSS Design Tokens
|
|
11
|
+
|
|
12
|
+
Design tokens are defined in `src/css/tokens.css` and provide the foundation for all UI styling.
|
|
13
|
+
|
|
14
|
+
### Surface & Background Colors
|
|
15
|
+
|
|
16
|
+
```css
|
|
17
|
+
/* Light mode */
|
|
18
|
+
--pu-body: #f8fafc; /* Page background */
|
|
19
|
+
--pu-surface: #ffffff; /* Main surface (cards, panels) */
|
|
20
|
+
--pu-surface-alt: #f1f5f9; /* Alternate surface (headers) */
|
|
21
|
+
--pu-surface-raised: #ffffff; /* Elevated elements */
|
|
22
|
+
--pu-surface-overlay: rgba(255, 255, 255, 0.95);
|
|
23
|
+
|
|
24
|
+
/* Dark mode (.dark class) */
|
|
25
|
+
--pu-body: #0f172a;
|
|
26
|
+
--pu-surface: #1e293b;
|
|
27
|
+
--pu-surface-alt: #0f172a;
|
|
28
|
+
--pu-surface-raised: #334155;
|
|
29
|
+
--pu-surface-overlay: rgba(30, 41, 59, 0.95);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Text Colors
|
|
33
|
+
|
|
34
|
+
```css
|
|
35
|
+
/* Light mode */
|
|
36
|
+
--pu-text: #0f172a; /* Primary text */
|
|
37
|
+
--pu-text-muted: #64748b; /* Secondary text */
|
|
38
|
+
--pu-text-subtle: #94a3b8; /* Tertiary/disabled text */
|
|
39
|
+
|
|
40
|
+
/* Dark mode */
|
|
41
|
+
--pu-text: #f8fafc;
|
|
42
|
+
--pu-text-muted: #94a3b8;
|
|
43
|
+
--pu-text-subtle: #64748b;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Border Colors
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
/* Light mode */
|
|
50
|
+
--pu-border: #e2e8f0; /* Standard borders */
|
|
51
|
+
--pu-border-muted: #f1f5f9; /* Subtle borders */
|
|
52
|
+
--pu-border-strong: #cbd5e1; /* Emphasized borders */
|
|
53
|
+
|
|
54
|
+
/* Dark mode */
|
|
55
|
+
--pu-border: #334155;
|
|
56
|
+
--pu-border-muted: #1e293b;
|
|
57
|
+
--pu-border-strong: #475569;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Form Tokens
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
--pu-input-bg: #ffffff; /* Input background */
|
|
64
|
+
--pu-input-border: #e2e8f0; /* Input border */
|
|
65
|
+
--pu-input-focus-ring: theme(colors.primary.500);
|
|
66
|
+
--pu-input-placeholder: #94a3b8; /* Placeholder text */
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Card Tokens
|
|
70
|
+
|
|
71
|
+
```css
|
|
72
|
+
--pu-card-bg: #ffffff;
|
|
73
|
+
--pu-card-border: #e2e8f0;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Shadow System
|
|
77
|
+
|
|
78
|
+
```css
|
|
79
|
+
--pu-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.03), 0 1px 3px 0 rgb(0 0 0 / 0.05);
|
|
80
|
+
--pu-shadow-md: 0 2px 4px -1px rgb(0 0 0 / 0.04), 0 4px 6px -1px rgb(0 0 0 / 0.06);
|
|
81
|
+
--pu-shadow-lg: 0 4px 6px -2px rgb(0 0 0 / 0.03), 0 10px 15px -3px rgb(0 0 0 / 0.08);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Border Radius
|
|
85
|
+
|
|
86
|
+
```css
|
|
87
|
+
--pu-radius-sm: 0.375rem; /* 6px */
|
|
88
|
+
--pu-radius-md: 0.5rem; /* 8px */
|
|
89
|
+
--pu-radius-lg: 0.75rem; /* 12px */
|
|
90
|
+
--pu-radius-xl: 1rem; /* 16px */
|
|
91
|
+
--pu-radius-full: 9999px; /* Fully rounded */
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Spacing
|
|
95
|
+
|
|
96
|
+
```css
|
|
97
|
+
--pu-space-xs: 0.25rem; /* 4px */
|
|
98
|
+
--pu-space-sm: 0.5rem; /* 8px */
|
|
99
|
+
--pu-space-md: 1rem; /* 16px */
|
|
100
|
+
--pu-space-lg: 1.5rem; /* 24px */
|
|
101
|
+
--pu-space-xl: 2rem; /* 32px */
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Transitions
|
|
105
|
+
|
|
106
|
+
```css
|
|
107
|
+
--pu-transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
108
|
+
--pu-transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
109
|
+
--pu-transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Component Classes
|
|
113
|
+
|
|
114
|
+
Component classes are defined in `src/css/components.css` and provide ready-to-use styled components.
|
|
115
|
+
|
|
116
|
+
### Buttons
|
|
117
|
+
|
|
118
|
+
Base class with size variants:
|
|
119
|
+
|
|
120
|
+
```css
|
|
121
|
+
.pu-btn /* Base button styles */
|
|
122
|
+
.pu-btn-md /* Medium size (default) */
|
|
123
|
+
.pu-btn-sm /* Small size */
|
|
124
|
+
.pu-btn-xs /* Extra small size */
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Solid variants (with hover lift animation):
|
|
128
|
+
|
|
129
|
+
```css
|
|
130
|
+
.pu-btn-primary /* Primary action */
|
|
131
|
+
.pu-btn-secondary /* Secondary action */
|
|
132
|
+
.pu-btn-danger /* Destructive action */
|
|
133
|
+
.pu-btn-success /* Success action */
|
|
134
|
+
.pu-btn-warning /* Warning action */
|
|
135
|
+
.pu-btn-info /* Informational action */
|
|
136
|
+
.pu-btn-accent /* Accent action */
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Other variants:
|
|
140
|
+
|
|
141
|
+
```css
|
|
142
|
+
.pu-btn-ghost /* Minimal, text-like */
|
|
143
|
+
.pu-btn-outline /* Bordered, transparent background */
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Soft variants (tinted backgrounds for secondary contexts):
|
|
147
|
+
|
|
148
|
+
```css
|
|
149
|
+
.pu-btn-soft-primary
|
|
150
|
+
.pu-btn-soft-danger
|
|
151
|
+
.pu-btn-soft-success
|
|
152
|
+
.pu-btn-soft-warning
|
|
153
|
+
.pu-btn-soft-info
|
|
154
|
+
.pu-btn-soft-secondary
|
|
155
|
+
.pu-btn-soft-accent
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Usage:
|
|
159
|
+
|
|
160
|
+
```erb
|
|
161
|
+
<%= form.submit "Save", class: "pu-btn pu-btn-md pu-btn-primary" %>
|
|
162
|
+
<%= form.submit "Delete", class: "pu-btn pu-btn-md pu-btn-danger" %>
|
|
163
|
+
<%= form.submit "Disable", class: "pu-btn pu-btn-md pu-btn-warning" %>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Form Inputs
|
|
167
|
+
|
|
168
|
+
```css
|
|
169
|
+
.pu-input /* Base input styles */
|
|
170
|
+
.pu-input-invalid /* Error state */
|
|
171
|
+
.pu-input-valid /* Valid state */
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Usage:
|
|
175
|
+
|
|
176
|
+
```erb
|
|
177
|
+
<%= form.text_field :name, class: "pu-input #{errors? ? 'pu-input-invalid' : ''}" %>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Labels & Text
|
|
181
|
+
|
|
182
|
+
```css
|
|
183
|
+
.pu-label /* Form labels */
|
|
184
|
+
.pu-label-required /* Adds red asterisk after label */
|
|
185
|
+
.pu-hint /* Helper text below inputs */
|
|
186
|
+
.pu-error /* Error messages */
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Usage:
|
|
190
|
+
|
|
191
|
+
```erb
|
|
192
|
+
<%= form.label :email, class: "pu-label" %>
|
|
193
|
+
<span class="pu-error">Email is required</span>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Checkboxes
|
|
197
|
+
|
|
198
|
+
```css
|
|
199
|
+
.pu-checkbox /* Styled checkbox/radio */
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Usage:
|
|
203
|
+
|
|
204
|
+
```erb
|
|
205
|
+
<%= form.check_box :remember_me, class: "pu-checkbox" %>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Cards
|
|
209
|
+
|
|
210
|
+
```css
|
|
211
|
+
.pu-card /* Card container with border, shadow, radius */
|
|
212
|
+
.pu-card-body /* Card content padding */
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Panels
|
|
216
|
+
|
|
217
|
+
```css
|
|
218
|
+
.pu-panel-header /* Panel header with background */
|
|
219
|
+
.pu-panel-title /* Panel title text */
|
|
220
|
+
.pu-panel-description /* Panel description text */
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Tables
|
|
224
|
+
|
|
225
|
+
```css
|
|
226
|
+
.pu-table-wrapper /* Scrollable container with card styling */
|
|
227
|
+
.pu-table /* Base table styles */
|
|
228
|
+
.pu-table-header /* Header row */
|
|
229
|
+
.pu-table-header-cell /* Header cell */
|
|
230
|
+
.pu-table-body-row /* Body row with hover */
|
|
231
|
+
.pu-table-body-row-selected /* Selected row */
|
|
232
|
+
.pu-table-body-cell /* Body cell */
|
|
233
|
+
.pu-selection-cell /* Checkbox column */
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Toolbar
|
|
237
|
+
|
|
238
|
+
```css
|
|
239
|
+
.pu-toolbar /* Toolbar container with gradient */
|
|
240
|
+
.pu-toolbar-text /* Toolbar text */
|
|
241
|
+
.pu-toolbar-actions /* Toolbar action buttons */
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Empty State
|
|
245
|
+
|
|
246
|
+
```css
|
|
247
|
+
.pu-empty-state /* Centered container */
|
|
248
|
+
.pu-empty-state-icon /* Icon styling */
|
|
249
|
+
.pu-empty-state-title /* Title text */
|
|
250
|
+
.pu-empty-state-description /* Description text */
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Ruby Component Classes
|
|
254
|
+
|
|
255
|
+
The `Plutonium::UI::ComponentClasses` module provides Ruby constants for consistent class usage.
|
|
256
|
+
|
|
257
|
+
Location: `lib/plutonium/ui/component_classes.rb`
|
|
258
|
+
|
|
259
|
+
### Button Classes
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
ComponentClasses::Button::BASE # "pu-btn"
|
|
263
|
+
ComponentClasses::Button::SIZE_DEFAULT # "pu-btn-md"
|
|
264
|
+
ComponentClasses::Button::SIZE_SM # "pu-btn-sm"
|
|
265
|
+
ComponentClasses::Button::SIZE_XS # "pu-btn-xs"
|
|
266
|
+
|
|
267
|
+
ComponentClasses::Button::VARIANTS[:primary] # "pu-btn-primary"
|
|
268
|
+
ComponentClasses::Button::VARIANTS[:danger] # "pu-btn-danger"
|
|
269
|
+
ComponentClasses::Button::SOFT_VARIANTS[:primary] # "pu-btn-soft-primary"
|
|
270
|
+
|
|
271
|
+
# Helper method
|
|
272
|
+
ComponentClasses::Button.classes(variant: :primary, size: :default, soft: false)
|
|
273
|
+
# => "pu-btn pu-btn-md pu-btn-primary"
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Form Classes
|
|
277
|
+
|
|
278
|
+
```ruby
|
|
279
|
+
ComponentClasses::Form::INPUT # "pu-input"
|
|
280
|
+
ComponentClasses::Form::INPUT_INVALID # "pu-input pu-input-invalid"
|
|
281
|
+
ComponentClasses::Form::INPUT_VALID # "pu-input pu-input-valid"
|
|
282
|
+
ComponentClasses::Form::LABEL # "pu-label"
|
|
283
|
+
ComponentClasses::Form::HINT # "pu-hint"
|
|
284
|
+
ComponentClasses::Form::ERROR # "pu-error"
|
|
285
|
+
ComponentClasses::Form::BUTTON # "pu-btn pu-btn-md pu-btn-primary"
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Table Classes
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
ComponentClasses::Table::WRAPPER # "pu-table-wrapper"
|
|
292
|
+
ComponentClasses::Table::BASE # "pu-table"
|
|
293
|
+
ComponentClasses::Table::HEADER # "pu-table-header"
|
|
294
|
+
ComponentClasses::Table::HEADER_CELL # "pu-table-header-cell"
|
|
295
|
+
ComponentClasses::Table::BODY_ROW # "pu-table-body-row"
|
|
296
|
+
ComponentClasses::Table::BODY_ROW_SELECTED # "pu-table-body-row-selected"
|
|
297
|
+
ComponentClasses::Table::BODY_CELL # "pu-table-body-cell"
|
|
298
|
+
ComponentClasses::Table::CHECKBOX # "pu-checkbox"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Card Classes
|
|
302
|
+
|
|
303
|
+
```ruby
|
|
304
|
+
ComponentClasses::Card::BASE # "pu-card"
|
|
305
|
+
ComponentClasses::Card::BODY # "pu-card-body"
|
|
306
|
+
ComponentClasses::Card::HEADER # "pu-panel-header"
|
|
307
|
+
ComponentClasses::Card::TITLE # "pu-panel-title"
|
|
308
|
+
ComponentClasses::Card::DESCRIPTION # "pu-panel-description"
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Using Tokens in Templates
|
|
312
|
+
|
|
313
|
+
### ERB Templates
|
|
314
|
+
|
|
315
|
+
```erb
|
|
316
|
+
<%# Text colors %>
|
|
317
|
+
<h1 class="text-[var(--pu-text)]">Title</h1>
|
|
318
|
+
<p class="text-[var(--pu-text-muted)]">Description</p>
|
|
319
|
+
|
|
320
|
+
<%# Surfaces %>
|
|
321
|
+
<div class="bg-[var(--pu-surface)] border border-[var(--pu-border)] rounded-[var(--pu-radius-lg)]">
|
|
322
|
+
Content
|
|
323
|
+
</div>
|
|
324
|
+
|
|
325
|
+
<%# With shadows %>
|
|
326
|
+
<div class="bg-[var(--pu-card-bg)]" style="box-shadow: var(--pu-shadow-md)">
|
|
327
|
+
Card content
|
|
328
|
+
</div>
|
|
329
|
+
|
|
330
|
+
<%# Form fields %>
|
|
331
|
+
<%= form.label :name, class: "pu-label" %>
|
|
332
|
+
<%= form.text_field :name, class: "pu-input" %>
|
|
333
|
+
<span class="pu-error">Error message</span>
|
|
334
|
+
|
|
335
|
+
<%# Buttons %>
|
|
336
|
+
<%= form.submit "Save", class: "w-full pu-btn pu-btn-md pu-btn-primary" %>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Phlex Components
|
|
340
|
+
|
|
341
|
+
```ruby
|
|
342
|
+
class MyComponent < Plutonium::UI::Component::Base
|
|
343
|
+
def view_template
|
|
344
|
+
div(class: "bg-[var(--pu-surface)] border border-[var(--pu-border)] rounded-[var(--pu-radius-lg)]",
|
|
345
|
+
style: "box-shadow: var(--pu-shadow-md)") {
|
|
346
|
+
h2(class: "text-lg font-semibold text-[var(--pu-text)]") { "Title" }
|
|
347
|
+
p(class: "text-[var(--pu-text-muted)]") { "Description" }
|
|
348
|
+
}
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Link Styling Patterns
|
|
354
|
+
|
|
355
|
+
Plutonium uses consistent link styling patterns:
|
|
356
|
+
|
|
357
|
+
```erb
|
|
358
|
+
<%# Primary links %>
|
|
359
|
+
<%= link_to "Link", path, class: "font-medium text-secondary-600 dark:text-secondary-400 hover:underline transition-colors" %>
|
|
360
|
+
|
|
361
|
+
<%# Muted links %>
|
|
362
|
+
<%= link_to "Link", path, class: "text-[var(--pu-text-muted)] hover:text-primary-600 transition-colors" %>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Dark Mode
|
|
366
|
+
|
|
367
|
+
All tokens automatically switch values when the `.dark` class is present on `<html>`:
|
|
368
|
+
|
|
369
|
+
```html
|
|
370
|
+
<!-- Light mode -->
|
|
371
|
+
<html>
|
|
372
|
+
<body class="bg-[var(--pu-body)]">...</body>
|
|
373
|
+
</html>
|
|
374
|
+
|
|
375
|
+
<!-- Dark mode -->
|
|
376
|
+
<html class="dark">
|
|
377
|
+
<body class="bg-[var(--pu-body)]">...</body>
|
|
378
|
+
</html>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
No additional classes needed - tokens handle the switch automatically.
|
|
382
|
+
|
|
383
|
+
## Customizing Tokens
|
|
384
|
+
|
|
385
|
+
Override tokens in your application CSS:
|
|
386
|
+
|
|
387
|
+
```css
|
|
388
|
+
/* app/assets/stylesheets/application.tailwind.css */
|
|
389
|
+
@import "gem:plutonium/src/css/plutonium.css";
|
|
390
|
+
@import "tailwindcss";
|
|
391
|
+
|
|
392
|
+
:root {
|
|
393
|
+
/* Override light mode tokens */
|
|
394
|
+
--pu-surface: #fafafa;
|
|
395
|
+
--pu-border: #d1d5db;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.dark {
|
|
399
|
+
/* Override dark mode tokens */
|
|
400
|
+
--pu-surface: #111827;
|
|
401
|
+
--pu-border: #374151;
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Migration from Hardcoded Classes
|
|
406
|
+
|
|
407
|
+
When updating views to use the design token system:
|
|
408
|
+
|
|
409
|
+
| Old Pattern | New Pattern |
|
|
410
|
+
|-------------|-------------|
|
|
411
|
+
| `text-gray-900 dark:text-white` | `text-[var(--pu-text)]` |
|
|
412
|
+
| `text-gray-500 dark:text-gray-400` | `text-[var(--pu-text-muted)]` |
|
|
413
|
+
| `bg-gray-50 dark:bg-gray-700` | `bg-[var(--pu-surface)]` |
|
|
414
|
+
| `border-gray-300 dark:border-gray-600` | `border-[var(--pu-border)]` |
|
|
415
|
+
| `bg-gray-50 border ... (long input class)` | `pu-input` |
|
|
416
|
+
| `block mb-2 text-sm font-semibold ...` | `pu-label` |
|
|
417
|
+
| `text-red-600 dark:text-red-400` | `pu-error` |
|
|
418
|
+
| `(long button class)` | `pu-btn pu-btn-md pu-btn-primary` |
|
|
419
|
+
|
|
420
|
+
## Related Skills
|
|
421
|
+
|
|
422
|
+
- `plutonium-assets` - TailwindCSS configuration and asset setup
|
|
423
|
+
- `plutonium-forms` - Form component customization
|
|
424
|
+
- `plutonium-views` - View and layout customization
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: views
|
|
2
|
+
name: plutonium-views
|
|
3
3
|
description: Customizing Plutonium views - pages, forms, displays, tables, and layouts using Phlex
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -555,9 +555,9 @@ end
|
|
|
555
555
|
|
|
556
556
|
## Related Skills
|
|
557
557
|
|
|
558
|
-
- `forms` - Custom form templates and field builders
|
|
559
|
-
- `assets` - TailwindCSS and component theming
|
|
560
|
-
- `definition-fields` - Field/input/display configuration
|
|
561
|
-
- `definition-actions` - Action buttons and interactions
|
|
562
|
-
- `controller` - Presentation hooks (`present_parent?`, etc.)
|
|
563
|
-
- `portal` - Portal-specific customization
|
|
558
|
+
- `plutonium-forms` - Custom form templates and field builders
|
|
559
|
+
- `plutonium-assets` - TailwindCSS and component theming
|
|
560
|
+
- `plutonium-definition-fields` - Field/input/display configuration
|
|
561
|
+
- `plutonium-definition-actions` - Action buttons and interactions
|
|
562
|
+
- `plutonium-controller` - Presentation hooks (`present_parent?`, etc.)
|
|
563
|
+
- `plutonium-portal` - Portal-specific customization
|