playbook_ui 14.9.0.pre.alpha.PBNTR746datepickerdefaultbug4903 → 14.9.0.pre.alpha.PBNTR767advancedtablemultiheadercolumns5136

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/CollapsibleTrail.tsx +1 -6
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +32 -19
  4. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +3 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +48 -3
  6. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +33 -19
  7. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +2 -2
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_collapsible_trail_rails.html.erb +36 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_collapsible_trail_rails.md +1 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers.jsx +60 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers.md +1 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_multiple.jsx +74 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_multiple.md +1 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +3 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +4 -2
  17. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +8 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +2 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.html.erb +8 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.rb +2 -0
  21. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_custom.jsx +53 -49
  22. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_custom_rails.html.erb +29 -36
  23. data/app/pb_kits/playbook/pb_card/_card.tsx +7 -7
  24. data/app/pb_kits/playbook/pb_card/_card_mixin.scss +1 -1
  25. data/app/pb_kits/playbook/pb_card/docs/_card_header.html.erb +21 -1
  26. data/app/pb_kits/playbook/pb_card/docs/_card_header.jsx +50 -0
  27. data/app/pb_kits/playbook/pb_card/docs/_card_header.md +1 -1
  28. data/app/pb_kits/playbook/pb_collapsible/_collapsible.tsx +9 -4
  29. data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleContent.tsx +2 -2
  30. data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleMain.tsx +2 -2
  31. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +2 -4
  32. data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +2 -2
  33. data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +57 -0
  34. data/app/pb_kits/playbook/pb_form_group/_form_group.scss +11 -2
  35. data/app/pb_kits/playbook/pb_gauge/_gauge.scss +31 -1
  36. data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +3 -3
  37. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_complex.jsx +25 -5
  38. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +17 -1
  39. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_emphasis.html.erb +17 -1
  40. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_emphasis.jsx +15 -0
  41. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_emphasis.md +2 -1
  42. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.rb +15 -1
  43. data/app/pb_kits/playbook/pb_home_address_street/none_emphasis.html.erb +32 -0
  44. data/app/pb_kits/playbook/pb_home_address_street/none_emphasis.rb +29 -0
  45. data/app/pb_kits/playbook/pb_layout/_layout.tsx +30 -11
  46. data/app/pb_kits/playbook/pb_link/_link.scss +3 -3
  47. data/app/pb_kits/playbook/pb_skeleton_loading/docs/_skeleton_loading_filter.jsx +166 -0
  48. data/app/pb_kits/playbook/pb_skeleton_loading/docs/_skeleton_loading_height_width.jsx +2 -0
  49. data/app/pb_kits/playbook/pb_skeleton_loading/docs/_skeleton_loading_user.jsx +89 -0
  50. data/app/pb_kits/playbook/pb_skeleton_loading/docs/example.yml +2 -1
  51. data/app/pb_kits/playbook/pb_skeleton_loading/docs/index.js +2 -0
  52. data/app/pb_kits/playbook/pb_table/_table.tsx +6 -6
  53. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.html.erb +30 -48
  54. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_rails.md +1 -0
  55. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible.jsx +75 -0
  56. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible.md +1 -0
  57. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.jsx +108 -0
  58. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.md +2 -0
  59. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_content.jsx +94 -0
  60. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_content.md +0 -0
  61. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows.jsx +83 -0
  62. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows.md +3 -0
  63. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table.jsx +120 -0
  64. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table.md +1 -0
  65. data/app/pb_kits/playbook/pb_table/docs/example.yml +7 -0
  66. data/app/pb_kits/playbook/pb_table/docs/index.js +5 -0
  67. data/app/pb_kits/playbook/pb_table/index.ts +5 -3
  68. data/app/pb_kits/playbook/pb_table/styles/_all.scss +2 -1
  69. data/app/pb_kits/playbook/pb_table/styles/_collapsible.scss +35 -0
  70. data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +28 -3
  71. data/app/pb_kits/playbook/pb_table/styles/_sticky_columns.scss +0 -1
  72. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +106 -1
  73. data/app/pb_kits/playbook/pb_table/table.html.erb +7 -1
  74. data/app/pb_kits/playbook/pb_table/table.rb +4 -0
  75. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +35 -3
  76. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.jsx +88 -0
  77. data/app/pb_kits/playbook/pb_text_input/docs/example.yml +1 -0
  78. data/app/pb_kits/playbook/pb_text_input/docs/index.js +1 -0
  79. data/app/pb_kits/playbook/pb_text_input/inputMask.ts +64 -0
  80. data/app/pb_kits/playbook/pb_text_input/text_input.test.js +139 -2
  81. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +115 -46
  82. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_highlight.jsx +9 -2
  83. data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +3 -2
  84. data/dist/chunks/_typeahead-C63YYbKQ.js +22 -0
  85. data/dist/chunks/_weekday_stacked-CPOjyT4z.js +45 -0
  86. data/dist/chunks/lib-sMFo2JZy.js +29 -0
  87. data/dist/chunks/{pb_form_validation-DXJs12Hd.js → pb_form_validation-CgvjWbOK.js} +1 -1
  88. data/dist/chunks/vendor.js +1 -1
  89. data/dist/menu.yml +1 -1
  90. data/dist/playbook-doc.js +1 -1
  91. data/dist/playbook-rails-react-bindings.js +1 -1
  92. data/dist/playbook-rails.js +1 -1
  93. data/dist/playbook.css +1 -1
  94. data/lib/playbook/version.rb +1 -1
  95. metadata +31 -6
  96. data/dist/chunks/_typeahead-8iXlv4ii.js +0 -22
  97. data/dist/chunks/_weekday_stacked-QiMNKnzf.js +0 -45
  98. data/dist/chunks/lib-orI4wF5u.js +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7b3f96db16633e2d11c150f69e673e06c4b00563a4443b4488b3c70c076e545
4
- data.tar.gz: 1d7bd6f688a3bab9fc3dfdb1865bffc92a88258164a35f99d32ac658222b7a1d
3
+ metadata.gz: 4e0587b55894626bf9c1b536de994c6be32b554343ab23d48fbce936348df99c
4
+ data.tar.gz: c27323f03b333905152b3f074197c3a151e3e64adf7c145a486e060d59e1168a
5
5
  SHA512:
6
- metadata.gz: f7651cee71bffcb59d7fc86fd04ef361acc68620d3a16ecdad34886e240d8447983a06ae0b150c146508a28166bc1efce89a73f5910eeae6482e15069d52bf77
7
- data.tar.gz: 13dda38a57028c9134c8398b2aec92ca4bb50ec6f51db65a1232d3cb704a2113cb7d7a1a6e4a2b1bd589bc4aeff821c293ae206c5202228ed65e8adc39860496
6
+ metadata.gz: e2743697539265ab20f86e4a9ee8399c71ab490d02a22a14098f65c6002a8c598a81cfb429e086aa720e4008be1693ac5c467e44243abf9b5fbe31feaed54f4a
7
+ data.tar.gz: eb592ba87c70fc8b736db3ce899a78447d4b7f2a78e2949067b063f588c0cfdea52f2936614147bc4c52a613242be414c44d50c5b59c00c4c28db04d0fb7e5f2
@@ -3,18 +3,13 @@ import React from "react"
3
3
  //CollapsibleTrail component
4
4
  const CollapsibleTrail = ({ leftOffset }: { leftOffset: number }) => {
5
5
  const style: { [key: string]: string | number } = {
6
- position: "absolute",
7
6
  left: `${leftOffset}em`,
8
- top: 0,
9
- bottom: 0,
10
- width: "2px",
11
- backgroundColor: "#E4E8F0",
12
7
  }
13
8
 
14
9
  return (
15
10
  <div
16
11
  className="collapsible-trail"
17
- style={style}
12
+ style={style}
18
13
  />
19
14
  )
20
15
  }
@@ -40,46 +40,59 @@ export const TableHeaderCell = ({
40
40
 
41
41
  const toggleSortButton = (event: React.SyntheticEvent) => {
42
42
  if (sortControl) {
43
- const sortIsDesc = header.column.getIsSorted() === "desc"
43
+ const sortIsDesc = header?.column.getIsSorted() === "desc"
44
44
  sortIsDesc
45
45
  ? sortControl.onChange({ desc: true })
46
46
  : sortControl.onChange({ desc: false })
47
47
  } else {
48
- header.column.getToggleSortingHandler()(event)
48
+ header?.column.getToggleSortingHandler()(event)
49
49
  }
50
50
  }
51
51
 
52
- const cellClassName = classnames("table-header-cells",
53
- `${isChrome() ? "chrome-styles" : ""}`,
52
+ const isLeafColumn =
53
+ header?.column.getLeafColumns().length === 1 &&
54
+ header?.column.getLeafColumns()[0].id === header.column.id
55
+
56
+ const isLastHeaderCell =
57
+ header?.column.parent?.columns.at(-1) === header?.column ||
58
+ (header?.colSpan > 1 && header?.column.parent !== undefined);
59
+
60
+ const cellClassName = classnames(
61
+ "table-header-cells",
62
+ `${isChrome() ? "chrome-styles" : ""}`,
54
63
  `${enableSorting ? "table-header-cells-active" : ""}`,
55
- { 'pinned-left': responsive === "scroll" && isPinnedLeft },
56
- )
64
+ { "pinned-left": responsive === "scroll" && isPinnedLeft },
65
+ isLastHeaderCell ? "last-header-cell" : ""
66
+ );
57
67
 
58
68
  const cellId = `${loading ?
59
- `loading-${header.id}`
60
- : `${header.id}`
69
+ `loading-${header?.id}`
70
+ : `${header?.id}`
61
71
  }`
62
72
 
63
73
  const isToggleExpansionEnabledLoading =
64
- header.index === 0 &&
74
+ header?.index === 0 &&
65
75
  loading &&
66
76
  (enableToggleExpansion === "all" || "header") &&
67
77
  enableToggleExpansion !== "none"
68
78
 
69
79
  const isToggleExpansionEnabled =
70
- header.index === 0 &&
80
+ header?.index === 0 &&
71
81
  !loading &&
72
82
  (enableToggleExpansion === "all" || "header") &&
73
83
  enableToggleExpansion !== "none"
74
84
 
85
+ const justifyHeader = isLeafColumn ? "end" : "center"
86
+
75
87
  return (
76
88
  <th
77
89
  align="right"
78
90
  className={cellClassName}
91
+ colSpan={header?.colSpan}
79
92
  id={cellId}
80
- key={`${header.id}-header`}
93
+ key={`${header?.id}-header`}
81
94
  >
82
- {header.isPlaceholder ? null : headerChildren && header.index === 0 ? (
95
+ {header?.isPlaceholder ? null : headerChildren && header?.index === 0 ? (
83
96
  <Flex alignItems="center">
84
97
  {headerChildren}
85
98
  <div>
@@ -89,7 +102,7 @@ const isToggleExpansionEnabled =
89
102
  ) : (
90
103
  <Flex
91
104
  alignItems="center"
92
- justify={header.index === 0 && enableSorting ? "between" : header.index === 0 && !enableSorting ? "start" : "end"}
105
+ justify={header?.index === 0 && enableSorting ? "between" : header?.index === 0 && !enableSorting ? "start" : justifyHeader}
93
106
  >
94
107
  {isToggleExpansionEnabled && (
95
108
  <ToggleIconButton onClick={handleExpandOrCollapse} />
@@ -100,11 +113,11 @@ const isToggleExpansionEnabled =
100
113
  )}
101
114
 
102
115
  <Flex
103
- className={`${header.index === 0 &&
116
+ className={`${header?.index === 0 &&
104
117
  enableSorting &&
105
118
  "header-sort-button pb_th_link"}`}
106
- cursor={header.index === 0 && enableSorting ? "pointer" : "default"}
107
- {...(header.index === 0 &&
119
+ cursor={header?.index === 0 && enableSorting ? "pointer" : "default"}
120
+ {...(header?.index === 0 &&
108
121
  enableSorting && {
109
122
  htmlOptions: {
110
123
  onClick: (event: React.MouseEvent) => toggleSortButton(event),
@@ -116,14 +129,14 @@ const isToggleExpansionEnabled =
116
129
  tabIndex: 0,
117
130
  },
118
131
  })}
119
- justify={header.index === 0 && enableSorting ? "between" : "none"}
132
+ justify={header?.index === 0 && enableSorting ? "between" : "none"}
120
133
  paddingLeft={enableSorting ? "xxs" : "xs"}
121
134
  >
122
135
  <div>
123
- {flexRender(header.column.columnDef.header, header.getContext())}
136
+ {flexRender(header?.column.columnDef.header, header?.getContext())}
124
137
  </div>
125
138
 
126
- {header.index === 0 &&
139
+ {header?.index === 0 &&
127
140
  header.column.getCanSort() &&
128
141
  enableSorting &&
129
142
  (loading ? (
@@ -86,6 +86,7 @@ export const TableBody = ({
86
86
  >
87
87
  {row.getVisibleCells().map((cell, i) => {
88
88
  const isPinnedLeft = columnPinning.left.includes(cell.column.id)
89
+ const isLastCell = cell.column.parent?.columns.at(-1)?.id === cell.column.id
89
90
 
90
91
  return (
91
92
  <td
@@ -93,7 +94,8 @@ export const TableBody = ({
93
94
  className={classnames(
94
95
  `${cell.id}-cell position_relative`,
95
96
  isChrome() ? "chrome-styles" : "",
96
- isPinnedLeft && 'pinned-left'
97
+ isPinnedLeft && 'pinned-left',
98
+ isLastCell && 'last-cell',
97
99
  )}
98
100
  key={`${cell.id}-data`}
99
101
  >
@@ -31,6 +31,43 @@
31
31
  min-width: 180px;
32
32
  }
33
33
 
34
+ .pb_advanced_table_header {
35
+ > tr:not(:first-child) {
36
+ .last-header-cell {
37
+ border-right: 1px solid $border_light !important;
38
+ }
39
+
40
+ th {
41
+ border-radius: 0px !important;
42
+ border-width: 0 0 1px 0 !important;
43
+ }
44
+ th:first-child {
45
+ border-left-width: 1px !important;
46
+ @media only screen and (max-width: $screen-xl-min) {
47
+ border-left-width: 0 !important;
48
+ }
49
+ }
50
+ th:last-child {
51
+ border-right-width: 1px !important;
52
+ @media only screen and (max-width: $screen-xl-min) {
53
+ border-right-width: 0 !important;
54
+ }
55
+ }
56
+ }
57
+ th[colspan]:not([colspan="1"]) {
58
+ border-right: 1px solid $border_light;
59
+ }
60
+
61
+
62
+ }
63
+
64
+ .pb_advanced_table_body {
65
+ .last-cell {
66
+ border-right: 1px solid $border_light !important;
67
+ }
68
+ }
69
+
70
+
34
71
  .table-header-cells-active:first-child {
35
72
  color: $primary !important;
36
73
  }
@@ -110,9 +147,17 @@
110
147
  height: auto;
111
148
  }
112
149
 
150
+ .collapsible-trail {
151
+ background-color: $border_light;
152
+ position: absolute;
153
+ top: 0;
154
+ bottom: 0;
155
+ width: 2px;
156
+ }
157
+
113
158
  // Responsive Styles
114
159
  @media only screen and (max-width: $screen-xl-min) {
115
- &[class*="table-responsive-scroll"] {
160
+ &[class*="advanced-table-responsive-scroll"] {
116
161
  border-radius: 4px;
117
162
  box-shadow: 1px 0 0 0px $border_light,
118
163
  -1px 0 0 0px $border_light;
@@ -150,7 +195,7 @@
150
195
  }
151
196
  }
152
197
  @media only screen and (min-width: $screen-xl-min) {
153
- &[class*="table-responsive-scroll"] {
198
+ &[class*="advanced-table-responsive-scroll"] {
154
199
  overflow-x: visible;
155
200
  }
156
201
  }
@@ -200,7 +245,7 @@
200
245
  }
201
246
  // Dark Mode Responsive Styles
202
247
  @media only screen and (max-width: $screen-xl-min) {
203
- &[class*="table-responsive-scroll"] {
248
+ &[class*="advanced-table-responsive-scroll"] {
204
249
  border-radius: 4px;
205
250
  box-shadow: 1px 0 0 0px $border_dark,
206
251
  -1px 0 0 0px $border_dark;
@@ -142,27 +142,41 @@ const AdvancedTable = (props: AdvancedTableProps) => {
142
142
  }
143
143
  return columnCells
144
144
  }
145
- //Create column array in format needed by Tanstack
146
- const columns =
147
- columnDefinitions &&
145
+
146
+ const buildColumns = (columnDefinitions: GenericObject[]): any => {
147
+ return (
148
+ columnDefinitions &&
148
149
  columnDefinitions.map((column, index) => {
149
- // Define the base column structure
150
- const columnStructure = {
151
- ...columnHelper.accessor(column.accessor, {
152
- header: column.label,
153
- }),
154
- }
150
+ //Checking to see if grouped column or not
151
+ if (column.columns && column.columns.length > 0) {
152
+ return {
153
+ header: column.label || "",
154
+ columns: buildColumns(column.columns),
155
+ };
156
+ } else {
157
+ // Define the base column structure
158
+ const columnStructure = {
159
+ ...columnHelper.accessor(column.accessor, {
160
+ header: column.label || "",
161
+ }),
162
+ };
155
163
 
156
- if (column.cellAccessors || column.customRenderer) {
157
- columnStructure.cell = createCellFunction(
158
- column.cellAccessors,
159
- column.customRenderer,
160
- index
161
- )
162
- }
164
+ if (column.cellAccessors || column.customRenderer) {
165
+ columnStructure.cell = createCellFunction(
166
+ column.cellAccessors,
167
+ column.customRenderer,
168
+ index
169
+ );
170
+ }
171
+
172
+ return columnStructure;
173
+ }
174
+ })
175
+ );
176
+ };
163
177
 
164
- return columnStructure
165
- })
178
+ //Create column array in format needed by Tanstack
179
+ const columns = buildColumns(columnDefinitions);
166
180
 
167
181
  //Syntax for sorting Array if we want to manage state ourselves
168
182
  const sorting = [
@@ -240,7 +254,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
240
254
  const htmlProps = buildHtmlProps(htmlOptions)
241
255
  const classes = classnames(
242
256
  buildCss("pb_advanced_table"),
243
- `table-responsive-${responsive}`,
257
+ `advanced-table-responsive-${responsive}`,
244
258
  globalProps(props),
245
259
  className
246
260
  )
@@ -468,7 +468,7 @@ test("responsive prop functions as expected", () => {
468
468
  )
469
469
 
470
470
  const kit = screen.getByTestId(testId)
471
- expect(kit).toHaveClass("pb_advanced_table table-responsive-scroll")
471
+ expect(kit).toHaveClass("pb_advanced_table advanced-table-responsive-scroll")
472
472
  })
473
473
 
474
474
  test("responsive none prop functions as expected", () => {
@@ -483,7 +483,7 @@ test("responsive none prop functions as expected", () => {
483
483
  )
484
484
 
485
485
  const kit = screen.getByTestId(testId)
486
- expect(kit).toHaveClass("pb_advanced_table table-responsive-none")
486
+ expect(kit).toHaveClass("pb_advanced_table advanced-table-responsive-none")
487
487
  })
488
488
 
489
489
  test("customRenderer prop functions as expected", () => {
@@ -0,0 +1,36 @@
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
+ <%= pb_rails("advanced_table", props: { id: "collapsible_trail", table_data: @table_data, column_definitions: column_definitions }) do %>
34
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: column_definitions }) %>
35
+ <%= pb_rails("advanced_table/table_body", props: { table_data: @table_data, column_definitions: column_definitions, collapsible_trail: false }) %>
36
+ <% end %>
@@ -0,0 +1 @@
1
+ `collapsible_trail` is an optional prop that is set to 'true' by default. If set to 'false', it will remove the trail on the left of the rows when subRows are toggled open.
@@ -0,0 +1,60 @@
1
+ import React from "react"
2
+ import { AdvancedTable } from "playbook-ui"
3
+ import MOCK_DATA from "./advanced_table_mock_data.json"
4
+
5
+ const AdvancedTableColumnHeaders = (props) => {
6
+ const columnDefinitions = [
7
+ {
8
+ accessor: "year",
9
+ label: "Year",
10
+ cellAccessors: ["quarter", "month", "day"],
11
+ },
12
+ {
13
+ label: "Enrollment Data",
14
+ columns: [
15
+ {
16
+ accessor: "newEnrollments",
17
+ label: "New Enrollments",
18
+ },
19
+ {
20
+ accessor: "scheduledMeetings",
21
+ label: "Scheduled Meetings",
22
+ },
23
+ ],
24
+ },
25
+ {
26
+ label: "Performance Data",
27
+ columns: [
28
+ {
29
+ accessor: "attendanceRate",
30
+ label: "Attendance Rate",
31
+ },
32
+ {
33
+ accessor: "completedClasses",
34
+ label: "Completed Classes",
35
+ },
36
+ {
37
+ accessor: "classCompletionRate",
38
+ label: "Class Completion Rate",
39
+ },
40
+ {
41
+ accessor: "graduatedStudents",
42
+ label: "Graduated Students",
43
+ },
44
+ ],
45
+ },
46
+ ];
47
+
48
+
49
+ return (
50
+ <>
51
+ <AdvancedTable
52
+ columnDefinitions={columnDefinitions}
53
+ tableData={MOCK_DATA}
54
+ {...props}
55
+ />
56
+ </>
57
+ )
58
+ }
59
+
60
+ export default AdvancedTableColumnHeaders
@@ -0,0 +1 @@
1
+ Use a nested `columns` array in your columnDefinitions to create multiple header rows. Any column with `columns` is treated as a grouped header, and its child columns are displayed beneath it.
@@ -0,0 +1,74 @@
1
+ import React from "react";
2
+ import { AdvancedTable } from "playbook-ui";
3
+ import MOCK_DATA from "./advanced_table_mock_data.json";
4
+
5
+ const AdvancedTableColumnHeadersMultiple = (props) => {
6
+ const columnDefinitions = [
7
+ {
8
+ accessor: "year",
9
+ label: "Year",
10
+ cellAccessors: ["quarter", "month", "day"],
11
+ },
12
+ {
13
+ label: "Enrollment Data",
14
+ columns: [
15
+ {
16
+ label: "Enrollment Stats",
17
+ columns: [
18
+ {
19
+ accessor: "newEnrollments",
20
+ label: "New Enrollments",
21
+ },
22
+ {
23
+ accessor: "scheduledMeetings",
24
+ label: "Scheduled Meetings",
25
+ },
26
+ ],
27
+ },
28
+ ],
29
+ },
30
+ {
31
+ label: "Performance Data",
32
+ columns: [
33
+ {
34
+ label: "Completion Metrics",
35
+ columns: [
36
+ {
37
+ accessor: "completedClasses",
38
+ label: "Completed Classes",
39
+ },
40
+ {
41
+ accessor: "classCompletionRate",
42
+ label: "Class Completion Rate",
43
+ },
44
+ ],
45
+ },
46
+ {
47
+ label: "Attendance",
48
+ columns: [
49
+ {
50
+ accessor: "attendanceRate",
51
+ label: "Attendance Rate",
52
+ },
53
+ {
54
+ accessor: "scheduledMeetings",
55
+ label: "Scheduled Meetings",
56
+ },
57
+ ],
58
+ },
59
+ ],
60
+ },
61
+ ];
62
+
63
+ return (
64
+ <>
65
+ <AdvancedTable
66
+ columnDefinitions={columnDefinitions}
67
+ tableData={MOCK_DATA}
68
+ {...props}
69
+ />
70
+ </>
71
+ );
72
+ };
73
+
74
+ export default AdvancedTableColumnHeadersMultiple;
@@ -0,0 +1 @@
1
+ Multiple levels of column headers can also be rendered as seen here.
@@ -2,6 +2,7 @@ examples:
2
2
  rails:
3
3
  - advanced_table_beta: Default (Required Props)
4
4
  - advanced_table_beta_subrow_headers: SubRow Headers
5
+ - advanced_table_collapsible_trail_rails: Collapsible Trail
5
6
  - advanced_table_beta_sort: Enable Sorting
6
7
  - advanced_table_custom_cell_rails: Custom Components for Cells
7
8
 
@@ -20,3 +21,5 @@ examples:
20
21
  - advanced_table_custom_cell: Custom Components for Cells
21
22
  - advanced_table_pagination: Pagination
22
23
  - advanced_table_pagination_with_props: Pagination Props
24
+ - advanced_table_column_headers: Multi-Header Columns
25
+ - advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
@@ -12,3 +12,5 @@ export { default as AdvancedTableResponsive } from './_advanced_table_responsive
12
12
  export { default as AdvancedTableCustomCell } from './_advanced_table_custom_cell.jsx'
13
13
  export { default as AdvancedTablePagination } from './_advanced_table_pagination.jsx'
14
14
  export { default as AdvancedTablePaginationWithProps } from './_advanced_table_pagination_with_props.jsx'
15
+ export { default as AdvancedTableColumnHeaders } from './_advanced_table_column_headers.jsx'
16
+ export { default as AdvancedTableColumnHeadersMultiple } from './_advanced_table_column_headers_multiple.jsx'
@@ -14,14 +14,16 @@ module Playbook
14
14
  default: "header"
15
15
  prop :subrow_headers, type: Playbook::Props::Array,
16
16
  default: []
17
+ prop :collapsible_trail, type: Playbook::Props::Boolean,
18
+ default: true
17
19
 
18
20
  def render_row_and_children(row, column_definitions, current_depth, first_parent_child)
19
21
  output = ActiveSupport::SafeBuffer.new
20
22
  is_first_child_of_subrow = current_depth.positive? && first_parent_child && subrow_headers[current_depth - 1].present?
21
23
 
22
- output << pb_rails("advanced_table/table_subrow_header", props: { row: row, column_definitions: column_definitions, depth: current_depth, subrow_header: subrow_headers[current_depth - 1] }) if is_first_child_of_subrow && enable_toggle_expansion == "all"
24
+ output << pb_rails("advanced_table/table_subrow_header", props: { row: row, column_definitions: column_definitions, depth: current_depth, subrow_header: subrow_headers[current_depth - 1], collapsible_trail: collapsible_trail }) if is_first_child_of_subrow && enable_toggle_expansion == "all"
23
25
 
24
- output << pb_rails("advanced_table/table_row", props: { id: id, row: row, column_definitions: column_definitions, depth: current_depth })
26
+ output << pb_rails("advanced_table/table_row", props: { id: id, row: row, column_definitions: column_definitions, depth: current_depth, collapsible_trail: collapsible_trail })
25
27
 
26
28
  if row[:children].present?
27
29
  output << content_tag(:div, class: "toggle-content", data: { advanced_table_content: row.object_id.to_s + id }) do
@@ -2,6 +2,14 @@
2
2
  <% object.column_definitions.each_with_index do |column, index| %>
3
3
  <%= pb_rails("table/table_cell", props: { tag:"div", classname:object.td_classname}) do %>
4
4
  <%= pb_rails("flex", props:{ align: "center", justify: index.zero? ? "start" : "end" }) do %>
5
+ <% if collapsible_trail && index.zero? %>
6
+ <% (1..depth).each do |i| %>
7
+ <% additional_offset = i > 1 ? (i - 1) * 0.25 : 0 %>
8
+ <% left_offset = i * 1.0 + additional_offset %>
9
+ <div class="collapsible-trail" style="left: <%= left_offset %>em"></div>
10
+ <% end %>
11
+ <% end %>
12
+
5
13
  <div style="padding-left: <%= depth * 1.25 %>em">
6
14
  <%= pb_rails("flex", props:{align: "center", column_gap: "xs"}) do %>
7
15
  <% if index.zero? && object.row[:children].present? %>
@@ -9,6 +9,8 @@ module Playbook
9
9
  default: []
10
10
  prop :row
11
11
  prop :depth
12
+ prop :collapsible_trail, type: Playbook::Props::Boolean,
13
+ default: true
12
14
 
13
15
  def classname
14
16
  generate_classname("pb_table_tr", "bg-white", subrow_depth_classname, separator: " ")
@@ -6,6 +6,14 @@
6
6
  <% object.column_definitions.each_with_index do |column, index| %>
7
7
  <%= pb_rails("table/table_cell", props: { tag: "div", classname: object.td_classname}) do %>
8
8
  <%= pb_rails("flex", props:{ align: "center", justify: "start" }) do %>
9
+ <% if collapsible_trail && index.zero? %>
10
+ <% (1..depth).each do |i| %>
11
+ <% additional_offset = i > 1 ? (i - 1) * 0.25 : 0 %>
12
+ <% left_offset = i * 1.0 + additional_offset %>
13
+ <div class="collapsible-trail" style="left: <%= left_offset %>em"></div>
14
+ <% end %>
15
+ <% end %>
16
+
9
17
  <div style="padding-left: <%= depth * 1.25 %>em">
10
18
  <%= pb_rails("flex", props:{align: "center", column_gap: "xs"}) do %>
11
19
  <% if index.zero? && object.row[:children].present? %>
@@ -12,6 +12,8 @@ module Playbook
12
12
  default: "header"
13
13
  prop :subrow_header, type: Playbook::Props::String,
14
14
  default: ""
15
+ prop :collapsible_trail, type: Playbook::Props::Boolean,
16
+ default: true
15
17
 
16
18
  def classname
17
19
  generate_classname("pb_table_tr", "bg-white", subrow_depth_classname, separator: " ")