Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Drawer): add keepMounted prop #321

Merged
merged 5 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/components/Drawer/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ export interface DrawerItemProps {

/** The maximum width of the resizable drawer item */
maxResizeWidth?: number;

/**
* Keep child components mounted when closed, prioritized over Drawer.keepMounted property
* @default false
* */
keepMounted?: boolean;
}

export const DrawerItem = React.forwardRef<HTMLDivElement, DrawerItemProps>(
Expand All @@ -71,6 +77,7 @@ export const DrawerItem = React.forwardRef<HTMLDivElement, DrawerItemProps>(
minResizeWidth,
maxResizeWidth,
onResize,
keepMounted = false,
} = props;

const itemRef = React.useRef<HTMLDivElement>(null);
Expand All @@ -95,7 +102,8 @@ export const DrawerItem = React.forwardRef<HTMLDivElement, DrawerItemProps>(
<CSSTransition
in={visible}
timeout={TIMEOUT}
unmountOnExit
mountOnEnter={!keepMounted}
unmountOnExit={!keepMounted}
classNames={b('item-transition', {direction: cssDirection})}
nodeRef={itemRef}
>
Expand Down Expand Up @@ -144,6 +152,12 @@ export interface DrawerProps {

/** Optional flag to not use `Portal` for drawer */
disablePortal?: boolean;

/**
* Keep child components mounted when closed
* @default false
* */
keepMounted?: boolean;
}

export const Drawer: React.FC<DrawerProps> = ({
Expand All @@ -156,6 +170,7 @@ export const Drawer: React.FC<DrawerProps> = ({
preventScrollBody = true,
hideVeil,
disablePortal = true,
keepMounted = false,
}) => {
let someItemVisible = false;
React.Children.forEach(children, (child) => {
Expand Down Expand Up @@ -190,8 +205,8 @@ export const Drawer: React.FC<DrawerProps> = ({
<Transition
in={someItemVisible}
timeout={{enter: 0, exit: TIMEOUT}}
mountOnEnter
unmountOnExit
mountOnEnter={!keepMounted}
unmountOnExit={!keepMounted}
nodeRef={containerRef}
>
{(state) => {
Expand All @@ -218,6 +233,7 @@ export const Drawer: React.FC<DrawerProps> = ({
) {
const childVisible = Boolean(child.props.visible);
return React.cloneElement(child, {
keepMounted,
...child.props,
visible: childVisible && childrenVisible,
});
Expand Down
2 changes: 2 additions & 0 deletions src/components/Drawer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ The Drawer module consists of two primary components: `Drawer` and `DrawerItem`.
| onResize | Callback function called at the end of resizing. Can be used to save the new width. | `(width: number) => void` | |
| minResizeWidth | The minimum width of the resizable drawer item | `number` | |
| maxResizeWidth | The maximum width of the resizable drawer item | `number` | |
| keepMounted | Keep child components mounted when closed, prioritized over Drawer.keepMounted property | `boolean` | `false` |

### `Drawer` Props

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

## CSS API

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 27 additions & 1 deletion src/components/Drawer/__stories__/DrawerShowcase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export function DrawerShowcase() {
const [direction, setDirection] = React.useState<string>('left');
const [direction2, setDirection2] = React.useState<string>('left');

const [keepMountedGlobal, setKeepMountedGlobal] = React.useState<boolean>(false);
const [keepMounted1, setKeepMounted1] = React.useState<boolean>(false);

const hideAll = React.useCallback(() => {
setVisible1(false);
setVisible2(false);
Expand All @@ -41,9 +44,32 @@ export function DrawerShowcase() {
<RadioButton.Option value="left">left</RadioButton.Option>
<RadioButton.Option value="right">right</RadioButton.Option>
</RadioButton>
<br /> Keep Mounted Drawer: &nbsp;
<Button
view="action"
size="l"
onClick={() => setKeepMountedGlobal(!keepMountedGlobal)}
>
{keepMountedGlobal ? 'On' : 'Off'}
</Button>
&nbsp;&nbsp; Keep Mounted 1: &nbsp;
<Button
disabled={!keepMountedGlobal}
view="action"
size="l"
onClick={() => setKeepMounted1(!keepMounted1)}
>
{keepMounted1 ? 'On' : 'Off'}
</Button>
</div>
<Drawer className={b('drawer')} onVeilClick={hideAll} onEscape={hideAll}>
<Drawer
className={b('drawer')}
onVeilClick={hideAll}
onEscape={hideAll}
keepMounted={keepMountedGlobal}
>
<DrawerItem
keepMounted={keepMounted1}
visible={visible1}
id="item-1"
className={b('item-1')}
Expand Down
Loading