playbook_ui 15.4.0.pre.rc.4 → 15.5.0.pre.rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +25 -11
- data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.tsx +20 -13
- data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.rb +6 -4
- data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.test.js +17 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_show_current_year.html.erb +4 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_show_current_year.jsx +43 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_description.md +1 -1
- data/app/pb_kits/playbook/pb_date_range_inline/docs/example.yml +3 -2
- data/app/pb_kits/playbook/pb_date_range_inline/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_date_stacked/_date_stacked.tsx +6 -4
- data/app/pb_kits/playbook/pb_date_stacked/date_stacked.html.erb +2 -3
- data/app/pb_kits/playbook/pb_date_stacked/date_stacked.rb +11 -5
- data/app/pb_kits/playbook/pb_date_stacked/date_stacked.test.js +26 -9
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_current_year.html.erb +12 -0
- data/app/pb_kits/playbook/pb_date_stacked/docs/{_date_stacked_not_current_year.jsx → _date_stacked_current_year.jsx} +6 -5
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_default.html.erb +1 -1
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_date_stacked/docs/_description.md +1 -1
- data/app/pb_kits/playbook/pb_date_stacked/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_date_stacked/docs/index.js +1 -1
- data/app/pb_kits/playbook/pb_dropdown/index.js +1 -1
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx +31 -9
- data/app/pb_kits/playbook/pb_flex/_flex_item.tsx +12 -5
- data/app/pb_kits/playbook/pb_flex/docs/_flex_item_example.jsx +1 -0
- data/app/pb_kits/playbook/pb_nav/_item.tsx +18 -4
- data/app/pb_kits/playbook/pb_nav/_nav.scss +30 -5
- data/app/pb_kits/playbook/pb_nav/_nav_item.test.js +192 -0
- data/app/pb_kits/playbook/pb_nav/_vertical_nav.scss +1 -1
- data/app/pb_kits/playbook/pb_nav/docs/_horizontal_nav_disabled.html.erb +21 -0
- data/app/pb_kits/playbook/pb_nav/docs/_horizontal_nav_disabled.jsx +113 -0
- data/app/pb_kits/playbook/pb_nav/docs/_horizontal_nav_disabled.md +1 -0
- data/app/pb_kits/playbook/pb_nav/docs/_vertical_nav_disabled.html.erb +30 -0
- data/app/pb_kits/playbook/pb_nav/docs/_vertical_nav_disabled.jsx +117 -0
- data/app/pb_kits/playbook/pb_nav/docs/_vertical_nav_disabled.md +1 -0
- data/app/pb_kits/playbook/pb_nav/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_nav/docs/index.js +3 -1
- data/app/pb_kits/playbook/pb_nav/item.html.erb +6 -4
- data/app/pb_kits/playbook/pb_nav/item.rb +11 -2
- data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/Toolbar.tsx +1 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +61 -8
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_default_rails.md +7 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_focus.html.erb +10 -2
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_inline_rails.md +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_preview.html.erb +19 -11
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_simple.html.erb +5 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_sticky.html.erb +1 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_sticky_rails.md +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb +16 -7
- data/dist/chunks/{_line_graph-C-AuMGN2.js → _line_graph-eQNOB_GQ.js} +1 -1
- data/dist/chunks/_typeahead-vbfetkuE.js +24 -0
- data/dist/chunks/{_weekday_stacked-Fx-KHOwY.js → _weekday_stacked-CvJHyUq6.js} +3 -3
- data/dist/chunks/{lib-BXBHAZMY.js → lib-BCrK6CFU.js} +1 -1
- data/dist/chunks/{pb_form_validation-BNfSnIUF.js → pb_form_validation-Cj4vdjWI.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/playbook-doc.js +1 -19
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +2 -2
- metadata +22 -9
- data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_not_current_year.html.erb +0 -5
- data/dist/chunks/_typeahead--38pnHwS.js +0 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from "react";
|
|
1
|
+
import React, { useEffect, useState, useRef } from "react";
|
|
2
2
|
import classnames from "classnames";
|
|
3
3
|
|
|
4
4
|
import { globalProps, GlobalProps } from "../utilities/globalProps";
|
|
@@ -36,6 +36,7 @@ type FixedConfirmationToastProps = {
|
|
|
36
36
|
|
|
37
37
|
const FixedConfirmationToast = (props: FixedConfirmationToastProps): React.ReactElement => {
|
|
38
38
|
const [showToast, toggleToast] = useState(true);
|
|
39
|
+
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
39
40
|
|
|
40
41
|
const {
|
|
41
42
|
autoClose = 0,
|
|
@@ -67,21 +68,42 @@ const FixedConfirmationToast = (props: FixedConfirmationToastProps): React.React
|
|
|
67
68
|
|
|
68
69
|
const htmlProps = buildHtmlProps(htmlOptions);
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
toggleToast(open);
|
|
73
|
+
}, [open]);
|
|
74
|
+
|
|
75
|
+
// Manage auto-close timeout separately
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
// Clear any existing timeout
|
|
78
|
+
if (timeoutRef.current) {
|
|
79
|
+
clearTimeout(timeoutRef.current);
|
|
80
|
+
timeoutRef.current = null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Set new timeout if autoClose is enabled and toast is open
|
|
84
|
+
if (autoClose && open && showToast) {
|
|
85
|
+
timeoutRef.current = setTimeout(() => {
|
|
73
86
|
toggleToast(false);
|
|
74
87
|
onClose();
|
|
88
|
+
timeoutRef.current = null;
|
|
75
89
|
}, autoClose);
|
|
76
90
|
}
|
|
77
|
-
};
|
|
78
91
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
// Cleanup function to clear timeout on unmount or when dependencies change
|
|
93
|
+
return () => {
|
|
94
|
+
if (timeoutRef.current) {
|
|
95
|
+
clearTimeout(timeoutRef.current);
|
|
96
|
+
timeoutRef.current = null;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}, [autoClose, open, showToast, onClose]);
|
|
83
100
|
|
|
84
101
|
const handleClick = () => {
|
|
102
|
+
// Clear autoClose timeout when manually closing
|
|
103
|
+
if (timeoutRef.current) {
|
|
104
|
+
clearTimeout(timeoutRef.current);
|
|
105
|
+
timeoutRef.current = null;
|
|
106
|
+
}
|
|
85
107
|
toggleToast(!closeable);
|
|
86
108
|
onClose();
|
|
87
109
|
};
|
|
@@ -2,6 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import classnames from 'classnames'
|
|
3
3
|
import { buildCss, buildHtmlProps } from '../utilities/props'
|
|
4
4
|
import { globalProps, GlobalProps, globalInlineProps} from '../utilities/globalProps'
|
|
5
|
+
|
|
5
6
|
type FlexItemPropTypes = {
|
|
6
7
|
children: React.ReactNode[] | React.ReactNode,
|
|
7
8
|
fixedSize?: string,
|
|
@@ -28,22 +29,28 @@ const FlexItem = (props: FlexItemPropTypes): React.ReactElement => {
|
|
|
28
29
|
alignSelf,
|
|
29
30
|
displayFlex
|
|
30
31
|
} = props
|
|
32
|
+
|
|
31
33
|
const growClass = grow === true ? 'pb_flex_item_kit_grow' : ''
|
|
32
34
|
const displayFlexClass = displayFlex === true ? 'pb_flex_item_kit_display_flex' : ''
|
|
33
35
|
const flexClass = flex !== 'none' ? `pb_flex_item_kit_flex_${flex}` : ''
|
|
34
36
|
const shrinkClass = shrink === true ? 'pb_flex_item_kit_shrink' : ''
|
|
35
37
|
const alignSelfClass = alignSelf ? `pb_flex_item_kit_align_self_${alignSelf}` : ''
|
|
36
|
-
const fixedStyle =
|
|
37
|
-
fixedSize !== undefined ? { flexBasis: `${fixedSize}` } : null
|
|
38
|
+
const fixedStyle = fixedSize !== undefined ? { flexBasis: `${fixedSize}` } : null
|
|
38
39
|
const orderClass = order !== 'none' ? `pb_flex_item_kit_order_${order}` : ''
|
|
39
40
|
const dynamicInlineProps = globalInlineProps(props)
|
|
41
|
+
|
|
42
|
+
// Extract style from htmlOptions and remove it
|
|
43
|
+
const { style: htmlStyle, ...htmlOptionsWithoutStyle } = htmlOptions
|
|
44
|
+
const htmlStyleObj = htmlStyle && typeof htmlStyle === 'object' ? htmlStyle : {}
|
|
45
|
+
|
|
46
|
+
// Merge all styles
|
|
40
47
|
const combinedStyles = {
|
|
48
|
+
...htmlStyleObj,
|
|
41
49
|
...fixedStyle,
|
|
42
50
|
...dynamicInlineProps
|
|
43
51
|
}
|
|
44
52
|
|
|
45
|
-
const htmlProps = buildHtmlProps(
|
|
46
|
-
|
|
53
|
+
const htmlProps = buildHtmlProps(htmlOptionsWithoutStyle)
|
|
47
54
|
|
|
48
55
|
return (
|
|
49
56
|
<div
|
|
@@ -66,4 +73,4 @@ const FlexItem = (props: FlexItemPropTypes): React.ReactElement => {
|
|
|
66
73
|
)
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
export default FlexItem
|
|
76
|
+
export default FlexItem
|
|
@@ -43,6 +43,7 @@ type NavItemProps = {
|
|
|
43
43
|
marginLeft?: Spacing;
|
|
44
44
|
marginX?: Spacing;
|
|
45
45
|
marginY?: Spacing;
|
|
46
|
+
disabled?: boolean;
|
|
46
47
|
} & GlobalProps;
|
|
47
48
|
|
|
48
49
|
const NavItem = (props: NavItemProps) => {
|
|
@@ -89,6 +90,7 @@ const NavItem = (props: NavItemProps) => {
|
|
|
89
90
|
marginLeft,
|
|
90
91
|
marginX,
|
|
91
92
|
marginY,
|
|
93
|
+
disabled = false,
|
|
92
94
|
} = props;
|
|
93
95
|
|
|
94
96
|
const spacingMarginProps = {
|
|
@@ -140,11 +142,12 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing);
|
|
|
140
142
|
delete filteredProps?.marginLeft;
|
|
141
143
|
|
|
142
144
|
|
|
143
|
-
const isLink = !!link
|
|
145
|
+
const isLink = !!link && !disabled
|
|
144
146
|
const Tag = isLink ? "a" : "div"
|
|
145
147
|
const activeClass = active === true ? "active" : "";
|
|
146
148
|
const highlightedBorderClass = active === true && highlighted_border === false ? "highlighted_border_none" : "";
|
|
147
149
|
const collapsibleTrailClass = collapsible && collapsibleTrail ? "collapsible_trail" : "";
|
|
150
|
+
const disabledClass = disabled ? "pb_nav_item_disabled" : "";
|
|
148
151
|
|
|
149
152
|
const fontSizeMapping = {
|
|
150
153
|
"small": "font_size_small",
|
|
@@ -177,6 +180,7 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing);
|
|
|
177
180
|
fontWeightClass,
|
|
178
181
|
tagClasses,
|
|
179
182
|
collapsible ? globalProps(filteredProps, {...filteredPadding}) : globalProps(props, {...itemSpacing}),
|
|
183
|
+
disabledClass,
|
|
180
184
|
className
|
|
181
185
|
);
|
|
182
186
|
|
|
@@ -202,12 +206,21 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing);
|
|
|
202
206
|
const collapsibleClasses = buildCss("collapsible_nav_wrapper", activeClass, highlightedBorderClass, collapsibleTrailClass)
|
|
203
207
|
|
|
204
208
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
205
|
-
if (!isLink && (e.key === "Enter" || e.key === " ")) {
|
|
209
|
+
if (!disabled && !isLink && (e.key === "Enter" || e.key === " ")) {
|
|
206
210
|
e.preventDefault()
|
|
207
211
|
onClick?.()
|
|
208
212
|
}
|
|
209
213
|
}
|
|
210
214
|
|
|
215
|
+
const handleClick = (e: React.MouseEvent) => {
|
|
216
|
+
if (disabled) {
|
|
217
|
+
e.preventDefault()
|
|
218
|
+
e.stopPropagation()
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
onClick?.()
|
|
222
|
+
}
|
|
223
|
+
|
|
211
224
|
return (
|
|
212
225
|
<>
|
|
213
226
|
{collapsible ? (
|
|
@@ -275,13 +288,14 @@ const { filteredPadding, filteredMargin } = filterItemSpacing(itemSpacing);
|
|
|
275
288
|
{...ariaProps}
|
|
276
289
|
{...dataProps}
|
|
277
290
|
{...htmlProps}
|
|
291
|
+
aria-disabled={disabled}
|
|
278
292
|
className={classes}
|
|
279
293
|
href={isLink ? link : undefined}
|
|
280
294
|
id={id}
|
|
281
|
-
onClick={
|
|
295
|
+
onClick={handleClick}
|
|
282
296
|
onKeyDown={!isLink ? handleKeyDown : undefined}
|
|
283
297
|
role={!isLink ? "button" : undefined}
|
|
284
|
-
tabIndex={!isLink ? 0 : undefined}
|
|
298
|
+
tabIndex={disabled ? -1 : (!isLink ? 0 : undefined)}
|
|
285
299
|
target={isLink ? target : undefined}
|
|
286
300
|
>
|
|
287
301
|
{imageUrl && (
|
|
@@ -45,16 +45,18 @@
|
|
|
45
45
|
|
|
46
46
|
[class*="pb_nav_list_kit_item"],
|
|
47
47
|
[class*="pb_nav_list_item"] {
|
|
48
|
-
&:hover {
|
|
48
|
+
&:hover {
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
}
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
.pb_nav_extended_underline {
|
|
53
55
|
position: relative;
|
|
54
|
-
|
|
56
|
+
|
|
55
57
|
// Add full-width border using pseudo-element so as not to break the active item border
|
|
56
58
|
&::after {
|
|
57
|
-
content:
|
|
59
|
+
content: "";
|
|
58
60
|
position: absolute;
|
|
59
61
|
bottom: 0;
|
|
60
62
|
left: 0;
|
|
@@ -65,8 +67,8 @@
|
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
.pb_nav_list_kit_item_active.pb_nav_list_item_link {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
position: relative;
|
|
71
|
+
z-index: 2;
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
&.dark {
|
|
@@ -75,3 +77,26 @@
|
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
}
|
|
80
|
+
|
|
81
|
+
// Disabled scss
|
|
82
|
+
.pb_nav_item_disabled {
|
|
83
|
+
cursor: not-allowed !important;
|
|
84
|
+
.pb_nav_list_item_text,
|
|
85
|
+
.pb_nav_list_item_icon_left,
|
|
86
|
+
.pb_nav_list_item_icon_right,
|
|
87
|
+
.pb_nav_list_item_icon_section {
|
|
88
|
+
color: $text_lt_lighter !important;
|
|
89
|
+
cursor: not-allowed !important;
|
|
90
|
+
}
|
|
91
|
+
@media (hover: hover) {
|
|
92
|
+
&:hover {
|
|
93
|
+
background-color: unset !important;
|
|
94
|
+
color: $text_lt_lighter !important;
|
|
95
|
+
.pb_nav_list_item_text,
|
|
96
|
+
.pb_nav_list_item_icon_left,
|
|
97
|
+
.pb_nav_list_item_icon_right {
|
|
98
|
+
color: $text_lt_lighter !important;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -5,6 +5,8 @@ import Nav from './_nav'
|
|
|
5
5
|
import NavItem from './_item'
|
|
6
6
|
|
|
7
7
|
const navTestId = 'nav'
|
|
8
|
+
const navDisabledTestId = 'nav-disabled'
|
|
9
|
+
const itemDisabledTestId = 'item-disabled'
|
|
8
10
|
const itemTestId = 'item'
|
|
9
11
|
const activeTestBorderlessId = 'activeborderless'
|
|
10
12
|
const activeTestBorderId = 'active'
|
|
@@ -105,3 +107,193 @@ test('should have a left icon', () => {
|
|
|
105
107
|
const icon = kit.querySelector(".pb_custom_icon.pb_nav_list_item_icon_left")
|
|
106
108
|
expect(icon).toBeInTheDocument()
|
|
107
109
|
})
|
|
110
|
+
|
|
111
|
+
test('should apply disabled class when disabled (horizontal nav)', () => {
|
|
112
|
+
[
|
|
113
|
+
"default",
|
|
114
|
+
"subtle",
|
|
115
|
+
"bold"
|
|
116
|
+
].forEach((variant) => {
|
|
117
|
+
render(
|
|
118
|
+
<Nav
|
|
119
|
+
aria={{ label: navDisabledTestId }}
|
|
120
|
+
className={navClassName}
|
|
121
|
+
data={{ testid: navDisabledTestId }}
|
|
122
|
+
orientation="horizontal"
|
|
123
|
+
variant={variant}
|
|
124
|
+
>
|
|
125
|
+
<NavItem
|
|
126
|
+
aria={{ label: `${itemDisabledTestId}-${variant}` }}
|
|
127
|
+
className={itemClassName}
|
|
128
|
+
data={{ testid: `${itemDisabledTestId}-${variant}` }}
|
|
129
|
+
disabled
|
|
130
|
+
link="#"
|
|
131
|
+
text="Files"
|
|
132
|
+
/>
|
|
133
|
+
</Nav>
|
|
134
|
+
)
|
|
135
|
+
const kit = screen.getByTestId(`${itemDisabledTestId}-${variant}`)
|
|
136
|
+
expect(kit).toHaveClass('pb_nav_item_disabled')
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
test('should set aria-disabled when disabled (horizontal nav)', () => {
|
|
141
|
+
[
|
|
142
|
+
"default",
|
|
143
|
+
"subtle",
|
|
144
|
+
"bold"
|
|
145
|
+
].forEach((variant) => {
|
|
146
|
+
render(
|
|
147
|
+
<Nav
|
|
148
|
+
aria={{ label: navDisabledTestId }}
|
|
149
|
+
className={navClassName}
|
|
150
|
+
data={{ testid: navDisabledTestId }}
|
|
151
|
+
orientation="horizontal"
|
|
152
|
+
variant={variant}
|
|
153
|
+
>
|
|
154
|
+
<NavItem
|
|
155
|
+
aria={{ label: `${itemDisabledTestId}-${variant}` }}
|
|
156
|
+
className={itemClassName}
|
|
157
|
+
data={{ testid: `${itemDisabledTestId}-${variant}` }}
|
|
158
|
+
disabled
|
|
159
|
+
link="#"
|
|
160
|
+
text="Files"
|
|
161
|
+
/>
|
|
162
|
+
</Nav>
|
|
163
|
+
)
|
|
164
|
+
const item = screen.getByTestId(`${itemDisabledTestId}-${variant}`)
|
|
165
|
+
expect(item).toHaveAttribute('aria-disabled', 'true')
|
|
166
|
+
})
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
test('should set tabIndex to -1 when disabled (horizontal nav)', () => {
|
|
170
|
+
[
|
|
171
|
+
"default",
|
|
172
|
+
"subtle",
|
|
173
|
+
"bold"
|
|
174
|
+
].forEach((variant) => {
|
|
175
|
+
render(
|
|
176
|
+
<Nav
|
|
177
|
+
aria={{ label: navDisabledTestId }}
|
|
178
|
+
className={navClassName}
|
|
179
|
+
data={{ testid: navDisabledTestId }}
|
|
180
|
+
orientation="horizontal"
|
|
181
|
+
variant={variant}
|
|
182
|
+
>
|
|
183
|
+
<NavItem
|
|
184
|
+
aria={{ label: `${itemDisabledTestId}-${variant}` }}
|
|
185
|
+
className={itemClassName}
|
|
186
|
+
data={{ testid: `${itemDisabledTestId}-${variant}` }}
|
|
187
|
+
disabled
|
|
188
|
+
link="#"
|
|
189
|
+
text="Files"
|
|
190
|
+
/>
|
|
191
|
+
</Nav>
|
|
192
|
+
)
|
|
193
|
+
const kit = screen.getByTestId(`${itemDisabledTestId}-${variant}`)
|
|
194
|
+
expect(kit).toHaveAttribute('tabIndex', '-1')
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
test('should prevent onClick when disabled', () => {
|
|
199
|
+
const handleClick = jest.fn()
|
|
200
|
+
render(
|
|
201
|
+
<NavItem
|
|
202
|
+
data={{ testid: 'disabled-click-item' }}
|
|
203
|
+
disabled
|
|
204
|
+
link="#"
|
|
205
|
+
onClick={handleClick}
|
|
206
|
+
text="Disabled Item"
|
|
207
|
+
/>
|
|
208
|
+
)
|
|
209
|
+
const kit = screen.getByTestId('disabled-click-item')
|
|
210
|
+
kit.click()
|
|
211
|
+
expect(handleClick).not.toHaveBeenCalled()
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
test('should apply disabled class when disabled (vertical nav)', () => {
|
|
215
|
+
[
|
|
216
|
+
"default",
|
|
217
|
+
"subtle",
|
|
218
|
+
"bold"
|
|
219
|
+
].forEach((variant) => {
|
|
220
|
+
render(
|
|
221
|
+
<Nav
|
|
222
|
+
aria={{ label: navDisabledTestId }}
|
|
223
|
+
className={navClassName}
|
|
224
|
+
data={{ testid: navDisabledTestId }}
|
|
225
|
+
orientation="vertical"
|
|
226
|
+
variant={variant}
|
|
227
|
+
>
|
|
228
|
+
<NavItem
|
|
229
|
+
aria={{ label: `${itemDisabledTestId}-${variant}` }}
|
|
230
|
+
className={itemClassName}
|
|
231
|
+
data={{ testid: `${itemDisabledTestId}-${variant}` }}
|
|
232
|
+
disabled
|
|
233
|
+
link="#"
|
|
234
|
+
text="Files"
|
|
235
|
+
/>
|
|
236
|
+
</Nav>
|
|
237
|
+
)
|
|
238
|
+
const kit = screen.getByTestId(`${itemDisabledTestId}-${variant}`)
|
|
239
|
+
expect(kit).toHaveClass('pb_nav_item_disabled')
|
|
240
|
+
})
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
test('should set aria-disabled when disabled (vertical nav)', () => {
|
|
244
|
+
[
|
|
245
|
+
"default",
|
|
246
|
+
"subtle",
|
|
247
|
+
"bold"
|
|
248
|
+
].forEach((variant) => {
|
|
249
|
+
render(
|
|
250
|
+
<Nav
|
|
251
|
+
aria={{ label: navDisabledTestId }}
|
|
252
|
+
className={navClassName}
|
|
253
|
+
data={{ testid: navDisabledTestId }}
|
|
254
|
+
orientation="vertical"
|
|
255
|
+
variant={variant}
|
|
256
|
+
>
|
|
257
|
+
<NavItem
|
|
258
|
+
aria={{ label: `${itemDisabledTestId}-${variant}` }}
|
|
259
|
+
className={itemClassName}
|
|
260
|
+
data={{ testid: `${itemDisabledTestId}-${variant}` }}
|
|
261
|
+
disabled
|
|
262
|
+
link="#"
|
|
263
|
+
text="Files"
|
|
264
|
+
/>
|
|
265
|
+
</Nav>
|
|
266
|
+
)
|
|
267
|
+
const item = screen.getByTestId(`${itemDisabledTestId}-${variant}`)
|
|
268
|
+
expect(item).toHaveAttribute('aria-disabled', 'true')
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
test('should set tabIndex to -1 when disabled (vertical nav)', () => {
|
|
273
|
+
[
|
|
274
|
+
"default",
|
|
275
|
+
"subtle",
|
|
276
|
+
"bold"
|
|
277
|
+
].forEach((variant) => {
|
|
278
|
+
render(
|
|
279
|
+
<Nav
|
|
280
|
+
aria={{ label: navDisabledTestId }}
|
|
281
|
+
className={navClassName}
|
|
282
|
+
data={{ testid: navDisabledTestId }}
|
|
283
|
+
orientation="vertical"
|
|
284
|
+
variant={variant}
|
|
285
|
+
>
|
|
286
|
+
<NavItem
|
|
287
|
+
aria={{ label: `${itemDisabledTestId}-${variant}` }}
|
|
288
|
+
className={itemClassName}
|
|
289
|
+
data={{ testid: `${itemDisabledTestId}-${variant}` }}
|
|
290
|
+
disabled
|
|
291
|
+
link="#"
|
|
292
|
+
text="Files"
|
|
293
|
+
/>
|
|
294
|
+
</Nav>
|
|
295
|
+
)
|
|
296
|
+
const kit = screen.getByTestId(`${itemDisabledTestId}-${variant}`)
|
|
297
|
+
expect(kit).toHaveAttribute('tabIndex', '-1')
|
|
298
|
+
})
|
|
299
|
+
})
|
|
@@ -44,7 +44,7 @@ $selector: ".pb_nav_list";
|
|
|
44
44
|
transition-duration: 0.15s;
|
|
45
45
|
transition-timing-function: $bezier;
|
|
46
46
|
@media (hover: hover) {
|
|
47
|
-
&:hover {
|
|
47
|
+
&:hover:not(.pb_nav_item_disabled) {
|
|
48
48
|
background-color: rgba($primary, 0.03);
|
|
49
49
|
[class*="_icon"] {
|
|
50
50
|
color: $primary;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%= pb_rails("caption", props: { margin_bottom: "sm", text: "Default Variant" }) %>
|
|
2
|
+
<%= pb_rails("nav", props: { orientation: "horizontal" }) do %>
|
|
3
|
+
<%= pb_rails("nav/item", props: { text: "About", link: "#" }) %>
|
|
4
|
+
<%= pb_rails("nav/item", props: { text: "Case Studies", link: "#", active: true }) %>
|
|
5
|
+
<%= pb_rails("nav/item", props: { text: "Service ", link: "#", disabled: true }) %>
|
|
6
|
+
<%= pb_rails("nav/item", props: { text: "Contacts", link: "#" }) %>
|
|
7
|
+
<% end %>
|
|
8
|
+
<%= pb_rails("caption", props: { margin_bottom: "sm", margin_top:"lg", text: "Subtle Variant" }) %>
|
|
9
|
+
<%= pb_rails("nav", props: { orientation: "horizontal", variant: "subtle" }) do %>
|
|
10
|
+
<%= pb_rails("nav/item", props: { text: "About", link: "#" }) %>
|
|
11
|
+
<%= pb_rails("nav/item", props: { text: "Case Studies", link: "#", active: true }) %>
|
|
12
|
+
<%= pb_rails("nav/item", props: { text: "Service ", link: "#", disabled: true }) %>
|
|
13
|
+
<%= pb_rails("nav/item", props: { text: "Contacts", link: "#" }) %>
|
|
14
|
+
<% end %>
|
|
15
|
+
<%= pb_rails("caption", props: { margin_bottom: "sm", margin_top:"lg", text: "Bold Variant" }) %>
|
|
16
|
+
<%= pb_rails("nav", props: { orientation: "horizontal", variant: "bold" }) do %>
|
|
17
|
+
<%= pb_rails("nav/item", props: { text: "About", link: "#" }) %>
|
|
18
|
+
<%= pb_rails("nav/item", props: { text: "Case Studies", link: "#", active: true }) %>
|
|
19
|
+
<%= pb_rails("nav/item", props: { text: "Service ", link: "#", disabled: true }) %>
|
|
20
|
+
<%= pb_rails("nav/item", props: { text: "Contacts", link: "#" }) %>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import Nav from '../_nav'
|
|
4
|
+
import NavItem from '../_item'
|
|
5
|
+
import Caption from '../../pb_caption/_caption'
|
|
6
|
+
|
|
7
|
+
const HorizontalNavDisabled = (props) => {
|
|
8
|
+
return (
|
|
9
|
+
<>
|
|
10
|
+
<Caption marginBottom="sm">Default Variant</Caption>
|
|
11
|
+
<Nav
|
|
12
|
+
link="#"
|
|
13
|
+
orientation="horizontal"
|
|
14
|
+
{...props}
|
|
15
|
+
>
|
|
16
|
+
<NavItem
|
|
17
|
+
link="#"
|
|
18
|
+
text="About"
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
<NavItem
|
|
22
|
+
active
|
|
23
|
+
link="#"
|
|
24
|
+
text="Case Studies"
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
<NavItem
|
|
28
|
+
disabled
|
|
29
|
+
link="#"
|
|
30
|
+
text="Service"
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
<NavItem
|
|
34
|
+
link="#"
|
|
35
|
+
text="Contacts"
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
</Nav>
|
|
39
|
+
<Caption
|
|
40
|
+
marginBottom="sm"
|
|
41
|
+
marginTop="lg"
|
|
42
|
+
>
|
|
43
|
+
Subtle Variant
|
|
44
|
+
</Caption>
|
|
45
|
+
<Nav
|
|
46
|
+
link="#"
|
|
47
|
+
orientation="horizontal"
|
|
48
|
+
variant="subtle"
|
|
49
|
+
{...props}
|
|
50
|
+
>
|
|
51
|
+
<NavItem
|
|
52
|
+
link="#"
|
|
53
|
+
text="About"
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
<NavItem
|
|
57
|
+
active
|
|
58
|
+
link="#"
|
|
59
|
+
text="Case Studies"
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
<NavItem
|
|
63
|
+
disabled
|
|
64
|
+
link="#"
|
|
65
|
+
text="Service"
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
68
|
+
<NavItem
|
|
69
|
+
link="#"
|
|
70
|
+
text="Contacts"
|
|
71
|
+
{...props}
|
|
72
|
+
/>
|
|
73
|
+
</Nav>
|
|
74
|
+
<Caption
|
|
75
|
+
marginBottom="sm"
|
|
76
|
+
marginTop="lg"
|
|
77
|
+
>
|
|
78
|
+
Bold Variant
|
|
79
|
+
</Caption>
|
|
80
|
+
<Nav
|
|
81
|
+
link="#"
|
|
82
|
+
orientation="horizontal"
|
|
83
|
+
variant="bold"
|
|
84
|
+
{...props}
|
|
85
|
+
>
|
|
86
|
+
<NavItem
|
|
87
|
+
link="#"
|
|
88
|
+
text="About"
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
<NavItem
|
|
92
|
+
active
|
|
93
|
+
link="#"
|
|
94
|
+
text="Case Studies"
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
<NavItem
|
|
98
|
+
disabled
|
|
99
|
+
link="#"
|
|
100
|
+
text="Service"
|
|
101
|
+
{...props}
|
|
102
|
+
/>
|
|
103
|
+
<NavItem
|
|
104
|
+
link="#"
|
|
105
|
+
text="Contacts"
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
</Nav>
|
|
109
|
+
</>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export default HorizontalNavDisabled
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Use the `disabled` prop on a `navItem`/`nav_item` within a horizontal nav to set it as disabled. This will render the UI as disabled, prevent clicks and not allow for tabIndex to access the item.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<%= pb_rails("flex", props: { justify: "between" }) do %>
|
|
2
|
+
<%= pb_rails("flex", props: { orientation:"column", wrap: true }) do %>
|
|
3
|
+
<%= pb_rails("caption", props: { margin_bottom: "sm", text: "Default Variant" }) %>
|
|
4
|
+
<%= pb_rails("nav") do %>
|
|
5
|
+
<%= pb_rails("nav/item", props: { text: "About", link: "#" }) %>
|
|
6
|
+
<%= pb_rails("nav/item", props: { text: "Case Studies", link: "#", active: true }) %>
|
|
7
|
+
<%= pb_rails("nav/item", props: { text: "Service ", link: "#", disabled: true }) %>
|
|
8
|
+
<%= pb_rails("nav/item", props: { text: "Contacts", link: "#" }) %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<% end %>
|
|
11
|
+
<%= pb_rails("flex", props: { orientation:"column", wrap: true }) do %>
|
|
12
|
+
<%= pb_rails("caption", props: { margin_bottom: "sm", text: "Subtle Variant" }) %>
|
|
13
|
+
<%= pb_rails("nav", props:{variant: "subtle"}) do %>
|
|
14
|
+
<%= pb_rails("nav/item", props: { text: "About", link: "#" }) %>
|
|
15
|
+
<%= pb_rails("nav/item", props: { text: "Case Studies", link: "#", active: true }) %>
|
|
16
|
+
<%= pb_rails("nav/item", props: { text: "Service ", link: "#", disabled: true }) %>
|
|
17
|
+
<%= pb_rails("nav/item", props: { text: "Contacts", link: "#" }) %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<%= pb_rails("flex", props: { orientation:"column", wrap: true }) do %>
|
|
21
|
+
<%= pb_rails("caption", props: { margin_bottom: "sm", text: "Bold Variant" }) %>
|
|
22
|
+
<%= pb_rails("nav", props:{variant: "bold"}) do %>
|
|
23
|
+
<%= pb_rails("nav/item", props: { text: "About", link: "#" }) %>
|
|
24
|
+
<%= pb_rails("nav/item", props: { text: "Case Studies", link: "#", active: true }) %>
|
|
25
|
+
<%= pb_rails("nav/item", props: { text: "Service ", link: "#", disabled: true }) %>
|
|
26
|
+
<%= pb_rails("nav/item", props: { text: "Contacts", link: "#" }) %>
|
|
27
|
+
<% end %>
|
|
28
|
+
<% end %>
|
|
29
|
+
|
|
30
|
+
<% end %>
|