Skip to content

Commit 19163d5

Browse files
Serge Pavlyukbenax-se
authored andcommitted
feat(Drawer): add keepMounted prop (#321)
* feat(Drawer): keepMounted prop * chore(Drawer): fix documentation and jsdoc * chore(Drawer): update screenshots * fix(Drawer): revert visibility hidden on transition exit done
1 parent e4c8684 commit 19163d5

File tree

7 files changed

+48
-4
lines changed

7 files changed

+48
-4
lines changed

src/components/Drawer/Drawer.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ export interface DrawerItemProps {
5656

5757
/** The maximum width of the resizable drawer item */
5858
maxResizeWidth?: number;
59+
60+
/**
61+
* Keep child components mounted when closed, prioritized over Drawer.keepMounted property
62+
* @default false
63+
* */
64+
keepMounted?: boolean;
5965
}
6066

6167
export const DrawerItem = React.forwardRef<HTMLDivElement, DrawerItemProps>(
@@ -71,6 +77,7 @@ export const DrawerItem = React.forwardRef<HTMLDivElement, DrawerItemProps>(
7177
minResizeWidth,
7278
maxResizeWidth,
7379
onResize,
80+
keepMounted = false,
7481
} = props;
7582

7683
const itemRef = React.useRef<HTMLDivElement>(null);
@@ -95,7 +102,8 @@ export const DrawerItem = React.forwardRef<HTMLDivElement, DrawerItemProps>(
95102
<CSSTransition
96103
in={visible}
97104
timeout={TIMEOUT}
98-
unmountOnExit
105+
mountOnEnter={!keepMounted}
106+
unmountOnExit={!keepMounted}
99107
classNames={b('item-transition', {direction: cssDirection})}
100108
nodeRef={itemRef}
101109
>
@@ -144,6 +152,12 @@ export interface DrawerProps {
144152

145153
/** Optional flag to not use `Portal` for drawer */
146154
disablePortal?: boolean;
155+
156+
/**
157+
* Keep child components mounted when closed
158+
* @default false
159+
* */
160+
keepMounted?: boolean;
147161
}
148162

149163
export const Drawer: React.FC<DrawerProps> = ({
@@ -156,6 +170,7 @@ export const Drawer: React.FC<DrawerProps> = ({
156170
preventScrollBody = true,
157171
hideVeil,
158172
disablePortal = true,
173+
keepMounted = false,
159174
}) => {
160175
let someItemVisible = false;
161176
React.Children.forEach(children, (child) => {
@@ -190,8 +205,8 @@ export const Drawer: React.FC<DrawerProps> = ({
190205
<Transition
191206
in={someItemVisible}
192207
timeout={{enter: 0, exit: TIMEOUT}}
193-
mountOnEnter
194-
unmountOnExit
208+
mountOnEnter={!keepMounted}
209+
unmountOnExit={!keepMounted}
195210
nodeRef={containerRef}
196211
>
197212
{(state) => {
@@ -218,6 +233,7 @@ export const Drawer: React.FC<DrawerProps> = ({
218233
) {
219234
const childVisible = Boolean(child.props.visible);
220235
return React.cloneElement(child, {
236+
keepMounted,
221237
...child.props,
222238
visible: childVisible && childrenVisible,
223239
});

src/components/Drawer/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ The Drawer module consists of two primary components: `Drawer` and `DrawerItem`.
7676
| onResize | Callback function called at the end of resizing. Can be used to save the new width. | `(width: number) => void` | |
7777
| minResizeWidth | The minimum width of the resizable drawer item | `number` | |
7878
| maxResizeWidth | The maximum width of the resizable drawer item | `number` | |
79+
| keepMounted | Keep child components mounted when closed, prioritized over Drawer.keepMounted property | `boolean` | `false` |
7980

8081
### `Drawer` Props
8182

@@ -90,6 +91,7 @@ The Drawer module consists of two primary components: `Drawer` and `DrawerItem`.
9091
| onEscape | Optional callback function that is called when the escape key is pressed, if the drawer is open. | `() => void` | |
9192
| hideVeil | Optional flag to hide the background darkening | `boolean` | |
9293
| disablePortal | Optional flag to not render drawer inside `Portal` | `boolean` | `true` |
94+
| keepMounted | Keep child components mounted when closed | `boolean` | `false` |
9395

9496
## CSS API
9597

8.18 KB
Loading
8.28 KB
Loading
7.97 KB
Loading
7.92 KB
Loading

src/components/Drawer/__stories__/DrawerShowcase.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ export function DrawerShowcase() {
1616
const [direction, setDirection] = React.useState<string>('left');
1717
const [direction2, setDirection2] = React.useState<string>('left');
1818

19+
const [keepMountedGlobal, setKeepMountedGlobal] = React.useState<boolean>(false);
20+
const [keepMounted1, setKeepMounted1] = React.useState<boolean>(false);
21+
1922
const hideAll = React.useCallback(() => {
2023
setVisible1(false);
2124
setVisible2(false);
@@ -41,9 +44,32 @@ export function DrawerShowcase() {
4144
<RadioButton.Option value="left">left</RadioButton.Option>
4245
<RadioButton.Option value="right">right</RadioButton.Option>
4346
</RadioButton>
47+
<br /> Keep Mounted Drawer: &nbsp;
48+
<Button
49+
view="action"
50+
size="l"
51+
onClick={() => setKeepMountedGlobal(!keepMountedGlobal)}
52+
>
53+
{keepMountedGlobal ? 'On' : 'Off'}
54+
</Button>
55+
&nbsp;&nbsp; Keep Mounted 1: &nbsp;
56+
<Button
57+
disabled={!keepMountedGlobal}
58+
view="action"
59+
size="l"
60+
onClick={() => setKeepMounted1(!keepMounted1)}
61+
>
62+
{keepMounted1 ? 'On' : 'Off'}
63+
</Button>
4464
</div>
45-
<Drawer className={b('drawer')} onVeilClick={hideAll} onEscape={hideAll}>
65+
<Drawer
66+
className={b('drawer')}
67+
onVeilClick={hideAll}
68+
onEscape={hideAll}
69+
keepMounted={keepMountedGlobal}
70+
>
4671
<DrawerItem
72+
keepMounted={keepMounted1}
4773
visible={visible1}
4874
id="item-1"
4975
className={b('item-1')}

0 commit comments

Comments
 (0)