playbook_ui 14.16.0 → 14.17.0.pre.rc.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +34 -2
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +86 -84
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +2 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +10 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.jsx +0 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.html.erb +39 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.html.erb +33 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows_rails.md +1 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.md +6 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/index.js +1 -1
  13. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +4 -2
  14. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +19 -9
  15. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +38 -1
  16. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +49 -37
  17. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +39 -0
  18. data/app/pb_kits/playbook/pb_button/_button.scss +5 -5
  19. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +29 -11
  20. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_default.html.erb +1 -1
  21. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb +4 -4
  22. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb +2 -0
  23. data/app/pb_kits/playbook/pb_table/_table.tsx +4 -0
  24. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless.jsx +50 -0
  25. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless_react.md +1 -0
  26. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating.jsx +59 -0
  27. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating_react.md +1 -0
  28. data/app/pb_kits/playbook/pb_table/docs/example.yml +2 -0
  29. data/app/pb_kits/playbook/pb_table/docs/index.js +2 -0
  30. data/app/pb_kits/playbook/pb_table/styles/_headers.scss +76 -0
  31. data/app/pb_kits/playbook/pb_table/subcomponents/_table_head.tsx +11 -1
  32. data/app/pb_kits/playbook/pb_table/subcomponents/_table_header.tsx +11 -1
  33. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +5 -0
  34. data/app/pb_kits/playbook/pb_table/table.test.js +17 -0
  35. data/dist/chunks/{_typeahead-BuTZG1Jn.js → _typeahead-N-EFroAX.js} +1 -1
  36. data/dist/chunks/_weekday_stacked-Db780bKR.js +45 -0
  37. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  38. data/dist/chunks/vendor.js +1 -1
  39. data/dist/playbook-doc.js +1 -1
  40. data/dist/playbook-rails-react-bindings.js +1 -1
  41. data/dist/playbook-rails.js +1 -1
  42. data/dist/playbook.css +1 -1
  43. data/lib/playbook/version.rb +2 -2
  44. metadata +15 -7
  45. data/dist/chunks/_weekday_stacked-oT22q75-.js +0 -45
  46. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
  47. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows.md → _advanced_table_selectable_rows_no_subrows_react.md} +0 -0
  48. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows.md → _advanced_table_selectable_rows_react.md} +0 -0
@@ -1,48 +1,60 @@
1
1
  <%= pb_content_tag(:tr) do %>
2
- <% object.column_definitions.each_with_index do |column, index| %>
3
- <% next unless column[:accessor].present? %>
4
- <%= pb_rails("table/table_cell", props: { classname:object.td_classname(column, index)}) do %>
5
- <%= pb_rails("flex", props:{ align: "center", justify: index.zero? ? "start" : "end", classname: object.loading ? "loading-cell" : "" }) do %>
6
- <% if collapsible_trail && index.zero? %>
7
- <% (1..depth).each do |i| %>
8
- <% additional_offset = i > 1 ? (i - 1) * 0.25 : 0 %>
9
- <% left_offset = i * 1.0 + additional_offset %>
10
- <div class="collapsible-trail" style="left: <%= left_offset %>em"></div>
11
- <% end %>
2
+ <% has_separate_checkbox = object.selectable_rows && object.enable_toggle_expansion == "none" %>
3
+ <% if has_separate_checkbox %>
4
+ <%= object.render_checkbox_cell %>
5
+ <% end %>
6
+ <% object.column_definitions.each_with_index do |column, index| %>
7
+ <% next unless column[:accessor].present? %>
8
+ <%= pb_rails("table/table_cell", props: { classname:object.td_classname(column, index)}) do %>
9
+ <%= pb_rails("flex", props:{ align: "center", justify: index.zero? ? "start" : "end", classname: object.loading ? "loading-cell" : "" }) do %>
10
+ <% if collapsible_trail && index.zero? %>
11
+ <% (1..depth).each do |i| %>
12
+ <% additional_offset = i > 1 ? (i - 1) * 0.25 : 0 %>
13
+ <% left_offset = i * 1.0 + additional_offset %>
14
+ <div class="collapsible-trail" style="left: <%= left_offset %>em"></div>
12
15
  <% end %>
16
+ <% end %>
13
17
 
14
- <div style="padding-left: <%= depth * 1.25 %>em">
15
- <%= pb_rails("flex", props:{align: "center", column_gap: "xs"}) do %>
16
- <% if index.zero? && object.row[:children].present? %>
17
- <button
18
- id="<%= "#{object.id}_#{object.row.object_id}" %>"
19
- class="gray-icon expand-toggle-icon"
20
- data-advanced-table="true">
21
- <%= pb_rails("icon", props: { id: "advanced-table_open_icon", icon: "circle-play", cursor: "pointer" }) %>
22
- <%= pb_rails("icon", props: { id: "advanced-table_close_icon", display: "none", icon: "circle-play", cursor: "pointer", rotation: 90 }) %>
23
- </button>
18
+ <div style="padding-left: <%= depth * 1.25 %>em">
19
+ <%= pb_rails("flex", props:{align: "center", column_gap: "xs"}) do %>
20
+ <% if index.zero? %>
21
+ <% has_integrated_checkbox = object.selectable_rows && object.enable_toggle_expansion != "none" %>
22
+ <% if has_integrated_checkbox %>
23
+ <%= pb_rails("flex/flex_item", props: { padding_right: "xs" }) do %>
24
+ <%= object.render_row_checkbox %>
25
+ <% end %>
24
26
  <% end %>
25
- <%= pb_rails("flex/flex_item", props:{padding_left: index.zero? && object.row[:children].present? ? "none" : "xs"}) do %>
26
- <% if column[:custom_renderer].present? %>
27
- <%= raw(column[:custom_renderer].call(object.row, custom_renderer_value(column, index))) %>
28
- <% elsif index.zero? %>
29
- <% if object.depth.zero? %>
30
- <%= object.row[column[:accessor].to_sym] %>
31
- <% else %>
32
- <% object.depth_accessors.each_with_index do |item, accessor_index| %>
33
- <% if object.depth - 1 == accessor_index %>
34
- <% key = item.to_sym %>
35
- <%= object.row[key] %>
36
- <% end %>
27
+ <% if object.row[:children].present? %>
28
+ <button
29
+ id="<%= "#{object.id}_#{object.row.object_id}" %>"
30
+ class="gray-icon expand-toggle-icon"
31
+ data-advanced-table="true">
32
+ <%= pb_rails("icon", props: { id: "advanced-table_open_icon", icon: "circle-play", cursor: "pointer" }) %>
33
+ <%= pb_rails("icon", props: { id: "advanced-table_close_icon", display: "none", icon: "circle-play", cursor: "pointer", rotation: 90 }) %>
34
+ </button>
35
+ <% end %>
36
+ <% end %>
37
+ <%= pb_rails("flex/flex_item", props:{padding_left: index.zero? && (object.row[:children].present? || has_integrated_checkbox) ? "none" : "xs"}) do %>
38
+ <% if column[:custom_renderer].present? %>
39
+ <%= raw(column[:custom_renderer].call(object.row, custom_renderer_value(column, index))) %>
40
+ <% elsif index.zero? %>
41
+ <% if object.depth.zero? %>
42
+ <%= object.row[column[:accessor].to_sym] %>
43
+ <% else %>
44
+ <% object.depth_accessors.each_with_index do |item, accessor_index| %>
45
+ <% if object.depth - 1 == accessor_index %>
46
+ <% key = item.to_sym %>
47
+ <%= object.row[key] %>
37
48
  <% end %>
38
49
  <% end %>
39
- <% else %>
40
- <%= object.row[column[:accessor].to_sym] %>
41
50
  <% end %>
51
+ <% else %>
52
+ <%= object.row[column[:accessor].to_sym] %>
42
53
  <% end %>
43
54
  <% end %>
44
- </div>
45
- <% end %>
55
+ <% end %>
56
+ </div>
46
57
  <% end %>
47
58
  <% end %>
48
- <% end %>
59
+ <% end %>
60
+ <% end %>
@@ -20,6 +20,13 @@ module Playbook
20
20
  default: "scroll"
21
21
  prop :is_pinned_left, type: Playbook::Props::Boolean,
22
22
  default: false
23
+ prop :selectable_rows, type: Playbook::Props::Boolean,
24
+ default: false
25
+ prop :row_id, type: Playbook::Props::String,
26
+ default: ""
27
+ prop :enable_toggle_expansion, type: Playbook::Props::Enum,
28
+ values: %w[all header none],
29
+ default: "header"
23
30
 
24
31
  def data
25
32
  Hash(prop(:data)).merge(table_data_attributes)
@@ -42,6 +49,38 @@ module Playbook
42
49
  end.compact
43
50
  end
44
51
 
52
+ # Selectable Rows No Subrows - checkboxes in their own first cell
53
+ def render_checkbox_cell
54
+ if selectable_rows
55
+ pb_rails("table/table_cell", props: {
56
+ classname: "checkbox-cell",
57
+ }) do
58
+ pb_rails("checkbox", props: {
59
+ id: "select-row-#{row_id || row.object_id}",
60
+ name: "select-row-#{row_id || row.object_id}",
61
+ data: {
62
+ row_id: row_id || row.object_id.to_s,
63
+ action: "click->pb-advanced-table#toggleRowSelection",
64
+ },
65
+ })
66
+ end
67
+ end
68
+ end
69
+
70
+ # Selectable Rows w/ Subrows - checkboxes part of toggleable first cell
71
+ def render_row_checkbox
72
+ if selectable_rows
73
+ pb_rails("checkbox", props: {
74
+ id: "select-row-#{row_id || row.object_id}",
75
+ name: "select-row-#{row_id || row.object_id}",
76
+ data: {
77
+ row_id: row_id || row.object_id.to_s,
78
+ action: "click->pb-advanced-table#toggleRowSelection",
79
+ },
80
+ })
81
+ end
82
+ end
83
+
45
84
  private
46
85
 
47
86
  def custom_renderer_value(column, index)
@@ -63,11 +63,6 @@ $pb_button_sizes: (
63
63
  color: $text_lt_lighter;
64
64
  }
65
65
 
66
- // Disabled =================
67
- &[class*=_disabled] {
68
- @include pb_button_disabled;
69
- }
70
-
71
66
  // Block ====================
72
67
  &[class*=_block] {
73
68
  @include pb_button_block;
@@ -83,6 +78,11 @@ $pb_button_sizes: (
83
78
  @include pb_button_danger;
84
79
  }
85
80
 
81
+ // Disabled =================
82
+ &[class*=_disabled] {
83
+ @include pb_button_disabled;
84
+ }
85
+
86
86
  // Dark Variants =============
87
87
  &.dark {
88
88
  &[class*=_primary] {
@@ -32,11 +32,12 @@ type RichTextEditorProps = {
32
32
  advancedEditor?: any,
33
33
  advancedEditorToolbar?: boolean,
34
34
  toolbarBottom?: boolean,
35
- children?: React.ReactNode | React.ReactNode[]
35
+ children?: React.ReactNode | React.ReactNode[],
36
36
  className?: string,
37
37
  data?: { [key: string]: string },
38
38
  focus?: boolean,
39
- htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
39
+ htmlOptions?: { [key: string]: string | number | boolean | (() => void) },
40
+ inputOptions?: { [key: string]: string | number | boolean | (() => void) },
40
41
  id?: string,
41
42
  inline?: boolean,
42
43
  extensions?: { [key: string]: string }[],
@@ -61,6 +62,7 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
61
62
  data = {},
62
63
  focus = false,
63
64
  htmlOptions = {},
65
+ inputOptions = {},
64
66
  inline = false,
65
67
  extensions,
66
68
  name,
@@ -70,7 +72,7 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
70
72
  sticky = false,
71
73
  template = '',
72
74
  value = '',
73
- maxWidth="md"
75
+ maxWidth = "md"
74
76
  } = props
75
77
 
76
78
  const ariaProps = buildAriaProps(aria),
@@ -79,12 +81,28 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
79
81
 
80
82
  const htmlProps = buildHtmlProps(htmlOptions)
81
83
 
82
- const handleOnEditorReady = (editorInstance: Editor) => setEditor(editorInstance),
83
- element = editor?.element
84
+ const handleOnEditorReady = (editorInstance: Editor) => {
85
+ setEditor(editorInstance)
86
+ setTimeout(() => {
87
+ const oldId = editorInstance.element.getAttribute('input')
88
+ if (oldId) {
89
+ const hiddenInput = document.getElementById(oldId)
90
+ if (hiddenInput) {
91
+ const newId = (inputOptions.id as string) || oldId
92
+ hiddenInput.id = newId
93
+ editorInstance.element.setAttribute('input', newId)
94
+
95
+ if (inputOptions.name) {
96
+ hiddenInput.setAttribute('name', inputOptions.name as string)
97
+ }
98
+ }
99
+ }
100
+ })
101
+ }
84
102
 
85
103
  // DOM manipulation must wait for editor to be ready
86
- if (editor) {
87
- const toolbarElement = element.parentElement.querySelector('trix-toolbar') as HTMLElement,
104
+ if (editor && editor.element) {
105
+ const toolbarElement = editor.element.parentElement.querySelector('trix-toolbar') as HTMLElement,
88
106
  blockCodeButton = toolbarElement.querySelector('[data-trix-attribute=code]') as HTMLElement
89
107
 
90
108
  // replace default trix "block code" button with "inline code" button
@@ -118,8 +136,8 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
118
136
  }, [editor, template])
119
137
 
120
138
  useEffect(() => {
121
- if (!element) return
122
- element.addEventListener('click', ({ target }: Event) => {
139
+ if (!editor?.element) return
140
+ editor.element.addEventListener('click', ({ target }: Event) => {
123
141
  const trixEditorContainer = (target as Element).closest('.pb_rich_text_editor_kit')
124
142
  if (!trixEditorContainer) return
125
143
 
@@ -128,7 +146,7 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
128
146
 
129
147
  if (anchorElement.hasAttribute('href')) window.open(anchorElement.href)
130
148
  })
131
- }, [element])
149
+ }, [editor])
132
150
 
133
151
  const richTextEditorClass = 'pb_rich_text_editor_kit',
134
152
  simpleClass = simple ? 'simple' : '',
@@ -137,7 +155,7 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
137
155
  inlineClass = inline ? 'inline' : '',
138
156
  toolbarBottomClass = toolbarBottom ? 'toolbar-bottom' : ''
139
157
 
140
- let css = classnames(globalProps(props, {maxWidth}), className)
158
+ let css = classnames(globalProps(props, { maxWidth }), className)
141
159
  css = classnames(
142
160
  richTextEditorClass,
143
161
  simpleClass,
@@ -1 +1 @@
1
- <%= pb_rails("rich_text_editor", props: {id: "default", value: "Add your text here. You can format your text, add links, quotes, and bullets."}) %>
1
+ <%= pb_rails("rich_text_editor", props: {input_options: { id: 'hidden_input_id', name: "hidden_input_name" }, value: "Add your text here. You can format your text, add links, quotes, and bullets."}) %>
@@ -1,5 +1,5 @@
1
1
  <%= react_component('RichTextEditor',
2
- object.rich_text_options,
3
- aria: object.aria,
4
- data: object.data
5
- ) %>
2
+ object.rich_text_options,
3
+ aria: object.aria,
4
+ data: object.data
5
+ ) %>
@@ -20,6 +20,7 @@ module Playbook
20
20
  prop :value
21
21
  prop :template
22
22
  prop :placeholder
23
+ prop :input_options
23
24
 
24
25
  def classname
25
26
  generate_classname("pb_rich_text_editor_kit", simple_class, focus_class, sticky_class, separator: " ")
@@ -49,6 +50,7 @@ module Playbook
49
50
  value: value,
50
51
  template: template,
51
52
  placeholder: placeholder,
53
+ inputOptions: input_options,
52
54
  }
53
55
  end
54
56
  end
@@ -21,6 +21,7 @@ type TableProps = {
21
21
  data?: { [key: string]: string },
22
22
  dataTable: boolean,
23
23
  disableHover?: boolean,
24
+ headerStyle?: "default" | "borderless" | "floating"
24
25
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) },
25
26
  id?: string,
26
27
  outerPadding?: "none" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl",
@@ -46,6 +47,7 @@ const Table = (props: TableProps): React.ReactElement => {
46
47
  data = {},
47
48
  dataTable = false,
48
49
  disableHover = false,
50
+ headerStyle = "default",
49
51
  htmlOptions = {},
50
52
  id,
51
53
  outerPadding = '',
@@ -85,6 +87,8 @@ const Table = (props: TableProps): React.ReactElement => {
85
87
  'sticky-left-column': stickyLeftColumn,
86
88
  'sticky-right-column': stickyRightColumn,
87
89
  'striped': striped,
90
+ 'header-borderless': headerStyle === 'borderless',
91
+ 'header-floating': headerStyle === 'floating',
88
92
  [outerPaddingCss]: outerPadding !== '',
89
93
  },
90
94
  globalProps(props),
@@ -0,0 +1,50 @@
1
+ import React from 'react'
2
+
3
+ import Table from '../../pb_table/_table'
4
+
5
+ const TableWithHeaderStyleBorderless = (props) => {
6
+ return (
7
+ <>
8
+ <Table
9
+ headerStyle="borderless"
10
+ size="sm"
11
+ {...props}
12
+ >
13
+ <thead>
14
+ <tr>
15
+ <th>{'Column 1'}</th>
16
+ <th>{'Column 2'}</th>
17
+ <th>{'Column 3'}</th>
18
+ <th>{'Column 4'}</th>
19
+ <th>{'Column 5'}</th>
20
+ </tr>
21
+ </thead>
22
+ <tbody>
23
+ <tr>
24
+ <td>{'Value 1'}</td>
25
+ <td>{'Value 2'}</td>
26
+ <td>{'Value 3'}</td>
27
+ <td>{'Value 4'}</td>
28
+ <td>{'Value 5'}</td>
29
+ </tr>
30
+ <tr>
31
+ <td>{'Value 1'}</td>
32
+ <td>{'Value 2'}</td>
33
+ <td>{'Value 3'}</td>
34
+ <td>{'Value 4'}</td>
35
+ <td>{'Value 5'}</td>
36
+ </tr>
37
+ <tr>
38
+ <td>{'Value 1'}</td>
39
+ <td>{'Value 2'}</td>
40
+ <td>{'Value 3'}</td>
41
+ <td>{'Value 4'}</td>
42
+ <td>{'Value 5'}</td>
43
+ </tr>
44
+ </tbody>
45
+ </Table>
46
+ </>
47
+ )
48
+ }
49
+
50
+ export default TableWithHeaderStyleBorderless
@@ -0,0 +1 @@
1
+ Customize your header by removing the header borders with the `headerStyle="borderless"` prop.
@@ -0,0 +1,59 @@
1
+ import React from 'react'
2
+
3
+ import Background from '../../pb_background/_background'
4
+ import Card from '../../pb_card/_card'
5
+ import Table from '../../pb_table/_table'
6
+
7
+ const TableWithHeaderStyleFloating = (props) => {
8
+ return (
9
+ <>
10
+ <Card background="light"
11
+ {...props}
12
+ >
13
+ <Table
14
+ headerStyle="floating"
15
+ size="sm"
16
+ {...props}
17
+ >
18
+ <Table.Head>
19
+ <Background backgroundColor="light"
20
+ tag="tr"
21
+ {...props}
22
+ >
23
+ <Table.Header>{'Column 1'}</Table.Header>
24
+ <Table.Header>{'Column 2'}</Table.Header>
25
+ <Table.Header>{'Column 3'}</Table.Header>
26
+ <Table.Header>{'Column 4'}</Table.Header>
27
+ <Table.Header>{'Column 5'}</Table.Header>
28
+ </Background>
29
+ </Table.Head>
30
+ <Table.Body>
31
+ <Table.Row>
32
+ <Table.Cell>{'Value 1'}</Table.Cell>
33
+ <Table.Cell>{'Value 2'}</Table.Cell>
34
+ <Table.Cell>{'Value 3'}</Table.Cell>
35
+ <Table.Cell>{'Value 4'}</Table.Cell>
36
+ <Table.Cell>{'Value 5'}</Table.Cell>
37
+ </Table.Row>
38
+ <Table.Row>
39
+ <Table.Cell>{'Value 1'}</Table.Cell>
40
+ <Table.Cell>{'Value 2'}</Table.Cell>
41
+ <Table.Cell>{'Value 3'}</Table.Cell>
42
+ <Table.Cell>{'Value 4'}</Table.Cell>
43
+ <Table.Cell>{'Value 5'}</Table.Cell>
44
+ </Table.Row>
45
+ <Table.Row>
46
+ <Table.Cell>{'Value 1'}</Table.Cell>
47
+ <Table.Cell>{'Value 2'}</Table.Cell>
48
+ <Table.Cell>{'Value 3'}</Table.Cell>
49
+ <Table.Cell>{'Value 4'}</Table.Cell>
50
+ <Table.Cell>{'Value 5'}</Table.Cell>
51
+ </Table.Row>
52
+ </Table.Body>
53
+ </Table>
54
+ </Card>
55
+ </>
56
+ )
57
+ }
58
+
59
+ export default TableWithHeaderStyleFloating
@@ -0,0 +1 @@
1
+ Further customize your header by using the [table with background kit](https://playbook.powerapp.cloud/kits/table/react#table-with-background-kit) logic to give your table header a custom background color. Use the `headerStyle="floating"` prop to visually nest the borderless table within a card or collapsible with a matching background color (the `backgroundColor` passed to Background kit should match the `backgroundColor` for the element in which it is nested).
@@ -75,3 +75,5 @@ examples:
75
75
  - table_with_collapsible_with_nested_table: Table with Collapsible with Nested Table
76
76
  - table_with_clickable_rows: Table with Clickable Rows
77
77
  - table_with_selectable_rows: Table with Selectable Rows
78
+ - table_with_header_style_borderless: Header Style Borderless
79
+ - table_with_header_style_floating: Header Style Floating
@@ -35,3 +35,5 @@ export { default as TableWithCollapsibleWithNestedRows } from './_table_with_col
35
35
  export { default as TableWithCollapsibleWithCustomClick } from './_table_with_collapsible_with_custom_click.jsx'
36
36
  export { default as TableWithSelectableRows } from './_table_with_selectable_rows.jsx'
37
37
  export { default as TableWithClickableRows } from './_table_with_clickable_rows.jsx'
38
+ export { default as TableWithHeaderStyleBorderless } from './_table_with_header_style_borderless.jsx'
39
+ export { default as TableWithHeaderStyleFloating } from './_table_with_header_style_floating.jsx'
@@ -14,3 +14,79 @@
14
14
  }
15
15
  }
16
16
  }
17
+ // remove all outward facing borders from header
18
+ .header-borderless > thead,
19
+ .header-borderless > thead > tr,
20
+ .header-borderless > thead > tr > th,
21
+ .header-borderless > .pb_table_thead,
22
+ .header-borderless > .pb_table_thead > .pb_table_tr,
23
+ .header-borderless > .pb_table_thead .pb_table_th {
24
+ border-top: none !important;
25
+ border-left: none !important;
26
+ border-right: none !important;
27
+ }
28
+
29
+ // remove bottom border (internal to table) on header cells - only light mode needs this redundancy handled likely due to a difference in the base scss and table-dark.scss
30
+ .header-borderless:not(.table-dark) > thead > tr:last-child > th,
31
+ .header-borderless:not(.table-dark) > .pb_table_thead > .pb_table_tr:last-child > .pb_table_th {
32
+ border-bottom: none !important;
33
+ }
34
+
35
+ // preserves top rounded corners to header at top of table-card for unnested card
36
+ .header-borderless > thead > tr:first-child > th:first-child,
37
+ .header-borderless > .pb_table_thead > .pb_table_tr:first-child > .pb_table_th:first-child {
38
+ border-top-left-radius: $border_radius_md !important;
39
+ }
40
+
41
+ .header-borderless > thead > tr:first-child > th:last-child,
42
+ .header-borderless > .pb_table_thead > .pb_table_tr:first-child > .pb_table_th:last-child {
43
+ border-top-right-radius: $border_radius_md !important;
44
+ }
45
+
46
+ // ensures top border is from first row of body to prevent double borders
47
+ .header-borderless > tbody > tr:first-child > td,
48
+ .header-borderless > .pb_table_tbody > .pb_table_tr:first-child > .pb_table_td {
49
+ border-top: 1px solid $border_light !important;
50
+ }
51
+
52
+ // floating code - this carries over everything for header-borderless
53
+ .header-floating > thead,
54
+ .header-floating > thead > tr,
55
+ .header-floating > thead > tr > th,
56
+ .header-floating > .pb_table_thead,
57
+ .header-floating > .pb_table_thead > .pb_table_tr,
58
+ .header-floating > .pb_table_thead .pb_table_th {
59
+ border-top: none !important;
60
+ border-left: none !important;
61
+ border-right: none !important;
62
+ }
63
+
64
+ .header-floating:not(.table-dark) > thead > tr:last-child > th,
65
+ .header-floating:not(.table-dark) > .pb_table_thead > .pb_table_tr:last-child > .pb_table_th {
66
+ border-bottom: none !important;
67
+ }
68
+
69
+ .header-floating > thead > tr:first-child > th:first-child,
70
+ .header-floating > .pb_table_thead > .pb_table_tr:first-child > .pb_table_th:first-child {
71
+ border-top-left-radius: $border_radius_md !important;
72
+ }
73
+
74
+ .header-floating > thead > tr:first-child > th:last-child,
75
+ .header-floating > .pb_table_thead > .pb_table_tr:first-child > .pb_table_th:last-child {
76
+ border-top-right-radius: $border_radius_md !important;
77
+ }
78
+
79
+ .header-floating > tbody > tr:first-child > td,
80
+ .header-floating > .pb_table_tbody > .pb_table_tr:first-child > .pb_table_td {
81
+ border-top: 1px solid $border_light !important;
82
+ }
83
+
84
+ // flatten out corners for floating headerstyle variant to avoid small triangle of white/empty space
85
+ .header-floating > thead > tr:first-child > th:first-child,
86
+ .header-floating > .pb_table_thead > .pb_table_tr:first-child > .pb_table_th:first-child {
87
+ border-top-left-radius: 0 !important;
88
+ }
89
+ .header-floating > thead > tr:first-child > th:last-child,
90
+ .header-floating > .pb_table_thead > .pb_table_tr:first-child > .pb_table_th:last-child {
91
+ border-top-right-radius: 0 !important;
92
+ }
@@ -12,6 +12,7 @@ type TableHeadPropTypes = {
12
12
  children: React.ReactNode[] | React.ReactNode;
13
13
  className: string;
14
14
  data?: { [key: string]: string };
15
+ headerStyle?: "default" | "borderless" | "floating";
15
16
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
16
17
  id?: string;
17
18
  tag?: "table" | "div";
@@ -23,6 +24,7 @@ const TableHead = (props: TableHeadPropTypes): React.ReactElement => {
23
24
  children,
24
25
  className,
25
26
  data = {},
27
+ headerStyle = "default",
26
28
  htmlOptions = {},
27
29
  id,
28
30
  tag = "table",
@@ -31,7 +33,15 @@ const TableHead = (props: TableHeadPropTypes): React.ReactElement => {
31
33
  const ariaProps = buildAriaProps(aria);
32
34
  const dataProps = buildDataProps(data);
33
35
  const htmlProps = buildHtmlProps(htmlOptions);
34
- const classes = classnames("pb_table_thead", globalProps(props), className);
36
+ const classes = classnames(
37
+ "pb_table_thead",
38
+ {
39
+ "pb_table_thead_borderless": headerStyle === "borderless" || headerStyle === "floating",
40
+ "pb_table_thead_floating": headerStyle === "floating",
41
+ },
42
+ globalProps(props),
43
+ className
44
+ );
35
45
  const isTableTag = tag === "table";
36
46
 
37
47
  return (
@@ -12,6 +12,7 @@ type TableHeaderPropTypes = {
12
12
  children: React.ReactNode[] | React.ReactNode;
13
13
  className: string;
14
14
  data?: { [key: string]: string };
15
+ headerStyle?: "default" | "borderless" | "floating";
15
16
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
16
17
  id?: string;
17
18
  tag?: "table" | "div";
@@ -24,6 +25,7 @@ const TableHeader = (props: TableHeaderPropTypes): React.ReactElement => {
24
25
  children,
25
26
  className,
26
27
  data = {},
28
+ headerStyle = "default",
27
29
  htmlOptions = {},
28
30
  id,
29
31
  tag = "table",
@@ -33,7 +35,15 @@ const TableHeader = (props: TableHeaderPropTypes): React.ReactElement => {
33
35
  const ariaProps = buildAriaProps(aria);
34
36
  const dataProps = buildDataProps(data);
35
37
  const htmlProps = buildHtmlProps(htmlOptions);
36
- const classes = classnames("pb_table_th", globalProps(props), className);
38
+ const classes = classnames(
39
+ "pb_table_th",
40
+ {
41
+ "pb_table_thead_borderless": headerStyle === "borderless" || headerStyle === "floating",
42
+ "pb_table_thead_floating": headerStyle === "floating",
43
+ },
44
+ globalProps(props),
45
+ className
46
+ );
37
47
  const isTableTag = tag === "table";
38
48
 
39
49
  return (
@@ -22,6 +22,7 @@ type TableRowPropTypes = {
22
22
  dark?: boolean;
23
23
  dragId?: string;
24
24
  draggableItem?: boolean;
25
+ headerStyle?: "default" | "borderless" | "floating";
25
26
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
26
27
  id?: string;
27
28
  toggleCellId?: string;
@@ -41,6 +42,7 @@ const TableRow = (props: TableRowPropTypes): React.ReactElement => {
41
42
  dark = false,
42
43
  dragId,
43
44
  draggableItem = false,
45
+ headerStyle = "default",
44
46
  htmlOptions = {},
45
47
  id,
46
48
  toggleCellId,
@@ -60,6 +62,9 @@ const TableRow = (props: TableRowPropTypes): React.ReactElement => {
60
62
  const classes = classnames(
61
63
  buildCss("pb_table_row_kit", sideHighlightClass),
62
64
  "pb_table_tr",
65
+ {
66
+ "pb_table_tr_borderless_header": headerStyle === "borderless",
67
+ },
63
68
  collapsibleRow,
64
69
  globalProps(props),
65
70
  className
@@ -167,3 +167,20 @@ test("Should have outerPadding class", () => {
167
167
  const kit = renderKit(Table, props, { outerPadding: "sm" })
168
168
  expect(kit).toHaveClass("pb_table table-sm table-responsive-collapse table-card outer_padding_space_sm table-collapse-sm")
169
169
  })
170
+
171
+ test("when headerStyle is default", () => {
172
+ const kit = renderKit(Table, props)
173
+ expect(kit).toHaveClass("pb_table table-sm table-responsive-collapse table-card table-collapse-sm")
174
+ expect(kit).not.toHaveClass("header-borderless")
175
+ expect(kit).not.toHaveClass("header-floating")
176
+ })
177
+
178
+ test("when headerStyle is borderless", () => {
179
+ const kit = renderKit(Table, props, { headerStyle: "borderless" })
180
+ expect(kit).toHaveClass("pb_table table-sm table-responsive-collapse table-card header-borderless table-collapse-sm")
181
+ })
182
+
183
+ test("when headerStyle is floating", () => {
184
+ const kit = renderKit(Table, props, { headerStyle: "floating" })
185
+ expect(kit).toHaveClass("pb_table table-sm table-responsive-collapse table-card header-floating table-collapse-sm")
186
+ })