playbook_ui_docs 16.8.0.pre.alpha.PLAY298616637 → 16.8.0.pre.alpha.play293416802

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.html.erb +62 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.md +7 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.jsx +12 -4
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.md +4 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.html.erb +16 -2
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.md +4 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.jsx +68 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.md +7 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +16 -2
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.jsx +12 -5
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +4 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +5 -3
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
  16. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_dialog_submission.jsx +2 -2
  17. data/app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb +5 -1
  18. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive.html.erb +116 -0
  19. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive.md +14 -0
  20. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.jsx +153 -0
  21. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.md +10 -0
  22. data/app/pb_kits/playbook/pb_filter/docs/example.yml +2 -0
  23. data/app/pb_kits/playbook/pb_filter/docs/index.js +2 -1
  24. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.html.erb +85 -83
  25. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.jsx +88 -86
  26. data/app/pb_kits/playbook/pb_table/docs/_table_sticky.md +3 -1
  27. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_external_filter_rails.md +1 -1
  28. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_default.md +3 -1
  29. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.html.erb +24 -0
  30. data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler_rails.md +6 -0
  31. data/app/pb_kits/playbook/pb_time_picker/docs/example.yml +1 -0
  32. metadata +13 -3
  33. /data/app/pb_kits/playbook/pb_time_picker/docs/{_time_picker_on_handler.md → _time_picker_on_handler_react.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 596ee7f7c70ef9f133fad473e4e2c4060753e23339f76965b077b081884a0992
4
- data.tar.gz: 2303ee885e0c4deb40a56bac5716e84ab82237ace88081528b84902087d53678
3
+ metadata.gz: f113ae8f11b4e289b8de3c2b1b554a6b36606b142f024acf02a60475c479f6e0
4
+ data.tar.gz: 0dad54e09afb9bd5ec35b431e97cd8b221a64dbf8084353548e062e789d3186e
5
5
  SHA512:
6
- metadata.gz: 306aee1005a77f0d518fcaff7f7bc08a8527a621ea12b0224a77484b0cdf5544242bc143ef6658a229343e5d7e9c4c8f7b74da17adf062d95ee4280b59b17756
7
- data.tar.gz: 1dd8e7002156fa66d8adee2dd12c2addaab61a4e44450e61a746533eadd9ed022996ced4bbe201001b0b448f9666f722e3fccd819fd9871fbfc6469f81569b7d
6
+ metadata.gz: 1c69733472ccbf8d63187222c45516050c6d52f271a3dcdab9349104d1cfac2d0b9b3b071af0c90db93d4be5dfb88bf5644dd7896ad68867819ae3fcf3ba4d99
7
+ data.tar.gz: fcbe504b76d1b96bf2d36ce9ad4c5f51ced0a160b5e504c7fdd1aa8d77226928ae45df2a97a99d84f981d4c4a69c12d93ced5192601bb31d972a350d1adb7f5e
@@ -0,0 +1,62 @@
1
+ <%
2
+ column_definitions = [
3
+ {
4
+ accessor: "year",
5
+ label: "Year",
6
+ cellAccessors: ["quarter", "month", "day"],
7
+ },
8
+ {
9
+ accessor: "newEnrollments",
10
+ label: "New Enrollments",
11
+ },
12
+ {
13
+ accessor: "scheduledMeetings",
14
+ label: "Scheduled Meetings",
15
+ },
16
+ {
17
+ accessor: "attendanceRate",
18
+ label: "Attendance Rate",
19
+ },
20
+ {
21
+ accessor: "completedClasses",
22
+ label: "Completed Classes",
23
+ },
24
+ {
25
+ accessor: "classCompletionRate",
26
+ label: "Class Completion Rate",
27
+ },
28
+ {
29
+ accessor: "graduatedStudents",
30
+ label: "Graduated Students",
31
+ }
32
+ ]
33
+
34
+ subrow_headers = ["Quarter", "Month", "Day"]
35
+ %>
36
+
37
+ <%= pb_rails("title", props: { size: 4, text: "Normal Structure", margin_bottom: "sm" }) %>
38
+
39
+ <%= pb_rails("advanced_table", props: {
40
+ id: "enable-toggle-expansion-normal",
41
+ table_data: @table_data,
42
+ column_definitions: column_definitions,
43
+ enable_toggle_expansion: "all"
44
+ }) %>
45
+
46
+ <%= pb_rails("title", props: { size: 4, text: "Subcomponent Structure", margin_top: "lg", margin_bottom: "sm" }) %>
47
+
48
+ <%= pb_rails("advanced_table", props: { id: "enable-toggle-expansion-subcomponents" }) do %>
49
+ <%= pb_rails("advanced_table/table_header", props: {
50
+ table_id: "enable-toggle-expansion-subcomponents",
51
+ table_data: @table_data,
52
+ column_definitions: column_definitions,
53
+ enable_toggle_expansion: "all"
54
+ }) %>
55
+ <%= pb_rails("advanced_table/table_body", props: {
56
+ table_id: "enable-toggle-expansion-subcomponents",
57
+ table_data: @table_data,
58
+ column_definitions: column_definitions,
59
+ subrow_headers: subrow_headers,
60
+ enable_toggle_expansion: "all"
61
+ }) %>
62
+ <% end %>
@@ -0,0 +1,7 @@
1
+ `enable_toggle_expansion` controls where AdvancedTable renders toggle-all expansion controls. It accepts `"header"`, `"all"`, or `"none"` and defaults to `"header"`.
2
+
3
+ When using the normal Rails structure, pass `enable_toggle_expansion` to `advanced_table`. The parent kit renders its own `table_header` and `table_body`, so the prop is passed down automatically.
4
+
5
+ When using the Rails subcomponent structure, pass `enable_toggle_expansion` directly to the subcomponents that need it. `advanced_table/table_header` uses it for the table header toggle-all button. **NOTE**: you must pass `table_data` to `advanced_table/table_header` as well so it can detect whether expandable rows exist. `advanced_table/table_body` uses it for nested subrow header toggle controls, such as when `subrow_headers` is present.
6
+
7
+ Use `"all"` when you want toggle-all controls in both the table header and subrow headers. Use `"header"` when you only want the table header toggle-all control. Use `"none"` to suppress the header toggle-all control.
@@ -1,13 +1,21 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../../pb_advanced_table/_advanced_table'
3
- import MOCK_DATA from "./advanced_table_mock_data.json"
3
+
4
+ const tableData = Array.from({ length: 15 }, (_, index) => ({
5
+ year: String(2020 + index),
6
+ newEnrollments: String(20 + index),
7
+ scheduledMeetings: String(10 + index),
8
+ attendanceRate: `${50 + index}%`,
9
+ completedClasses: String(3 + index),
10
+ classCompletionRate: `${30 + index}%`,
11
+ graduatedStudents: String(19 + index),
12
+ }))
4
13
 
5
14
  const AdvancedTableStickyHeader = (props) => {
6
15
  const columnDefinitions = [
7
16
  {
8
17
  accessor: "year",
9
18
  label: "Year",
10
- cellAccessors: ["quarter", "month", "day"],
11
19
  },
12
20
  {
13
21
  accessor: "newEnrollments",
@@ -40,11 +48,11 @@ const AdvancedTableStickyHeader = (props) => {
40
48
  }
41
49
 
42
50
  return (
43
- <div>
51
+ <div style={{ maxHeight: "320px", overflowY: "auto" }}>
44
52
  <AdvancedTable
45
53
  columnDefinitions={columnDefinitions}
46
54
  responsive="none"
47
- tableData={MOCK_DATA}
55
+ tableData={tableData}
48
56
  tableProps={tableProps}
49
57
  {...props}
50
58
  />
@@ -1,3 +1,7 @@
1
1
  The `TableProps` prop can also be used to render a sticky header for the Advanced Table.
2
2
 
3
+ This doc example uses a scroll container with flat rows so sticky behavior is visible in the docs without expanding subrows. Scroll inside the preview to see the header stick.
4
+
5
+ This example builds flat table data inline for the docs preview. For typical `tableData` setup, see [Default (Required Props)](/kits/advanced_table/default/react#advanced_table_default).
6
+
3
7
  This doc example showcases how to set a sticky header for a nonresponsive table (see the `responsive` prop set to "none"). To achieve sticky header AND responsive functionality, see the "Sticky Header for Responsive Table" doc example below.
@@ -2,7 +2,6 @@
2
2
  {
3
3
  accessor: "year",
4
4
  label: "Year",
5
- cellAccessors: ["quarter", "month", "day"],
6
5
  },
7
6
  {
8
7
  accessor: "newEnrollments",
@@ -30,4 +29,19 @@
30
29
  }
31
30
  ] %>
32
31
 
33
- <%= pb_rails("advanced_table", props: { id: "sticky_header_table", table_data: @table_data, column_definitions: column_definitions, responsive: "none", table_props: { sticky: true }}) %>
32
+ <% table_data = 15.times.map do |index|
33
+ {
34
+ year: (2020 + index).to_s,
35
+ id: (2020 + index).to_s,
36
+ newEnrollments: (20 + index).to_s,
37
+ scheduledMeetings: (10 + index).to_s,
38
+ attendanceRate: "#{50 + index}%",
39
+ completedClasses: (3 + index).to_s,
40
+ classCompletionRate: "#{30 + index}%",
41
+ graduatedStudents: (19 + index).to_s,
42
+ }
43
+ end %>
44
+
45
+ <div style="max-height: 320px; overflow-y: auto;">
46
+ <%= pb_rails("advanced_table", props: { id: "sticky_header_table", table_data: table_data, column_definitions: column_definitions, responsive: "none", table_props: { sticky: true }}) %>
47
+ </div>
@@ -1,3 +1,7 @@
1
1
  The `table_props` prop can also be used to render a sticky header for the Advanced Table.
2
2
 
3
+ This doc example uses a scroll container with flat rows so sticky behavior is visible in the docs without expanding subrows. Scroll inside the preview to see the header stick.
4
+
5
+ This example builds flat table data inline for the docs preview. For typical `table_data` setup, see [Default (Required Props)](/kits/advanced_table/default/rails#advanced_table_beta).
6
+
3
7
  This doc example showcases how to set a sticky header for a nonresponsive table (see the `responsive` prop set to "none"). To achieve sticky header AND responsive functionality, see the "[Sticky Header for Responsive Table](https://playbook.powerapp.cloud/kits/advanced_table/react#sticky-header-for-responsive-table)" doc example below.
@@ -0,0 +1,68 @@
1
+ import React from "react"
2
+ import AdvancedTable from "../../pb_advanced_table/_advanced_table"
3
+ import Title from "../../pb_title/_title"
4
+
5
+ const COLUMN_COUNT = 10
6
+ const ROW_COUNT = 40
7
+
8
+ const columnDefinitions = [
9
+ {
10
+ accessor: "region",
11
+ label: "Region",
12
+ id: "region",
13
+ columnStyling: { minWidth: 160 },
14
+ },
15
+ ...Array.from({ length: COLUMN_COUNT }, (_, index) => ({
16
+ accessor: `metric${index + 1}`,
17
+ label: `Metric ${index + 1}`,
18
+ id: `metric${index + 1}`,
19
+ columnStyling: { minWidth: 180 },
20
+ })),
21
+ ]
22
+
23
+ const tableData = Array.from({ length: ROW_COUNT }, (_, row) => ({
24
+ region: `Region ${row + 1}`,
25
+ ...Object.fromEntries(
26
+ Array.from({ length: COLUMN_COUNT }, (_, col) => [
27
+ `metric${col + 1}`,
28
+ String((row + 1) * (col + 1)),
29
+ ])
30
+ ),
31
+ }))
32
+
33
+ const tableProps = { sticky: true }
34
+
35
+ const AdvancedTableStickyScrollLimitation = (props) => (
36
+ <div>
37
+ <Title
38
+ size={4}
39
+ text="Without maxHeight"
40
+ {...props}
41
+ />
42
+ <AdvancedTable
43
+ columnDefinitions={columnDefinitions}
44
+ responsive="none"
45
+ stickyLeftColumn={["region"]}
46
+ tableData={tableData}
47
+ tableProps={tableProps}
48
+ {...props}
49
+ />
50
+ <Title
51
+ paddingTop="sm"
52
+ size={4}
53
+ text="With maxHeight"
54
+ {...props}
55
+ />
56
+ <AdvancedTable
57
+ columnDefinitions={columnDefinitions}
58
+ maxHeight="sm"
59
+ responsive="none"
60
+ stickyLeftColumn={["region"]}
61
+ tableData={tableData}
62
+ tableProps={tableProps}
63
+ {...props}
64
+ />
65
+ </div>
66
+ )
67
+
68
+ export default AdvancedTableStickyScrollLimitation
@@ -0,0 +1,7 @@
1
+ `stickyLeftColumn` adds horizontal overflow to the table wrapper. Without `maxHeight`, the page scrolls vertically while the table scrolls horizontally — two scroll containers.
2
+
3
+ Sticky columns work in that setup, but the sticky header cannot stick to the page. Scroll down on the page, then scroll the first table horizontally to see the conflict.
4
+
5
+ The second table uses `maxHeight` so both axes share one scroll container. The header sticks to the top of the table box instead of the page.
6
+
7
+ For a typical implementation with subrows, see [Sticky Columns with Sticky Header](#sticky-columns-with-sticky-header).
@@ -2,7 +2,6 @@
2
2
  {
3
3
  accessor: "year",
4
4
  label: "Year",
5
- cellAccessors: ["quarter", "month", "day"],
6
5
  },
7
6
  {
8
7
  accessor: "newEnrollments",
@@ -30,4 +29,19 @@
30
29
  }
31
30
  ] %>
32
31
 
33
- <%= pb_rails("advanced_table", props: { id: "table_props_sticky_table", table_data: @table_data, column_definitions: column_definitions, max_height: "xs", table_props: { sticky: true }}) %>
32
+ <% table_data = 15.times.map do |index|
33
+ {
34
+ year: (2020 + index).to_s,
35
+ id: (2020 + index).to_s,
36
+ newEnrollments: (20 + index).to_s,
37
+ scheduledMeetings: (10 + index).to_s,
38
+ attendanceRate: "#{50 + index}%",
39
+ completedClasses: (3 + index).to_s,
40
+ classCompletionRate: "#{30 + index}%",
41
+ graduatedStudents: (19 + index).to_s,
42
+ }
43
+ end %>
44
+
45
+ <div style="max-height: 320px; overflow-y: auto;">
46
+ <%= pb_rails("advanced_table", props: { id: "table_props_sticky_table", table_data: table_data, column_definitions: column_definitions, table_props: { sticky: true }}) %>
47
+ </div>
@@ -1,13 +1,21 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../../pb_advanced_table/_advanced_table'
3
- import MOCK_DATA from "./advanced_table_mock_data.json"
3
+
4
+ const tableData = Array.from({ length: 15 }, (_, index) => ({
5
+ year: String(2020 + index),
6
+ newEnrollments: String(20 + index),
7
+ scheduledMeetings: String(10 + index),
8
+ attendanceRate: `${50 + index}%`,
9
+ completedClasses: String(3 + index),
10
+ classCompletionRate: `${30 + index}%`,
11
+ graduatedStudents: String(19 + index),
12
+ }))
4
13
 
5
14
  const AdvancedTableTablePropsStickyHeader = (props) => {
6
15
  const columnDefinitions = [
7
16
  {
8
17
  accessor: "year",
9
18
  label: "Year",
10
- cellAccessors: ["quarter", "month", "day"],
11
19
  },
12
20
  {
13
21
  accessor: "newEnrollments",
@@ -40,11 +48,10 @@ const AdvancedTableTablePropsStickyHeader = (props) => {
40
48
  }
41
49
 
42
50
  return (
43
- <div>
51
+ <div style={{ maxHeight: "320px", overflowY: "auto" }}>
44
52
  <AdvancedTable
45
53
  columnDefinitions={columnDefinitions}
46
- maxHeight="xs"
47
- tableData={MOCK_DATA}
54
+ tableData={tableData}
48
55
  tableProps={tableProps}
49
56
  {...props}
50
57
  />
@@ -2,6 +2,10 @@ Create a sticky header that works for responsive Advanced Tables by setting `sti
2
2
 
3
3
  **NOTE**: This behavior requires a `max_height` to work. The header is sticky within the table container, allowing for it to work along with the first column stickiness of a responsive table on smaller screen sizes.
4
4
 
5
+ Scroll inside the table preview to see the header stick.
6
+
7
+ This example builds flat table data inline for the docs preview. For typical `table_data` setup, see [Default (Required Props)](/kits/advanced_table/default/rails#advanced_table_beta).
8
+
5
9
  Expand the table above to see this in action.
6
10
 
7
11
  A sticky header on a nonresponsive table is demonstrated in the ["Sticky Header"](https://playbook.powerapp.cloud/kits/advanced_table#sticky-header) doc example above.
@@ -1,7 +1,9 @@
1
- Create a sticky header that works for responsive Advanced Tables by setting `sticky: true` via `tableProps` and giving the AdvancedTable a `maxHeight` using our [Max Height](https://playbook.powerapp.cloud/global_props/max_height) global prop.
1
+ Create a sticky header that works for responsive Advanced Tables by setting `sticky: true` via `tableProps` and wrapping the table in a scroll container (or using `maxHeight`).
2
2
 
3
- **NOTE**: This behavior requires a `maxHeight` to work. The header is sticky within the table container, allowing for it to work along with the first column stickiness of a responsive table on smaller screen sizes.
3
+ **NOTE**: The header is sticky within the table scroll area. The live example uses flat rows so you can scroll inside the preview without expanding subrows.
4
4
 
5
- Expand the table above to see this in action.
5
+ This example builds flat table data inline for the docs preview. For typical `tableData` setup, see [Default (Required Props)](/kits/advanced_table/default/react#advanced_table_default).
6
+
7
+ Expand the table above to see responsive behavior in action.
6
8
 
7
9
  A sticky header on a nonresponsive table is demonstrated in the ["Sticky Header"](https://playbook.powerapp.cloud/kits/advanced_table/react#sticky-header) doc example above.
@@ -3,6 +3,7 @@ examples:
3
3
  - advanced_table_beta: Default (Required Props)
4
4
  - advanced_table_loading: Loading State
5
5
  - advanced_table_beta_subrow_headers: SubRow Headers
6
+ - advanced_table_enable_toggle_expansion_rails: Enable Toggle Expansion
6
7
  - advanced_table_collapsible_trail_rails: Collapsible Trail
7
8
  - advanced_table_table_props: Table Props
8
9
  - advanced_table_sticky_header_rails: Sticky Header
@@ -52,6 +53,7 @@ examples:
52
53
  - advanced_table_table_props_sticky_header: Sticky Header for Responsive Table
53
54
  - advanced_table_sticky_columns: Sticky Columns
54
55
  - advanced_table_sticky_columns_and_header: Sticky Columns with Sticky Header
56
+ - advanced_table_sticky_scroll_limitation: Sticky Header and Column Scroll Limitation
55
57
  - advanced_table_responsive: Responsive Tables
56
58
  - advanced_table_custom_cell: Custom Components for Cells
57
59
  - advanced_table_with_custom_header: Custom Header Cell
@@ -27,6 +27,7 @@ export { default as AdvancedTableFullscreen } from './_advanced_table_fullscreen
27
27
  export { default as AdvancedTableStickyColumns } from './_advanced_table_sticky_columns.jsx'
28
28
  export { default as AdvancedTableStickyHeader } from './_advanced_table_sticky_header.jsx'
29
29
  export { default as AdvancedTableStickyColumnsAndHeader } from './_advanced_table_sticky_columns_and_header.jsx'
30
+ export { default as AdvancedTableStickyScrollLimitation } from './_advanced_table_sticky_scroll_limitation.jsx'
30
31
  export { default as AdvancedTableExpandByDepth } from './_advanced_table_expand_by_depth.jsx'
31
32
  export { default as AdvancedTableColumnBorderColor} from './_advanced_table_column_border_color.jsx'
32
33
  export { default as AdvancedTableColumnVisibility } from './_advanced_table_column_visibility.jsx'
@@ -36,10 +36,10 @@ const DatePickerDialogSubmission = () => {
36
36
  <Dialog.Body>
37
37
  <DatePicker
38
38
  defaultDate={dateFixed || undefined}
39
- key={`fixed-${pickerInstance}`}
39
+ key={"fixed-" + pickerInstance}
40
40
  label="Date"
41
41
  onChange={(dateStr) => setDateFixed(dateStr || "")}
42
- pickerId={`datePickerFixed-${pickerInstance}`}
42
+ pickerId={"datePickerFixed-" + pickerInstance}
43
43
  staticPosition={false}
44
44
  />
45
45
  </Dialog.Body>
@@ -28,7 +28,11 @@
28
28
  <%= pb_rails("form", props: { form_system_options: { scope: :example, method: :get } }) do |form| %>
29
29
  <%= form.text_field :example_text_field, props: { label: true } %>
30
30
  <%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true } %>
31
-
31
+ <%= pb_rails("date_picker", props: {
32
+ label: "Start date",
33
+ name: "start_date",
34
+ picker_id: "filter-default",
35
+ }) %>
32
36
  <%= form.actions do |action| %>
33
37
  <%= action.submit props: {
34
38
  text: "Apply",
@@ -0,0 +1,116 @@
1
+ <%
2
+ territory_options = [
3
+ { value: "USA", label: "USA" },
4
+ { value: "Canada", label: "Canada" },
5
+ { value: "Brazil", label: "Brazil" },
6
+ { value: "Philippines", label: "Philippines" },
7
+ ]
8
+
9
+ status_options = [
10
+ { value: "open", label: "Open", id: "open" },
11
+ { value: "in_progress", label: "In progress", id: "in_progress" },
12
+ { value: "resolved", label: "Resolved", id: "resolved" },
13
+ { value: "closed", label: "Closed", id: "closed" },
14
+ ]
15
+
16
+ raw_example = params[:example]
17
+ example_params =
18
+ if raw_example.respond_to?(:permit)
19
+ raw_example.permit(:territory, :status, :date_range, :start_date)
20
+ else
21
+ raw_example || {}
22
+ end
23
+ current_territory = example_params[:territory].presence || "USA"
24
+ current_status = example_params[:status].presence || "open"
25
+ current_date_range = example_params[:date_range].presence || "quickpick-this-week"
26
+ current_start = example_params[:start_date].presence || "05/01/2026"
27
+ status_default = status_options.find { |o| o[:value] == current_status }
28
+ %>
29
+
30
+ <%=
31
+ pb_rails("filter", props: {
32
+ id: "filter-interactive-demo",
33
+ min_width: "360px",
34
+ margin_bottom: "xl",
35
+ template: "default",
36
+ results: 546,
37
+ filters: [
38
+ { name: "Territory", value: current_territory },
39
+ { name: "Status", value: current_status },
40
+ { name: "Date range", value: current_date_range },
41
+ { name: "Start date", value: current_start },
42
+ ],
43
+ interactive_filters: [
44
+ {
45
+ name: "Territory",
46
+ type: "select",
47
+ options: territory_options,
48
+ target_input: "filter-interactive-territory",
49
+ auto_submit: true,
50
+ },
51
+ {
52
+ name: "Status",
53
+ type: "dropdown",
54
+ options: status_options,
55
+ target_input: "filter-interactive-status",
56
+ auto_submit: true,
57
+ },
58
+ {
59
+ name: "Date range",
60
+ type: "dropdown",
61
+ variant: "quickpick",
62
+ target_input: "filter-interactive-date-range",
63
+ auto_submit: true,
64
+ },
65
+ {
66
+ name: "Start date",
67
+ type: "date-picker",
68
+ target_input: "filter-interactive-start",
69
+ format: "m/d/Y",
70
+ auto_submit: true,
71
+ },
72
+ ],
73
+ sort_menu: [
74
+ { item: "Popularity", link: "?q[sorts]=managers_popularity+asc", active: true, direction: "desc" },
75
+ ],
76
+ }) do
77
+ %>
78
+ <%= pb_rails("form", props: { form_system_options: { scope: :example, method: :get } }) do |form| %>
79
+ <%= pb_rails("select", props: {
80
+ label: "Territory",
81
+ name: "territory",
82
+ options: territory_options.map { |o| { value: o[:value], text: o[:label] } },
83
+ value: current_territory,
84
+ input_options: { id: "filter-interactive-territory" }
85
+ }) %>
86
+
87
+ <%= pb_rails("dropdown", props: {
88
+ id: "filter-interactive-status",
89
+ label: "Status",
90
+ name: "status",
91
+ options: status_options,
92
+ default_value: status_default,
93
+ margin_bottom: "sm",
94
+ }) %>
95
+
96
+ <%= pb_rails("dropdown", props: {
97
+ id: "filter-interactive-date-range",
98
+ label: "Date range",
99
+ name: "date_range",
100
+ variant: "quickpick",
101
+ margin_bottom: "sm",
102
+ }) %>
103
+
104
+ <%= pb_rails("date_picker", props: {
105
+ label: "Start date",
106
+ name: "start_date",
107
+ picker_id: "filter-interactive-start",
108
+ default_date: current_start,
109
+ }) %>
110
+
111
+ <%= form.actions do |action| %>
112
+ <%= action.submit props: { text: "Apply" } %>
113
+ <%= action.button props: { type: "reset", text: "Clear", variant: "secondary" } %>
114
+ <% end %>
115
+ <% end %>
116
+ <% end %>
@@ -0,0 +1,14 @@
1
+ Click an applied filter chip to edit it inline. `interactive_filters` supports:
2
+
3
+ - `type: 'select'` / `'dropdown'`: pick from a list of options.
4
+ - `type: 'date-picker'`: inline calendar. Supports `format`, `min_date`, `max_date`, and `mode`.
5
+
6
+ Each entry needs a `target_input` that points to the form control it updates. For `select` and `date-picker`, use the input's `id`. For `dropdown`, use the Dropdown kit's `id`.
7
+
8
+ For date ranges, use `type: 'dropdown'` with `variant: 'quickpick'`. The Filter kit generates the same quickpick options as Dropdown, so no `options` are needed. Values are quickpick ids, such as `quickpick-this-week`.
9
+
10
+ Chip edits update the linked control inside the filter popover. Click **Apply** to submit, then pass the submitted values back into `filters` so chips re-render with the latest labels.
11
+
12
+ To preserve space for results and sort controls, only the first four applied filters are interactive at `lg` screen sizes (`960px`) and larger. Below `960px`, applied filters render as static chips; edit values from the filter popover instead.
13
+
14
+ Use `auto_submit: true` to submit the form immediately after a chip value is picked.
@@ -0,0 +1,153 @@
1
+ import React, { useState } from "react";
2
+
3
+ import Filter from "../_filter";
4
+
5
+ import Button from "../../pb_button/_button";
6
+ import DatePicker from "../../pb_date_picker/_date_picker";
7
+ import Dropdown from "../../pb_dropdown/_dropdown";
8
+ import Flex from "../../pb_flex/_flex";
9
+ import Select from "../../pb_select/_select";
10
+
11
+ const territorySelectOptions = [
12
+ { value: "USA" },
13
+ { value: "Canada" },
14
+ { value: "Brazil" },
15
+ { value: "Philippines" },
16
+ ];
17
+
18
+ const statusDropdownOptions = [
19
+ { id: "open", label: "Open", value: "open" },
20
+ { id: "in_progress", label: "In progress", value: "in_progress" },
21
+ { id: "resolved", label: "Resolved", value: "resolved" },
22
+ { id: "closed", label: "Closed", value: "closed" },
23
+ ];
24
+
25
+ const INITIAL_FILTERS = {
26
+ territory: "USA",
27
+ status: "open",
28
+ dateRange: "quickpick-this-week",
29
+ startDate: "05/01/2026",
30
+ };
31
+
32
+ const statusOptionForValue = (value) =>
33
+ value
34
+ ? statusDropdownOptions.find((opt) => opt.value === value)
35
+ : undefined;
36
+
37
+ const FilterInteractive = (props) => {
38
+ const [filters, setFilters] = useState(INITIAL_FILTERS);
39
+
40
+ const updateFilter = (key) => (value) =>
41
+ setFilters((prev) => ({ ...prev, [key]: value }));
42
+
43
+ const handleClear = () => {
44
+ setFilters(INITIAL_FILTERS);
45
+ };
46
+
47
+ return (
48
+ <Filter
49
+ {...props}
50
+ filters={{
51
+ Territory: filters.territory,
52
+ Status: filters.status,
53
+ "Date range": filters.dateRange,
54
+ "Start date": filters.startDate,
55
+ }}
56
+ interactiveFilters={{
57
+ Territory: {
58
+ type: "select",
59
+ options: territorySelectOptions,
60
+ value: filters.territory,
61
+ onChange: updateFilter("territory"),
62
+ },
63
+ Status: {
64
+ type: "dropdown",
65
+ options: statusDropdownOptions,
66
+ value: filters.status,
67
+ onChange: updateFilter("status"),
68
+ },
69
+ "Date range": {
70
+ type: "dropdown",
71
+ variant: "quickpick",
72
+ value: filters.dateRange,
73
+ onChange: updateFilter("dateRange"),
74
+ },
75
+ "Start date": {
76
+ type: "date-picker",
77
+ value: filters.startDate,
78
+ onChange: updateFilter("startDate"),
79
+ format: "m/d/Y",
80
+ },
81
+ }}
82
+ minWidth="360px"
83
+ results={546}
84
+ sortOptions={{
85
+ popularity: "Popularity",
86
+ }}
87
+ sortValue={[{ name: "popularity", dir: "desc" }]}
88
+ >
89
+ {({ closePopover }) => (
90
+ <form>
91
+ <Select
92
+ {...props}
93
+ label="Territory"
94
+ name="location"
95
+ onChange={(e) => updateFilter("territory")(e.target.value)}
96
+ options={territorySelectOptions}
97
+ value={filters.territory}
98
+ />
99
+ <Dropdown
100
+ {...props}
101
+ blankSelection="Select status..."
102
+ defaultValue={statusOptionForValue(filters.status)}
103
+ key={filters.status || "cleared"}
104
+ label="Status"
105
+ marginBottom="sm"
106
+ onSelect={(option) =>
107
+ updateFilter("status")(option ? option.value : "")
108
+ }
109
+ options={statusDropdownOptions}
110
+ />
111
+
112
+ <Dropdown
113
+ {...props}
114
+ key={filters.dateRange || "cleared"}
115
+ label="Date range"
116
+ marginBottom="sm"
117
+ onSelect={(option) =>
118
+ updateFilter("dateRange")(option ? option.id : "")
119
+ }
120
+ variant="quickpick"
121
+ />
122
+
123
+ <DatePicker
124
+ {...props}
125
+ inputValue={filters.startDate}
126
+ label="Start date"
127
+ onChange={updateFilter("startDate")}
128
+ pickerId="filter-panel-start-date"
129
+ />
130
+
131
+ <Flex
132
+ {...props}
133
+ spacing="between"
134
+ >
135
+ <Button
136
+ {...props}
137
+ onClick={closePopover}
138
+ text="Apply"
139
+ />
140
+ <Button
141
+ {...props}
142
+ onClick={handleClear}
143
+ text="Clear"
144
+ variant="secondary"
145
+ />
146
+ </Flex>
147
+ </form>
148
+ )}
149
+ </Filter>
150
+ );
151
+ };
152
+
153
+ export default FilterInteractive;
@@ -0,0 +1,10 @@
1
+ Click an applied filter chip to edit it inline. `interactiveFilters` supports:
2
+
3
+ - `type: 'select'` / `'dropdown'`: pick from a list of options.
4
+ - `type: 'date-picker'`: inline calendar. Supports `format`, `minDate`, `maxDate`, and `mode`.
5
+
6
+ For date ranges, use `type: 'dropdown'` with `variant: 'quickpick'`. The Filter kit generates the same quickpick options as Dropdown, so no `options` are needed. Values are quickpick ids, such as `quickpick-this-week`.
7
+
8
+ Keep `filters`, `interactiveFilters.value`, and the filter popover fields backed by the same state so chip labels and form controls stay in sync.
9
+
10
+ To preserve space for results and sort controls, only the first four applied filters are interactive at `lg` screen sizes (`960px`) and larger. Below `960px`, applied filters render as static chips; edit values from the filter popover instead.
@@ -12,6 +12,7 @@ examples:
12
12
  - filter_placement: Filter Placement
13
13
  - filter_popover_props: Popover Props
14
14
  - filter_within_turbo_frames: Within Turbo Frames
15
+ - filter_interactive: Interactive Applied Filters
15
16
 
16
17
  react:
17
18
  - filter_default: Default
@@ -25,4 +26,5 @@ examples:
25
26
  - filter_placement: Filter Placement
26
27
  - filter_popover_props: Popover Props
27
28
  - filter_sidebar: Sidebar
29
+ - filter_interactive_react: Interactive Applied Filters
28
30
 
@@ -8,4 +8,5 @@ export { default as FilterMaxWidth } from './_filter_max_width.jsx'
8
8
  export { default as FilterMaxHeight } from './_filter_max_height.jsx'
9
9
  export { default as FilterPlacement } from './_filter_placement.jsx'
10
10
  export { default as FilterPopoverProps } from './_filter_popover_props.jsx'
11
- export { default as FilterSidebar } from './_filter_sidebar.jsx'
11
+ export { default as FilterSidebar } from './_filter_sidebar.jsx'
12
+ export { default as FilterInteractiveReact } from './_filter_interactive_react.jsx'
@@ -1,83 +1,85 @@
1
- <%= pb_rails("table", props: { sticky: true }) do %>
2
- <thead>
3
- <tr>
4
- <th>Column 1</th>
5
- <th>Column 2</th>
6
- <th>Column 3</th>
7
- <th>Column 4</th>
8
- <th>Column 5</th>
9
- </tr>
10
- </thead>
11
- <tbody>
12
- <tr>
13
- <td>Value 1</td>
14
- <td>Value 2</td>
15
- <td>Value 3</td>
16
- <td>Value 4</td>
17
- <td>Value 5</td>
18
- </tr>
19
- <tr>
20
- <td>Value 1</td>
21
- <td>Value 2</td>
22
- <td>Value 3</td>
23
- <td>Value 4</td>
24
- <td>Value 5</td>
25
- </tr>
26
- <tr>
27
- <td>Value 1</td>
28
- <td>Value 2</td>
29
- <td>Value 3</td>
30
- <td>Value 4</td>
31
- <td>Value 5</td>
32
- </tr>
33
- <tr>
34
- <td>Value 1</td>
35
- <td>Value 2</td>
36
- <td>Value 3</td>
37
- <td>Value 4</td>
38
- <td>Value 5</td>
39
- </tr>
40
- <tr>
41
- <td>Value 1</td>
42
- <td>Value 2</td>
43
- <td>Value 3</td>
44
- <td>Value 4</td>
45
- <td>Value 5</td>
46
- </tr>
47
- <tr>
48
- <td>Value 1</td>
49
- <td>Value 2</td>
50
- <td>Value 3</td>
51
- <td>Value 4</td>
52
- <td>Value 5</td>
53
- </tr>
54
- <tr>
55
- <td>Value 1</td>
56
- <td>Value 2</td>
57
- <td>Value 3</td>
58
- <td>Value 4</td>
59
- <td>Value 5</td>
60
- </tr>
61
- <tr>
62
- <td>Value 1</td>
63
- <td>Value 2</td>
64
- <td>Value 3</td>
65
- <td>Value 4</td>
66
- <td>Value 5</td>
67
- </tr>
68
- <tr>
69
- <td>Value 1</td>
70
- <td>Value 2</td>
71
- <td>Value 3</td>
72
- <td>Value 4</td>
73
- <td>Value 5</td>
74
- </tr>
75
- <tr>
76
- <td>Value 1</td>
77
- <td>Value 2</td>
78
- <td>Value 3</td>
79
- <td>Value 4</td>
80
- <td>Value 5</td>
81
- </tr>
82
- </tbody>
83
- <% end %>
1
+ <div style="max-height: 320px; overflow-y: auto;">
2
+ <%= pb_rails("table", props: { sticky: true }) do %>
3
+ <thead>
4
+ <tr>
5
+ <th>Column 1</th>
6
+ <th>Column 2</th>
7
+ <th>Column 3</th>
8
+ <th>Column 4</th>
9
+ <th>Column 5</th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <tr>
14
+ <td>Value 1</td>
15
+ <td>Value 2</td>
16
+ <td>Value 3</td>
17
+ <td>Value 4</td>
18
+ <td>Value 5</td>
19
+ </tr>
20
+ <tr>
21
+ <td>Value 1</td>
22
+ <td>Value 2</td>
23
+ <td>Value 3</td>
24
+ <td>Value 4</td>
25
+ <td>Value 5</td>
26
+ </tr>
27
+ <tr>
28
+ <td>Value 1</td>
29
+ <td>Value 2</td>
30
+ <td>Value 3</td>
31
+ <td>Value 4</td>
32
+ <td>Value 5</td>
33
+ </tr>
34
+ <tr>
35
+ <td>Value 1</td>
36
+ <td>Value 2</td>
37
+ <td>Value 3</td>
38
+ <td>Value 4</td>
39
+ <td>Value 5</td>
40
+ </tr>
41
+ <tr>
42
+ <td>Value 1</td>
43
+ <td>Value 2</td>
44
+ <td>Value 3</td>
45
+ <td>Value 4</td>
46
+ <td>Value 5</td>
47
+ </tr>
48
+ <tr>
49
+ <td>Value 1</td>
50
+ <td>Value 2</td>
51
+ <td>Value 3</td>
52
+ <td>Value 4</td>
53
+ <td>Value 5</td>
54
+ </tr>
55
+ <tr>
56
+ <td>Value 1</td>
57
+ <td>Value 2</td>
58
+ <td>Value 3</td>
59
+ <td>Value 4</td>
60
+ <td>Value 5</td>
61
+ </tr>
62
+ <tr>
63
+ <td>Value 1</td>
64
+ <td>Value 2</td>
65
+ <td>Value 3</td>
66
+ <td>Value 4</td>
67
+ <td>Value 5</td>
68
+ </tr>
69
+ <tr>
70
+ <td>Value 1</td>
71
+ <td>Value 2</td>
72
+ <td>Value 3</td>
73
+ <td>Value 4</td>
74
+ <td>Value 5</td>
75
+ </tr>
76
+ <tr>
77
+ <td>Value 1</td>
78
+ <td>Value 2</td>
79
+ <td>Value 3</td>
80
+ <td>Value 4</td>
81
+ <td>Value 5</td>
82
+ </tr>
83
+ </tbody>
84
+ <% end %>
85
+ </div>
@@ -3,92 +3,94 @@ import React from "react"
3
3
  import Table from "../_table"
4
4
 
5
5
  const TableSticky = (props) => (
6
- <Table
7
- sticky
8
- {...props}
9
- >
10
- <thead>
11
- <tr>
12
- <th>{'Column 1'}</th>
13
- <th>{'Column 2'}</th>
14
- <th>{'Column 3'}</th>
15
- <th>{'Column 4'}</th>
16
- <th>{'Column 5'}</th>
17
- </tr>
18
- </thead>
19
- <tbody>
20
- <tr>
21
- <td>{'Value 1'}</td>
22
- <td>{'Value 2'}</td>
23
- <td>{'Value 3'}</td>
24
- <td>{'Value 4'}</td>
25
- <td>{'Value 5'}</td>
26
- </tr>
27
- <tr>
28
- <td>{'Value 1'}</td>
29
- <td>{'Value 2'}</td>
30
- <td>{'Value 3'}</td>
31
- <td>{'Value 4'}</td>
32
- <td>{'Value 5'}</td>
33
- </tr>
34
- <tr>
35
- <td>{'Value 1'}</td>
36
- <td>{'Value 2'}</td>
37
- <td>{'Value 3'}</td>
38
- <td>{'Value 4'}</td>
39
- <td>{'Value 5'}</td>
40
- </tr>
41
- <tr>
42
- <td>{'Value 1'}</td>
43
- <td>{'Value 2'}</td>
44
- <td>{'Value 3'}</td>
45
- <td>{'Value 4'}</td>
46
- <td>{'Value 5'}</td>
47
- </tr>
48
- <tr>
49
- <td>{'Value 1'}</td>
50
- <td>{'Value 2'}</td>
51
- <td>{'Value 3'}</td>
52
- <td>{'Value 4'}</td>
53
- <td>{'Value 5'}</td>
54
- </tr>
55
- <tr>
56
- <td>{'Value 1'}</td>
57
- <td>{'Value 2'}</td>
58
- <td>{'Value 3'}</td>
59
- <td>{'Value 4'}</td>
60
- <td>{'Value 5'}</td>
61
- </tr>
62
- <tr>
63
- <td>{'Value 1'}</td>
64
- <td>{'Value 2'}</td>
65
- <td>{'Value 3'}</td>
66
- <td>{'Value 4'}</td>
67
- <td>{'Value 5'}</td>
68
- </tr>
69
- <tr>
70
- <td>{'Value 1'}</td>
71
- <td>{'Value 2'}</td>
72
- <td>{'Value 3'}</td>
73
- <td>{'Value 4'}</td>
74
- <td>{'Value 5'}</td>
75
- </tr>
76
- <tr>
77
- <td>{'Value 1'}</td>
78
- <td>{'Value 2'}</td>
79
- <td>{'Value 3'}</td>
80
- <td>{'Value 4'}</td>
81
- <td>{'Value 5'}</td>
82
- </tr>
83
- <tr>
84
- <td>{'Value 1'}</td>
85
- <td>{'Value 2'}</td>
86
- <td>{'Value 3'}</td>
87
- <td>{'Value 4'}</td>
88
- <td>{'Value 5'}</td>
89
- </tr>
90
- </tbody>
91
- </Table>
6
+ <div style={{ maxHeight: "320px", overflowY: "auto" }}>
7
+ <Table
8
+ sticky
9
+ {...props}
10
+ >
11
+ <thead>
12
+ <tr>
13
+ <th>{'Column 1'}</th>
14
+ <th>{'Column 2'}</th>
15
+ <th>{'Column 3'}</th>
16
+ <th>{'Column 4'}</th>
17
+ <th>{'Column 5'}</th>
18
+ </tr>
19
+ </thead>
20
+ <tbody>
21
+ <tr>
22
+ <td>{'Value 1'}</td>
23
+ <td>{'Value 2'}</td>
24
+ <td>{'Value 3'}</td>
25
+ <td>{'Value 4'}</td>
26
+ <td>{'Value 5'}</td>
27
+ </tr>
28
+ <tr>
29
+ <td>{'Value 1'}</td>
30
+ <td>{'Value 2'}</td>
31
+ <td>{'Value 3'}</td>
32
+ <td>{'Value 4'}</td>
33
+ <td>{'Value 5'}</td>
34
+ </tr>
35
+ <tr>
36
+ <td>{'Value 1'}</td>
37
+ <td>{'Value 2'}</td>
38
+ <td>{'Value 3'}</td>
39
+ <td>{'Value 4'}</td>
40
+ <td>{'Value 5'}</td>
41
+ </tr>
42
+ <tr>
43
+ <td>{'Value 1'}</td>
44
+ <td>{'Value 2'}</td>
45
+ <td>{'Value 3'}</td>
46
+ <td>{'Value 4'}</td>
47
+ <td>{'Value 5'}</td>
48
+ </tr>
49
+ <tr>
50
+ <td>{'Value 1'}</td>
51
+ <td>{'Value 2'}</td>
52
+ <td>{'Value 3'}</td>
53
+ <td>{'Value 4'}</td>
54
+ <td>{'Value 5'}</td>
55
+ </tr>
56
+ <tr>
57
+ <td>{'Value 1'}</td>
58
+ <td>{'Value 2'}</td>
59
+ <td>{'Value 3'}</td>
60
+ <td>{'Value 4'}</td>
61
+ <td>{'Value 5'}</td>
62
+ </tr>
63
+ <tr>
64
+ <td>{'Value 1'}</td>
65
+ <td>{'Value 2'}</td>
66
+ <td>{'Value 3'}</td>
67
+ <td>{'Value 4'}</td>
68
+ <td>{'Value 5'}</td>
69
+ </tr>
70
+ <tr>
71
+ <td>{'Value 1'}</td>
72
+ <td>{'Value 2'}</td>
73
+ <td>{'Value 3'}</td>
74
+ <td>{'Value 4'}</td>
75
+ <td>{'Value 5'}</td>
76
+ </tr>
77
+ <tr>
78
+ <td>{'Value 1'}</td>
79
+ <td>{'Value 2'}</td>
80
+ <td>{'Value 3'}</td>
81
+ <td>{'Value 4'}</td>
82
+ <td>{'Value 5'}</td>
83
+ </tr>
84
+ <tr>
85
+ <td>{'Value 1'}</td>
86
+ <td>{'Value 2'}</td>
87
+ <td>{'Value 3'}</td>
88
+ <td>{'Value 4'}</td>
89
+ <td>{'Value 5'}</td>
90
+ </tr>
91
+ </tbody>
92
+ </Table>
93
+ </div>
92
94
  )
93
95
 
94
96
  export default TableSticky
@@ -2,7 +2,9 @@ React: Use `sticky` on a table to allow the table header to be fixed in place wh
2
2
 
3
3
  Rails: Pass `sticky: true` to props.
4
4
 
5
- If the table header is not sticking in the right place you will need to pass a inline `top` style to the `thead`.
5
+ The live example uses a scroll container so sticky behavior is visible in the docs. Scroll inside the preview to see it.
6
+
7
+ If the table header is not sticking in the right place you will need to pass an inline `top` style to the `thead`. This is often needed when a parent adds padding above the table.
6
8
  React Example: `<thead style={{ top: "-16px" }}>`
7
9
  Rails Example: `<thead style="top: -16px">`
8
10
 
@@ -36,4 +36,4 @@ When `filter` is present, `filter_content` and `filter_props` are ignored.
36
36
  <% end %>
37
37
  ```
38
38
 
39
- For Nitro apps that use a shared search/filter pattern, reference the example on Alpha for implementation details.
39
+ For Nitro apps that use a shared search/filter pattern, reference the [example on Alpha](https://github.com/powerhome/nitro-web/pull/56859/changes/aa2afcdc97d39d74beb65cf53eb3bb2517eb2181) for implementation details.
@@ -1 +1,3 @@
1
- Use the Time Picker for time-only selection. For date and time selection, use the [DatePicker with Time Selection Enabled](https://playbook.powerapp.cloud/kits/date_picker/react#time-selection) instead.
1
+ Use the Time Picker for time-only selection. For date and time selection, use the [DatePicker with Time Selection Enabled](https://playbook.powerapp.cloud/kits/date_picker/react#time-selection) instead.
2
+
3
+ `id` is a **required prop** to instantiate the Time Picker. The presence of a unique `id` for each Time Picker on a page also associates the label with the input, providing the ability to focus the Time Picker by clicking the label.
@@ -0,0 +1,24 @@
1
+ <%= pb_rails("flex", props: { margin_bottom: "sm", orientation: "column" }) do %>
2
+ <%= pb_rails("body", props: { id: "time-picker-on-change-output", text: "" }) %>
3
+ <%= pb_rails("body", props: { id: "time-picker-on-close-output", text: "" }) %>
4
+ <% end %>
5
+
6
+ <%= pb_rails("time_picker", props: { id: "time-picker-on-handler" }) %>
7
+
8
+ <script>
9
+ (function() {
10
+ var picker = document.getElementById("time-picker-on-handler");
11
+ var changeOutput = document.getElementById("time-picker-on-change-output");
12
+ var closeOutput = document.getElementById("time-picker-on-close-output");
13
+
14
+ if (!picker) return;
15
+
16
+ picker.addEventListener("pb-time-picker-change", function(event) {
17
+ changeOutput.textContent = "onChange: " + (event.detail.time || "");
18
+ });
19
+
20
+ picker.addEventListener("pb-time-picker-close", function(event) {
21
+ closeOutput.textContent = "onClose: " + (event.detail.time || "");
22
+ });
23
+ })();
24
+ </script>
@@ -0,0 +1,6 @@
1
+ Demonstrates listening for Time Picker custom events on the Rails enhanced element. Attach listeners to the picker root element (the element with `data-pb-time-picker`).
2
+
3
+ | Event | When it fires | `event.detail` |
4
+ | --- | --- | --- |
5
+ | `pb-time-picker-change` | Hour, minute, or period changes while the dropdown is open | `{ time: string }` — 24-hour `HH:MM` value, or `""` when cleared |
6
+ | `pb-time-picker-close` | Dropdown closes with a valid selection | `{ time: string }` — 24-hour `HH:MM` value |
@@ -11,6 +11,7 @@ examples:
11
11
  - time_picker_disabled: Disabled
12
12
  - time_picker_required_indicator: Required Indicator
13
13
  - time_picker_input_options: Input Options
14
+ - time_picker_on_handler: onChange & onClose Handlers
14
15
 
15
16
 
16
17
  react:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playbook_ui_docs
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.8.0.pre.alpha.PLAY298616637
4
+ version: 16.8.0.pre.alpha.play293416802
5
5
  platform: ruby
6
6
  authors:
7
7
  - Power UX
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-05-27 00:00:00.000000000 Z
12
+ date: 2026-06-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: playbook_ui
@@ -94,6 +94,8 @@ files:
94
94
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_sort.md
95
95
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.jsx
96
96
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md
97
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.html.erb
98
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.md
97
99
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_expand_by_depth.jsx
98
100
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_expand_by_depth.md
99
101
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_expanded_control.jsx
@@ -175,6 +177,8 @@ files:
175
177
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.md
176
178
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.html.erb
177
179
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.md
180
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.jsx
181
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.md
178
182
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_subrow_headers.jsx
179
183
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_subrow_headers.md
180
184
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_options.jsx
@@ -1086,6 +1090,10 @@ files:
1086
1090
  - app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb
1087
1091
  - app/pb_kits/playbook/pb_filter/docs/_filter_default.jsx
1088
1092
  - app/pb_kits/playbook/pb_filter/docs/_filter_default.md
1093
+ - app/pb_kits/playbook/pb_filter/docs/_filter_interactive.html.erb
1094
+ - app/pb_kits/playbook/pb_filter/docs/_filter_interactive.md
1095
+ - app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.jsx
1096
+ - app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.md
1089
1097
  - app/pb_kits/playbook/pb_filter/docs/_filter_max_height.html.erb
1090
1098
  - app/pb_kits/playbook/pb_filter/docs/_filter_max_height.jsx
1091
1099
  - app/pb_kits/playbook/pb_filter/docs/_filter_max_width.html.erb
@@ -2625,8 +2633,10 @@ files:
2625
2633
  - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_min_max_time.html.erb
2626
2634
  - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_min_max_time.jsx
2627
2635
  - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_min_max_time.md
2636
+ - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.html.erb
2628
2637
  - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.jsx
2629
- - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.md
2638
+ - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler_rails.md
2639
+ - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler_react.md
2630
2640
  - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.html.erb
2631
2641
  - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.jsx
2632
2642
  - app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.md