Skip to content

Commit c6f29c3

Browse files
baxtergubaxtergu
andauthored
feat: add autoFocus props for drawer (#181)
* 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]>
1 parent 8d8353a commit c6f29c3

File tree

6 files changed

+54
-9
lines changed

6 files changed

+54
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ ReactDom.render(
6666
| onHandleClick | func | nul | handle icon click function |
6767
| keyboard | Boolean | true | Whether support press esc to close |
6868
| contentWrapperStyle | CSSProperties | null | content wrapper style |
69+
| autoFocus | Boolean | true | Whether focusing on the drawer after it opened |
6970

7071
> 2.0 Rename `onMaskClick` -> `onClose`, add `maskClosable`.
7172

src/DrawerChild.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
9393
} catch (err) {}
9494
this.passive = passiveSupported ? { passive: false } : false;
9595
}
96-
const { open, getContainer, showMask } = this.props;
96+
const { open, getContainer, showMask, autoFocus } = this.props;
9797
const container = getContainer && getContainer();
9898
this.drawerId = `drawer_id_${Number(
9999
(Date.now() + Math.random())
@@ -108,7 +108,9 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
108108
// 默认打开状态时推出 level;
109109
this.openLevelTransition();
110110
this.forceUpdate(() => {
111-
this.domFocus();
111+
if (autoFocus) {
112+
this.domFocus();
113+
}
112114
});
113115
if (showMask) {
114116
this.props.scrollLocker?.lock();
@@ -117,15 +119,23 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
117119
}
118120

119121
public componentDidUpdate(prevProps: IDrawerChildProps) {
120-
const { open, getContainer, scrollLocker, showMask } = this.props;
122+
const {
123+
open,
124+
getContainer,
125+
scrollLocker,
126+
showMask,
127+
autoFocus,
128+
} = this.props;
121129
const container = getContainer && getContainer();
122130
if (open !== prevProps.open) {
123131
if (container && container.parentNode === document.body) {
124132
currentDrawer[this.drawerId] = !!open;
125133
}
126134
this.openLevelTransition();
127135
if (open) {
128-
this.domFocus();
136+
if (autoFocus) {
137+
this.domFocus();
138+
}
129139
if (showMask) {
130140
scrollLocker?.lock();
131141
}
@@ -547,7 +557,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
547557
msTransform: transform,
548558
width: isNumeric(width) ? `${width}px` : width,
549559
height: isNumeric(height) ? `${height}px` : height,
550-
...contentWrapperStyle
560+
...contentWrapperStyle,
551561
}}
552562
ref={c => {
553563
this.contentWrapper = c as HTMLElement;

src/DrawerWrapper.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class DrawerWrapper extends React.Component<IDrawerProps, IState> {
3535
className: '',
3636
keyboard: true,
3737
forceRender: false,
38+
autoFocus: true,
3839
};
3940

4041
public static getDerivedStateFromProps(

src/IDrawerPropTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ interface IProps extends Omit<React.HTMLAttributes<any>, 'onChange'> {
3535
onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
3636
keyboard?: boolean;
3737
contentWrapperStyle?: React.CSSProperties;
38+
autoFocus?: boolean;
3839
}
3940

4041
export interface IDrawerProps extends IProps {

tests/drawer.spec.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
/* eslint-disable max-classes-per-file */
12
// eslint-disable react/no-multi-comp
23
import { mount } from 'enzyme';
34
import * as React from 'react';
45
import Drawer from '../src/';
5-
import { IDrawerProps } from '../src/IDrawerPropTypes';
6+
import type { IDrawerProps } from '../src/IDrawerPropTypes';
67
import toJson from 'enzyme-to-json';
78

8-
99
class DrawerTesterRef extends React.Component {
1010
public container: HTMLDivElement;
1111
public getContainer = () => {
@@ -51,7 +51,11 @@ class DrawerTesterDom extends React.Component<IDrawerProps, IState> {
5151
<div>
5252
<div ref={this.saveContainer} className="main" />
5353
{this.state.visible ? (
54-
<Drawer {...this.props} open={true} getContainer={this.getContainer()}>
54+
<Drawer
55+
{...this.props}
56+
open={true}
57+
getContainer={this.getContainer()}
58+
>
5559
<p className="text">Here is content of Drawer</p>
5660
</Drawer>
5761
) : null}
@@ -62,7 +66,7 @@ class DrawerTesterDom extends React.Component<IDrawerProps, IState> {
6266

6367
/* eslint react/no-multi-comp: 0 */
6468
// tslint:disable-next-line:max-classes-per-file
65-
const DrawerTesterBoolean = (props) => (
69+
const DrawerTesterBoolean = props => (
6670
<div>
6771
<Drawer {...props} open={true} getContainer={false}>
6872
<p className="text">Here is content of Drawer</p>

tests/index.spec.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,32 @@ describe('rc-drawer-menu', () => {
225225
const content = instance.find('.drawer-content-wrapper').instance() as any;
226226
expect(content.style.background).toBe('rgb(255, 0, 0)');
227227
});
228+
229+
it('autoFocus', () => {
230+
instance = mount(
231+
<Drawer
232+
autoFocus={false}
233+
open={true}
234+
getContainer={null}
235+
wrapperClassName="auto-focus-test-wrapper"
236+
>
237+
<p className="text">Here is content of Drawer</p>
238+
</Drawer>,
239+
);
240+
241+
// In case { autoFocus: false }, default activeElement shouldn't be drawer node
242+
expect(document.activeElement).not.toBe(
243+
instance.find('.auto-focus-test-wrapper .drawer').at(0).getDOMNode(),
244+
);
245+
246+
// Close and reopen drawer with props {autoFocus: true}
247+
instance.setProps({ open: false, autoFocus: true });
248+
249+
instance.setProps({ open: true });
250+
251+
// In case { autoFocus: true }, by which is also <Drawer />'s default, the activeElement will be drawer by itself
252+
expect(document.activeElement).toBe(
253+
instance.find('.auto-focus-test-wrapper .drawer').at(0).getDOMNode(),
254+
);
255+
});
228256
});

0 commit comments

Comments
 (0)