@kaizen/components 1.79.7 → 1.79.9
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.
- package/dist/cjs/src/Modal/GenericModal/GenericModal.cjs +14 -6
- package/dist/esm/src/Modal/GenericModal/GenericModal.mjs +14 -6
- package/dist/styles.css +9275 -9275
- package/package.json +1 -1
- package/src/Modal/GenericModal/GenericModal.tsx +21 -6
- package/src/__next__/Button/_docs/Button--api-specification.mdx +6 -0
- package/src/__next__/Button/_docs/Button.docs.stories.tsx +29 -0
- package/src/__next__/Menu/_docs/Menu--api-specification.mdx +6 -0
- package/src/__next__/Menu/_docs/Menu.stories.tsx +29 -0
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import { createPortal } from 'react-dom'
|
|
|
3
3
|
import { Transition } from '@headlessui/react'
|
|
4
4
|
import classnames from 'classnames'
|
|
5
5
|
import FocusLock from 'react-focus-lock'
|
|
6
|
+
import { useIsClientReady } from '../../utils/useIsClientReady'
|
|
6
7
|
import { warn } from '../util/console'
|
|
7
8
|
import { ModalContext } from './context/ModalContext'
|
|
8
9
|
import styles from './GenericModal.module.scss'
|
|
@@ -38,6 +39,8 @@ export const GenericModal = ({
|
|
|
38
39
|
const labelledByID = useId()
|
|
39
40
|
const describedByID = useId()
|
|
40
41
|
|
|
42
|
+
const isClientReady = useIsClientReady()
|
|
43
|
+
|
|
41
44
|
const [scrollLayer, setScrollLayer] = useState<HTMLDivElement | null>(null)
|
|
42
45
|
const [modalLayer, setModalLayer] = useState<HTMLDivElement | null>(null)
|
|
43
46
|
|
|
@@ -58,6 +61,8 @@ export const GenericModal = ({
|
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
const focusOnAccessibleLabel = (): void => {
|
|
64
|
+
if (!isClientReady) return
|
|
65
|
+
|
|
61
66
|
// Check if focus already exists within the modal
|
|
62
67
|
if (modalLayer?.contains(document.activeElement)) {
|
|
63
68
|
return
|
|
@@ -69,6 +74,8 @@ export const GenericModal = ({
|
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
const a11yWarn = (): void => {
|
|
77
|
+
if (!isClientReady) return
|
|
78
|
+
|
|
72
79
|
// Ensure that consumers have provided an element that labels the modal
|
|
73
80
|
// to meet ARIA accessibility guidelines.
|
|
74
81
|
if (!document.getElementById(labelledByID)) {
|
|
@@ -80,6 +87,8 @@ export const GenericModal = ({
|
|
|
80
87
|
}
|
|
81
88
|
|
|
82
89
|
const preventBodyScroll = (): void => {
|
|
90
|
+
if (!isClientReady) return
|
|
91
|
+
|
|
83
92
|
const hasScrollbar = window.innerWidth > document.documentElement.clientWidth
|
|
84
93
|
const scrollStyles = [styles.unscrollable]
|
|
85
94
|
|
|
@@ -111,28 +120,34 @@ export const GenericModal = ({
|
|
|
111
120
|
const onBeforeEnterHandler = (): void => {
|
|
112
121
|
preventBodyScroll()
|
|
113
122
|
|
|
114
|
-
if (onEscapeKeyup) {
|
|
123
|
+
if (onEscapeKeyup && isClientReady) {
|
|
115
124
|
document.addEventListener('keyup', escapeKeyHandler)
|
|
116
125
|
}
|
|
117
126
|
}
|
|
118
127
|
|
|
119
|
-
const cleanUpAfterClose = ()
|
|
128
|
+
const cleanUpAfterClose = useCallback(() => {
|
|
129
|
+
if (!isClientReady) return
|
|
130
|
+
|
|
120
131
|
document.documentElement.classList.remove(styles.unscrollable, styles.pseudoScrollbar)
|
|
121
132
|
|
|
122
133
|
if (onEscapeKeyup) {
|
|
123
134
|
document.removeEventListener('keyup', escapeKeyHandler)
|
|
124
135
|
}
|
|
125
|
-
}
|
|
136
|
+
}, [escapeKeyHandler, onEscapeKeyup, isClientReady])
|
|
126
137
|
|
|
127
138
|
/* Ensure sure add-on styles (e.g. unscrollable) and key event is cleaned up when the modal is unmounted*/
|
|
128
|
-
|
|
129
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
130
|
-
useEffect(() => () => cleanUpAfterClose(), [])
|
|
139
|
+
useEffect(() => () => cleanUpAfterClose(), [cleanUpAfterClose])
|
|
131
140
|
|
|
132
141
|
const onAfterLeaveHandler = (): void => {
|
|
133
142
|
cleanUpAfterClose()
|
|
134
143
|
propsOnAfterLeave?.()
|
|
135
144
|
}
|
|
145
|
+
|
|
146
|
+
// Don't render portal during SSR
|
|
147
|
+
if (!isClientReady) {
|
|
148
|
+
return <></>
|
|
149
|
+
}
|
|
150
|
+
|
|
136
151
|
return createPortal(
|
|
137
152
|
<Transition
|
|
138
153
|
appear={true}
|
|
@@ -156,6 +156,12 @@ If a button is statically the full width of a container you can use the `isFullW
|
|
|
156
156
|
|
|
157
157
|
For resizing on smaller screens, consider using the `className` prop to leverage CSS media or container queries, ie: `<Button className="w-full md:w-[initial]">Label</Button>`.
|
|
158
158
|
|
|
159
|
+
## Use a menu to show additional actions
|
|
160
|
+
|
|
161
|
+
Instead of a split button (now a [deprecated component](https://cultureamp.atlassian.net/wiki/spaces/DES/pages/4286611457/Deprecating+Split+Buttons+-+Design+Request+for+Comment+RFC)), use a Button with text followed by a Menu to show any additional actions related to the most critical action.
|
|
162
|
+
|
|
163
|
+
<Canvas className="mb-24" of={exampleStories.ButtonMenuPattern} />
|
|
164
|
+
|
|
159
165
|
## Additional API options
|
|
160
166
|
|
|
161
167
|
The following table is a collection of additional React Aria and native HTML props that are exposed from the React Aria API. These are not required for the implementation of `Button` but can be used to extend its functionality. Refer back to the [overview section](#overview) for the core props that enable most use cases.
|
|
@@ -391,3 +391,32 @@ export const DontExampleTertiaryButtonWithIcons: Story = {
|
|
|
391
391
|
variant: 'tertiary',
|
|
392
392
|
},
|
|
393
393
|
}
|
|
394
|
+
|
|
395
|
+
export const ButtonMenuPattern: Story = {
|
|
396
|
+
name: 'Button + Menu Pattern',
|
|
397
|
+
render: () => (
|
|
398
|
+
<div className="flex gap-4">
|
|
399
|
+
<Button size="large" variant="secondary">
|
|
400
|
+
Edit Survey
|
|
401
|
+
</Button>
|
|
402
|
+
<MenuTrigger>
|
|
403
|
+
<Button
|
|
404
|
+
size="large"
|
|
405
|
+
icon={<Icon name="more_horiz" isPresentational />}
|
|
406
|
+
variant="secondary"
|
|
407
|
+
hasHiddenLabel
|
|
408
|
+
>
|
|
409
|
+
More surveys
|
|
410
|
+
</Button>
|
|
411
|
+
<MenuPopover>
|
|
412
|
+
<Menu>
|
|
413
|
+
<MenuItem>Survey 1</MenuItem>
|
|
414
|
+
<MenuItem>Survey 2</MenuItem>
|
|
415
|
+
<MenuItem>Survey 3</MenuItem>
|
|
416
|
+
<MenuItem>Survey 4</MenuItem>
|
|
417
|
+
</Menu>
|
|
418
|
+
</MenuPopover>
|
|
419
|
+
</MenuTrigger>
|
|
420
|
+
</div>
|
|
421
|
+
),
|
|
422
|
+
}
|
|
@@ -83,3 +83,9 @@ Menu items can be disabled with the `isDisabled` prop.
|
|
|
83
83
|
By default, the open/closed state of the menu is handled under the hood. In cases where you need control over the open state, use the `isOpen` and `onOpenChange` props on the `MenuTrigger` component (both props must be used for this to work).
|
|
84
84
|
|
|
85
85
|
<Canvas className="mb-24" of={exampleStories.Controlled} />
|
|
86
|
+
|
|
87
|
+
## Use a menu to show additional actions
|
|
88
|
+
|
|
89
|
+
Instead of a split button (now a [deprecated component](https://cultureamp.atlassian.net/wiki/spaces/DES/pages/4286611457/Deprecating+Split+Buttons+-+Design+Request+for+Comment+RFC)), use a Button with text followed by a Menu to show any additional actions related to the most critical action.
|
|
90
|
+
|
|
91
|
+
<Canvas className="mb-24" of={exampleStories.ButtonMenuPattern} />
|
|
@@ -128,3 +128,32 @@ export const Sections: Story = {
|
|
|
128
128
|
</MenuTrigger>
|
|
129
129
|
),
|
|
130
130
|
}
|
|
131
|
+
|
|
132
|
+
export const ButtonMenuPattern: Story = {
|
|
133
|
+
name: 'Button + Menu Pattern',
|
|
134
|
+
render: ({ defaultOpen: _, ...args }) => (
|
|
135
|
+
<div className="flex gap-4">
|
|
136
|
+
<Button size="large" variant="secondary">
|
|
137
|
+
Edit Survey
|
|
138
|
+
</Button>
|
|
139
|
+
<MenuTrigger {...args}>
|
|
140
|
+
<Button
|
|
141
|
+
size="large"
|
|
142
|
+
icon={<Icon name="more_horiz" isPresentational />}
|
|
143
|
+
variant="secondary"
|
|
144
|
+
hasHiddenLabel
|
|
145
|
+
>
|
|
146
|
+
More surveys
|
|
147
|
+
</Button>
|
|
148
|
+
<MenuPopover>
|
|
149
|
+
<Menu>
|
|
150
|
+
<MenuItem>Survey 1</MenuItem>
|
|
151
|
+
<MenuItem>Survey 2</MenuItem>
|
|
152
|
+
<MenuItem>Survey 3</MenuItem>
|
|
153
|
+
<MenuItem>Survey 4</MenuItem>
|
|
154
|
+
</Menu>
|
|
155
|
+
</MenuPopover>
|
|
156
|
+
</MenuTrigger>
|
|
157
|
+
</div>
|
|
158
|
+
),
|
|
159
|
+
}
|