Skip to content

Commit ffaf2c1

Browse files
authored
fix(Popup): do not throw if context & trigger are missing (#4026)
1 parent 6768a7d commit ffaf2c1

File tree

5 files changed

+105
-39
lines changed

5 files changed

+105
-39
lines changed
Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
1-
import React, { createRef } from 'react'
1+
import React from 'react'
22
import { Button, Popup } from 'semantic-ui-react'
33

4-
class PopupExampleContextControlled extends React.Component {
5-
contextRef = createRef()
4+
function PopupExampleContext() {
5+
const contextRef = React.useRef()
66

7-
render() {
8-
return (
9-
<>
10-
<Popup
11-
trigger={<Button content='Trigger Popup' />}
12-
context={this.contextRef}
13-
content='Hello'
14-
position='top center'
15-
/>
16-
---------->
17-
<strong ref={this.contextRef}>here</strong>
18-
</>
19-
)
20-
}
7+
return (
8+
<>
9+
<Popup
10+
trigger={<Button content='Trigger Popup' />}
11+
context={contextRef}
12+
content='Hello'
13+
position='top center'
14+
/>
15+
---------->
16+
<strong ref={contextRef}>here</strong>
17+
</>
18+
)
2119
}
2220

23-
export default PopupExampleContextControlled
21+
export default PopupExampleContext
Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
import React from 'react'
22
import { Button, Popup } from 'semantic-ui-react'
33

4-
class PopupExampleContextControlled extends React.Component {
5-
state = {}
6-
contextRef = React.createRef()
4+
function PopupExampleContextControlled() {
5+
const contextRef = React.useRef()
6+
const [open, setOpen] = React.useState(false)
77

8-
toggle = () => this.setState((prevState) => ({ open: !prevState.open }))
9-
10-
render() {
11-
return (
12-
<>
13-
<Button content='Open controlled Popup' onClick={this.toggle} />
14-
<Popup
15-
context={this.contextRef}
16-
content='Hello'
17-
position='top center'
18-
open={this.state.open}
19-
/>
20-
---------->
21-
<strong ref={this.contextRef}>here</strong>
22-
</>
23-
)
24-
}
8+
return (
9+
<>
10+
<Button
11+
content='Open controlled Popup'
12+
onClick={() => setOpen((prevOpen) => !prevOpen)}
13+
/>
14+
<Popup
15+
context={contextRef}
16+
content='Hello'
17+
position='top center'
18+
open={open}
19+
/>
20+
---------->
21+
<strong ref={contextRef}>here</strong>
22+
</>
23+
)
2524
}
2625

2726
export default PopupExampleContextControlled
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import React from 'react'
2+
import { Menu, Popup, Segment } from 'semantic-ui-react'
3+
4+
function createContextFromEvent(e) {
5+
const left = e.clientX
6+
const top = e.clientY
7+
const right = left + 1
8+
const bottom = top + 1
9+
10+
return {
11+
getBoundingClientRect: () => ({
12+
left,
13+
top,
14+
right,
15+
bottom,
16+
17+
height: 0,
18+
width: 0,
19+
}),
20+
}
21+
}
22+
23+
function PopupExampleContextMenu() {
24+
const contextRef = React.useRef()
25+
const [open, setOpen] = React.useState(false)
26+
27+
return (
28+
<>
29+
<Segment
30+
onContextMenu={(e) => {
31+
e.preventDefault()
32+
33+
contextRef.current = createContextFromEvent(e)
34+
setOpen(true)
35+
}}
36+
secondary
37+
style={{ height: 200 }}
38+
tabIndex={0}
39+
>
40+
Press Context Menu button or perform a right click in this area to open
41+
a popup
42+
</Segment>
43+
44+
<Popup
45+
basic
46+
context={contextRef}
47+
onClose={() => setOpen(false)}
48+
open={open}
49+
>
50+
<Menu
51+
items={[
52+
{ key: 'copy', content: 'Copy', icon: 'copy' },
53+
{ key: 'code', content: 'View source code', icon: 'code' },
54+
]}
55+
onItemClick={() => setOpen(false)}
56+
secondary
57+
vertical
58+
/>
59+
</Popup>
60+
</>
61+
)
62+
}
63+
64+
export default PopupExampleContextMenu

docs/src/examples/modules/Popup/Usage/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ const PopupUsageExamples = () => (
9696
description='A popup can open over a DOM node when controlled.'
9797
examplePath='modules/Popup/Usage/PopupExampleContextControlled'
9898
/>
99+
<ComponentExample
100+
title='Context Menu'
101+
description='A popup can open over a DOM node as used as a context menu.'
102+
examplePath='modules/Popup/Usage/PopupExampleContextMenu'
103+
/>
99104
<ComponentExample
100105
title='Hide on scroll'
101106
description='A popup can be hidden on a scroll event.'

src/modules/Popup/lib/createReferenceProxy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class ReferenceProxy {
77
}
88

99
getBoundingClientRect() {
10-
return _.invoke(this.ref.current, 'getBoundingClientRect', {})
10+
return _.invoke(this.ref.current, 'getBoundingClientRect') || {}
1111
}
1212

1313
get clientWidth() {

0 commit comments

Comments
 (0)