playbook_ui 16.2.0.pre.rc.3 → 16.2.0.pre.rc.4
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 +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort.md +1 -1
- data/app/pb_kits/playbook/pb_checkbox/_checkbox.scss +1 -1
- data/app/pb_kits/playbook/pb_checkbox/_checkbox.tsx +17 -0
- data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +10 -1
- data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +2 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.html.erb +6 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.jsx +17 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +46 -11
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +1 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.html.erb +6 -3
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.jsx +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.md +3 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +11 -5
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +9 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +15 -10
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +4 -0
- data/app/pb_kits/playbook/pb_dropdown/index.js +132 -79
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +16 -0
- data/app/pb_kits/playbook/pb_dropdown/utilities/clickOutsideHelper.tsx +6 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_with_required_indicator.html.erb +5 -3
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +7 -0
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +638 -549
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +3 -3
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +4 -7
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.md +3 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +4 -4
- data/app/pb_kits/playbook/pb_nav/_item.tsx +5 -3
- data/app/pb_kits/playbook/pb_nav/_nav.scss +82 -3
- data/app/pb_kits/playbook/pb_nav/docs/_collapsible_nav_disabled_item.html.erb +24 -0
- data/app/pb_kits/playbook/pb_nav/docs/_collapsible_nav_disabled_item.jsx +87 -0
- data/app/pb_kits/playbook/pb_nav/docs/example.yml +2 -6
- data/app/pb_kits/playbook/pb_nav/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_nav/item.html.erb +1 -1
- data/app/pb_kits/playbook/pb_nav/item.rb +1 -1
- data/app/pb_kits/playbook/pb_nav/navTypes.ts +1 -0
- data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +10 -10
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +29 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +411 -323
- data/app/pb_kits/playbook/pb_typeahead/components/Control.tsx +2 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.html.erb +16 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.jsx +23 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +22 -21
- data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +3 -2
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +3 -1
- data/app/pb_kits/playbook/tokens/_colors.scss +3 -0
- data/app/pb_kits/playbook/tokens/_colors_accessible.scss +250 -0
- data/app/pb_kits/playbook/tokens/exports/_colors.module.scss +10 -0
- data/dist/chunks/{_pb_line_graph-CG2X7d4a.js → _pb_line_graph-CC2Ywwix.js} +1 -1
- data/dist/chunks/_typeahead-CmMqokN8.js +1 -0
- data/dist/chunks/{globalProps-B_OY_vR9.js → globalProps-DYr2qrIf.js} +1 -1
- data/dist/chunks/lib-DgqmX9CF.js +29 -0
- data/dist/chunks/vendor.js +2 -2
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +2 -2
- data/dist/reset.css +1 -1
- data/lib/playbook/forms/builder/form_field_builder.rb +1 -1
- data/lib/playbook/forms/builder/typeahead_field.rb +15 -1
- data/lib/playbook/forms/builder.rb +2 -2
- data/lib/playbook/version.rb +1 -1
- metadata +16 -6
- data/dist/chunks/_typeahead-DjDiMPdY.js +0 -1
- data/dist/chunks/lib-9vEH4omL.js +0 -29
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6cbd889b9a1aa2f70a8e5face90b1685b992b488955160332f43ec6f1318002a
|
|
4
|
+
data.tar.gz: a33d29f7f1ff25e1bdbb43310eeb9c37921dbca784b743b1ff915113f94a7789
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cee893abfc5a440ffeb004484e5f511a7514a76f7ef2816f87749f648241b9c8a7c1ede0a93d9610d639a863e0934588b85585941edd8abab59ef54e37d02cb1
|
|
7
|
+
data.tar.gz: 230cd647c00dae8f14eac937320e4ebd9d4128bf2ac92e3f3700be1c19b52df2c65b83e3667558aa569c76099c99990a9e7a76286530359a661ea7773f5f9ad6
|
|
@@ -2,4 +2,4 @@ the `enableSorting` prop is a boolean prop set to false by default. If true, the
|
|
|
2
2
|
|
|
3
3
|
### sortIcon
|
|
4
4
|
|
|
5
|
-
An optional prop, `sortIcon` allows you to customize your icon sets by passing it an array of any comma-separated pair of icon values. The first icon value will replace the kit's default icon when sort direction is desc, and the second value will replace the default icon when sort direction is asc. `sortIcon` also allows you to pass it a single icon as a string, in which case the icon will not toggle with the sort state. Default for this prop is `["arrow-up-short
|
|
5
|
+
An optional prop, `sortIcon` allows you to customize your icon sets by passing it an array of any comma-separated pair of icon values. The first icon value will replace the kit's default icon when sort direction is desc, and the second value will replace the default icon when sort direction is asc. `sortIcon` also allows you to pass it a single icon as a string, in which case the icon will not toggle with the sort state. Default for this prop is `["arrow-up-wide-short", "arrow-down-short-wide"]`. All strings must be valid FA icons.
|
|
@@ -4,6 +4,8 @@ import Icon from '../pb_icon/_icon'
|
|
|
4
4
|
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
|
|
5
5
|
import classnames from 'classnames'
|
|
6
6
|
import { globalProps, GlobalProps } from '../utilities/globalProps'
|
|
7
|
+
import colors from '../tokens/exports/_colors.module.scss'
|
|
8
|
+
import spacing from '../tokens/exports/_spacing.module.scss'
|
|
7
9
|
|
|
8
10
|
type CheckboxProps = {
|
|
9
11
|
aria?: {[key: string]: string},
|
|
@@ -19,6 +21,7 @@ type CheckboxProps = {
|
|
|
19
21
|
indeterminate?: boolean,
|
|
20
22
|
name?: string,
|
|
21
23
|
onChange?: (event: React.FormEvent<HTMLInputElement>) => void,
|
|
24
|
+
requiredIndicator?: boolean,
|
|
22
25
|
tabIndex?: number,
|
|
23
26
|
text?: string,
|
|
24
27
|
value?: string,
|
|
@@ -39,6 +42,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
|
|
39
42
|
indeterminate = false,
|
|
40
43
|
name = '',
|
|
41
44
|
onChange = () => { void 0 },
|
|
45
|
+
requiredIndicator = false,
|
|
42
46
|
tabIndex,
|
|
43
47
|
text = '',
|
|
44
48
|
value = '',
|
|
@@ -124,7 +128,20 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
|
|
124
128
|
variant={null}
|
|
125
129
|
>
|
|
126
130
|
{text}
|
|
131
|
+
{requiredIndicator && (
|
|
132
|
+
<span
|
|
133
|
+
aria-hidden="true"
|
|
134
|
+
className="pb_required_indicator"
|
|
135
|
+
style={{
|
|
136
|
+
color: colors.error,
|
|
137
|
+
marginLeft: spacing.space_xs,
|
|
138
|
+
}}
|
|
139
|
+
>
|
|
140
|
+
{'*'}
|
|
141
|
+
</span>
|
|
142
|
+
)}
|
|
127
143
|
</Body>
|
|
144
|
+
|
|
128
145
|
</label>
|
|
129
146
|
)
|
|
130
147
|
})
|
|
@@ -5,6 +5,15 @@
|
|
|
5
5
|
<%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon hidden", fixed_width: true}) %>
|
|
6
6
|
</span>
|
|
7
7
|
<span class="pb_checkbox_label">
|
|
8
|
-
<%= pb_rails("body", props: { status: object.checkbox_label_status,
|
|
8
|
+
<%= pb_rails("body", props: { status: object.checkbox_label_status, dark: object.dark, margin_right: object.form_spacing ? "xs" : "" }) do %>
|
|
9
|
+
<%= object.text%>
|
|
10
|
+
<% if object.required_indicator %>
|
|
11
|
+
<span
|
|
12
|
+
class="pb_checkbox_required_indicator"
|
|
13
|
+
aria-hidden="true"
|
|
14
|
+
style="color: #DA0014;"
|
|
15
|
+
>*</span>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% end %>
|
|
9
18
|
</span>
|
|
10
19
|
<% end %>
|
|
@@ -23,6 +23,8 @@ module Playbook
|
|
|
23
23
|
prop :hidden_input, type: Playbook::Props::Boolean,
|
|
24
24
|
default: false
|
|
25
25
|
prop :hidden_value
|
|
26
|
+
prop :required_indicator, type: Playbook::Props::Boolean,
|
|
27
|
+
default: false
|
|
26
28
|
|
|
27
29
|
def classname
|
|
28
30
|
generate_classname("pb_checkbox_kit", checked_class) + error_class
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import Checkbox from '../_checkbox'
|
|
3
|
+
|
|
4
|
+
const CheckboxRequiredIndicator = () => {
|
|
5
|
+
return (
|
|
6
|
+
<div>
|
|
7
|
+
<Checkbox
|
|
8
|
+
name="checkbox-name"
|
|
9
|
+
requiredIndicator
|
|
10
|
+
text="Checkbox label"
|
|
11
|
+
value="check-box value"
|
|
12
|
+
/>
|
|
13
|
+
</div>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default CheckboxRequiredIndicator
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
The `requiredIndicator`/`required_indicator` prop displays a red asterisk (*) next to the label, visually indicating that the field is required. This is purely visual and does not enforce validation.
|
|
2
|
+
|
|
3
|
+
You can use `requiredIndicator`/`required_indicator` with any validation approach: HTML5 validation via the `required` prop, client-side validation, or backend validation. For this reason, it works independently and doesn't need to be paired with the `required` prop.
|
|
@@ -8,6 +8,7 @@ examples:
|
|
|
8
8
|
- checkbox_indeterminate: Indeterminate Checkbox
|
|
9
9
|
- checkbox_disabled: Disabled Checkbox
|
|
10
10
|
- checkbox_form: Form and Hidden Input
|
|
11
|
+
# - checkbox_required_indicator: Required Indicator
|
|
11
12
|
|
|
12
13
|
react:
|
|
13
14
|
- checkbox_default: Default
|
|
@@ -17,6 +18,7 @@ examples:
|
|
|
17
18
|
- checkbox_error: Default w/ Error
|
|
18
19
|
- checkbox_indeterminate: Indeterminate Checkbox
|
|
19
20
|
- checkbox_disabled: Disabled Checkbox
|
|
21
|
+
# - checkbox_required_indicator: Required Indicator
|
|
20
22
|
|
|
21
23
|
swift:
|
|
22
24
|
- checkbox_default_swift: Default
|
|
@@ -5,3 +5,4 @@ export { default as CheckboxError } from './_checkbox_error.jsx'
|
|
|
5
5
|
export { default as CheckboxChecked } from './_checkbox_checked.jsx'
|
|
6
6
|
export { default as CheckboxIndeterminate } from './_checkbox_indeterminate.jsx'
|
|
7
7
|
export { default as CheckboxDisabled } from './_checkbox_disabled.jsx'
|
|
8
|
+
export { default as CheckboxRequiredIndicator } from './_checkbox_required_indicator.jsx'
|
|
@@ -119,6 +119,16 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
119
119
|
|
|
120
120
|
const [isDropDownClosed, setIsDropDownClosed, toggleDropdown] = useDropdown(isClosed);
|
|
121
121
|
|
|
122
|
+
// Use a suffix for the trigger ID to avoid conflict with the outer div's id
|
|
123
|
+
const sanitizeForId = (str: string) =>
|
|
124
|
+
str.toLowerCase().replace(/\s+/g, "_").replace(/[^a-z0-9_]/g, "");
|
|
125
|
+
const selectId = id
|
|
126
|
+
? `${id}_trigger`
|
|
127
|
+
: label
|
|
128
|
+
? sanitizeForId(label)
|
|
129
|
+
: undefined;
|
|
130
|
+
const errorId = error ? `${selectId}-error` : undefined;
|
|
131
|
+
|
|
122
132
|
const [filterItem, setFilterItem] = useState("");
|
|
123
133
|
const initialSelected = useMemo(() => {
|
|
124
134
|
// Handle quickpick variant with string defaultValue (e.g., "This Month")
|
|
@@ -151,9 +161,19 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
151
161
|
|
|
152
162
|
const dropdownRef = useRef(null);
|
|
153
163
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
154
|
-
const inputWrapperRef = useRef(null);
|
|
164
|
+
const inputWrapperRef = useRef<HTMLDivElement | null>(null);
|
|
155
165
|
const dropdownContainerRef = useRef(null);
|
|
156
166
|
|
|
167
|
+
const handleLabelClick = (e: React.MouseEvent) => {
|
|
168
|
+
e.stopPropagation();
|
|
169
|
+
if (selectId) {
|
|
170
|
+
const trigger = document.getElementById(selectId);
|
|
171
|
+
if (trigger) trigger.focus();
|
|
172
|
+
}
|
|
173
|
+
setIsInputFocused(true);
|
|
174
|
+
toggleDropdown();
|
|
175
|
+
};
|
|
176
|
+
|
|
157
177
|
const selectedArray = Array.isArray(selected)
|
|
158
178
|
? selected
|
|
159
179
|
: selected && Object.keys(selected).length
|
|
@@ -411,9 +431,12 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
411
431
|
autocomplete,
|
|
412
432
|
clearable,
|
|
413
433
|
dropdownContainerRef,
|
|
414
|
-
|
|
434
|
+
error,
|
|
435
|
+
errorId,
|
|
415
436
|
filterItem,
|
|
437
|
+
filteredOptions,
|
|
416
438
|
focusedOptionIndex,
|
|
439
|
+
label,
|
|
417
440
|
formPillProps,
|
|
418
441
|
handleBackspace,
|
|
419
442
|
handleChange,
|
|
@@ -423,6 +446,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
423
446
|
inputWrapperRef,
|
|
424
447
|
isDropDownClosed,
|
|
425
448
|
isInputFocused,
|
|
449
|
+
selectId,
|
|
426
450
|
multiSelect,
|
|
427
451
|
onSelect,
|
|
428
452
|
optionsWithBlankSelection,
|
|
@@ -434,13 +458,20 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
434
458
|
toggleDropdown
|
|
435
459
|
}}
|
|
436
460
|
>
|
|
437
|
-
{label &&
|
|
438
|
-
<
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
461
|
+
{label && (
|
|
462
|
+
<label
|
|
463
|
+
data-dropdown="pb-dropdown-label"
|
|
464
|
+
htmlFor={selectId}
|
|
465
|
+
onClick={handleLabelClick}
|
|
466
|
+
>
|
|
467
|
+
<Caption
|
|
468
|
+
className="pb_dropdown_kit_label"
|
|
469
|
+
dark={dark}
|
|
470
|
+
marginBottom="xs"
|
|
471
|
+
text={label}
|
|
472
|
+
/>
|
|
473
|
+
</label>
|
|
474
|
+
)}
|
|
444
475
|
<div className={`dropdown_wrapper ${error ? 'error' : ''}`}
|
|
445
476
|
onBlur={() => {
|
|
446
477
|
// Debounce to delay the execution to prevent jumpiness in Focus state
|
|
@@ -473,12 +504,16 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
|
473
504
|
</>
|
|
474
505
|
)}
|
|
475
506
|
|
|
476
|
-
{error &&
|
|
507
|
+
{error && (
|
|
477
508
|
<Body
|
|
509
|
+
aria={{ atomic: "true", live: "polite" }}
|
|
510
|
+
dark={dark}
|
|
511
|
+
htmlOptions={{ role: "alert" }}
|
|
512
|
+
id={errorId}
|
|
478
513
|
status="negative"
|
|
479
514
|
text={error}
|
|
480
515
|
/>
|
|
481
|
-
}
|
|
516
|
+
)}
|
|
482
517
|
</div>
|
|
483
518
|
</DropdownContext.Provider>
|
|
484
519
|
</div>
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
const option = e.detail;
|
|
77
77
|
const dropdown = e.target;
|
|
78
78
|
|
|
79
|
-
const display = dropdown.querySelector("
|
|
79
|
+
const display = dropdown.querySelector("[data-dropdown-trigger-custom-display]");
|
|
80
80
|
if (!display) return;
|
|
81
81
|
|
|
82
82
|
const nameEl = display.querySelector("#dropdown-avatar-name");
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
<%
|
|
1
|
+
<%
|
|
2
2
|
options = [
|
|
3
3
|
{ label: 'United States', value: 'unitedStates', id: 'us' },
|
|
4
4
|
{ label: 'Canada', value: 'canada', id: 'ca' },
|
|
5
5
|
{ label: 'Pakistan', value: 'pakistan', id: 'pk' },
|
|
6
6
|
]
|
|
7
|
-
|
|
8
7
|
%>
|
|
9
8
|
|
|
10
|
-
<%= pb_rails("dropdown", props: {
|
|
9
|
+
<%= pb_rails("dropdown", props: {
|
|
10
|
+
id: "select_a_country",
|
|
11
|
+
label: "Select a Country",
|
|
12
|
+
options: options
|
|
13
|
+
}) %>
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
The top-level Dropdown component optionally accepts any string through a `label` prop to produce a label above your trigger element.
|
|
1
|
+
The top-level Dropdown component optionally accepts any string through a `label` prop to produce a label above your trigger element.
|
|
2
|
+
|
|
3
|
+
Add an `id` to wire the label to the trigger so that clicking the label will move focus directly to the input, and open the drop-down.
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<%= pb_content_tag do %>
|
|
2
2
|
<% if object.label.present? %>
|
|
3
|
-
|
|
3
|
+
<label for="<%= object.select_id %>" data-dropdown="pb-dropdown-label">
|
|
4
|
+
<%= pb_rails("caption", props: { text: object.label, margin_bottom: "xs", classname: "pb_dropdown_kit_label", dark: object.dark }) %>
|
|
5
|
+
</label>
|
|
4
6
|
<% end %>
|
|
5
7
|
<div class="dropdown_wrapper<%= error_class %>" style="position: relative">
|
|
6
8
|
<input
|
|
7
9
|
data-default-value="<%= input_default_value %>"
|
|
8
|
-
|
|
10
|
+
data-dropdown-selected-option
|
|
9
11
|
name="<%= object.name %><%= '[]' if object.multi_select %>"
|
|
10
12
|
style="display: none"
|
|
11
13
|
<%= object.required ? "required" : ""%>
|
|
@@ -16,9 +18,11 @@
|
|
|
16
18
|
<% end %>
|
|
17
19
|
<% if content.present? %>
|
|
18
20
|
<%= content.presence %>
|
|
19
|
-
|
|
21
|
+
<% if object.error.present? %>
|
|
22
|
+
<%= pb_rails("body", props: { status: "negative", text: object.error, id: object.error_id, aria: { atomic: "true", live: "polite" }, html_options: { role: "alert" }, dark: object.dark }) %>
|
|
23
|
+
<% end %>
|
|
20
24
|
<% else %>
|
|
21
|
-
<%= pb_rails("dropdown/dropdown_trigger", props:{ autocomplete: object.autocomplete, multi_select:object.multi_select, placeholder: object.placeholder }) %>
|
|
25
|
+
<%= pb_rails("dropdown/dropdown_trigger", props: { autocomplete: object.autocomplete, multi_select: object.multi_select, placeholder: object.placeholder, select_id: object.select_id, label: object.label, error_id: object.error_id, error: object.error }) %>
|
|
22
26
|
<%= pb_rails("dropdown/dropdown_container", props: { searchbar: object.searchbar, constrain_height: object.constrain_height }) do %>
|
|
23
27
|
<% if options_with_blank.present? %>
|
|
24
28
|
<% options_with_blank.each do |option| %>
|
|
@@ -27,7 +31,9 @@
|
|
|
27
31
|
<% end %>
|
|
28
32
|
<% end %>
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
<% if object.error.present? %>
|
|
35
|
+
<%= pb_rails("body", props: { status: "negative", text: object.error, id: object.error_id, aria: { atomic: "true", live: "polite" }, html_options: { role: "alert" }, dark: object.dark }) %>
|
|
36
|
+
<% end %>
|
|
31
37
|
<% end %>
|
|
32
38
|
</div>
|
|
33
39
|
<% end %>
|
|
@@ -10,6 +10,7 @@ module Playbook
|
|
|
10
10
|
prop :label, type: Playbook::Props::String
|
|
11
11
|
prop :name, type: Playbook::Props::String
|
|
12
12
|
prop :error, type: Playbook::Props::String
|
|
13
|
+
prop :id, type: Playbook::Props::String
|
|
13
14
|
prop :required, type: Playbook::Props::Boolean,
|
|
14
15
|
default: false
|
|
15
16
|
prop :default_value
|
|
@@ -68,6 +69,14 @@ module Playbook
|
|
|
68
69
|
generate_classname("pb_dropdown", variant, separators_class)
|
|
69
70
|
end
|
|
70
71
|
|
|
72
|
+
def select_id
|
|
73
|
+
id.presence || (label.present? ? label.downcase.gsub(/\s+/, "_").gsub(/[^a-z0-9_]/, "") : nil)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def error_id
|
|
77
|
+
error.present? ? "#{select_id || 'dropdown_trigger'}-error" : nil
|
|
78
|
+
end
|
|
79
|
+
|
|
71
80
|
private
|
|
72
81
|
|
|
73
82
|
def error_class
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
<%= pb_content_tag do %>
|
|
2
2
|
<% if content.present? %>
|
|
3
|
-
<div style="display: inline-block" tabindex="0" data-dropdown-custom-trigger
|
|
3
|
+
<div style="display: inline-block" tabindex="0" data-dropdown="pb-dropdown-trigger" data-dropdown-custom-trigger aria-invalid="<%= object.error.present? %>"
|
|
4
|
+
<% if object.label.present? %> aria-label="<%= [object.label, object.default_display_placeholder].join(', ') %>"<% end %>
|
|
5
|
+
<% if object.select_id.present? %> id="<%= object.select_id %>"<% end %>
|
|
6
|
+
<% if object.error_id.present? %> aria-describedby="<%= object.error_id %>"<% end %>
|
|
7
|
+
>
|
|
4
8
|
<%= content.presence %>
|
|
5
9
|
</div>
|
|
6
10
|
<% else %>
|
|
@@ -9,24 +13,25 @@
|
|
|
9
13
|
border_radius:"lg",
|
|
10
14
|
classname: object.trigger_wrapper_classes,
|
|
11
15
|
cursor: object.autocomplete ? "text" : "pointer",
|
|
16
|
+
id: object.select_id,
|
|
12
17
|
justify: "between",
|
|
13
18
|
padding_x:"sm",
|
|
14
19
|
padding_y:"xs",
|
|
15
|
-
html_options: {tabindex:"0"}
|
|
20
|
+
html_options: { tabindex: "0", "aria-label": object.label.present? ? [object.label, object.default_display_placeholder].join(", ") : nil, "aria-describedby": object.error_id, "aria-invalid": object.error.present?, "data-dropdown": "pb-dropdown-trigger" }
|
|
16
21
|
}) do %>
|
|
17
22
|
<%= pb_rails("flex/flex_item", props: { fixed_size: object.multi_select ? "85%" : "" }) do %>
|
|
18
23
|
<%= pb_rails("flex", props: {align: "center"}) do %>
|
|
19
24
|
<% if object.custom_display.present? %>
|
|
20
25
|
<%= pb_rails("flex", props: {align: "center"}) do %>
|
|
21
|
-
<div
|
|
26
|
+
<div data-dropdown-trigger-custom-display style="display: none;">
|
|
22
27
|
<%= object.custom_display %>
|
|
23
28
|
</div>
|
|
24
|
-
<%= pb_rails("body", props: {text: object.default_display_placeholder,
|
|
29
|
+
<%= pb_rails("body", props: {text: object.default_display_placeholder, data: { 'dropdown-trigger-display': true }}) %>
|
|
25
30
|
<% end %>
|
|
26
31
|
<% else %>
|
|
27
32
|
<% if object.multi_select %>
|
|
28
33
|
<%= pb_rails("flex", props: { align: "center", wrap: true }) do %>
|
|
29
|
-
<%= pb_rails("flex", props: {
|
|
34
|
+
<%= pb_rails("flex", props: { data: { 'dropdown-pills-wrapper': true }, wrap: true }) do %>
|
|
30
35
|
<% end %>
|
|
31
36
|
<% if object.autocomplete %>
|
|
32
37
|
<input
|
|
@@ -37,7 +42,7 @@
|
|
|
37
42
|
autocomplete="off"
|
|
38
43
|
/>
|
|
39
44
|
<% else %>
|
|
40
|
-
<%= pb_rails("body", props: {text: object.default_display_placeholder,
|
|
45
|
+
<%= pb_rails("body", props: {text: object.default_display_placeholder, data: { "dropdown-trigger-display-multi-select": true }}) %>
|
|
41
46
|
<% end %>
|
|
42
47
|
<% end %>
|
|
43
48
|
<% else %>
|
|
@@ -50,7 +55,7 @@
|
|
|
50
55
|
autocomplete="off"
|
|
51
56
|
/>
|
|
52
57
|
<% else %>
|
|
53
|
-
<%= pb_rails("body", props: {text: object.default_display_placeholder,
|
|
58
|
+
<%= pb_rails("body", props: {text: object.default_display_placeholder, data: { 'dropdown-trigger-display': true }}) %>
|
|
54
59
|
<% end %>
|
|
55
60
|
<% end %>
|
|
56
61
|
<% end %>
|
|
@@ -58,9 +63,9 @@
|
|
|
58
63
|
<% end %>
|
|
59
64
|
<%= pb_rails("flex/flex_item") do %>
|
|
60
65
|
<%= pb_rails("body", props: {display: "flex", align_items:"center" }) do %>
|
|
61
|
-
<%= pb_rails("icon", props: {icon: "times", cursor: "pointer", size:"sm",
|
|
62
|
-
<%= pb_rails("icon", props: {icon: "chevron-down", cursor: "pointer", size:"sm",
|
|
63
|
-
<%= pb_rails("icon", props: {icon: "chevron-up", cursor: "pointer", size:"sm",
|
|
66
|
+
<%= pb_rails("icon", props: {icon: "times", cursor: "pointer", size:"sm", data:{'dropdown-clear-icon': true }, padding_right:"xs" }) %>
|
|
67
|
+
<%= pb_rails("icon", props: {icon: "chevron-down", cursor: "pointer", size:"sm", data:{'dropdown-open-icon': true }}) %>
|
|
68
|
+
<%= pb_rails("icon", props: {icon: "chevron-up", cursor: "pointer", size:"sm", data:{ 'dropdown-close-icon': true }}) %>
|
|
64
69
|
<% end %>
|
|
65
70
|
<% end %>
|
|
66
71
|
<% end %>
|
|
@@ -13,6 +13,10 @@ module Playbook
|
|
|
13
13
|
default: false
|
|
14
14
|
prop :multi_select, type: Playbook::Props::Boolean,
|
|
15
15
|
default: false
|
|
16
|
+
prop :select_id, type: Playbook::Props::String
|
|
17
|
+
prop :label, type: Playbook::Props::String
|
|
18
|
+
prop :error_id, type: Playbook::Props::String
|
|
19
|
+
prop :error, type: Playbook::Props::String
|
|
16
20
|
|
|
17
21
|
def data
|
|
18
22
|
Hash(prop(:data)).merge(dropdown_trigger: true, dropdown_placeholder: default_display_placeholder)
|