Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

Commit de6b9cf

Browse files
lucasecdbMatt Goo
authored and
Matt Goo
committed
feat(drawer): add innerRef prop (#758)
1 parent 0f7ebba commit de6b9cf

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

packages/drawer/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ modal | Boolean | Indicates that the drawer is of type modal.
419419
dismissible | Boolean | Indicates that the drawer is of type dismissible.
420420
tag | String | Customizes the drawer tag type (default to `<aside>`).
421421
open | boolean | If true, opens drawer. If false, closes drawer.
422+
innerRef | RefObject | Root drawer element ref.
422423

423424
## Sass Mixins
424425

packages/drawer/index.tsx

+28-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import {FocusTrap} from 'focus-trap';
3939

4040
const {cssClasses: listCssClasses} = MDCListFoundation;
4141

42+
type RefCallback<T> = (node: T) => void;
43+
4244
export interface DrawerProps extends React.HTMLProps<HTMLElement>{
4345
className?: string;
4446
open?: boolean;
@@ -47,12 +49,17 @@ export interface DrawerProps extends React.HTMLProps<HTMLElement>{
4749
tag?: string;
4850
dismissible?: boolean;
4951
modal?: boolean;
52+
innerRef?: RefCallback<HTMLElement> | React.RefObject<HTMLElement>;
5053
};
5154

5255
interface DrawerState {
5356
classList: Set<string>;
5457
};
5558

59+
const isRefObject = function(ref: DrawerProps['innerRef']): ref is React.RefObject<HTMLElement> {
60+
return typeof ref !== 'function';
61+
};
62+
5663
class Drawer extends React.Component<DrawerProps, DrawerState> {
5764
previousFocus: HTMLElement | null = null;
5865
foundation: MDCDismissibleDrawerFoundation | MDCModalDrawerFoundation;
@@ -193,6 +200,25 @@ class Drawer extends React.Component<DrawerProps, DrawerState> {
193200
this.foundation.handleTransitionEnd(evt);
194201
};
195202

203+
attachRef = (node: HTMLElement) => {
204+
const {innerRef} = this.props;
205+
206+
// https://github.com/facebook/react/issues/13029#issuecomment-410002316
207+
// @ts-ignore this is acceptable according to the comment above
208+
this.drawerElement.current = node;
209+
210+
if (!innerRef) {
211+
return;
212+
}
213+
214+
if (isRefObject(innerRef)) {
215+
// @ts-ignore same as above
216+
innerRef.current = node;
217+
} else {
218+
innerRef(node);
219+
}
220+
}
221+
196222
render() {
197223
const {
198224
/* eslint-disable no-unused-vars */
@@ -203,6 +229,7 @@ class Drawer extends React.Component<DrawerProps, DrawerState> {
203229
dismissible,
204230
children,
205231
className,
232+
innerRef,
206233
/* eslint-enable no-unused-vars */
207234
tag: Tag,
208235
modal,
@@ -215,7 +242,7 @@ class Drawer extends React.Component<DrawerProps, DrawerState> {
215242
// @ts-ignore */}
216243
<Tag
217244
className={this.classes}
218-
ref={this.drawerElement}
245+
ref={this.attachRef}
219246
onKeyDown={this.handleKeyDown}
220247
onTransitionEnd={this.handleTransitionEnd}
221248
{...otherProps}

test/unit/drawer/index.test.tsx

+14
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,17 @@ test('click on scrim calls #foundation.handleScrimClick', () => {
283283
scrim.simulate('click');
284284
td.verify(wrapper.instance().foundation.handleScrimClick(), {times: 1});
285285
});
286+
287+
test('handles object refs correctly', () => {
288+
const myRef = React.createRef<HTMLElement>();
289+
const wrapper = mount<Drawer>(<Drawer innerRef={myRef} />);
290+
assert.isNotNull(myRef.current);
291+
assert.isNotNull(wrapper.instance().drawerElement.current);
292+
});
293+
294+
test('it handles function refs correctly', () => {
295+
const refFn = coerceForTesting<(node: HTMLElement) => void>(td.func());
296+
const wrapper = mount<Drawer>(<Drawer innerRef={refFn} />);
297+
assert.isNotNull(wrapper.instance().drawerElement.current);
298+
td.verify(refFn(wrapper.instance().drawerElement.current!), {times: 1});
299+
});

0 commit comments

Comments
 (0)