playbook_ui_docs 16.3.0.pre.alpha.play285814889 → 16.3.0.pre.alpha.railspinnedrows14948

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22e0f89223c61e36588232c3bb4007f762fa5b2744b84968a842126baeee495b
4
- data.tar.gz: 11f02cbe0dfb6e47296421e1a2ca123d8433844bc92fd105ce0774f100c3b79e
3
+ metadata.gz: 3ac6f53ece515aa91c29deed635a80641ecadb2ecf4496d21bb57ed87a37b1b7
4
+ data.tar.gz: 00c01eda8b523b90d017f04f7e7123cfec0ac53d8c115ad14f363b1fd9445685
5
5
  SHA512:
6
- metadata.gz: 25cd200a848064e0c3f74fcbd1f864d7340930397c64f8e84b05d5735554945b8bfa5e2fb3d2ffec3a52d38a2aa2caa84c39fdd94404eb3325caac0363ae69af
7
- data.tar.gz: b8dd1bc01692c1f5f9422b1f898bf2d09ee02a443f6b8d0747d625ed58ea88cc2d4f4942ea5cf2de13140c2d4ca4c7c3b24b7ea568efb6d3cc89f966ddf7c584
6
+ metadata.gz: adfb8b2ea44c1fd11b99b3600316ca3aea9162a8f3bc72ad0a2aa08b280b80f427f0a24dfb7ebebf9bfc62cb7c6b0245890f9e8bb516518cd6f9ffa11062f954
7
+ data.tar.gz: 67d545c81692a86ece74d1c9495e99559f533bd31ba67fd648f7d38fb3688ccb031c20e83a77a46388c89f3d01aa54df8292302fe9f9cb09aa930ce7ca56ed64
@@ -0,0 +1,57 @@
1
+ <%# Example sort method for demonstration purposes %>
2
+ <% if params["sort"] %>
3
+ <% sort_param = params["sort"].gsub(/_(asc|desc)\z/, "") %>
4
+ <% sort_direction = params["sort"].end_with?("_asc") ? 1 : -1 %>
5
+ <% @table_data_with_id.sort! do |a, b|
6
+ value_a = a[sort_param] || a[sort_param.to_sym]
7
+ value_b = b[sort_param] || b[sort_param.to_sym]
8
+
9
+ value_a = value_a.to_i if value_a.is_a?(String) && value_a.match?(/^\d+$/)
10
+ value_b = value_b.to_i if value_b.is_a?(String) && value_b.match?(/^\d+$/)
11
+
12
+ sort_direction * (value_a <=> value_b)
13
+ end %>
14
+ <% end %>
15
+
16
+ <% column_definitions = [
17
+ {
18
+ accessor: "year",
19
+ label: "Year",
20
+ cellAccessors: ["quarter", "month", "day"],
21
+ sort_menu: [
22
+ { item: "Year", link: "?sort=year_asc#pinned_rows_table", active: params["sort"] == "year_asc", direction: "asc" },
23
+ { item: "Year", link: "?sort=year_desc#pinned_rows_table", active: params["sort"] == "year_desc", direction: "desc" }
24
+ ],
25
+ },
26
+ {
27
+ accessor: "newEnrollments",
28
+ label: "New Enrollments",
29
+ },
30
+ {
31
+ accessor: "scheduledMeetings",
32
+ label: "Scheduled Meetings",
33
+ },
34
+ {
35
+ accessor: "attendanceRate",
36
+ label: "Attendance Rate",
37
+ },
38
+ {
39
+ accessor: "completedClasses",
40
+ label: "Completed Classes",
41
+ },
42
+ {
43
+ accessor: "classCompletionRate",
44
+ label: "Class Completion Rate",
45
+ },
46
+ {
47
+ accessor: "graduatedStudents",
48
+ label: "Graduated Students",
49
+ }
50
+ ] %>
51
+
52
+ <% pinned_rows = { top: ["8"] } %>
53
+
54
+ <%= pb_rails("advanced_table", props: { id: "pinned_rows_table", table_data: @table_data_with_id, column_definitions: column_definitions, max_height: "xs", pinned_rows: pinned_rows, responsive: "none", table_props: { sticky: true }}) do %>
55
+ <%= pb_rails("advanced_table/table_header", props: { table_id: "pinned_rows_table", column_definitions: column_definitions }) %>
56
+ <%= pb_rails("advanced_table/table_body", props: { table_id: "pinned_rows_table", table_data: @table_data_with_id, column_definitions: column_definitions, pinned_rows: pinned_rows }) %>
57
+ <% end %>
@@ -0,0 +1,7 @@
1
+ Use the `pinned_rows` prop to pin specific rows to the top of an Advanced Table. Pinned rows will remain at the top when scrolling through table data and will not change position if sorting is used.
2
+
3
+ **NOTE:**
4
+ - Sticky header required: Pinned rows must be used with `sticky: true` via `table_props` (works with both responsive and non-responsive tables)
5
+ - Row ids required: Each object within the `table_data` array must contain a unique `id` in order to attach an id to all Rows for this to function.
6
+ - `pinned_rows` takes a hash with a `top` key containing an array of row ids, as shown in the code snippet below.
7
+ - For expandable rows, use the parent id in `pinned_rows[:top]`; all its children will automatically be pinned with it. If a child id is passed without the parent being pinned, nothing will be pinned.
@@ -0,0 +1,175 @@
1
+ import React from "react"
2
+ import AdvancedTable from '../../pb_advanced_table/_advanced_table'
3
+ import MOCK_DATA from "./advanced_table_mock_data.json"
4
+
5
+ import Caption from "../../pb_caption/_caption"
6
+
7
+ const sharedColumnDefinitions = [
8
+ {
9
+ accessor: "year",
10
+ label: "Year",
11
+ cellAccessors: ["quarter", "month", "day"],
12
+ },
13
+ {
14
+ accessor: "newEnrollments",
15
+ label: "New Enrollments",
16
+ },
17
+ {
18
+ accessor: "scheduledMeetings",
19
+ label: "Scheduled Meetings",
20
+ },
21
+ {
22
+ accessor: "attendanceRate",
23
+ label: "Attendance Rate",
24
+ },
25
+ {
26
+ accessor: "completedClasses",
27
+ label: "Completed Classes",
28
+ },
29
+ {
30
+ accessor: "classCompletionRate",
31
+ label: "Class Completion Rate",
32
+ },
33
+ {
34
+ accessor: "graduatedStudents",
35
+ label: "Graduated Students",
36
+ },
37
+ ]
38
+
39
+ const sortByColumnDefinitions = [
40
+ {
41
+ accessor: "year",
42
+ label: "Year",
43
+ cellAccessors: ["quarter", "month", "day"],
44
+ },
45
+ {
46
+ accessor: "newEnrollments",
47
+ label: "New Enrollments",
48
+ enableSort: true,
49
+ },
50
+ {
51
+ accessor: "scheduledMeetings",
52
+ label: "Scheduled Meetings",
53
+ },
54
+ {
55
+ accessor: "attendanceRate",
56
+ label: "Attendance Rate",
57
+ enableSort: true,
58
+ },
59
+ {
60
+ accessor: "completedClasses",
61
+ label: "Completed Classes",
62
+ },
63
+ {
64
+ accessor: "classCompletionRate",
65
+ label: "Class Completion Rate",
66
+ },
67
+ {
68
+ accessor: "graduatedStudents",
69
+ label: "Graduated Students",
70
+ },
71
+ ]
72
+
73
+ const sortByColumnMultiDefinitions = [
74
+ {
75
+ accessor: "year",
76
+ label: "Year",
77
+ cellAccessors: ["quarter", "month", "day"],
78
+ },
79
+ {
80
+ label: "Enrollment Data",
81
+ columns: [
82
+ {
83
+ label: "Enrollment Stats",
84
+ columns: [
85
+ {
86
+ accessor: "newEnrollments",
87
+ label: "New Enrollments",
88
+ enableSort: true,
89
+ },
90
+ {
91
+ accessor: "scheduledMeetings",
92
+ label: "Scheduled Meetings",
93
+ },
94
+ ],
95
+ },
96
+ ],
97
+ },
98
+ {
99
+ label: "Performance Data",
100
+ columns: [
101
+ {
102
+ label: "Completion Metrics",
103
+ columns: [
104
+ {
105
+ accessor: "completedClasses",
106
+ label: "Completed Classes",
107
+ enableSort: true,
108
+ },
109
+ {
110
+ accessor: "classCompletionRate",
111
+ label: "Class Completion Rate",
112
+ },
113
+ ],
114
+ },
115
+ {
116
+ label: "Attendance",
117
+ columns: [
118
+ {
119
+ accessor: "attendanceRate",
120
+ label: "Attendance Rate",
121
+ },
122
+ {
123
+ accessor: "scheduledMeetings",
124
+ label: "Scheduled Meetings",
125
+ },
126
+ ],
127
+ },
128
+ ],
129
+ },
130
+ ]
131
+
132
+ const AdvancedTableSortParentOnly = (props) => {
133
+ return (
134
+ <div>
135
+ <Caption text="Enable Sorting (first column) + sortParentOnly" />
136
+ <AdvancedTable
137
+ columnDefinitions={sharedColumnDefinitions}
138
+ sortParentOnly
139
+ tableData={MOCK_DATA}
140
+ {...props}
141
+ >
142
+ <AdvancedTable.Header enableSorting />
143
+ <AdvancedTable.Body />
144
+ </AdvancedTable>
145
+ <Caption marginTop="md"
146
+ text="Sort by column + sortParentOnly"
147
+ />
148
+ <AdvancedTable
149
+ columnDefinitions={sortByColumnDefinitions}
150
+ enableSortingRemoval
151
+ sortParentOnly
152
+ tableData={MOCK_DATA}
153
+ {...props}
154
+ >
155
+ <AdvancedTable.Header />
156
+ <AdvancedTable.Body />
157
+ </AdvancedTable>
158
+ <Caption marginTop="md"
159
+ text="Sort by column (multi-column) + sortParentOnly"
160
+ />
161
+ <AdvancedTable
162
+ columnDefinitions={sortByColumnMultiDefinitions}
163
+ enableSortingRemoval
164
+ sortParentOnly
165
+ tableData={MOCK_DATA}
166
+ {...props}
167
+ >
168
+ <AdvancedTable.Header enableSorting />
169
+ <AdvancedTable.Body />
170
+ </AdvancedTable>
171
+ </div>
172
+ )
173
+ }
174
+
175
+ export default AdvancedTableSortParentOnly
@@ -0,0 +1,5 @@
1
+ The `sortParentOnly` prop is a boolean set to `false` by default. When set to `true`, only parent (depth-0) rows are re-ordered when sorting; children and grandchildren stay grouped under their parent and keep their original order.
2
+
3
+ `sortParentOnly` works with every sorting mode: `enableSorting` on the header, per-column `enableSort: true`, and sortable leaf columns in the multi-header variant. Sort indicators behave as usual.
4
+
5
+ When omitted or `false`, sorting applies to all levels.
@@ -7,6 +7,7 @@ examples:
7
7
  - advanced_table_table_props: Table Props
8
8
  - advanced_table_sticky_header_rails: Sticky Header
9
9
  - advanced_table_table_props_sticky_header: Sticky Header for Responsive Table
10
+ - advanced_table_pinned_rows_rails: Pinned Rows
10
11
  - advanced_table_beta_sort: Enable Sorting
11
12
  - advanced_table_responsive: Responsive Tables
12
13
  - advanced_table_custom_cell_rails: Custom Components for Cells
@@ -39,6 +40,7 @@ examples:
39
40
  - advanced_table_sort_per_column: Enable Sort By Column
40
41
  - advanced_table_sort_per_column_for_multi_column: Enable Sort By Column (Multi-Column)
41
42
  - advanced_table_custom_sort: Custom Sort
43
+ - advanced_table_sort_parent_only: Sort Parent Only
42
44
  - advanced_table_expanded_control: Expanded Control
43
45
  - advanced_table_expand_by_depth: Expand by Depth
44
46
  - advanced_table_subrow_headers: SubRow Headers
@@ -49,4 +49,5 @@ export { default as AdvancedTablePaddingControlPerRow } from './_advanced_table_
49
49
  export { default as AdvancedTableColumnStylingBackground } from './_advanced_table_column_styling_background.jsx'
50
50
  export { default as AdvancedTableColumnStylingBackgroundMulti } from './_advanced_table_column_styling_background_multi.jsx'
51
51
  export { default as AdvancedTableColumnStylingBackgroundCustom } from './_advanced_table_column_styling_background_custom.jsx'
52
- export { default as AdvancedTableCascadeCollapse } from './_advanced_table_cascade_collapse.jsx'
52
+ export { default as AdvancedTableCascadeCollapse } from './_advanced_table_cascade_collapse.jsx'
53
+ export { default as AdvancedTableSortParentOnly } from './_advanced_table_sort_parent_only.jsx'
@@ -0,0 +1,224 @@
1
+ <%
2
+ default_options = [
3
+ { label: 'United States', value: 'unitedStates', id: 'us' },
4
+ { label: 'Canada', value: 'canada', id: 'ca' },
5
+ { label: 'Pakistan', value: 'pakistan', id: 'pk' },
6
+ { label: 'India', value: 'India', id: 'in' },
7
+ { label: 'Mexico', value: 'Mexico', id: 'mx' },
8
+ ]
9
+
10
+ multi_options = [
11
+ { label: 'United States', value: 'unitedStates', id: 'us' },
12
+ { label: 'Canada', value: 'canada', id: 'ca' },
13
+ { label: 'Pakistan', value: 'pakistan', id: 'pk' },
14
+ { label: 'India', value: 'india', id: 'in' },
15
+ { label: 'United Kingdom', value: 'unitedKingdom', id: 'uk' },
16
+ ]
17
+
18
+ autocomplete_options = [
19
+ { label: "United States", value: "unitedStates", areaCode: "+1", icon: "🇺🇸", id: "us" },
20
+ { label: "United Kingdom", value: "unitedKingdom", areaCode: "+44", icon: "🇬🇧", id: "gb" },
21
+ { label: "Pakistan", value: "pakistan", areaCode: "+92", icon: "🇵🇰", id: "pk" },
22
+ ]
23
+
24
+ custom_display_options = [
25
+ { label: "Strong Bad", value: "strongBad", id: "strong-bad", status: "Offline" },
26
+ { label: "Strong Mad", value: "strongMad", id: "strong-mad", status: "Online" },
27
+ { label: "Strong Sad", value: "strongSad", id: "strong-sad", status: "Away" },
28
+ ]
29
+
30
+ custom_display_content = capture do
31
+ pb_rails("flex", props: { align: "center" }) do
32
+ concat(pb_rails("avatar", props: { name: "", size: "xs", id: "cet-dropdown-avatar" }))
33
+ concat(pb_rails("body", props: { text: "", size: "xs", margin_x: "xs", id: "cet-dropdown-avatar-name" }))
34
+ concat(pb_rails("badge", props: { text: "", id: "cet-dropdown-avatar-status" }))
35
+ end
36
+ end
37
+ %>
38
+
39
+ <!-- Example 1: Default dropdown -->
40
+ <%= pb_rails("dropdown", props: {
41
+ custom_event_type: "form:submitted,pb:dropdown:clearRequest",
42
+ id: "dropdown-default-cet",
43
+ label: "Default dropdown",
44
+ margin_bottom: "sm",
45
+ options: default_options,
46
+ }) %>
47
+ <%= pb_rails("flex", props: { wrap: true, gap: "sm", align: "center", margin_bottom: "md" }) do %>
48
+ <%= pb_rails("button", props: { id: "clear-default-cet", text: "Clear", variant: "primary" }) %>
49
+ <%= pb_rails("button", props: { id: "select-default-cet", text: "Select Canada", variant: "secondary" }) %>
50
+ <%= pb_rails("button", props: { id: "simulate-default-cet", text: "Simulate form submit", variant: "secondary" }) %>
51
+ <% end %>
52
+
53
+ <script>
54
+ (function() {
55
+ var id = "dropdown-default-cet";
56
+ document.getElementById("clear-default-cet").addEventListener("click", function() {
57
+ document.dispatchEvent(new CustomEvent("pb:dropdown:clearRequest", { detail: { dropdownId: id } }));
58
+ });
59
+ document.getElementById("select-default-cet").addEventListener("click", function() {
60
+ document.dispatchEvent(new CustomEvent("pb:dropdown:select", { detail: { dropdownId: id, optionId: "ca" } }));
61
+ });
62
+ document.getElementById("simulate-default-cet").addEventListener("click", function() {
63
+ document.dispatchEvent(new CustomEvent("form:submitted", { detail: { dropdownId: id } }));
64
+ });
65
+ })();
66
+ </script>
67
+
68
+ <!-- Example 2: Multi select -->
69
+ <%= pb_rails("dropdown", props: {
70
+ custom_event_type: "form:submitted,pb:dropdown:clearRequest",
71
+ id: "dropdown-multi-cet",
72
+ label: "Multi select dropdown",
73
+ margin_bottom: "sm",
74
+ multi_select: true,
75
+ options: multi_options,
76
+ }) %>
77
+ <%= pb_rails("flex", props: { wrap: true, gap: "sm", align: "center", margin_bottom: "md" }) do %>
78
+ <%= pb_rails("button", props: { id: "clear-multi-cet", text: "Clear", variant: "primary" }) %>
79
+ <%= pb_rails("button", props: { id: "select-multi-cet", text: "Select US + UK", variant: "secondary" }) %>
80
+ <%= pb_rails("button", props: { id: "simulate-multi-cet", text: "Simulate form submit", variant: "secondary" }) %>
81
+ <% end %>
82
+
83
+ <script>
84
+ (function() {
85
+ var id = "dropdown-multi-cet";
86
+ document.getElementById("clear-multi-cet").addEventListener("click", function() {
87
+ document.dispatchEvent(new CustomEvent("pb:dropdown:clearRequest", { detail: { dropdownId: id } }));
88
+ });
89
+ document.getElementById("select-multi-cet").addEventListener("click", function() {
90
+ document.dispatchEvent(new CustomEvent("pb:dropdown:select", { detail: { dropdownId: id, optionIds: ["us", "uk"] } }));
91
+ });
92
+ document.getElementById("simulate-multi-cet").addEventListener("click", function() {
93
+ document.dispatchEvent(new CustomEvent("form:submitted", { detail: { dropdownId: id } }));
94
+ });
95
+ })();
96
+ </script>
97
+
98
+ <!-- Example 3: Autocomplete -->
99
+ <%= pb_rails("dropdown", props: {
100
+ autocomplete: true,
101
+ custom_event_type: "form:submitted,pb:dropdown:clearRequest",
102
+ id: "dropdown-autocomplete-cet",
103
+ label: "Autocomplete dropdown",
104
+ margin_bottom: "sm",
105
+ options: autocomplete_options,
106
+ }) %>
107
+ <%= pb_rails("flex", props: { wrap: true, gap: "sm", align: "center", margin_bottom: "md" }) do %>
108
+ <%= pb_rails("button", props: { id: "clear-autocomplete-cet", text: "Clear", variant: "primary" }) %>
109
+ <%= pb_rails("button", props: { id: "select-autocomplete-cet", text: "Select Pakistan", variant: "secondary" }) %>
110
+ <%= pb_rails("button", props: { id: "simulate-autocomplete-cet", text: "Simulate form submit", variant: "secondary" }) %>
111
+ <% end %>
112
+
113
+ <script>
114
+ (function() {
115
+ var id = "dropdown-autocomplete-cet";
116
+ document.getElementById("clear-autocomplete-cet").addEventListener("click", function() {
117
+ document.dispatchEvent(new CustomEvent("pb:dropdown:clearRequest", { detail: { dropdownId: id } }));
118
+ });
119
+ document.getElementById("select-autocomplete-cet").addEventListener("click", function() {
120
+ document.dispatchEvent(new CustomEvent("pb:dropdown:select", { detail: { dropdownId: id, optionId: "pk" } }));
121
+ });
122
+ document.getElementById("simulate-autocomplete-cet").addEventListener("click", function() {
123
+ document.dispatchEvent(new CustomEvent("form:submitted", { detail: { dropdownId: id } }));
124
+ });
125
+ })();
126
+ </script>
127
+
128
+ <!-- Example 4: Quick pick (Date Range) -->
129
+ <%= pb_rails("dropdown", props: {
130
+ custom_event_type: "form:submitted,pb:dropdown:clearRequest",
131
+ id: "dropdown-quickpick-cet",
132
+ label: "Quickpick dropdown",
133
+ margin_bottom: "sm",
134
+ variant: "quickpick",
135
+ }) %>
136
+ <%= pb_rails("flex", props: { wrap: true, gap: "sm", align: "center", margin_bottom: "md" }) do %>
137
+ <%= pb_rails("button", props: { id: "clear-quickpick-cet", text: "Clear", variant: "primary" }) %>
138
+ <%= pb_rails("button", props: { id: "select-quickpick-cet", text: "Select This Week", variant: "secondary" }) %>
139
+ <%= pb_rails("button", props: { id: "simulate-quickpick-cet", text: "Simulate form submit", variant: "secondary" }) %>
140
+ <% end %>
141
+
142
+ <script>
143
+ (function() {
144
+ var id = "dropdown-quickpick-cet";
145
+ document.getElementById("clear-quickpick-cet").addEventListener("click", function() {
146
+ document.dispatchEvent(new CustomEvent("pb:dropdown:clearRequest", { detail: { dropdownId: id } }));
147
+ });
148
+ document.getElementById("select-quickpick-cet").addEventListener("click", function() {
149
+ document.dispatchEvent(new CustomEvent("pb:dropdown:select", { detail: { dropdownId: id, optionId: "quickpick-this-week" } }));
150
+ });
151
+ document.getElementById("simulate-quickpick-cet").addEventListener("click", function() {
152
+ document.dispatchEvent(new CustomEvent("form:submitted", { detail: { dropdownId: id } }));
153
+ });
154
+ })();
155
+ </script>
156
+
157
+ <!-- Example 5: Custom display -->
158
+ <%= pb_rails("dropdown", props: {
159
+ custom_event_type: "form:submitted,pb:dropdown:clearRequest",
160
+ id: "dropdown-custom-display-cet",
161
+ label: "Custom display (Subcomponent) dropdown",
162
+ margin_bottom: "sm",
163
+ options: custom_display_options,
164
+ }) do %>
165
+ <%= pb_rails("dropdown/dropdown_trigger", props: { placeholder: "Select a User", custom_display: custom_display_content }) %>
166
+ <%= pb_rails("dropdown/dropdown_container") do %>
167
+ <% custom_display_options.each do |option| %>
168
+ <%= pb_rails("dropdown/dropdown_option", props: { option: option }) do %>
169
+ <%= pb_rails("flex", props: { align: "center", justify: "between" }) do %>
170
+ <%= pb_rails("flex/flex_item") do %>
171
+ <%= pb_rails("user", props: { name: option[:label], align: "left", avatar: true, orientation: "horizontal" }) %>
172
+ <% end %>
173
+ <%= pb_rails("flex/flex_item") do %>
174
+ <%= pb_rails("badge", props: { rounded: true, dark: true, text: option[:status], variant: option[:status] == "Offline" ? "neutral" : option[:status] == "Online" ? "success" : "warning" }) %>
175
+ <% end %>
176
+ <% end %>
177
+ <% end %>
178
+ <% end %>
179
+ <% end %>
180
+ <% end %>
181
+ <%= pb_rails("flex", props: { wrap: true, gap: "sm", align: "center", margin_bottom: "md" }) do %>
182
+ <%= pb_rails("button", props: { id: "clear-custom-display-cet", text: "Clear", variant: "primary" }) %>
183
+ <%= pb_rails("button", props: { id: "select-custom-display-cet", text: "Select Strong Sad", variant: "secondary" }) %>
184
+ <%= pb_rails("button", props: { id: "simulate-custom-display-cet", text: "Simulate form submit", variant: "secondary" }) %>
185
+ <% end %>
186
+
187
+ <script>
188
+ (function() {
189
+ var id = "dropdown-custom-display-cet";
190
+ document.getElementById("clear-custom-display-cet").addEventListener("click", function() {
191
+ document.dispatchEvent(new CustomEvent("pb:dropdown:clearRequest", { detail: { dropdownId: id } }));
192
+ });
193
+ document.getElementById("select-custom-display-cet").addEventListener("click", function() {
194
+ document.dispatchEvent(new CustomEvent("pb:dropdown:select", { detail: { dropdownId: id, optionId: "strong-sad" } }));
195
+ });
196
+ document.getElementById("simulate-custom-display-cet").addEventListener("click", function() {
197
+ document.dispatchEvent(new CustomEvent("form:submitted", { detail: { dropdownId: id } }));
198
+ });
199
+
200
+ document.addEventListener("pb:dropdown:selected", function(e) {
201
+ if (e.target && e.target.id === id && e.detail) {
202
+ var display = e.target.querySelector("[data-dropdown-trigger-custom-display]");
203
+ if (!display) return;
204
+ var nameEl = display.querySelector("#cet-dropdown-avatar-name");
205
+ if (nameEl) nameEl.textContent = e.detail.label;
206
+ var avatarEl = display.querySelector("#cet-dropdown-avatar");
207
+ if (avatarEl) {
208
+ var wrapper = avatarEl.querySelector(".avatar_wrapper");
209
+ if (wrapper) {
210
+ var initials = (e.detail.label[0] + (e.detail.label.split(" ").pop() || "")[0]).toUpperCase();
211
+ wrapper.dataset.name = e.detail.label;
212
+ wrapper.setAttribute("data-initials", initials);
213
+ }
214
+ }
215
+ var badgeEl = display.querySelector("#cet-dropdown-avatar-status");
216
+ if (badgeEl && e.detail.status) {
217
+ var variant = e.detail.status === "Online" ? "success" : e.detail.status === "Offline" ? "neutral" : "warning";
218
+ badgeEl.querySelector("span").textContent = e.detail.status;
219
+ badgeEl.className = "pb_badge_kit_" + variant;
220
+ }
221
+ }
222
+ });
223
+ })();
224
+ </script>
@@ -0,0 +1,7 @@
1
+ The `custom_event_type` prop lets the dropdown clear when specific events are dispatched. Set it to a comma-separated list of event names (e.g. Turbo or app-specific); when any of those events fire with optional `detail: { dropdownId }`, the matching dropdown clears. You can also listen for selection changes (`pb:dropdown:selected`), clear by dispatching `pb:dropdown:clear`, or set the selection by dispatching `pb:dropdown:select` with `detail: { dropdownId, optionId }` (or `optionIds` for multi-select).
2
+
3
+ The examples show five distinct variants (default, multi select, autocomplete, quick pick, custom display). In each example, the first button clears the dropdown by dispatching a custom event that the dropdown listens for via `custom_event_type`. The second button sets the selection by dispatching `pb:dropdown:select`. The third button simulates a form submit by dispatching another custom event in `custom_event_type`, so the dropdown clears as it would after a real form submission.
4
+
5
+ Turbo events (e.g. `turbo:frame-load`, `turbo:frame-render`, `turbo:submit-end`) often fire for many actions or across the page, so using them as `custom_event_type` can clear the dropdown more often than intended. Use them when that scope is what you want; otherwise use app-specific event names and dispatch with `detail: { dropdownId }` when the action happens, or dispatch `pb:dropdown:clear` from your own handler.
6
+
7
+ Dropdowns with subcomponent structures that show custom displays (e.g. custom trigger or custom display) require a `pb:dropdown:selected` listener to update the visible UI from `event.detail` when a selection is made; clear is handled by the kit.
@@ -33,6 +33,7 @@ examples:
33
33
  - dropdown_quickpick_with_date_pickers_rails: Quick Pick with Date Pickers
34
34
  - dropdown_quickpick_with_date_pickers_default_rails: Quick Pick with Date Pickers (Default Value)
35
35
  - dropdown_required_indicator: Required Indicator
36
+ - dropdown_custom_event_type: Custom Event Type
36
37
 
37
38
  react:
38
39
  - dropdown_default: Default
@@ -0,0 +1,46 @@
1
+ <%= pb_rails("button", props: { text: "Top Nav Toast", variant: "secondary", data: { toast: "#top-nav" } }) %>
2
+
3
+ <%= pb_rails("fixed_confirmation_toast", props: {
4
+ classname: "top-nav-margin",
5
+ closeable: true,
6
+ id: "top-nav",
7
+ multi_line: true,
8
+ text: "Top nav Margin.",
9
+ status: "tip",
10
+ vertical: "top",
11
+ horizontal: "center",
12
+ nav_margin_top: true
13
+ }) %>
14
+
15
+
16
+
17
+ <script type="text/javascript">
18
+ const navtoast = document.querySelectorAll(".top-nav-margin")
19
+ const navbutton = document.querySelectorAll("button[data-toast]")
20
+
21
+ const hideNavToast = () => {
22
+ navtoast.forEach((toast) => {
23
+ toast.style.display = "none"
24
+ })
25
+ }
26
+
27
+ // Hide toasts immediately
28
+ hideNavToast()
29
+
30
+ // Handle various page load/restore events
31
+ window.addEventListener('pageshow', hideNavToast)
32
+ document.addEventListener('DOMContentLoaded', hideNavToast)
33
+ document.addEventListener('turbolinks:load', hideNavToast)
34
+ document.addEventListener('turbo:load', hideNavToast)
35
+
36
+ navbutton.forEach((button) => {
37
+ button.onclick = () => {
38
+ hideNavToast()
39
+ let toast = document.querySelector(button.getAttribute("data-toast"))
40
+
41
+ if (toast) {
42
+ toast.style.display = "flex"
43
+ }
44
+ }
45
+ })
46
+ </script>
@@ -0,0 +1,42 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import Button from '../../pb_button/_button'
4
+ import FixedConfirmationToast from '../_fixed_confirmation_toast'
5
+
6
+ const FixedConfirmationToastNavMargin = (props) => {
7
+ const [openToast, setOpenToast] = useState(false)
8
+
9
+
10
+ const handleClickShort = () => {
11
+ setOpenToast(true)
12
+ }
13
+
14
+ const handleCloseShort = () => {
15
+ setOpenToast(false)
16
+ }
17
+
18
+ return (
19
+ <div>
20
+ <Button
21
+ onClick={handleClickShort}
22
+ text="Top Nav Margin"
23
+ variant="secondary"
24
+ {...props}
25
+ />
26
+
27
+ <FixedConfirmationToast
28
+ closeable
29
+ horizontal='center'
30
+ navMarginTop
31
+ onClose={handleCloseShort}
32
+ open={openToast}
33
+ status="tip"
34
+ text="Top nav Margin."
35
+ vertical='top'
36
+ {...props}
37
+ />
38
+ </div>
39
+ )
40
+ }
41
+
42
+ export default FixedConfirmationToastNavMargin
@@ -0,0 +1 @@
1
+ Use the `nav_margin_top` prop to position the toast lower on the page. This is useful for cases where we want to position the toast below a header or nav.
@@ -0,0 +1 @@
1
+ Use the `navMarginTop` prop to position the toast lower on the page. This is useful for cases where we want to position the toast below a header or nav.
@@ -2,6 +2,7 @@ examples:
2
2
 
3
3
  rails:
4
4
  - fixed_confirmation_toast_default: Default
5
+ - fixed_confirmation_toast_nav_margin: Nav Margin Top
5
6
  - fixed_confirmation_toast_multi_line: Multi Line
6
7
  - fixed_confirmation_toast_close: Click to Close
7
8
  - fixed_confirmation_toast_positions: Click to Show Positions
@@ -12,6 +13,7 @@ examples:
12
13
 
13
14
  react:
14
15
  - fixed_confirmation_toast_default: Default
16
+ - fixed_confirmation_toast_nav_margin: Nav Margin Top
15
17
  - fixed_confirmation_toast_multi_line: Multi Line
16
18
  - fixed_confirmation_toast_close: Click to Close
17
19
  - fixed_confirmation_toast_positions: Click to Show Positions
@@ -5,4 +5,5 @@ export { default as FixedConfirmationToastPositions } from './_fixed_confirmatio
5
5
  export { default as FixedConfirmationToastAutoClose } from './_fixed_confirmation_toast_auto_close.jsx'
6
6
  export { default as FixedConfirmationToastChildren } from './_fixed_confirmation_toast_children.jsx'
7
7
  export { default as FixedConfirmationToastCustomIcon } from './_fixed_confirmation_toast_custom_icon.jsx'
8
- export { default as FixedConfirmationToastNoIcon } from './_fixed_confirmation_toast_no_icon.jsx'
8
+ export { default as FixedConfirmationToastNoIcon } from './_fixed_confirmation_toast_no_icon.jsx'
9
+ export { default as FixedConfirmationToastNavMargin } from './_fixed_confirmation_toast_nav_margin.jsx'
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.3.0.pre.alpha.play285814889
4
+ version: 16.3.0.pre.alpha.railspinnedrows14948
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-03-10 00:00:00.000000000 Z
12
+ date: 2026-03-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: playbook_ui
@@ -125,6 +125,8 @@ files:
125
125
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.jsx
126
126
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.md
127
127
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx
128
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_rails.html.erb
129
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_rails.md
128
130
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md
129
131
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_responsive.html.erb
130
132
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_responsive.jsx
@@ -155,6 +157,8 @@ files:
155
157
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort.md
156
158
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_control.jsx
157
159
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_control.md
160
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_parent_only.jsx
161
+ - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_parent_only.md
158
162
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_per_column.jsx
159
163
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_per_column.md
160
164
  - app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_per_column_for_multi_column.jsx
@@ -863,6 +867,8 @@ files:
863
867
  - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_closing_options.md
864
868
  - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_closing_options_rails.html.erb
865
869
  - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_closing_options_rails.md
870
+ - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_custom_event_type.html.erb
871
+ - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_custom_event_type.md
866
872
  - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.jsx
867
873
  - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.md
868
874
  - app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb
@@ -1053,6 +1059,10 @@ files:
1053
1059
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_multi_line.jsx
1054
1060
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_multi_line.md
1055
1061
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_multi_line_swift.md
1062
+ - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin.html.erb
1063
+ - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin.jsx
1064
+ - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin_rails.md
1065
+ - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin_react.md
1056
1066
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_no_icon.html.erb
1057
1067
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_no_icon.jsx
1058
1068
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_no_icon.md