From 4b8275157cadfadba8adcbde6068bca199e260b1 Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Wed, 28 Jul 2021 16:51:55 +0200 Subject: [PATCH] chore(Dimmer|Grid|Sidebar): use React.forwardRef() (#4260) --- src/collections/Grid/Grid.js | 7 +- src/collections/Grid/GridColumn.js | 7 +- src/collections/Grid/GridRow.js | 7 +- src/modules/Dimmer/Dimmer.js | 71 +++---- src/modules/Dimmer/DimmerDimmable.js | 7 +- src/modules/Dimmer/DimmerInner.js | 138 ++++++-------- src/modules/Sidebar/Sidebar.js | 177 +++++++++--------- src/modules/Sidebar/SidebarPushable.js | 7 +- src/modules/Sidebar/SidebarPusher.js | 7 +- test/specs/collections/Grid/Grid-test.js | 1 + .../specs/collections/Grid/GridColumn-test.js | 1 + test/specs/collections/Grid/GridRow-test.js | 1 + test/specs/modules/Dimmer/Dimmer-test.js | 1 + .../modules/Dimmer/DimmerDimmable-test.js | 1 + test/specs/modules/Dimmer/DimmerInner-test.js | 10 +- test/specs/modules/Sidebar/Sidebar-test.js | 12 +- .../modules/Sidebar/SidebarPushable-test.js | 1 + .../modules/Sidebar/SidebarPusher-test.js | 1 + 18 files changed, 233 insertions(+), 224 deletions(-) diff --git a/src/collections/Grid/Grid.js b/src/collections/Grid/Grid.js index 6104c69811..7f856c5bdf 100644 --- a/src/collections/Grid/Grid.js +++ b/src/collections/Grid/Grid.js @@ -20,7 +20,7 @@ import GridRow from './GridRow' /** * A grid is used to harmonize negative space in a layout. */ -function Grid(props) { +const Grid = React.forwardRef(function (props, ref) { const { celled, centered, @@ -63,15 +63,16 @@ function Grid(props) { const ElementType = getElementType(Grid, props) return ( - + {children} ) -} +}) Grid.Column = GridColumn Grid.Row = GridRow +Grid.displayName = 'Grid' Grid.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/collections/Grid/GridColumn.js b/src/collections/Grid/GridColumn.js index b9b134bdc0..44d2e9be8a 100644 --- a/src/collections/Grid/GridColumn.js +++ b/src/collections/Grid/GridColumn.js @@ -19,7 +19,7 @@ import { /** * A column sub-component for Grid. */ -function GridColumn(props) { +const GridColumn = React.forwardRef(function (props, ref) { const { children, className, @@ -57,12 +57,13 @@ function GridColumn(props) { const ElementType = getElementType(GridColumn, props) return ( - + {children} ) -} +}) +GridColumn.displayName = 'GridColumn' GridColumn.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/collections/Grid/GridRow.js b/src/collections/Grid/GridRow.js index bd81472bdf..b84de480bc 100644 --- a/src/collections/Grid/GridRow.js +++ b/src/collections/Grid/GridRow.js @@ -17,7 +17,7 @@ import { /** * A row sub-component for Grid. */ -function GridRow(props) { +const GridRow = React.forwardRef(function (props, ref) { const { centered, children, @@ -49,12 +49,13 @@ function GridRow(props) { const ElementType = getElementType(GridRow, props) return ( - + {children} ) -} +}) +GridRow.displayName = 'GridRow' GridRow.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/modules/Dimmer/Dimmer.js b/src/modules/Dimmer/Dimmer.js index 9972452f74..0d2b55d079 100644 --- a/src/modules/Dimmer/Dimmer.js +++ b/src/modules/Dimmer/Dimmer.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, { Component } from 'react' +import React from 'react' import { createShorthandFactory, getUnhandledProps, isBrowser } from '../../lib' import Portal from '../../addons/Portal' @@ -9,46 +9,49 @@ import DimmerInner from './DimmerInner' /** * A dimmer hides distractions to focus attention on particular content. */ -export default class Dimmer extends Component { - handlePortalMount = () => { - if (!isBrowser()) return +const Dimmer = React.forwardRef(function (props, ref) { + const { active, page } = props + const rest = getUnhandledProps(Dimmer, props) - // Heads up, IE doesn't support second argument in add() - document.body.classList.add('dimmed') - document.body.classList.add('dimmable') - } + if (page) { + const handlePortalMount = () => { + if (!isBrowser()) { + return + } - handlePortalUnmount = () => { - if (!isBrowser()) return + // Heads up, IE doesn't support second argument in add() + document.body.classList.add('dimmed') + document.body.classList.add('dimmable') + } - // Heads up, IE doesn't support second argument in add() - document.body.classList.remove('dimmed') - document.body.classList.remove('dimmable') - } + const handlePortalUnmount = () => { + if (!isBrowser()) { + return + } - render() { - const { active, page } = this.props - const rest = getUnhandledProps(Dimmer, this.props) - - if (page) { - return ( - - - - ) + // Heads up, IE doesn't support second argument in add() + document.body.classList.remove('dimmed') + document.body.classList.remove('dimmable') } - return + return ( + + + + ) } -} + return +}) + +Dimmer.displayName = 'Dimmer' Dimmer.propTypes = { /** An active dimmer will dim its parent container. */ active: PropTypes.bool, @@ -61,3 +64,5 @@ Dimmer.Dimmable = DimmerDimmable Dimmer.Inner = DimmerInner Dimmer.create = createShorthandFactory(Dimmer, (value) => ({ content: value })) + +export default Dimmer diff --git a/src/modules/Dimmer/DimmerDimmable.js b/src/modules/Dimmer/DimmerDimmable.js index fe04d664ad..5219cf8d1f 100644 --- a/src/modules/Dimmer/DimmerDimmable.js +++ b/src/modules/Dimmer/DimmerDimmable.js @@ -13,7 +13,7 @@ import { /** * A dimmable sub-component for Dimmer. */ -function DimmerDimmable(props) { +const DimmerDimmable = React.forwardRef(function (props, ref) { const { blurring, className, children, content, dimmed } = props const classes = cx( @@ -26,12 +26,13 @@ function DimmerDimmable(props) { const ElementType = getElementType(DimmerDimmable, props) return ( - + {childrenUtils.isNil(children) ? content : children} ) -} +}) +DimmerDimmable.displayName = 'DimmerDimmable' DimmerDimmable.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/modules/Dimmer/DimmerInner.js b/src/modules/Dimmer/DimmerInner.js index 79d96746c7..78680f065b 100644 --- a/src/modules/Dimmer/DimmerInner.js +++ b/src/modules/Dimmer/DimmerInner.js @@ -1,8 +1,7 @@ -import { Ref } from '@fluentui/react-component-ref' import cx from 'clsx' import _ from 'lodash' import PropTypes from 'prop-types' -import React, { Component, createRef } from 'react' +import React from 'react' import { childrenUtils, @@ -12,94 +11,79 @@ import { getUnhandledProps, useKeyOnly, useVerticalAlignProp, + useIsomorphicLayoutEffect, + useMergedRefs, } from '../../lib' /** * An inner element for a Dimmer. */ -export default class DimmerInner extends Component { - containerRef = createRef() - contentRef = createRef() - - componentDidMount() { - const { active } = this.props - - this.toggleStyles(active) - } - - componentDidUpdate(prevProps) { - const { active: currentActive } = this.props - const { active: prevActive } = prevProps - - if (prevActive !== currentActive) this.toggleStyles(currentActive) - } - - handleClick = (e) => { - const contentRef = this.contentRef.current - - _.invoke(this.props, 'onClick', e, this.props) - - if (contentRef && contentRef !== e.target && doesNodeContainClick(contentRef, e)) { +const DimmerInner = React.forwardRef(function (props, ref) { + const { + active, + children, + className, + content, + disabled, + inverted, + page, + simple, + verticalAlign, + } = props + + const containerRef = useMergedRefs(ref, React.useRef()) + const contentRef = React.useRef() + + useIsomorphicLayoutEffect(() => { + if (!containerRef.current?.style) { return } - _.invoke(this.props, 'onClickOutside', e, this.props) - } - - toggleStyles(active) { - const containerRef = this.containerRef.current - - if (!containerRef || !containerRef.style) return if (active) { - containerRef.style.setProperty('display', 'flex', 'important') + containerRef.current.style.setProperty('display', 'flex', 'important') } else { - containerRef.style.removeProperty('display') + containerRef.current.style.removeProperty('display') } - } + }, [active]) - render() { - const { - active, - children, - className, - content, - disabled, - inverted, - page, - simple, - verticalAlign, - } = this.props - - const classes = cx( - 'ui', - useKeyOnly(active, 'active transition visible'), - useKeyOnly(disabled, 'disabled'), - useKeyOnly(inverted, 'inverted'), - useKeyOnly(page, 'page'), - useKeyOnly(simple, 'simple'), - useVerticalAlignProp(verticalAlign), - 'dimmer', - className, - ) - const rest = getUnhandledProps(DimmerInner, this.props) - const ElementType = getElementType(DimmerInner, this.props) - - const childrenContent = childrenUtils.isNil(children) ? content : children - - return ( - - - {childrenContent && ( -
- {childrenContent} -
- )} -
-
- ) + const handleClick = (e) => { + _.invoke(props, 'onClick', e, props) + + if (contentRef.current !== e.target && doesNodeContainClick(contentRef.current, e)) { + return + } + + _.invoke(props, 'onClickOutside', e, props) } -} + const classes = cx( + 'ui', + useKeyOnly(active, 'active transition visible'), + useKeyOnly(disabled, 'disabled'), + useKeyOnly(inverted, 'inverted'), + useKeyOnly(page, 'page'), + useKeyOnly(simple, 'simple'), + useVerticalAlignProp(verticalAlign), + 'dimmer', + className, + ) + const rest = getUnhandledProps(DimmerInner, props) + const ElementType = getElementType(DimmerInner, props) + + const childrenContent = childrenUtils.isNil(children) ? content : children + + return ( + + {childrenContent && ( +
+ {childrenContent} +
+ )} +
+ ) +}) + +DimmerInner.displayName = 'DimmerInner' DimmerInner.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, @@ -147,3 +131,5 @@ DimmerInner.propTypes = { /** A dimmer can have its content top or bottom aligned. */ verticalAlign: PropTypes.oneOf(['bottom', 'top']), } + +export default DimmerInner diff --git a/src/modules/Sidebar/Sidebar.js b/src/modules/Sidebar/Sidebar.js index fbe5c0a1e3..b5b9d7d486 100644 --- a/src/modules/Sidebar/Sidebar.js +++ b/src/modules/Sidebar/Sidebar.js @@ -1,9 +1,9 @@ import { EventListener, documentRef } from '@fluentui/react-component-event-listener' -import { Ref, isRefObject } from '@fluentui/react-component-ref' +import { isRefObject } from '@fluentui/react-component-ref' import cx from 'clsx' import _ from 'lodash' import PropTypes from 'prop-types' -import React, { Component, createRef } from 'react' +import React from 'react' import { childrenUtils, @@ -12,117 +12,115 @@ import { getUnhandledProps, getElementType, useKeyOnly, + useIsomorphicLayoutEffect, + useEventCallback, + useMergedRefs, + usePrevious, } from '../../lib' import SidebarPushable from './SidebarPushable' import SidebarPusher from './SidebarPusher' /** - * A sidebar hides additional content beside a page. + * We use `animationTick` to understand when an animation should be scheduled. + * + * @param {Boolean} visible */ -class Sidebar extends Component { - ref = createRef() +function useAnimationTick(visible) { + const previousVisible = usePrevious(visible) + const tickIncrement = !!visible === !!previousVisible ? 0 : 1 - constructor(props) { - super(props) + const animationTick = React.useRef(0) + const [, forceUpdate] = React.useReducer((x) => x + 1, 0) - this.state = { - animationTick: 0, - visible: props.visible, - } - } + const currentTick = animationTick.current + tickIncrement + const resetAnimationTick = React.useCallback(() => { + animationTick.current = 0 + forceUpdate() + }, []) - static getDerivedStateFromProps(props, state) { - // We use `animationTick` to understand when an animation should be scheduled - const tickIncrement = !!props.visible === !!state.visible ? 0 : 1 + React.useEffect(() => { + animationTick.current = currentTick + }) - return { - animationTick: state.animationTick + tickIncrement, - visible: props.visible, - } - } + return [currentTick, resetAnimationTick] +} - componentDidUpdate(prevProps, prevState) { - if (this.state.animationTick > prevState.animationTick) { - this.handleAnimationStart() - } - } +/** + * A sidebar hides additional content beside a page. + */ +const Sidebar = React.forwardRef((props, ref) => { + const { animation, className, children, content, direction, target, visible, width } = props - componentWillUnmount() { - clearTimeout(this.animationTimer) - } + const [animationTick, resetAnimationTick] = useAnimationTick(visible) + const elementRef = useMergedRefs(ref, React.useRef()) - handleAnimationStart = () => { - const { visible } = this.props + const animationTimer = React.useRef() + const skipNextCallback = React.useRef() + + const handleAnimationEnd = useEventCallback(() => { + const callback = visible ? 'onShow' : 'onHidden' + + resetAnimationTick() + _.invoke(props, callback, null, props) + }) + + const handleAnimationStart = useEventCallback(() => { const callback = visible ? 'onVisible' : 'onHide' - clearTimeout(this.animationTimer) - this.animationTimer = setTimeout(this.handleAnimationEnd, Sidebar.animationDuration) + clearTimeout(animationTimer.current) + animationTimer.current = setTimeout(handleAnimationEnd, Sidebar.animationDuration) - if (this.skipNextCallback) { - this.skipNextCallback = false + if (skipNextCallback.current) { + skipNextCallback.current = false return } - _.invoke(this.props, callback, null, this.props) - } - - handleAnimationEnd = () => { - const { visible } = this.props - const callback = visible ? 'onShow' : 'onHidden' - - this.setState({ animationTick: 0 }) - _.invoke(this.props, callback, null, this.props) - } + _.invoke(props, callback, null, props) + }) - handleDocumentClick = (e) => { - if (!doesNodeContainClick(this.ref.current, e)) { - this.skipNextCallback = true - _.invoke(this.props, 'onHide', e, { ...this.props, visible: false }) + const handleDocumentClick = (e) => { + if (!doesNodeContainClick(elementRef.current, e)) { + skipNextCallback.current = true + _.invoke(props, 'onHide', e, { ...props, visible: false }) } } - render() { - const { - animation, - className, - children, - content, - direction, - target, - visible, - width, - } = this.props - const { animationTick } = this.state - - const classes = cx( - 'ui', - animation, - direction, - width, - useKeyOnly(animationTick > 0, 'animating'), - useKeyOnly(visible, 'visible'), - 'sidebar', - className, - ) - const rest = getUnhandledProps(Sidebar, this.props) - const ElementType = getElementType(Sidebar, this.props) - const targetProp = isRefObject(target) ? { targetRef: target } : { target } - - return ( - <> - - - {childrenUtils.isNil(children) ? content : children} - - - {visible && ( - - )} - - ) - } -} + useIsomorphicLayoutEffect(() => { + handleAnimationStart() + }, [animationTick]) + React.useEffect(() => { + return () => { + clearTimeout(animationTimer.current) + } + }, []) + + const classes = cx( + 'ui', + animation, + direction, + width, + useKeyOnly(animationTick > 0, 'animating'), + useKeyOnly(visible, 'visible'), + 'sidebar', + className, + ) + const rest = getUnhandledProps(Sidebar, props) + const ElementType = getElementType(Sidebar, props) + const targetProp = isRefObject(target) ? { targetRef: target } : { target } + + return ( + <> + + {childrenUtils.isNil(children) ? content : children} + + + {visible && } + + ) +}) + +Sidebar.displayName = 'Sidebar' Sidebar.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, @@ -198,7 +196,6 @@ Sidebar.defaultProps = { } Sidebar.animationDuration = 500 -Sidebar.autoControlledProps = ['visible'] Sidebar.Pushable = SidebarPushable Sidebar.Pusher = SidebarPusher diff --git a/src/modules/Sidebar/SidebarPushable.js b/src/modules/Sidebar/SidebarPushable.js index 437b74943f..ab7ce6b604 100644 --- a/src/modules/Sidebar/SidebarPushable.js +++ b/src/modules/Sidebar/SidebarPushable.js @@ -7,19 +7,20 @@ import { childrenUtils, customPropTypes, getElementType, getUnhandledProps } fro /** * A pushable sub-component for Sidebar. */ -function SidebarPushable(props) { +const SidebarPushable = React.forwardRef(function (props, ref) { const { className, children, content } = props const classes = cx('pushable', className) const rest = getUnhandledProps(SidebarPushable, props) const ElementType = getElementType(SidebarPushable, props) return ( - + {childrenUtils.isNil(children) ? content : children} ) -} +}) +SidebarPushable.displayName = 'SidebarPushable' SidebarPushable.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/modules/Sidebar/SidebarPusher.js b/src/modules/Sidebar/SidebarPusher.js index 10ef660378..670e92eb92 100644 --- a/src/modules/Sidebar/SidebarPusher.js +++ b/src/modules/Sidebar/SidebarPusher.js @@ -13,7 +13,7 @@ import { /** * A pushable sub-component for Sidebar. */ -function SidebarPusher(props) { +const SidebarPusher = React.forwardRef(function (props, ref) { const { className, dimmed, children, content } = props const classes = cx('pusher', useKeyOnly(dimmed, 'dimmed'), className) @@ -21,12 +21,13 @@ function SidebarPusher(props) { const ElementType = getElementType(SidebarPusher, props) return ( - + {childrenUtils.isNil(children) ? content : children} ) -} +}) +SidebarPusher.displayName = 'SidebarPusher' SidebarPusher.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/test/specs/collections/Grid/Grid-test.js b/test/specs/collections/Grid/Grid-test.js index 24ace8487e..4056d3a038 100644 --- a/test/specs/collections/Grid/Grid-test.js +++ b/test/specs/collections/Grid/Grid-test.js @@ -7,6 +7,7 @@ import { SUI } from 'src/lib' describe('Grid', () => { common.isConformant(Grid) + common.forwardsRef(Grid) common.hasSubcomponents(Grid, [GridRow, GridColumn]) common.hasUIClassName(Grid) common.rendersChildren(Grid, { diff --git a/test/specs/collections/Grid/GridColumn-test.js b/test/specs/collections/Grid/GridColumn-test.js index 4af1491cb1..36ca5e58c2 100644 --- a/test/specs/collections/Grid/GridColumn-test.js +++ b/test/specs/collections/Grid/GridColumn-test.js @@ -4,6 +4,7 @@ import * as common from 'test/specs/commonTests' describe('GridColumn', () => { common.isConformant(GridColumn) + common.forwardsRef(GridColumn) common.rendersChildren(GridColumn, { rendersContent: false, }) diff --git a/test/specs/collections/Grid/GridRow-test.js b/test/specs/collections/Grid/GridRow-test.js index 131dd780cd..fd785c6878 100644 --- a/test/specs/collections/Grid/GridRow-test.js +++ b/test/specs/collections/Grid/GridRow-test.js @@ -4,6 +4,7 @@ import * as common from 'test/specs/commonTests' describe('GridRow', () => { common.isConformant(GridRow) + common.forwardsRef(GridRow) common.rendersChildren(GridRow, { rendersContent: false, }) diff --git a/test/specs/modules/Dimmer/Dimmer-test.js b/test/specs/modules/Dimmer/Dimmer-test.js index 1a4204daf1..3a084b921c 100644 --- a/test/specs/modules/Dimmer/Dimmer-test.js +++ b/test/specs/modules/Dimmer/Dimmer-test.js @@ -8,6 +8,7 @@ import * as common from 'test/specs/commonTests' describe('Dimmer', () => { common.isConformant(Dimmer) + common.forwardsRef(Dimmer) common.hasSubcomponents(Dimmer, [DimmerDimmable, DimmerInner]) common.implementsCreateMethod(Dimmer) diff --git a/test/specs/modules/Dimmer/DimmerDimmable-test.js b/test/specs/modules/Dimmer/DimmerDimmable-test.js index 35aa391b15..2ed952e94b 100644 --- a/test/specs/modules/Dimmer/DimmerDimmable-test.js +++ b/test/specs/modules/Dimmer/DimmerDimmable-test.js @@ -3,6 +3,7 @@ import * as common from 'test/specs/commonTests' describe('DimmerDimmable', () => { common.isConformant(DimmerDimmable) + common.forwardsRef(DimmerDimmable) common.rendersChildren(DimmerDimmable) common.propKeyOnlyToClassName(DimmerDimmable, 'blurring') diff --git a/test/specs/modules/Dimmer/DimmerInner-test.js b/test/specs/modules/Dimmer/DimmerInner-test.js index 26965d4c53..a2aac04319 100644 --- a/test/specs/modules/Dimmer/DimmerInner-test.js +++ b/test/specs/modules/Dimmer/DimmerInner-test.js @@ -7,6 +7,7 @@ import { sandbox } from 'test/utils' describe('DimmerInner', () => { common.isConformant(DimmerInner) + common.forwardsRef(DimmerInner) common.hasUIClassName(DimmerInner) common.rendersChildren(DimmerInner) @@ -32,7 +33,7 @@ describe('DimmerInner', () => { describe('onClickOutside', () => { it('called when Dimmer has not children', () => { const onClickOutside = sandbox.spy() - const wrapper = shallow() + const wrapper = mount() wrapper.childAt(0).simulate('click') onClickOutside.should.have.been.calledOnce() @@ -60,10 +61,11 @@ describe('DimmerInner', () => { it('called when click on Dimmer', () => { const onClickOutside = sandbox.spy() - - mount( + const wrapper = mount( {faker.hacker.phrase()}, - ).simulate('click') + ) + + wrapper.simulate('click') onClickOutside.should.have.been.calledOnce() }) diff --git a/test/specs/modules/Sidebar/Sidebar-test.js b/test/specs/modules/Sidebar/Sidebar-test.js index 8e38e944ad..21afd96f93 100644 --- a/test/specs/modules/Sidebar/Sidebar-test.js +++ b/test/specs/modules/Sidebar/Sidebar-test.js @@ -2,10 +2,11 @@ import React from 'react' import Sidebar from 'src/modules/Sidebar/Sidebar' import * as common from 'test/specs/commonTests' -import { domEvent, sandbox } from 'test/utils' +import { assertWithTimeout, domEvent, sandbox } from 'test/utils' describe('Sidebar', () => { common.isConformant(Sidebar) + common.forwardsRef(Sidebar) common.hasUIClassName(Sidebar) common.rendersChildren(Sidebar) @@ -23,12 +24,17 @@ describe('Sidebar', () => { common.propValueOnlyToClassName(Sidebar, 'width', ['very thin', 'thin', 'wide', 'very wide']) describe('componentWillUnmount', () => { - it('will call "clearTimeout"', () => { + it('will call "clearTimeout"', (done) => { const clear = sandbox.spy(window, 'clearTimeout') const wrapper = mount() + // start animation wrapper.setProps({ visible: true }) - clear.should.have.been.calledOnce() + wrapper.unmount() + + assertWithTimeout(() => { + clear.should.have.been.called() + }, done) }) }) diff --git a/test/specs/modules/Sidebar/SidebarPushable-test.js b/test/specs/modules/Sidebar/SidebarPushable-test.js index a1ed8ee0aa..5ab1a9c00f 100644 --- a/test/specs/modules/Sidebar/SidebarPushable-test.js +++ b/test/specs/modules/Sidebar/SidebarPushable-test.js @@ -3,5 +3,6 @@ import * as common from 'test/specs/commonTests' describe('SidebarPushable', () => { common.isConformant(SidebarPushable) + common.forwardsRef(SidebarPushable) common.rendersChildren(SidebarPushable) }) diff --git a/test/specs/modules/Sidebar/SidebarPusher-test.js b/test/specs/modules/Sidebar/SidebarPusher-test.js index f1394a0a23..1787971775 100644 --- a/test/specs/modules/Sidebar/SidebarPusher-test.js +++ b/test/specs/modules/Sidebar/SidebarPusher-test.js @@ -3,6 +3,7 @@ import * as common from 'test/specs/commonTests' describe('SidebarPusher', () => { common.isConformant(SidebarPusher) + common.forwardsRef(SidebarPusher) common.rendersChildren(SidebarPusher) common.propKeyOnlyToClassName(SidebarPusher, 'dimmed')