Skip to content

Commit a8bd097

Browse files
committed
chore(Dimmer|Grid|Sidebar): use React.forwardRef() (#4260)
1 parent a6b0d89 commit a8bd097

18 files changed

+233
-224
lines changed

src/collections/Grid/Grid.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import GridRow from './GridRow'
2020
/**
2121
* A grid is used to harmonize negative space in a layout.
2222
*/
23-
function Grid(props) {
23+
const Grid = React.forwardRef(function (props, ref) {
2424
const {
2525
celled,
2626
centered,
@@ -63,15 +63,16 @@ function Grid(props) {
6363
const ElementType = getElementType(Grid, props)
6464

6565
return (
66-
<ElementType {...rest} className={classes}>
66+
<ElementType {...rest} className={classes} ref={ref}>
6767
{children}
6868
</ElementType>
6969
)
70-
}
70+
})
7171

7272
Grid.Column = GridColumn
7373
Grid.Row = GridRow
7474

75+
Grid.displayName = 'Grid'
7576
Grid.propTypes = {
7677
/** An element type to render as (string or function). */
7778
as: PropTypes.elementType,

src/collections/Grid/GridColumn.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
/**
2020
* A column sub-component for Grid.
2121
*/
22-
function GridColumn(props) {
22+
const GridColumn = React.forwardRef(function (props, ref) {
2323
const {
2424
children,
2525
className,
@@ -57,12 +57,13 @@ function GridColumn(props) {
5757
const ElementType = getElementType(GridColumn, props)
5858

5959
return (
60-
<ElementType {...rest} className={classes}>
60+
<ElementType {...rest} className={classes} ref={ref}>
6161
{children}
6262
</ElementType>
6363
)
64-
}
64+
})
6565

66+
GridColumn.displayName = 'GridColumn'
6667
GridColumn.propTypes = {
6768
/** An element type to render as (string or function). */
6869
as: PropTypes.elementType,

src/collections/Grid/GridRow.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
/**
1818
* A row sub-component for Grid.
1919
*/
20-
function GridRow(props) {
20+
const GridRow = React.forwardRef(function (props, ref) {
2121
const {
2222
centered,
2323
children,
@@ -49,12 +49,13 @@ function GridRow(props) {
4949
const ElementType = getElementType(GridRow, props)
5050

5151
return (
52-
<ElementType {...rest} className={classes}>
52+
<ElementType {...rest} className={classes} ref={ref}>
5353
{children}
5454
</ElementType>
5555
)
56-
}
56+
})
5757

58+
GridRow.displayName = 'GridRow'
5859
GridRow.propTypes = {
5960
/** An element type to render as (string or function). */
6061
as: PropTypes.elementType,

src/modules/Dimmer/Dimmer.js

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import PropTypes from 'prop-types'
2-
import React, { Component } from 'react'
2+
import React from 'react'
33

44
import { createShorthandFactory, getUnhandledProps, isBrowser } from '../../lib'
55
import Portal from '../../addons/Portal'
@@ -9,46 +9,49 @@ import DimmerInner from './DimmerInner'
99
/**
1010
* A dimmer hides distractions to focus attention on particular content.
1111
*/
12-
export default class Dimmer extends Component {
13-
handlePortalMount = () => {
14-
if (!isBrowser()) return
12+
const Dimmer = React.forwardRef(function (props, ref) {
13+
const { active, page } = props
14+
const rest = getUnhandledProps(Dimmer, props)
1515

16-
// Heads up, IE doesn't support second argument in add()
17-
document.body.classList.add('dimmed')
18-
document.body.classList.add('dimmable')
19-
}
16+
if (page) {
17+
const handlePortalMount = () => {
18+
if (!isBrowser()) {
19+
return
20+
}
2021

21-
handlePortalUnmount = () => {
22-
if (!isBrowser()) return
22+
// Heads up, IE doesn't support second argument in add()
23+
document.body.classList.add('dimmed')
24+
document.body.classList.add('dimmable')
25+
}
2326

24-
// Heads up, IE doesn't support second argument in add()
25-
document.body.classList.remove('dimmed')
26-
document.body.classList.remove('dimmable')
27-
}
27+
const handlePortalUnmount = () => {
28+
if (!isBrowser()) {
29+
return
30+
}
2831

29-
render() {
30-
const { active, page } = this.props
31-
const rest = getUnhandledProps(Dimmer, this.props)
32-
33-
if (page) {
34-
return (
35-
<Portal
36-
closeOnEscape={false}
37-
closeOnDocumentClick={false}
38-
onMount={this.handlePortalMount}
39-
onUnmount={this.handlePortalUnmount}
40-
open={active}
41-
openOnTriggerClick={false}
42-
>
43-
<DimmerInner {...rest} active={active} page={page} />
44-
</Portal>
45-
)
32+
// Heads up, IE doesn't support second argument in add()
33+
document.body.classList.remove('dimmed')
34+
document.body.classList.remove('dimmable')
4635
}
4736

48-
return <DimmerInner {...rest} active={active} page={page} />
37+
return (
38+
<Portal
39+
closeOnEscape={false}
40+
closeOnDocumentClick={false}
41+
onMount={handlePortalMount}
42+
onUnmount={handlePortalUnmount}
43+
open={active}
44+
openOnTriggerClick={false}
45+
>
46+
<DimmerInner {...rest} active={active} page={page} ref={ref} />
47+
</Portal>
48+
)
4949
}
50-
}
5150

51+
return <DimmerInner {...rest} active={active} page={page} ref={ref} />
52+
})
53+
54+
Dimmer.displayName = 'Dimmer'
5255
Dimmer.propTypes = {
5356
/** An active dimmer will dim its parent container. */
5457
active: PropTypes.bool,
@@ -61,3 +64,5 @@ Dimmer.Dimmable = DimmerDimmable
6164
Dimmer.Inner = DimmerInner
6265

6366
Dimmer.create = createShorthandFactory(Dimmer, (value) => ({ content: value }))
67+
68+
export default Dimmer

src/modules/Dimmer/DimmerDimmable.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
/**
1414
* A dimmable sub-component for Dimmer.
1515
*/
16-
function DimmerDimmable(props) {
16+
const DimmerDimmable = React.forwardRef(function (props, ref) {
1717
const { blurring, className, children, content, dimmed } = props
1818

1919
const classes = cx(
@@ -26,12 +26,13 @@ function DimmerDimmable(props) {
2626
const ElementType = getElementType(DimmerDimmable, props)
2727

2828
return (
29-
<ElementType {...rest} className={classes}>
29+
<ElementType {...rest} className={classes} ref={ref}>
3030
{childrenUtils.isNil(children) ? content : children}
3131
</ElementType>
3232
)
33-
}
33+
})
3434

35+
DimmerDimmable.displayName = 'DimmerDimmable'
3536
DimmerDimmable.propTypes = {
3637
/** An element type to render as (string or function). */
3738
as: PropTypes.elementType,

src/modules/Dimmer/DimmerInner.js

Lines changed: 62 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { Ref } from '@fluentui/react-component-ref'
21
import cx from 'clsx'
32
import _ from 'lodash'
43
import PropTypes from 'prop-types'
5-
import React, { Component, createRef } from 'react'
4+
import React from 'react'
65

76
import {
87
childrenUtils,
@@ -12,94 +11,79 @@ import {
1211
getUnhandledProps,
1312
useKeyOnly,
1413
useVerticalAlignProp,
14+
useIsomorphicLayoutEffect,
15+
useMergedRefs,
1516
} from '../../lib'
1617

1718
/**
1819
* An inner element for a Dimmer.
1920
*/
20-
export default class DimmerInner extends Component {
21-
containerRef = createRef()
22-
contentRef = createRef()
23-
24-
componentDidMount() {
25-
const { active } = this.props
26-
27-
this.toggleStyles(active)
28-
}
29-
30-
componentDidUpdate(prevProps) {
31-
const { active: currentActive } = this.props
32-
const { active: prevActive } = prevProps
33-
34-
if (prevActive !== currentActive) this.toggleStyles(currentActive)
35-
}
36-
37-
handleClick = (e) => {
38-
const contentRef = this.contentRef.current
39-
40-
_.invoke(this.props, 'onClick', e, this.props)
41-
42-
if (contentRef && contentRef !== e.target && doesNodeContainClick(contentRef, e)) {
21+
const DimmerInner = React.forwardRef(function (props, ref) {
22+
const {
23+
active,
24+
children,
25+
className,
26+
content,
27+
disabled,
28+
inverted,
29+
page,
30+
simple,
31+
verticalAlign,
32+
} = props
33+
34+
const containerRef = useMergedRefs(ref, React.useRef())
35+
const contentRef = React.useRef()
36+
37+
useIsomorphicLayoutEffect(() => {
38+
if (!containerRef.current?.style) {
4339
return
4440
}
4541

46-
_.invoke(this.props, 'onClickOutside', e, this.props)
47-
}
48-
49-
toggleStyles(active) {
50-
const containerRef = this.containerRef.current
51-
52-
if (!containerRef || !containerRef.style) return
5342
if (active) {
54-
containerRef.style.setProperty('display', 'flex', 'important')
43+
containerRef.current.style.setProperty('display', 'flex', 'important')
5544
} else {
56-
containerRef.style.removeProperty('display')
45+
containerRef.current.style.removeProperty('display')
5746
}
58-
}
47+
}, [active])
5948

60-
render() {
61-
const {
62-
active,
63-
children,
64-
className,
65-
content,
66-
disabled,
67-
inverted,
68-
page,
69-
simple,
70-
verticalAlign,
71-
} = this.props
72-
73-
const classes = cx(
74-
'ui',
75-
useKeyOnly(active, 'active transition visible'),
76-
useKeyOnly(disabled, 'disabled'),
77-
useKeyOnly(inverted, 'inverted'),
78-
useKeyOnly(page, 'page'),
79-
useKeyOnly(simple, 'simple'),
80-
useVerticalAlignProp(verticalAlign),
81-
'dimmer',
82-
className,
83-
)
84-
const rest = getUnhandledProps(DimmerInner, this.props)
85-
const ElementType = getElementType(DimmerInner, this.props)
86-
87-
const childrenContent = childrenUtils.isNil(children) ? content : children
88-
89-
return (
90-
<Ref innerRef={this.containerRef}>
91-
<ElementType {...rest} className={classes} onClick={this.handleClick}>
92-
{childrenContent && (
93-
<div className='content' ref={this.contentRef}>
94-
{childrenContent}
95-
</div>
96-
)}
97-
</ElementType>
98-
</Ref>
99-
)
49+
const handleClick = (e) => {
50+
_.invoke(props, 'onClick', e, props)
51+
52+
if (contentRef.current !== e.target && doesNodeContainClick(contentRef.current, e)) {
53+
return
54+
}
55+
56+
_.invoke(props, 'onClickOutside', e, props)
10057
}
101-
}
10258

59+
const classes = cx(
60+
'ui',
61+
useKeyOnly(active, 'active transition visible'),
62+
useKeyOnly(disabled, 'disabled'),
63+
useKeyOnly(inverted, 'inverted'),
64+
useKeyOnly(page, 'page'),
65+
useKeyOnly(simple, 'simple'),
66+
useVerticalAlignProp(verticalAlign),
67+
'dimmer',
68+
className,
69+
)
70+
const rest = getUnhandledProps(DimmerInner, props)
71+
const ElementType = getElementType(DimmerInner, props)
72+
73+
const childrenContent = childrenUtils.isNil(children) ? content : children
74+
75+
return (
76+
<ElementType {...rest} className={classes} onClick={handleClick} ref={containerRef}>
77+
{childrenContent && (
78+
<div className='content' ref={contentRef}>
79+
{childrenContent}
80+
</div>
81+
)}
82+
</ElementType>
83+
)
84+
})
85+
86+
DimmerInner.displayName = 'DimmerInner'
10387
DimmerInner.propTypes = {
10488
/** An element type to render as (string or function). */
10589
as: PropTypes.elementType,
@@ -147,3 +131,5 @@ DimmerInner.propTypes = {
147131
/** A dimmer can have its content top or bottom aligned. */
148132
verticalAlign: PropTypes.oneOf(['bottom', 'top']),
149133
}
134+
135+
export default DimmerInner

0 commit comments

Comments
 (0)