playbook_ui 15.1.0 → 15.2.0.pre.alpha.PLAY2428advancedtablerailscellpadding11387

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +7 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_background_control_rails.html.erb +113 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_background_control_rails.md +1 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.md +1 -1
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_rails.md +1 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_padding_control_per_row_rails.html.erb +51 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_padding_control_per_row_rails.md +1 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_padding_control_rails.html.erb +40 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_padding_control_rails.md +1 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling_rails.md +1 -1
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling_react.md +1 -1
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +3 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +2 -1
  15. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +44 -0
  16. data/app/pb_kits/playbook/pb_button/_button.scss +6 -0
  17. data/app/pb_kits/playbook/pb_button/docs/_button_loading.html.erb +7 -3
  18. data/app/pb_kits/playbook/pb_button/docs/_button_loading.jsx +29 -0
  19. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled.html.erb +31 -0
  20. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled.md +7 -0
  21. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled_helper.html.erb +21 -0
  22. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled_helper.md +7 -0
  23. data/app/pb_kits/playbook/pb_button/docs/example.yml +2 -0
  24. data/app/pb_kits/playbook/pb_button/index.js +99 -0
  25. data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +4 -0
  26. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.html.erb +16 -16
  27. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.jsx +2 -1
  28. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.html.erb +31 -31
  29. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.jsx +4 -3
  30. data/app/pb_kits/playbook/pb_draggable/_draggable.scss +8 -0
  31. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +105 -29
  32. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +12 -1
  33. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.tsx +2 -2
  34. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.scss +15 -21
  35. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.tsx +6 -5
  36. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.html.erb +2 -0
  37. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.rb +11 -3
  38. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.test.js +9 -8
  39. data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.scss +36 -9
  40. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +105 -22
  41. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +3 -0
  42. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +14 -6
  43. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.html.erb +8 -4
  44. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.jsx +5 -0
  45. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.md +1 -0
  46. data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +3 -1
  47. data/app/pb_kits/playbook/pb_text_input/text_input.rb +6 -0
  48. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +250 -233
  49. data/app/pb_kits/playbook/pb_timeline/_timeline.tsx +1 -1
  50. data/app/pb_kits/playbook/pb_timeline/timeline.test.js +2 -2
  51. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +10 -10
  52. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +39 -1
  53. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +2 -0
  54. data/app/pb_kits/playbook/utilities/_hover.scss +2 -2
  55. data/app/pb_kits/playbook/utilities/globalProps.ts +2 -2
  56. data/dist/chunks/{_line_graph-CW8Ygzyq.js → _line_graph-DY4PK6AH.js} +1 -1
  57. data/dist/chunks/_typeahead-fQDb_yVO.js +6 -0
  58. data/dist/chunks/{_weekday_stacked-3-FtXg76.js → _weekday_stacked-D_bGbWtk.js} +3 -3
  59. data/dist/chunks/{lib-izYrkvOQ.js → lib-QZuu1ltS.js} +2 -2
  60. data/dist/chunks/{pb_form_validation-Cah5Z5J3.js → pb_form_validation-CleM960_.js} +1 -1
  61. data/dist/chunks/vendor.js +1 -1
  62. data/dist/menu.yml +1 -1
  63. data/dist/playbook-doc.js +2 -2
  64. data/dist/playbook-rails-react-bindings.js +1 -1
  65. data/dist/playbook-rails.js +1 -1
  66. data/dist/playbook.css +1 -1
  67. data/lib/playbook/hover.rb +5 -1
  68. data/lib/playbook/pb_forms_helper.rb +7 -6
  69. data/lib/playbook/version.rb +2 -2
  70. metadata +19 -7
  71. data/dist/chunks/_typeahead-DUIMqJiu.js +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a9b97f8b1cfbe21c7f5950db6fb2a233b94de20e5f2dc2d5d41222f71bce0f3
4
- data.tar.gz: 825330d08fa7304d115fc3b6916855f9b04ff43e6cc6fc6839ea3dea2269e871
3
+ metadata.gz: 37409d35c89e4ef6225f10adb8eaca07531e78bfb205e5219d1f193162bf7422
4
+ data.tar.gz: 396f3d13c672cad83733a9c0100e8954aaae51d6f298b3507e173a919e1cac5d
5
5
  SHA512:
6
- metadata.gz: 83f8b4447c6cf013383fcfe5932a52d5a50865c4c27db488cd082d76f124a3c34ef542289de2f2fc0b5f36827c968cb1f693c99cefbdb3c543de35caed2ed5f6
7
- data.tar.gz: 03f0a987a4da2bbe382ea13c1fe18525d2a23f4ff637794218686aa57beed6b48c86c94565519df870b48165566c4c9635c319c263a568a6f8bae7ff92a77435
6
+ metadata.gz: dc694540cb052b950104c77578df15934f008005a08c2fd036795d0b5eb7ed21396537ddec6550750f70ac815da9c08e1d94007d724f5bb2e527bf6736139da8
7
+ data.tar.gz: b2c6e18dbb4e448b0d066dd2e7a0b3229eb8e1069ebfe45dcf809b02e6242f1f4c5133fe5458682985385b4bce222f3a2b303207f36cd86ff676e1decaac1dec
@@ -203,6 +203,13 @@ export function useTableState({
203
203
  onRowPinningChange({ top: allPinned });
204
204
  }, [table, pinnedRows?.value?.top?.join(',')]);
205
205
 
206
+ // Set pagination state when pagination is enabled
207
+ useEffect(() => {
208
+ if (pagination && paginationProps?.pageSize) {
209
+ table.setPageSize(paginationProps.pageSize);
210
+ }
211
+ }, [pagination, paginationProps?.pageSize, table]);
212
+
206
213
  // Check if table has any sub-rows
207
214
  const hasAnySubRows = table.getRowModel().rows.some(row => row.subRows && row.subRows.length > 0);
208
215
  const selectedRowsLength = Object.keys(table.getState().rowSelection).length;
@@ -0,0 +1,113 @@
1
+ <% column_definitions = [
2
+ {
3
+ accessor: "year",
4
+ label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
6
+ },
7
+ {
8
+ accessor: "newEnrollments",
9
+ label: "New Enrollments",
10
+ column_styling: {
11
+ cell_background_color: ->(row) { row[:newEnrollments].to_i > 20 ? "success_secondary" : "warning_secondary" }
12
+ }
13
+ },
14
+ {
15
+ accessor: "scheduledMeetings",
16
+ label: "Scheduled Meetings",
17
+ },
18
+ {
19
+ accessor: "attendanceRate",
20
+ label: "Attendance Rate",
21
+ },
22
+ {
23
+ accessor: "completedClasses",
24
+ label: "Completed Classes",
25
+ },
26
+ {
27
+ accessor: "classCompletionRate",
28
+ label: "Class Completion Rate",
29
+ },
30
+ {
31
+ accessor: "graduatedStudents",
32
+ label: "Graduated Students",
33
+ }
34
+ ] %>
35
+
36
+ <%= pb_rails("advanced_table", props: { id: "padding-control", table_data: @table_data, column_definitions: column_definitions }) do %>
37
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: column_definitions }) %>
38
+ <%= pb_rails("advanced_table/table_body", props: { table_data: @table_data, column_definitions: column_definitions }) %>
39
+ <% end %>
40
+
41
+ <% multi_header_column_definitions = [
42
+ {
43
+ accessor: "year",
44
+ label: "Year",
45
+ cellAccessors: ["quarter", "month", "day"],
46
+ },
47
+ {
48
+ label: "Enrollment Data",
49
+ columns: [
50
+ {
51
+ label: "Enrollment Stats",
52
+ columns: [
53
+ {
54
+ accessor: "newEnrollments",
55
+ label: "New Enrollments",
56
+ column_styling: {
57
+ cell_background_color: ->(row) { row[:newEnrollments].to_i > 20 ? "success_secondary" : "warning_secondary" }
58
+ }
59
+ },
60
+ {
61
+ accessor: "scheduledMeetings",
62
+ label: "Scheduled Meetings",
63
+ },
64
+ ],
65
+ },
66
+ ],
67
+ },
68
+ {
69
+ label: "Performance Data",
70
+ columns: [
71
+ {
72
+ label: "Completion Metrics",
73
+ columns: [
74
+ {
75
+ accessor: "completedClasses",
76
+ label: "Completed Classes",
77
+ column_styling: {
78
+ cell_background_color: ->(row) { row[:completedClasses].to_i > 15 ? "info_secondary" : "neutral_secondary" }
79
+ }
80
+ },
81
+ {
82
+ accessor: "classCompletionRate",
83
+ label: "Class Completion Rate",
84
+ column_styling: {
85
+ cell_background_color: ->(row) { row[:completedClasses].to_i > 15 ? "neutral_secondary" : "info_secondary" }
86
+ }
87
+ },
88
+ ],
89
+ },
90
+ {
91
+ label: "Attendance",
92
+ columns: [
93
+ {
94
+ accessor: "attendanceRate",
95
+ label: "Attendance Rate",
96
+ },
97
+ {
98
+ accessor: "graduatedStudents",
99
+ label: "Graduated Students",
100
+ column_styling: {
101
+ cell_background_color: ->(row) { row[:graduatedStudents].to_i > 10 ? "primary_secondary" : "error_secondary" }
102
+ }
103
+ },
104
+ ],
105
+ },
106
+ ],
107
+ },
108
+ ] %>
109
+
110
+ <%= pb_rails("advanced_table", props: { id: "padding-control-multi-header", table_data: @table_data, column_definitions: multi_header_column_definitions, padding_top: "lg" }) do %>
111
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: multi_header_column_definitions }) %>
112
+ <%= pb_rails("advanced_table/table_body", props: { table_data: @table_data, column_definitions: multi_header_column_definitions }) %>
113
+ <% end %>
@@ -0,0 +1 @@
1
+ `column_styling` can also be used to control the background color on all cells in a given column via the use of the `cell_background_color` key/value pair. Use `cell_background_color` to achieve custom background colors for individual cells as seen here.
@@ -1,4 +1,4 @@
1
- The `columnStyling` prop is an optional item that can be used within `columnDefinitions` as shown in the code snippet below. It is an object that has 2 optional key/value pairs:
1
+ The `columnStyling` prop is an optional item that can be used within `columnDefinitions` as shown in the code snippet below. It is an object that has several optional key/value pairs, this doc example highlights the following:
2
2
 
3
3
  1) `headerAlignment`: This will allow you to control alignment of header content which is set to right aligned by default. you can set this to `left`, `right` or `center`.
4
4
 
@@ -1,4 +1,4 @@
1
- The `column_styling` prop is an optional item that can be used within `column_definitions` as shown in the code snippet below. It is an object that has 2 optional key/value pairs:
1
+ The `column_styling` prop is an optional item that can be used within `column_definitions` as shown in the code snippet below. It is an object that has several optional key/value pairs, this doc example highlights the following:
2
2
 
3
3
  1) `header_alignment`: This will allow you to control alignment of header content which is set to right aligned by default. you can set this to `left`, `right` or `center`.
4
4
 
@@ -0,0 +1,51 @@
1
+ <% column_definitions = [
2
+ {
3
+ accessor: "year",
4
+ label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
6
+ },
7
+ {
8
+ accessor: "newEnrollments",
9
+ label: "New Enrollments",
10
+ },
11
+ {
12
+ accessor: "scheduledMeetings",
13
+ label: "Scheduled Meetings",
14
+ },
15
+ {
16
+ accessor: "attendanceRate",
17
+ label: "Attendance Rate",
18
+ },
19
+ {
20
+ accessor: "completedClasses",
21
+ label: "Completed Classes",
22
+ },
23
+ {
24
+ accessor: "classCompletionRate",
25
+ label: "Class Completion Rate",
26
+ },
27
+ {
28
+ accessor: "graduatedStudents",
29
+ label: "Graduated Students",
30
+ }
31
+ ] %>
32
+
33
+ <% row_styling = [
34
+ {
35
+ row_id: "1",
36
+ cell_padding: "md"
37
+ },
38
+ {
39
+ row_id: "3",
40
+ cell_padding: "lg"
41
+ },
42
+ {
43
+ row_id: "5",
44
+ cell_padding: "none"
45
+ },
46
+ ] %>
47
+
48
+ <%= pb_rails("advanced_table", props: { id: "padding-control-per-row", table_data: @table_data_with_id, column_definitions: column_definitions, row_styling: row_styling }) do %>
49
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: column_definitions }) %>
50
+ <%= pb_rails("advanced_table/table_body", props: { table_data: @table_data_with_id, column_definitions: column_definitions, row_styling: row_styling }) %>
51
+ <% end %>
@@ -0,0 +1 @@
1
+ `row_styling` can also be used to control padding on all cells in a given row via the use of the `cell_padding` key/value pair as shown here. `cell_padding` lets you use 'xxs', 'xs', 'sm', 'md', 'lg', 'xl' and 'none'.
@@ -0,0 +1,40 @@
1
+ <% column_definitions = [
2
+ {
3
+ accessor: "year",
4
+ label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
6
+ },
7
+ {
8
+ accessor: "newEnrollments",
9
+ label: "New Enrollments",
10
+ column_styling: {
11
+ cell_padding: "none",
12
+ }
13
+ },
14
+ {
15
+ accessor: "scheduledMeetings",
16
+ label: "Scheduled Meetings",
17
+ },
18
+ {
19
+ accessor: "attendanceRate",
20
+ label: "Attendance Rate",
21
+ column_styling: { cell_padding: "md" },
22
+ },
23
+ {
24
+ accessor: "completedClasses",
25
+ label: "Completed Classes",
26
+ },
27
+ {
28
+ accessor: "classCompletionRate",
29
+ label: "Class Completion Rate",
30
+ },
31
+ {
32
+ accessor: "graduatedStudents",
33
+ label: "Graduated Students",
34
+ }
35
+ ] %>
36
+
37
+ <%= pb_rails("advanced_table", props: { id: "padding-control", table_data: @table_data, column_definitions: column_definitions }) do %>
38
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: column_definitions }) %>
39
+ <%= pb_rails("advanced_table/table_body", props: { table_data: @table_data, column_definitions: column_definitions }) %>
40
+ <% end %>
@@ -0,0 +1 @@
1
+ `column_styling` can also be used to control padding on all cells in a given column via the use of the `cell_padding` key/value pair. `cell_padding` lets you use 'xxs', 'xs', 'sm', 'md', 'lg', 'xl' and 'none'.
@@ -1,4 +1,4 @@
1
- The `row_styling` prop can be used in conjunction with row ids to control certain styling options on individual rows. Currently, `row_styling` gives you 3 optional controls:
1
+ The `row_styling` prop can be used in conjunction with row ids to control certain styling options on individual rows. It is an object that has several optional key/value pairs, this doc example highlights the following:
2
2
 
3
3
  - `background_color` : use this to control the background color of the row
4
4
  - `font_color`: use this to control font color for each row if needed, for example if using a darker background color.
@@ -1,4 +1,4 @@
1
- The `rowStyling` prop can be used in conjunction with row ids to control certain styling options on individual rows. Currently, `rowStyling` gives you 3 optional controls:
1
+ The `rowStyling` prop can be used in conjunction with row ids to control certain styling options on individual rows. It is an object that has several optional key/value pairs, this doc example highlights the following:
2
2
 
3
3
  - `backgroundColor` : use this to control the background color of the row
4
4
  - `fontColor`: use this to control font color for each row if needed, for example if using a darker background color.
@@ -21,8 +21,11 @@ examples:
21
21
  - advanced_table_selectable_rows_header_rails: Selectable Rows (No Actions Bar)
22
22
  - advanced_table_scrollbar_none: Advanced Table Scrollbar None
23
23
  - advanced_table_row_styling: Row Styling
24
+ - advanced_table_padding_control_per_row_rails: Padding Control using Row Styling
24
25
  - advanced_table_column_styling_rails: Column Styling
25
26
  - advanced_table_column_styling_column_headers_rails: Column Styling with Multiple Headers
27
+ - advanced_table_padding_control_rails: Padding Control using Column Styling
28
+ - advanced_table_background_control_rails: Background Control using Column Styling
26
29
  - advanced_table_column_border_color_rails: Column Group Border Color
27
30
 
28
31
 
@@ -12,7 +12,8 @@
12
12
  <% end %>
13
13
  <% object.column_definitions.each_with_index do |column, index| %>
14
14
  <% next unless column[:accessor].present? %>
15
- <%= pb_rails("table/table_cell", props: { html_options: { style: { "background-color": bg_color, color: font_color } }, classname:object.td_classname(column, index)}) do %>
15
+ <% component_info = object.cell_component_info(column, index, bg_color, font_color) %>
16
+ <%= pb_rails(component_info[:name], props: component_info[:props]) do %>
16
17
  <%= pb_rails("flex", props:{ align: "center", justify: object.justify_for(column, index), classname: object.loading ? "loading-cell" : "" }) do %>
17
18
  <% if collapsible_trail && index.zero? %>
18
19
  <% (1..depth).each do |i| %>
@@ -46,9 +46,53 @@ module Playbook
46
46
  classes = %w[id-cell]
47
47
  classes << "last-cell" if column[:is_last_in_group]
48
48
  classes << "pinned-left" if index.zero? && is_pinned_left && responsive == "scroll"
49
+
50
+ row_style = row_styling.find { |style| style[:row_id].to_s == row_id.to_s }
51
+ row_padding = row_style&.[](:cell_padding)
52
+
53
+ if column[:accessor].present?
54
+ orig_def = find_column_def_by_accessor(column_definitions, column[:accessor])
55
+ column_padding = orig_def[:column_styling][:cell_padding] if orig_def && orig_def[:column_styling].is_a?(Hash) && orig_def[:column_styling][:cell_padding].present?
56
+ end
57
+
58
+ classes << "p_#{row_padding}" if row_padding.present?
59
+ classes << "p_#{column_padding}" if column_padding.present?
60
+
49
61
  classes.join(" ")
50
62
  end
51
63
 
64
+ def cell_background_color(column)
65
+ return nil unless column[:accessor].present?
66
+
67
+ orig_def = find_column_def_by_accessor(column_definitions, column[:accessor])
68
+ if orig_def && orig_def[:column_styling].is_a?(Hash) && orig_def[:column_styling][:cell_background_color].present?
69
+ bg_color = orig_def[:column_styling][:cell_background_color]
70
+ if bg_color.respond_to?(:call)
71
+ bg_color.call(row)
72
+ else
73
+ bg_color
74
+ end
75
+ end
76
+ end
77
+
78
+ def has_custom_background_color?(column)
79
+ cell_background_color(column).present?
80
+ end
81
+
82
+ # Uses a regular table/table_cell component if there is no custom background color; if there is a cell_background_color uses a background component with tag "td"
83
+ def cell_component_info(column, index, bg_color, font_color)
84
+ if has_custom_background_color?(column)
85
+ custom_bg_color = cell_background_color(column)
86
+ component_name = "background"
87
+ component_props = { background_color: custom_bg_color, tag: "td", classname: td_classname(column, index) }
88
+ else
89
+ component_name = "table/table_cell"
90
+ component_props = { html_options: { style: { "background-color": bg_color, color: font_color } }, classname: td_classname(column, index) }
91
+ end
92
+
93
+ { name: component_name, props: component_props }
94
+ end
95
+
52
96
  def depth_accessors
53
97
  column_definitions.flat_map do |column|
54
98
  column[:cellAccessors] if column.key?(:cellAccessors)
@@ -81,6 +81,12 @@ $pb_button_sizes: (
81
81
  // Loading state
82
82
  &.pb_button_loading {
83
83
  @include pb_button_loading(true);
84
+ &.pb_button_size_sm {
85
+ min-height: 30px;
86
+ }
87
+ &.pb_button_size_lg {
88
+ min-height: 45px;
89
+ }
84
90
  }
85
91
 
86
92
  // Disabled state
@@ -1,3 +1,7 @@
1
- <%= pb_rails("button", props: { aria: { label: "Loading" }, text: "Button Primary", loading: true, margin_right: "lg" }) %>
2
- <%= pb_rails("button", props: { aria: { label: "Loading" }, text: "Button Primary", variant: "secondary", loading: true, margin_right: "lg" }) %>
3
- <%= pb_rails("button", props: { aria: { label: "Loading" }, text: "Button Primary", variant: "link", loading: true, margin_right: "lg" }) %>
1
+ <%= pb_rails("caption", props: { margin_y: "md", text: "Button variants with loading" }) %>
2
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, loading: true, margin_right: "lg" }) %>
3
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, variant: "secondary", loading: true, margin_right: "lg" }) %>
4
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, variant: "link", loading: true, margin_right: "lg" }) %>
5
+ <%= pb_rails("caption", props: { margin_y: "md", text: "Button sizes with loading" }) %>
6
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, loading: true, size: "sm", margin_right: "lg" }) %>
7
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, loading: true, size: "lg", margin_right: "lg" }) %>
@@ -1,8 +1,13 @@
1
1
  import React from 'react'
2
2
  import Button from "../../pb_button/_button"
3
+ import Caption from "../../pb_caption/_caption"
3
4
 
4
5
  const ButtonLoading = (props) => (
5
6
  <div>
7
+ <Caption
8
+ marginY="md"
9
+ text="Button variants with loading"
10
+ />
6
11
  <Button
7
12
  aria={{ label: 'Loading' }}
8
13
  loading
@@ -31,6 +36,30 @@ const ButtonLoading = (props) => (
31
36
  variant="link"
32
37
  {...props}
33
38
  />
39
+ <br/>
40
+ <Caption
41
+ marginY="md"
42
+ text="Button sizes with loading"
43
+ />
44
+ <Button
45
+ aria={{ label: 'Loading' }}
46
+ loading
47
+ marginRight='lg'
48
+ size="sm"
49
+ tabIndex={0}
50
+ text="Small Button"
51
+ {...props}
52
+ />
53
+ {' '}
54
+ <Button
55
+ aria={{ label: 'Loading' }}
56
+ loading
57
+ marginRight='lg'
58
+ size="lg"
59
+ tabIndex={0}
60
+ text="Small Button"
61
+ {...props}
62
+ />
34
63
  </div>
35
64
  )
36
65
 
@@ -0,0 +1,31 @@
1
+ <%= pb_rails("body", props: { text: "Click to disable the Buttons below", id: "toggle-disabled-demo", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
2
+ <%= pb_rails("body", props: { text: "Click to enable the Buttons below", id: "toggle-enabled-demo", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
3
+
4
+ <%= pb_rails("card", props:{display:"flex", flex_direction:"row", justify_content:"center"}) do %>
5
+ <%= pb_rails("button", props: { text: "I am a Button", id: "normal_managed_button", data:{pb_button_managed: true}, margin_right: "lg" }) %>
6
+ <%= pb_rails("button", props: { text: "I am an <a> Button", id: "a_tag_managed_button", tag:"a", data:{pb_button_managed: true}, link: "http://google.com"}) %>
7
+ <% end %>
8
+ <script>
9
+ document.addEventListener('DOMContentLoaded', function () {
10
+ const disableTrigger = document.querySelector('#toggle-disabled-demo')
11
+ const enableTrigger = document.querySelector('#toggle-enabled-demo')
12
+
13
+ // Find the Buttons you want to 'manage'
14
+ const btn = document.querySelector('#normal_managed_button');
15
+ const link = document.querySelector('#a_tag_managed_button');
16
+
17
+ disableTrigger.addEventListener('click', (e) => {
18
+ // Disable default button
19
+ btn.setAttribute('disabled', true)
20
+ // Disable a tag button
21
+ link.setAttribute('aria-disabled', 'true')
22
+ });
23
+
24
+ enableTrigger.addEventListener('click', (e) => {
25
+ // Enable default button
26
+ btn.removeAttribute('disabled')
27
+ // Enable a tag button
28
+ link.removeAttribute('aria-disabled')
29
+ });
30
+ });
31
+ </script>
@@ -0,0 +1,7 @@
1
+ If needing to toggle the disabled state of the Button dynamically (for example, within a Turbo or Stimulus context), you can now do so in rails using the `pb-button-managed` data attribute.
2
+
3
+ 1) Add the following data attribute to your button kit: `data:{ pb-button-managed: true }`
4
+
5
+ 2) To toggle enabled/disabled state via attributes: for buttons set/remove disabled, for links set/remove aria-disabled="true". This will handle disabling the button, preventing clicks as well as all style changes so you don't have to.
6
+
7
+ Click to enable or disable the buttons above and view the code snippet below for details!
@@ -0,0 +1,21 @@
1
+ <%= pb_rails("body", props: { text: "Click to disable the Button below", id: "toggle-disabled-demo-with-helper", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
2
+ <%= pb_rails("body", props: { text: "Click to enable the Button below", id: "toggle-enabled-demo-with-helper", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
3
+ <br/>
4
+ <%= pb_rails("card", props:{display:"flex", flex_direction:"row", justify_content:"center"}) do %>
5
+ <%= pb_rails("button", props: { text: "Watch me Change!", id: "managed_button_with_helper", data:{pb_button_managed: true} }) %>
6
+ <% end %>
7
+
8
+ <script>
9
+ document.addEventListener('DOMContentLoaded', function () {
10
+ const disable = document.querySelector('#toggle-disabled-demo-with-helper')
11
+ const enable = document.querySelector('#toggle-enabled-demo-with-helper')
12
+
13
+ // Find the Button you want to 'manage'
14
+ const demoBtn = document.querySelector('#managed_button_with_helper')
15
+
16
+ // Use the pbButton object created by the kit to call the enable/disable methods
17
+ disable.addEventListener('click', (e) => {demoBtn._pbButton.disable()});
18
+ enable.addEventListener('click', (e) => {demoBtn._pbButton.enable()});
19
+
20
+ });
21
+ </script>
@@ -0,0 +1,7 @@
1
+ The disabled state for the button can also be toggled via small helpers available through the `pb-button-managed` data attribute.
2
+
3
+ 1) Add the following data attribute to your button kit: `data:{ pb-button-managed: true }`
4
+
5
+ 2) Toggle state via the provided `_pbButton.disable()` and `_pbButton.enable()` helpers as shown in the code snippet below.
6
+
7
+ Click to enable or disable the buttons above to see this in action!
@@ -11,6 +11,8 @@ examples:
11
11
  - button_options: Button Additional Options
12
12
  - button_size: Button Size
13
13
  - button_form: Button Form Attribute
14
+ - button_managed_disabled: Button Toggle Disabled State
15
+ - button_managed_disabled_helper: Button Toggle Disabled State Helper
14
16
 
15
17
  react:
16
18
  - button_default: Button Variants
@@ -0,0 +1,99 @@
1
+ import PbEnhancedElement from "../pb_enhanced_element"
2
+
3
+ const BUTTON_SELECTOR = "[data-pb-button-managed]"
4
+
5
+ export default class PbButton extends PbEnhancedElement {
6
+ static get selector() {
7
+ return BUTTON_SELECTOR
8
+ }
9
+
10
+ connect() {
11
+ this._attrManaged = this._attributesPresent()
12
+ this.element._pbButton = this
13
+
14
+ this._onClick = (e) => {
15
+ if (this.isDisabled()) {
16
+ e.preventDefault()
17
+ e.stopImmediatePropagation()
18
+ }
19
+ }
20
+ this.element.addEventListener("click", this._onClick, true)
21
+
22
+ if (this._attrManaged) this._syncClassesFromAttributes()
23
+
24
+ this._observer = new MutationObserver(() => {
25
+ this._attrManaged = true
26
+ this._syncClassesFromAttributes()
27
+ })
28
+ this._observer.observe(this.element, {
29
+ attributes: true,
30
+ attributeFilter: ["disabled", "aria-disabled"],
31
+ })
32
+ }
33
+
34
+ disconnect() {
35
+ this.element.removeEventListener("click", this._onClick, true)
36
+ this._observer?.disconnect()
37
+ delete this.element._pbButton
38
+ }
39
+
40
+ disable() { this.setDisabled(true) }
41
+ enable() { this.setDisabled(false) }
42
+
43
+ setDisabled(state) {
44
+ if (this._isButton()) {
45
+ state
46
+ ? this.element.setAttribute("disabled", "disabled")
47
+ : this.element.removeAttribute("disabled")
48
+ } else {
49
+ state
50
+ ? this.element.setAttribute("aria-disabled", "true")
51
+ : this.element.removeAttribute("aria-disabled")
52
+ }
53
+ this._attrManaged = true
54
+ this._applyClassState(state)
55
+ }
56
+
57
+ isDisabled() {
58
+ if (this._isButton()) {
59
+ if (this.element.hasAttribute("disabled")) return true
60
+ if (this._attrManaged && !this.element.hasAttribute("disabled")) return false
61
+ } else {
62
+ const aria = this.element.getAttribute("aria-disabled")
63
+ if (aria === "true") return true
64
+ if (this._attrManaged && aria !== "true") return false
65
+ }
66
+ return this.element.classList.contains("pb_button_disabled")
67
+ }
68
+
69
+ _isButton() {
70
+ return this.element.tagName === "BUTTON"
71
+ }
72
+
73
+ _attributesPresent() {
74
+ return this.element.hasAttribute("disabled") || this.element.hasAttribute("aria-disabled")
75
+ }
76
+
77
+ _syncClassesFromAttributes() {
78
+ const state = this._attrDisabledState()
79
+ const disabled = (state === null) ? false : state
80
+ this._applyClassState(disabled)
81
+ }
82
+
83
+ _attrDisabledState() {
84
+ if (this._isButton()) {
85
+ return this.element.hasAttribute("disabled") ? true : null
86
+ } else {
87
+ const aria = this.element.getAttribute("aria-disabled")
88
+ if (aria === "true") return true
89
+ if (aria === "false") return false
90
+ return this.element.hasAttribute("aria-disabled") ? false : null
91
+ }
92
+ }
93
+
94
+ _applyClassState(disabled) {
95
+ this.element.classList.toggle("pb_button_disabled", !!disabled)
96
+ this.element.classList.toggle("pb_button_enabled", !disabled)
97
+ }
98
+ }
99
+
@@ -19,6 +19,10 @@
19
19
  @import "./sass_partials/calendar_input_icon";
20
20
  }
21
21
 
22
+ label {
23
+ display: block !important;
24
+ }
25
+
22
26
  &:focus,
23
27
  :focus-within {
24
28
  div.cal_icon_wrapper,