Skip to content

Commit

Permalink
feat: add autoFocus props for drawer (#181)
Browse files Browse the repository at this point in the history
* feat: add autoFocus props for drawer

* fix: autoFocus keeps in props. move test case

* feat: add autoFocus test case

Co-authored-by: baxtergu <[email protected]>
  • Loading branch information
baxtergu and baxtergu authored Jul 7, 2021
1 parent 8d8353a commit c6f29c3
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 9 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ ReactDom.render(
| onHandleClick | func | nul | handle icon click function |
| keyboard | Boolean | true | Whether support press esc to close |
| contentWrapperStyle | CSSProperties | null | content wrapper style |
| autoFocus | Boolean | true | Whether focusing on the drawer after it opened |

> 2.0 Rename `onMaskClick` -> `onClose`, add `maskClosable`.
Expand Down
20 changes: 15 additions & 5 deletions src/DrawerChild.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
} catch (err) {}
this.passive = passiveSupported ? { passive: false } : false;
}
const { open, getContainer, showMask } = this.props;
const { open, getContainer, showMask, autoFocus } = this.props;
const container = getContainer && getContainer();
this.drawerId = `drawer_id_${Number(
(Date.now() + Math.random())
Expand All @@ -108,7 +108,9 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
// 默认打开状态时推出 level;
this.openLevelTransition();
this.forceUpdate(() => {
this.domFocus();
if (autoFocus) {
this.domFocus();
}
});
if (showMask) {
this.props.scrollLocker?.lock();
Expand All @@ -117,15 +119,23 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
}

public componentDidUpdate(prevProps: IDrawerChildProps) {
const { open, getContainer, scrollLocker, showMask } = this.props;
const {
open,
getContainer,
scrollLocker,
showMask,
autoFocus,
} = this.props;
const container = getContainer && getContainer();
if (open !== prevProps.open) {
if (container && container.parentNode === document.body) {
currentDrawer[this.drawerId] = !!open;
}
this.openLevelTransition();
if (open) {
this.domFocus();
if (autoFocus) {
this.domFocus();
}
if (showMask) {
scrollLocker?.lock();
}
Expand Down Expand Up @@ -547,7 +557,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
msTransform: transform,
width: isNumeric(width) ? `${width}px` : width,
height: isNumeric(height) ? `${height}px` : height,
...contentWrapperStyle
...contentWrapperStyle,
}}
ref={c => {
this.contentWrapper = c as HTMLElement;
Expand Down
1 change: 1 addition & 0 deletions src/DrawerWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class DrawerWrapper extends React.Component<IDrawerProps, IState> {
className: '',
keyboard: true,
forceRender: false,
autoFocus: true,
};

public static getDerivedStateFromProps(
Expand Down
1 change: 1 addition & 0 deletions src/IDrawerPropTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface IProps extends Omit<React.HTMLAttributes<any>, 'onChange'> {
onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
keyboard?: boolean;
contentWrapperStyle?: React.CSSProperties;
autoFocus?: boolean;
}

export interface IDrawerProps extends IProps {
Expand Down
12 changes: 8 additions & 4 deletions tests/drawer.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* eslint-disable max-classes-per-file */
// eslint-disable react/no-multi-comp
import { mount } from 'enzyme';
import * as React from 'react';
import Drawer from '../src/';
import { IDrawerProps } from '../src/IDrawerPropTypes';
import type { IDrawerProps } from '../src/IDrawerPropTypes';
import toJson from 'enzyme-to-json';


class DrawerTesterRef extends React.Component {
public container: HTMLDivElement;
public getContainer = () => {
Expand Down Expand Up @@ -51,7 +51,11 @@ class DrawerTesterDom extends React.Component<IDrawerProps, IState> {
<div>
<div ref={this.saveContainer} className="main" />
{this.state.visible ? (
<Drawer {...this.props} open={true} getContainer={this.getContainer()}>
<Drawer
{...this.props}
open={true}
getContainer={this.getContainer()}
>
<p className="text">Here is content of Drawer</p>
</Drawer>
) : null}
Expand All @@ -62,7 +66,7 @@ class DrawerTesterDom extends React.Component<IDrawerProps, IState> {

/* eslint react/no-multi-comp: 0 */
// tslint:disable-next-line:max-classes-per-file
const DrawerTesterBoolean = (props) => (
const DrawerTesterBoolean = props => (
<div>
<Drawer {...props} open={true} getContainer={false}>
<p className="text">Here is content of Drawer</p>
Expand Down
28 changes: 28 additions & 0 deletions tests/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,32 @@ describe('rc-drawer-menu', () => {
const content = instance.find('.drawer-content-wrapper').instance() as any;
expect(content.style.background).toBe('rgb(255, 0, 0)');
});

it('autoFocus', () => {
instance = mount(
<Drawer
autoFocus={false}
open={true}
getContainer={null}
wrapperClassName="auto-focus-test-wrapper"
>
<p className="text">Here is content of Drawer</p>
</Drawer>,
);

// In case { autoFocus: false }, default activeElement shouldn't be drawer node
expect(document.activeElement).not.toBe(
instance.find('.auto-focus-test-wrapper .drawer').at(0).getDOMNode(),
);

// Close and reopen drawer with props {autoFocus: true}
instance.setProps({ open: false, autoFocus: true });

instance.setProps({ open: true });

// In case { autoFocus: true }, by which is also <Drawer />'s default, the activeElement will be drawer by itself
expect(document.activeElement).toBe(
instance.find('.auto-focus-test-wrapper .drawer').at(0).getDOMNode(),
);
});
});

1 comment on commit c6f29c3

@vercel
Copy link

@vercel vercel bot commented on c6f29c3 Jul 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.