plutonium 0.28.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/app/assets/plutonium.css +2 -2
  4. data/app/assets/plutonium.js +13 -3
  5. data/app/assets/plutonium.js.map +3 -3
  6. data/app/assets/plutonium.min.js +1 -1
  7. data/app/assets/plutonium.min.js.map +2 -2
  8. data/docs/guide/theming.md +431 -0
  9. data/lib/plutonium/core/controller.rb +5 -0
  10. data/lib/plutonium/interaction/response/redirect.rb +8 -0
  11. data/lib/plutonium/resource/controllers/crud_actions.rb +1 -0
  12. data/lib/plutonium/ui/action_button.rb +11 -5
  13. data/lib/plutonium/ui/block.rb +4 -1
  14. data/lib/plutonium/ui/breadcrumbs.rb +10 -8
  15. data/lib/plutonium/ui/color_mode_selector.rb +2 -2
  16. data/lib/plutonium/ui/component/behaviour.rb +8 -0
  17. data/lib/plutonium/ui/component/kit.rb +1 -1
  18. data/lib/plutonium/ui/component/theme.rb +47 -0
  19. data/lib/plutonium/ui/display/components/attachment.rb +2 -2
  20. data/lib/plutonium/ui/display/theme.rb +16 -16
  21. data/lib/plutonium/ui/empty_card.rb +5 -2
  22. data/lib/plutonium/ui/form/components/key_value_store.rb +11 -11
  23. data/lib/plutonium/ui/form/components/secure_association.rb +2 -2
  24. data/lib/plutonium/ui/form/components/uppy.rb +5 -5
  25. data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +5 -5
  26. data/lib/plutonium/ui/form/query.rb +11 -11
  27. data/lib/plutonium/ui/form/resource.rb +2 -2
  28. data/lib/plutonium/ui/form/theme.rb +17 -17
  29. data/lib/plutonium/ui/layout/base.rb +2 -2
  30. data/lib/plutonium/ui/layout/header.rb +10 -7
  31. data/lib/plutonium/ui/layout/rodauth_layout.rb +5 -5
  32. data/lib/plutonium/ui/layout/sidebar.rb +2 -2
  33. data/lib/plutonium/ui/nav_grid_menu.rb +6 -6
  34. data/lib/plutonium/ui/nav_user.rb +8 -7
  35. data/lib/plutonium/ui/page/interactive_action.rb +4 -4
  36. data/lib/plutonium/ui/page_header.rb +7 -4
  37. data/lib/plutonium/ui/panel.rb +3 -3
  38. data/lib/plutonium/ui/sidebar_menu.rb +12 -12
  39. data/lib/plutonium/ui/skeleton_table.rb +8 -8
  40. data/lib/plutonium/ui/tab_list.rb +5 -3
  41. data/lib/plutonium/ui/table/components/attachment.rb +2 -2
  42. data/lib/plutonium/ui/table/components/pagy_info.rb +3 -3
  43. data/lib/plutonium/ui/table/components/pagy_pagination.rb +3 -3
  44. data/lib/plutonium/ui/table/components/scopes_bar.rb +14 -14
  45. data/lib/plutonium/ui/table/display_theme.rb +3 -3
  46. data/lib/plutonium/ui/table/resource.rb +2 -2
  47. data/lib/plutonium/ui/table/theme.rb +13 -13
  48. data/lib/plutonium/version.rb +1 -1
  49. data/lib/tasks/release.rake +48 -5
  50. data/package.json +1 -1
  51. data/src/css/core.css +2 -2
  52. data/src/css/easymde.css +8 -8
  53. data/src/css/intl_tel_input.css +7 -7
  54. data/src/css/slim_select.css +5 -5
  55. data/src/js/controllers/color_mode_controller.js +19 -3
  56. data/tailwind.options.js +75 -47
  57. metadata +4 -2
@@ -6,23 +6,23 @@ module Plutonium
6
6
  class Theme < Phlexi::Display::Theme
7
7
  def self.theme
8
8
  super.merge({
9
- base: "",
9
+ base: "pu-display",
10
10
  value_wrapper: "max-h-[300px] overflow-y-auto",
11
- fields_wrapper: "p-6 grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4 gap-6 gap-y-10 grid-flow-row-dense",
12
- label: "text-base font-bold text-gray-500 dark:text-gray-400 mb-1",
13
- description: "text-sm text-gray-400 dark:text-gray-500",
14
- placeholder: "text-md text-gray-500 dark:text-gray-300 mb-1 italic",
15
- string: "text-md text-gray-900 dark:text-white mb-1 whitespace-pre-line",
16
- text: "text-md text-gray-900 dark:text-white mb-1 whitespace-pre-line",
17
- link: "text-primary-600 dark:text-primary-500 whitespace-pre-line",
18
- color: "flex items-center text-md text-gray-900 dark:text-white mb-1 whitespace-pre-line",
19
- color_indicator: "w-10 h-10 rounded-full mr-2", # max-h-fit
20
- email: "flex items-center text-md text-primary-600 dark:text-primary-500 mb-1 whitespace-pre-line",
21
- phone: "flex items-center text-md text-primary-600 dark:text-primary-500 mb-1 whitespace-pre-line",
22
- json: "text-sm text-gray-900 dark:text-white mb-1 whitespace-pre font-mono shadow-inner p-4",
23
- prefixed_icon: "w-8 h-8 mr-2",
24
- markdown: "format dark:format-invert format-primary",
25
- attachment_value_wrapper: "grid grid-cols-[repeat(auto-fill,minmax(0,180px))]",
11
+ fields_wrapper: "pu-display-fields p-lg grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4 gap-lg gap-y-2xl grid-flow-row-dense",
12
+ label: "pu-display-label text-base font-bold text-gray-500 dark:text-gray-400 mb-xs",
13
+ description: "pu-display-description text-sm text-gray-400 dark:text-gray-500",
14
+ placeholder: "pu-display-placeholder text-md text-gray-500 dark:text-gray-300 mb-xs italic",
15
+ string: "pu-display-string text-md text-gray-900 dark:text-white mb-xs whitespace-pre-line",
16
+ text: "pu-display-text text-md text-gray-900 dark:text-white mb-xs whitespace-pre-line",
17
+ link: "pu-display-link text-primary-600 dark:text-primary-500 whitespace-pre-line",
18
+ color: "pu-display-color flex items-center text-md text-gray-900 dark:text-white mb-xs whitespace-pre-line",
19
+ color_indicator: "pu-display-color-indicator w-10 h-10 rounded-full mr-sm", # max-h-fit
20
+ email: "pu-display-email flex items-center text-md text-primary-600 dark:text-primary-500 mb-xs whitespace-pre-line",
21
+ phone: "pu-display-phone flex items-center text-md text-primary-600 dark:text-primary-500 mb-xs whitespace-pre-line",
22
+ json: "pu-display-json text-sm text-gray-900 dark:text-white mb-xs whitespace-pre font-mono shadow-inner p-md",
23
+ prefixed_icon: "pu-display-icon w-8 h-8 mr-sm",
24
+ markdown: "pu-display-markdown format dark:format-invert format-primary",
25
+ attachment_value_wrapper: "pu-display-attachments grid grid-cols-[repeat(auto-fill,minmax(0,180px))]",
26
26
  phlexi_render: :string
27
27
  })
28
28
  end
@@ -8,8 +8,11 @@ module Plutonium
8
8
  end
9
9
 
10
10
  def view_template
11
- div(class: "relative bg-white dark:bg-gray-800 shadow-md") do
12
- div(class: "p-6 flex items-center flex-col gap-2") do
11
+ div(class: tokens(
12
+ theme_class(:card, variant: :empty),
13
+ "relative bg-surface dark:bg-surface-dark shadow-md sm:rounded-sm"
14
+ )) do
15
+ div(class: "p-lg flex items-center flex-col gap-sm") do
13
16
  p(class: "text-gray-500 sm:text-lg dark:text-gray-200 text-center") { message }
14
17
  yield if block_given?
15
18
  end
@@ -60,7 +60,7 @@ module Plutonium
60
60
  end
61
61
 
62
62
  def render_key_value_pairs
63
- div(class: "key-value-pairs space-y-2", data_key_value_store_target: "container") do
63
+ div(class: "key-value-pairs space-y-sm", data_key_value_store_target: "container") do
64
64
  pairs.each_with_index do |(key, value), index|
65
65
  render_key_value_pair(key, value, index)
66
66
  end
@@ -69,7 +69,7 @@ module Plutonium
69
69
 
70
70
  def render_key_value_pair(key, value, index)
71
71
  div(
72
- class: "key-value-pair flex items-center gap-2 p-2 border border-gray-200 dark:border-gray-700 rounded",
72
+ class: "key-value-pair flex items-center gap-sm p-sm border border-gray-200 dark:border-gray-700 rounded",
73
73
  data_key_value_store_target: "pair"
74
74
  ) do
75
75
  # Key input
@@ -79,7 +79,7 @@ module Plutonium
79
79
  value: key,
80
80
  name: "#{field_name}[#{index}][key]",
81
81
  id: "#{field.dom.id}_#{index}_key",
82
- class: "flex-1 px-3 py-1 text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
82
+ class: "flex-1 px-sm py-xs text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
83
83
  data_key_value_store_target: "keyInput"
84
84
  )
85
85
 
@@ -90,14 +90,14 @@ module Plutonium
90
90
  value: value,
91
91
  name: "#{field_name}[#{index}][value]",
92
92
  id: "#{field.dom.id}_#{index}_value",
93
- class: "flex-1 px-3 py-1 text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
93
+ class: "flex-1 px-sm py-xs text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
94
94
  data_key_value_store_target: "valueInput"
95
95
  )
96
96
 
97
97
  # Remove button
98
98
  button(
99
99
  type: :button,
100
- class: "px-2 py-1 text-red-600 hover:text-red-800 focus:outline-none",
100
+ class: "px-sm py-xs text-red-600 hover:text-red-800 focus:outline-none",
101
101
  data_action: "key-value-store#removePair"
102
102
  ) do
103
103
  plain "×"
@@ -106,11 +106,11 @@ module Plutonium
106
106
  end
107
107
 
108
108
  def render_add_button
109
- div(class: "key-value-store-actions mt-2") do
109
+ div(class: "key-value-store-actions mt-sm") do
110
110
  button(
111
111
  type: :button,
112
112
  id: "#{field.dom.id}_add_button",
113
- class: "inline-flex items-center px-3 py-1 text-sm font-medium text-blue-600 bg-blue-50 border border-blue-200 rounded hover:bg-blue-100 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-blue-900 dark:text-blue-300 dark:border-blue-700 dark:hover:bg-blue-800",
113
+ class: "inline-flex items-center px-sm py-xs text-sm font-medium text-blue-600 bg-blue-50 border border-blue-200 rounded hover:bg-blue-100 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-blue-900 dark:text-blue-300 dark:border-blue-700 dark:hover:bg-blue-800",
114
114
  data: {
115
115
  action: "key-value-store#addPair",
116
116
  key_value_store_target: "addButton"
@@ -124,7 +124,7 @@ module Plutonium
124
124
  def render_template
125
125
  template(data_key_value_store_target: "template") do
126
126
  div(
127
- class: "key-value-pair flex items-center gap-2 p-2 border border-gray-200 dark:border-gray-700 rounded",
127
+ class: "key-value-pair flex items-center gap-sm p-sm border border-gray-200 dark:border-gray-700 rounded",
128
128
  data_key_value_store_target: "pair"
129
129
  ) do
130
130
  input(
@@ -132,7 +132,7 @@ module Plutonium
132
132
  placeholder: "Key",
133
133
  name: "#{field_name}[__INDEX__][key]",
134
134
  id: "#{field.dom.id}___INDEX___key",
135
- class: "flex-1 px-3 py-1 text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
135
+ class: "flex-1 px-sm py-xs text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
136
136
  data_key_value_store_target: "keyInput"
137
137
  )
138
138
 
@@ -141,13 +141,13 @@ module Plutonium
141
141
  placeholder: "Value",
142
142
  name: "#{field_name}[__INDEX__][value]",
143
143
  id: "#{field.dom.id}___INDEX___value",
144
- class: "flex-1 px-3 py-1 text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
144
+ class: "flex-1 px-sm py-xs text-sm border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
145
145
  data_key_value_store_target: "valueInput"
146
146
  )
147
147
 
148
148
  button(
149
149
  type: :button,
150
- class: "px-2 py-1 text-red-600 hover:text-red-800 focus:outline-none",
150
+ class: "px-sm py-xs text-red-600 hover:text-red-800 focus:outline-none",
151
151
  data_action: "key-value-store#removePair"
152
152
  ) do
153
153
  plain "×"
@@ -8,7 +8,7 @@ module Plutonium
8
8
  include Plutonium::UI::Component::Methods
9
9
 
10
10
  def view_template
11
- div(class: "flex space-x-1") do
11
+ div(class: "flex space-x-xs") do
12
12
  super
13
13
  render_add_button
14
14
  end
@@ -24,7 +24,7 @@ module Plutonium
24
24
  a(
25
25
  href: add_url,
26
26
  class:
27
- "bg-gray-100 dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-500 hover:bg-gray-200 border border-gray-300 rounded-lg p-3 focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none dark:text-white"
27
+ "bg-gray-100 dark:bg-gray-600 dark:hover:bg-gray-700 dark:border-gray-500 hover:bg-gray-200 border border-gray-300 rounded-sm p-sm focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none dark:text-white"
28
28
  ) do
29
29
  render Phlex::TablerIcons::Plus.new(class: "w-3 h-3")
30
30
  end
@@ -8,7 +8,7 @@ module Plutonium
8
8
  include Phlexi::Form::Components::Concerns::UploadsFile
9
9
 
10
10
  def view_template
11
- div(class: tokens(field.dom.id, "flex flex-col-reverse gap-2")) do
11
+ div(class: tokens(field.dom.id, "flex flex-col-reverse gap-sm")) do
12
12
  div do
13
13
  # Hidden field for ensuring removal of esp. has_one_attached attachments
14
14
  input(type: :hidden, name: attributes[:name], multiple: attributes[:multiple], value: nil, autocomplete: "off", hidden: true)
@@ -16,7 +16,7 @@ module Plutonium
16
16
  next if field.value.nil?
17
17
 
18
18
  div(
19
- class: "attachment-preview-container grid grid-cols-[repeat(auto-fill,minmax(0,180px))] gap-4",
19
+ class: "attachment-preview-container grid grid-cols-[repeat(auto-fill,minmax(0,180px))] gap-md",
20
20
  data_controller: "attachment-preview-container"
21
21
  ) do
22
22
  render_existing_attachments
@@ -67,7 +67,7 @@ module Plutonium
67
67
  end
68
68
 
69
69
  div(
70
- class: "attachment-preview group relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm hover:shadow-md transition-all duration-300",
70
+ class: "attachment-preview group relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-sm shadow-sm hover:shadow-md transition-all duration-300",
71
71
  data: {
72
72
  controller: "attachment-preview",
73
73
  attachment_preview_mime_type_value: attachment.content_type,
@@ -109,7 +109,7 @@ module Plutonium
109
109
 
110
110
  def render_filename(attachment)
111
111
  div(
112
- class: "px-2 py-1.5 text-sm text-gray-700 dark:text-gray-300 border-t border-gray-200 dark:border-gray-700 truncate text-center bg-white dark:bg-gray-800",
112
+ class: "px-sm py-xs.5 text-sm text-gray-700 dark:text-gray-300 border-t border-gray-200 dark:border-gray-700 truncate text-center bg-white dark:bg-gray-800",
113
113
  title: attachment.filename
114
114
  ) do
115
115
  plain attachment.filename.to_s
@@ -119,7 +119,7 @@ module Plutonium
119
119
  def render_delete_button
120
120
  button(
121
121
  type: "button",
122
- class: "w-full py-2 px-4 text-sm text-red-600 dark:text-red-400 bg-white dark:bg-gray-800 hover:bg-red-50 dark:hover:bg-red-900/50 rounded-b-lg transition-colors duration-200 flex items-center justify-center gap-2 border-t border-gray-200 dark:border-gray-700",
122
+ class: "w-full py-sm px-md text-sm text-red-600 dark:text-red-400 bg-white dark:bg-gray-800 hover:bg-red-50 dark:hover:bg-red-900/50 rounded-b-lg transition-colors duration-200 flex items-center justify-center gap-sm border-t border-gray-200 dark:border-gray-700",
123
123
  data: {action: "click->attachment-preview#remove"}
124
124
  ) do
125
125
  span(class: "bi bi-trash")
@@ -132,7 +132,7 @@ module Plutonium
132
132
 
133
133
  def render_nested_field_container(context, &)
134
134
  div(
135
- class: "col-span-full space-y-2 my-4",
135
+ class: "col-span-full space-y-sm my-md",
136
136
  data: {
137
137
  controller: "nested-resource-form-fields",
138
138
  nested_resource_form_fields_limit_value: context.options[:limit]
@@ -193,7 +193,7 @@ module Plutonium
193
193
  def render_nested_fields_fieldset(nested, context)
194
194
  fieldset(
195
195
  data_new_record: !nested.object&.persisted?,
196
- class: "nested-resource-form-fields border border-gray-200 dark:border-gray-700 rounded-lg p-4 space-y-4 relative"
196
+ class: "nested-resource-form-fields border border-gray-200 dark:border-gray-700 rounded-sm p-md space-y-md relative"
197
197
  ) do
198
198
  render_nested_fields_fieldset_content(nested, context)
199
199
  render_nested_fields_delete_button(nested, context.options)
@@ -201,7 +201,7 @@ module Plutonium
201
201
  end
202
202
 
203
203
  def render_nested_fields_fieldset_content(nested, context)
204
- div(class: "grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4 gap-4 grid-flow-row-dense") do
204
+ div(class: "grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4 gap-md grid-flow-row-dense") do
205
205
  render_nested_fields_hidden_fields(nested, context)
206
206
  render_nested_fields_visible_fields(nested, context)
207
207
  end
@@ -259,8 +259,8 @@ module Plutonium
259
259
  end
260
260
 
261
261
  def render_nested_fields_add_button_content(name)
262
- span(class: "bg-secondary-700 text-white hover:bg-secondary-800 focus:ring-secondary-300 dark:bg-secondary-600 dark:hover:bg-secondary-700 dark:focus:ring-secondary-800 flex items-center justify-center px-4 py-1.5 text-sm font-medium rounded-lg focus:outline-none focus:ring-4") do
263
- render Phlex::TablerIcons::Plus.new(class: "w-4 h-4 mr-1")
262
+ span(class: "bg-secondary-700 text-white hover:bg-secondary-800 focus:ring-secondary-300 dark:bg-secondary-600 dark:hover:bg-secondary-700 dark:focus:ring-secondary-800 flex items-center justify-center px-md py-xs.5 text-sm font-medium rounded-sm focus:outline-none focus:ring-4") do
263
+ render Phlex::TablerIcons::Plus.new(class: "w-4 h-4 mr-xs")
264
264
  span { "Add #{name.to_s.singularize.humanize}" }
265
265
  end
266
266
  end
@@ -11,7 +11,7 @@ module Plutonium
11
11
  options[:method] = :get
12
12
  attributes = mix(attributes.deep_merge(
13
13
  id: :search_form,
14
- class!: "space-y-2 mb-4",
14
+ class!: "space-y-sm mb-md",
15
15
  controller: "form",
16
16
  data: {controller: "form", turbo_frame: nil}
17
17
  ))
@@ -67,7 +67,7 @@ module Plutonium
67
67
 
68
68
  search_query = query_object.search_query
69
69
  div(class: "relative") do
70
- div(class: "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none") do
70
+ div(class: "absolute inset-y-0 left-0 flex items-center pl-sm pointer-events-none") do
71
71
  svg(
72
72
  class: "w-5 h-5 text-gray-500 dark:text-gray-400",
73
73
  aria_hidden: "true",
@@ -87,7 +87,7 @@ module Plutonium
87
87
  .placeholder("Search...")
88
88
  .input_tag(
89
89
  value: search_query,
90
- class: "block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
90
+ class: "block w-full p-sm pl-10 text-sm text-gray-900 border border-gray-300 rounded-sm bg-page focus:ring-primary-500 focus:border-primary-500 dark:bg-elevated-dark dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
91
91
  data: {
92
92
  action: "form#submit",
93
93
  turbo_permanent: true
@@ -99,10 +99,10 @@ module Plutonium
99
99
  def render_filter_fields
100
100
  return if query_object.filter_definitions.blank?
101
101
 
102
- div(class: "flex flex-wrap items-center gap-4") do
102
+ div(class: "flex flex-wrap items-center gap-md") do
103
103
  span(class: "text-sm font-medium text-gray-900 dark:text-white") { "Filters:" }
104
- div(class: "flex flex-wrap items-center gap-4 mr-auto") do
105
- div class: "flex flex-wrap items-center gap-4" do
104
+ div(class: "flex flex-wrap items-center gap-md mr-auto") do
105
+ div class: "flex flex-wrap items-center gap-md" do
106
106
  query_object.filter_definitions.each do |filter_name, definition|
107
107
  nest_one filter_name do |nested|
108
108
  definition.defined_inputs.each do |input_name, _|
@@ -112,22 +112,22 @@ module Plutonium
112
112
  end
113
113
  end
114
114
  end
115
- div(class: "flex flex-wrap items-center gap-2") do
115
+ div(class: "flex flex-wrap items-center gap-sm") do
116
116
  actions_wrapper do
117
117
  render field(:submit).submit_button_tag(
118
118
  name: nil,
119
- class!: "inline-flex items-center text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
119
+ class!: "inline-flex items-center text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-sm text-sm px-md py-sm dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
120
120
  ) do
121
- render Phlex::TablerIcons::Filter.new(class: "w-4 h-4 mr-2")
121
+ render Phlex::TablerIcons::Filter.new(class: "w-4 h-4 mr-sm")
122
122
  plain "Apply Filters"
123
123
  end
124
124
 
125
125
  render field(:reset).submit_button_tag(
126
126
  name: nil,
127
127
  type: :reset,
128
- class!: "inline-flex items-center text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-4 py-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700"
128
+ class!: "inline-flex items-center text-gray-900 bg-surface border border-gray-300 focus:outline-none hover:bg-interactive focus:ring-4 focus:ring-gray-200 font-medium rounded-sm text-sm px-md py-sm dark:bg-surface-dark dark:text-white dark:border-gray-600 dark:hover:bg-interactive-dark dark:hover:border-gray-600 dark:focus:ring-gray-700"
129
129
  ) do
130
- render Phlex::TablerIcons::X.new(class: "w-4 h-4 mr-2")
130
+ render Phlex::TablerIcons::X.new(class: "w-4 h-4 mr-sm")
131
131
  plain "Clear Filters"
132
132
  end
133
133
  end
@@ -41,14 +41,14 @@ module Plutonium
41
41
  type: :submit,
42
42
  name: "return_to",
43
43
  value: request.url,
44
- class: "px-4 py-2 bg-secondary-600 text-white rounded-md hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-secondary-500"
44
+ class: tokens(theme_class(:form, element: :button_secondary), "px-md py-sm bg-secondary-600 text-white rounded hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-secondary-500")
45
45
  ) { "Create and add another" }
46
46
  else
47
47
  button(
48
48
  type: :submit,
49
49
  name: "return_to",
50
50
  value: request.url,
51
- class: "px-4 py-2 bg-secondary-600 text-white rounded-md hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-secondary-500"
51
+ class: tokens(theme_class(:form, element: :button_secondary), "px-md py-sm bg-secondary-600 text-white rounded hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-secondary-500")
52
52
  ) { "Update and continue editing" }
53
53
  end
54
54
  end
@@ -6,43 +6,43 @@ module Plutonium
6
6
  class Theme < Phlexi::Form::Theme
7
7
  def self.theme
8
8
  super.merge({
9
- base: "relative bg-white dark:bg-gray-800 shadow-md sm:rounded-lg my-3 p-6 space-y-6",
10
- fields_wrapper: "grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4 gap-4 grid-flow-row-dense",
11
- actions_wrapper: "flex justify-end space-x-2",
12
- wrapper: nil,
13
- inner_wrapper: "w-full",
9
+ base: "pu-form relative bg-surface dark:bg-surface-dark shadow-md sm:rounded-sm my-sm p-lg space-y-lg",
10
+ fields_wrapper: "pu-form-fields grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4 gap-md grid-flow-row-dense",
11
+ actions_wrapper: "pu-form-actions flex justify-end space-x-sm",
12
+ wrapper: "pu-form-field",
13
+ inner_wrapper: "pu-form-field-inner w-full",
14
14
  # errors
15
- form_errors_wrapper: "flex p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400",
16
- form_errors_message: "font-medium",
17
- form_errors_list: "mt-1.5 list-disc list-inside",
15
+ form_errors_wrapper: "pu-form-errors flex p-md mb-md text-sm text-red-800 rounded-sm bg-red-50 dark:bg-surface-dark dark:text-red-400",
16
+ form_errors_message: "pu-form-errors-message font-medium",
17
+ form_errors_list: "pu-form-errors-list mt-xs.5 list-disc list-inside",
18
18
  # label themes
19
- label: "mt-2 block mb-2 text-base font-bold",
19
+ label: "pu-form-label mt-sm block mb-sm text-base font-bold",
20
20
  invalid_label: "text-red-700 dark:text-red-500",
21
21
  valid_label: "text-green-700 dark:text-green-500",
22
22
  neutral_label: "text-gray-500 dark:text-gray-400",
23
23
  # input themes
24
- input: "w-full p-2 border rounded-md shadow-sm font-medium text-sm dark:bg-gray-700 focus:ring-2",
24
+ input: "pu-form-input w-full p-sm border rounded shadow-sm font-medium text-sm dark:bg-elevated-dark focus:ring-2",
25
25
  invalid_input: "bg-red-50 border-red-500 dark:border-red-500 text-red-900 dark:text-red-500 placeholder-red-700 dark:placeholder-red-500 focus:ring-red-500 focus:border-red-500",
26
26
  valid_input: "bg-green-50 border-green-500 dark:border-green-500 text-green-900 dark:text-green-400 placeholder-green-700 dark:placeholder-green-500 focus:ring-green-500 focus:border-green-500",
27
27
  neutral_input: "border-gray-300 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white focus:ring-primary-500 focus:border-primary-500",
28
28
  # checkbox
29
- checkbox: "p-2 border rounded-md shadow-sm font-medium text-sm dark:bg-gray-700",
29
+ checkbox: "pu-form-checkbox p-sm border rounded shadow-sm font-medium text-sm dark:bg-elevated-dark",
30
30
  # radio buttons
31
- radio_button: "p-2 border shadow-sm font-medium text-sm dark:bg-gray-700",
31
+ radio_button: "pu-form-radio p-sm border shadow-sm font-medium text-sm dark:bg-elevated-dark",
32
32
  # color
33
33
  color: "pu-color-input appearance-none bg-transparent border-none cursor-pointer w-10 h-10",
34
34
  invalid_color: nil,
35
35
  valid_color: nil,
36
36
  neutral_color: nil,
37
37
  # file
38
- # file: "w-full border rounded-md shadow-sm font-medium text-sm dark:bg-gray-700 focus:outline-none",
39
- file: "w-full border rounded-md shadow-sm font-medium text-sm dark:bg-gray-700 border-gray-300 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white focus:ring-primary-500 focus:border-primary-500 focus:outline-none focus:ring-2 [&::file-selector-button]:mr-3 [&::file-selector-button]:px-4 [&::file-selector-button]:py-2 [&::file-selector-button]:bg-gray-50 [&::file-selector-button]:border-0 [&::file-selector-button]:rounded-l-md [&::file-selector-button]:text-sm [&::file-selector-button]:font-medium [&::file-selector-button]:text-gray-700 [&::file-selector-button]:hover:bg-gray-100 [&::file-selector-button]:cursor-pointer dark:[&::file-selector-button]:bg-gray-600 dark:[&::file-selector-button]:text-gray-200 dark:[&::file-selector-button]:hover:bg-gray-500",
38
+ # file: "w-full border rounded shadow-sm font-medium text-sm dark:bg-elevated-dark focus:outline-none",
39
+ file: "pu-form-file w-full border rounded shadow-sm font-medium text-sm dark:bg-elevated-dark border-gray-300 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white focus:ring-primary-500 focus:border-primary-500 focus:outline-none focus:ring-2 [&::file-selector-button]:mr-sm [&::file-selector-button]:px-md [&::file-selector-button]:py-sm [&::file-selector-button]:bg-page [&::file-selector-button]:border-0 [&::file-selector-button]:rounded-l-md [&::file-selector-button]:text-sm [&::file-selector-button]:font-medium [&::file-selector-button]:text-gray-700 [&::file-selector-button]:hover:bg-interactive [&::file-selector-button]:cursor-pointer dark:[&::file-selector-button]:bg-gray-600 dark:[&::file-selector-button]:text-gray-200 dark:[&::file-selector-button]:hover:bg-gray-500",
40
40
  # hint themes
41
- hint: "mt-2 text-sm text-gray-500 dark:text-gray-200 whitespace-pre",
41
+ hint: "pu-form-hint mt-sm text-sm text-gray-500 dark:text-gray-200 whitespace-pre",
42
42
  # error themes
43
- error: "mt-2 text-sm text-red-600 dark:text-red-500",
43
+ error: "pu-form-error mt-sm text-sm text-red-600 dark:text-red-500",
44
44
  # button themes
45
- button: "px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500",
45
+ button: "pu-form-button px-md py-sm bg-primary-600 text-white rounded hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500",
46
46
  # flatpickr
47
47
  flatpickr: :input,
48
48
  valid_flatpickr: :valid_input,
@@ -26,9 +26,9 @@ module Plutonium
26
26
 
27
27
  def html_attributes = {lang:, data_controller: "color-mode"}
28
28
 
29
- def body_attributes = {class: "antialiased min-h-screen bg-gray-50 dark:bg-gray-900"}
29
+ def body_attributes = {class: tokens(theme_class(:layout, element: :body), "antialiased min-h-screen bg-page dark:bg-page-dark")}
30
30
 
31
- def main_attributes = {class: "p-4 min-h-screen"}
31
+ def main_attributes = {class: tokens(theme_class(:layout, element: :main), "p-md min-h-screen")}
32
32
 
33
33
  def render_head
34
34
  head {
@@ -41,7 +41,7 @@ module Plutonium
41
41
  # @return [void]
42
42
  def view_template
43
43
  nav(
44
- class: "bg-white border-b border-gray-200 px-4 py-2.5 dark:bg-gray-800 dark:border-gray-700 fixed left-0 right-0 top-0 z-50",
44
+ class: tokens(theme_class(:header), "bg-surface border-b border-gray-200 px-md py-sm dark:bg-surface-dark dark:border-gray-700 fixed left-0 right-0 top-0 z-50"),
45
45
  data: {
46
46
  controller: "resource-header",
47
47
  resource_header_sidebar_outlet: "#sidebar-navigation"
@@ -59,7 +59,7 @@ module Plutonium
59
59
  # Renders the color mode toggle controls
60
60
  # @private
61
61
  def render_color_mode_controls
62
- div(class: "bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700") do
62
+ div(class: "bg-surface dark:bg-surface-dark border-gray-200 dark:border-gray-700") do
63
63
  render ColorModeSelector.new
64
64
  end
65
65
  end
@@ -80,10 +80,13 @@ module Plutonium
80
80
  button(
81
81
  data_action: "resource-header#toggleDrawer",
82
82
  aria_controls: "#sidebar-navigation",
83
- class: %(p-2 mr-2 text-gray-600 rounded-lg cursor-pointer lg:hidden hover:text-gray-900
84
- hover:bg-gray-100 focus:bg-gray-100 dark:focus:bg-gray-700 focus:ring-2
83
+ class: tokens(
84
+ theme_class(:header, element: :sidebar_toggle),
85
+ %(p-2 mr-sm text-gray-600 rounded-sm cursor-pointer lg:hidden hover:text-gray-900
86
+ hover:bg-interactive focus:bg-interactive dark:focus:bg-interactive-dark focus:ring-2
85
87
  focus:ring-gray-100 dark:focus:ring-gray-700 dark:text-gray-200
86
- dark:hover:bg-gray-700 dark:hover:text-white)
88
+ dark:hover:bg-interactive-dark dark:hover:text-white)
89
+ )
87
90
  ) do
88
91
  render_toggle_icons
89
92
  end
@@ -92,7 +95,7 @@ module Plutonium
92
95
  # Renders the brand section with logo and/or name
93
96
  # @private
94
97
  def render_brand
95
- a(href: root_path, class: "flex items-center space-x-2 md:min-w-60") do
98
+ a(href: root_path, class: "flex items-center space-x-sm md:min-w-60") do
96
99
  render brand_logo_slot if brand_logo_slot?
97
100
  if brand_name_slot?
98
101
  span(class: "self-center text-2xl font-semibold whitespace-nowrap dark:text-white hidden xs:block") do
@@ -119,7 +122,7 @@ module Plutonium
119
122
  # Renders the action buttons section
120
123
  # @private
121
124
  def render_actions
122
- div(class: "flex items-center space-x-2") do
125
+ div(class: "flex items-center space-x-sm") do
123
126
  render_color_mode_controls
124
127
 
125
128
  div(class: "flex items-center lg:order-2") do
@@ -11,14 +11,14 @@ module Plutonium
11
11
  end
12
12
 
13
13
  def main_attributes = mix(super, {
14
- class: "flex flex-col items-center justify-center gap-2 px-6 py-8 mx-auto lg:py-0"
14
+ class: "flex flex-col items-center justify-center gap-sm px-lg py-xl mx-auto lg:py-0"
15
15
  })
16
16
 
17
17
  def render_content(&)
18
18
  render_logo
19
19
 
20
- div(class: "w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700") {
21
- div(class: "p-6 space-y-4 md:space-y-6 sm:p-8", &)
20
+ div(class: "w-full bg-surface rounded-sm shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-surface-dark dark:border-gray-700") {
21
+ div(class: "p-lg space-y-md md:space-y-lg sm:p-xl", &)
22
22
  }
23
23
 
24
24
  render_links
@@ -26,12 +26,12 @@ module Plutonium
26
26
 
27
27
  def render_logo
28
28
  link_to root_path, class: "flex items-center text-2xl font-semibold text-gray-900 dark:text-white mb-2" do
29
- helpers.resource_logo_tag classname: "w-24 h-24 mr-2 rounded-md"
29
+ helpers.resource_logo_tag classname: "w-24 h-24 mr-sm rounded"
30
30
  end
31
31
  end
32
32
 
33
33
  def render_links
34
- div(class: "mt-4 flex items-center font-medium text-secondary-600 dark:text-secondary-400 hover:underline") {
34
+ div(class: "mt-md flex items-center font-medium text-secondary-600 dark:text-secondary-400 hover:underline") {
35
35
  render Phlex::TablerIcons::Home2.new
36
36
  link_to "Home", root_path, class: "font-medium text-secondary-600 dark:text-secondary-400"
37
37
  }
@@ -26,7 +26,7 @@ module Plutonium
26
26
  data: {controller: "sidebar"},
27
27
  id: "sidebar-navigation",
28
28
  aria: {label: "Sidebar Navigation"},
29
- class: "fixed top-0 left-0 z-40 w-64 h-screen pt-14 transition-transform -translate-x-full lg:translate-x-0",
29
+ class: tokens(theme_class(:sidebar, element: :container), "fixed top-0 left-0 z-40 w-64 h-screen pt-14 transition-transform -translate-x-full lg:translate-x-0"),
30
30
  &
31
31
  )
32
32
  end
@@ -36,7 +36,7 @@ module Plutonium
36
36
  div(
37
37
  id: "sidebar-navigation-content",
38
38
  data: {turbo_permanent: true},
39
- class: "overflow-y-auto py-5 px-3 h-full bg-white border-r border-gray-200 dark:bg-gray-800 dark:border-gray-700",
39
+ class: tokens(theme_class(:sidebar, element: :content), "overflow-y-auto py-md px-sm h-full bg-surface border-r border-gray-200 dark:bg-surface-dark dark:border-gray-700"),
40
40
  &
41
41
  )
42
42
  end
@@ -32,7 +32,7 @@ module Plutonium
32
32
 
33
33
  def view_template
34
34
  a(
35
- class: "block p-4 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-600 group",
35
+ class: tokens(theme_class(:nav, variant: :grid, element: :item), "block p-md rounded-sm hover:bg-interactive dark:hover:bg-interactive-dark group"),
36
36
  href: @href
37
37
  ) do
38
38
  render @icon.new(
@@ -55,7 +55,7 @@ module Plutonium
55
55
  end
56
56
 
57
57
  def view_template
58
- div(data: {controller: "resource-drop-down"}) do
58
+ div(class: theme_class(:nav, variant: :grid), data: {controller: "resource-drop-down"}) do
59
59
  render_trigger_button
60
60
  render_dropdown_menu
61
61
  end
@@ -67,7 +67,7 @@ module Plutonium
67
67
  button(
68
68
  type: "button",
69
69
  data: {resource_drop_down_target: "trigger"},
70
- class: "p-2 text-gray-500 rounded-lg hover:text-gray-900 hover:bg-gray-100 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-700 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
70
+ class: tokens(theme_class(:nav, variant: :grid, element: :trigger), "p-2 text-gray-500 rounded-sm hover:text-gray-900 hover:bg-interactive dark:text-gray-200 dark:hover:text-white dark:hover:bg-interactive-dark focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600")
71
71
  ) do
72
72
  span(class: "sr-only") { "View #{@label}" }
73
73
  render @icon.new(class: "w-6 h-6")
@@ -76,14 +76,14 @@ module Plutonium
76
76
 
77
77
  def render_dropdown_menu
78
78
  div(
79
- class: "hidden overflow-hidden z-50 my-4 max-w-sm text-base list-none bg-white divide-y divide-gray-100 shadow-lg dark:bg-gray-700 dark:divide-gray-600 rounded-xl",
79
+ class: tokens(theme_class(:nav, variant: :grid, element: :dropdown), "hidden overflow-hidden z-50 my-md max-w-sm text-base list-none bg-surface divide-y divide-gray-100 shadow-lg dark:bg-elevated-dark dark:divide-gray-600 rounded"),
80
80
  data: {resource_drop_down_target: "menu"}
81
81
  ) do
82
82
  div(
83
- class: "block py-2 px-4 text-base font-medium text-center text-gray-700 bg-gray-50 dark:bg-gray-600 dark:text-gray-300"
83
+ class: "block py-sm px-md text-base font-medium text-center text-gray-700 bg-page dark:bg-gray-600 dark:text-gray-300"
84
84
  ) { @label }
85
85
 
86
- div(class: "grid grid-cols-3 gap-4 p-4") do
86
+ div(class: "grid grid-cols-3 gap-md p-md") do
87
87
  item_slots.each { |item| render item }
88
88
  end
89
89
  end
@@ -18,7 +18,8 @@ module Plutonium
18
18
  def view_template
19
19
  a(
20
20
  class: tokens(
21
- "flex justify-between items-center py-2 px-4 text-sm hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white",
21
+ theme_class(:nav_user, element: :link),
22
+ "flex justify-between items-center py-sm px-md text-sm hover:bg-interactive dark:hover:bg-interactive-dark dark:hover:text-white",
22
23
  @attributes.delete(:class)
23
24
  ),
24
25
  href: @href,
@@ -40,7 +41,7 @@ module Plutonium
40
41
 
41
42
  def view_template
42
43
  ul(
43
- class: "text-gray-700 dark:text-gray-300",
44
+ class: tokens(theme_class(:nav_user, element: :section), "text-gray-700 dark:text-gray-300"),
44
45
  aria: {labelledby: "user-nav-dropdown-toggle"}
45
46
  ) do
46
47
  link_slots.each do |link|
@@ -59,7 +60,7 @@ module Plutonium
59
60
  end
60
61
 
61
62
  def view_template
62
- div(data: {controller: "resource-drop-down"}) do
63
+ div(class: theme_class(:nav_user), data: {controller: "resource-drop-down"}) do
63
64
  render_trigger_button
64
65
  render_dropdown_menu
65
66
  end
@@ -78,7 +79,7 @@ module Plutonium
78
79
  def render_avatar_button
79
80
  button(
80
81
  type: "button",
81
- class: "flex mx-3 text-sm bg-gray-800 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600",
82
+ class: tokens(theme_class(:nav_user, element: :button), "flex mx-sm text-sm bg-gray-800 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"),
82
83
  aria: {expanded: "false"},
83
84
  id: "user-nav-dropdown-toggle",
84
85
  data: {resource_drop_down_target: "trigger"}
@@ -91,7 +92,7 @@ module Plutonium
91
92
  def render_default_button
92
93
  button(
93
94
  type: "button",
94
- class: "flex mx-3 text-sm border border-gray-600 text-gray-500 hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-700 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600",
95
+ class: tokens(theme_class(:nav_user, element: :button), "flex mx-sm text-sm border border-gray-600 text-gray-500 hover:text-gray-900 hover:bg-interactive dark:text-gray-400 dark:hover:text-white dark:hover:bg-interactive-dark rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"),
95
96
  aria: {expanded: "false"},
96
97
  id: "user-nav-dropdown-toggle",
97
98
  data: {resource_drop_down_target: "trigger"}
@@ -103,10 +104,10 @@ module Plutonium
103
104
 
104
105
  def render_dropdown_menu
105
106
  div(
106
- class: "hidden z-50 my-4 w-56 text-base list-none bg-white divide-y divide-gray-100 shadow dark:bg-gray-700 dark:divide-gray-600 rounded-xl",
107
+ class: tokens(theme_class(:nav_user, element: :menu), "hidden z-50 my-md w-56 text-base list-none bg-surface divide-y divide-gray-100 shadow dark:bg-elevated-dark dark:divide-gray-600 rounded"),
107
108
  data: {resource_drop_down_target: "menu"}
108
109
  ) do
109
- div(class: "py-3 px-4") do
110
+ div(class: "py-sm px-md") do
110
111
  if @name.present?
111
112
  span(class: "block text-sm font-semibold text-gray-900 dark:text-white") { @name }
112
113
  end