Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit affbec0

Browse files
authored
feat(Popup): close popup on click (#410)
* close popup on outside click * remove eventStack async logic * simplify Popup examples * introduce recommended API changes * do not close popup when clicked inside popup area * simplify handler logic * remove unnecessary unsub instruction * remove state that was previously used in controlled mode * update changelog * make method name to be more descriptive * properly maintain Popup state on component updates * rename method to better reflect semantics
1 parent 34bf5f1 commit affbec0

15 files changed

Lines changed: 218 additions & 213 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2828
### Features
2929
- Make `Grid` keyboard navigable by implementing `gridBehavior` @sophieH29 ([#398](https://github.com/stardust-ui/react/pull/398))
3030
- Set the ref of the `FocusZone` in `Embed` mode @sophieH29 ([#435](https://github.com/stardust-ui/react/pull/435))
31+
- Close `Popup` on outside click @kuzhelov ([#410](https://github.com/stardust-ui/react/pull/410))
3132
- Set default `chatBehavior` which uses Enter/Esc keys @sophieH29 ([#443](https://github.com/stardust-ui/react/pull/443))
3233

3334
### Documentation

docs/src/components/Editor/Editor.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'brace/mode/html'
88
import 'brace/mode/jsx'
99
import 'brace/mode/sh'
1010
import 'brace/theme/tomorrow_night'
11-
import { eventStack, doesNodeContainClick } from 'src/lib'
11+
import { doesNodeContainClick, EventStack } from 'src/lib'
1212

1313
const parentComponents = []
1414

@@ -61,6 +61,7 @@ export const EDITOR_GUTTER_COLOR = '#26282d'
6161

6262
class Editor extends React.Component<EditorProps> {
6363
private static readonly refName = 'aceEditor'
64+
private clickSubscription = EventStack.noSubscription
6465

6566
public static propTypes = {
6667
id: PropTypes.string.isRequired,
@@ -142,11 +143,12 @@ class Editor extends React.Component<EditorProps> {
142143
}
143144

144145
private addDocumentListener() {
145-
eventStack.sub('click', this.handleDocumentClick)
146+
this.clickSubscription.unsubscribe()
147+
this.clickSubscription = EventStack.subscribe('click', this.handleDocumentClick)
146148
}
147149

148150
private removeDocumentListener() {
149-
eventStack.unsub('click', this.handleDocumentClick)
151+
this.clickSubscription.unsubscribe()
150152
}
151153

152154
private get editor() {
Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,25 @@
11
import React from 'react'
22
import { Button, Popup } from '@stardust-ui/react'
33

4-
class PopupContentWrapperExample extends React.Component<any, any> {
5-
state = {
6-
firstPopupOpen: false,
7-
secondPopupOpen: false,
4+
const PopupContentWrapperExample = () => {
5+
const plainContentStyle = {
6+
zIndex: 1000,
7+
padding: 5,
88
}
99

10-
render() {
11-
const plainContentStyle = {
12-
zIndex: 1000,
13-
padding: 5,
14-
}
10+
return (
11+
<>
12+
<Popup
13+
content={<p style={plainContentStyle}>Plain popup content rendered 'as is'.</p>}
14+
trigger={<Button icon="expand" content="Popup with plain content" />}
15+
/>
1516

16-
return (
17-
<>
18-
<Popup
19-
open={this.state.firstPopupOpen}
20-
content={<p style={plainContentStyle}>Plain popup content rendered 'as is'.</p>}
21-
trigger={
22-
<Button
23-
icon="expand"
24-
onClick={() => this.setState(prev => ({ firstPopupOpen: !prev.firstPopupOpen }))}
25-
content="Popup with plain content"
26-
/>
27-
}
28-
/>
29-
30-
<Popup
31-
open={this.state.secondPopupOpen}
32-
content={{ content: <p style={plainContentStyle}>Popup content rendered in wrapper.</p> }}
33-
trigger={
34-
<Button
35-
icon="expand"
36-
onClick={() => this.setState(prev => ({ secondPopupOpen: !prev.secondPopupOpen }))}
37-
content="Popup with wrapped content"
38-
/>
39-
}
40-
/>
41-
</>
42-
)
43-
}
17+
<Popup
18+
content={{ content: <p style={plainContentStyle}>Popup content rendered in wrapper.</p> }}
19+
trigger={<Button icon="expand" content="Popup with wrapped content" />}
20+
/>
21+
</>
22+
)
4423
}
4524

4625
export default PopupContentWrapperExample
Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,25 @@
11
import React from 'react'
22
import { Button, Popup } from '@stardust-ui/react'
33

4-
class PopupContentWrapperExample extends React.Component<any, any> {
5-
state = {
6-
firstPopupOpen: false,
7-
secondPopupOpen: false,
4+
const PopupContentWrapperExample = () => {
5+
const plainContentStyle = {
6+
zIndex: 1000,
7+
padding: 5,
88
}
99

10-
render() {
11-
const plainContentStyle = {
12-
zIndex: 1000,
13-
padding: 5,
14-
}
10+
return (
11+
<>
12+
<Popup content={<p style={plainContentStyle}>Plain popup content rendered 'as is'.</p>}>
13+
<Button icon="expand" content="Popup with plain content" />
14+
</Popup>
1515

16-
return (
17-
<>
18-
<Popup
19-
open={this.state.firstPopupOpen}
20-
content={<p style={plainContentStyle}>Plain popup content rendered 'as is'.</p>}
21-
>
22-
<Button
23-
icon="expand"
24-
onClick={() => this.setState(prev => ({ firstPopupOpen: !prev.firstPopupOpen }))}
25-
content="Popup with plain content"
26-
/>
27-
</Popup>
28-
29-
<Popup
30-
open={this.state.secondPopupOpen}
31-
content={{ content: <p style={plainContentStyle}>Popup content rendered in wrapper.</p> }}
32-
>
33-
<Button
34-
icon="expand"
35-
onClick={() => this.setState(prev => ({ secondPopupOpen: !prev.secondPopupOpen }))}
36-
content="Popup with wrapped content"
37-
/>
38-
</Popup>
39-
</>
40-
)
41-
}
16+
<Popup
17+
content={{ content: <p style={plainContentStyle}>Popup content rendered in wrapper.</p> }}
18+
>
19+
<Button icon="expand" content="Popup with wrapped content" />
20+
</Popup>
21+
</>
22+
)
4223
}
4324

4425
export default PopupContentWrapperExample

docs/src/examples/components/Popup/Types/PopupCustomTargetExample.shorthand.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { Popup, Divider, Icon, Text, Grid } from '@stardust-ui/react'
2+
import { Popup, Button, Divider, Text, Grid } from '@stardust-ui/react'
33
import { findDOMNode } from 'react-dom'
44

55
class PopupExample extends React.Component {
@@ -16,7 +16,7 @@ class PopupExample extends React.Component {
1616
{/* CUSTOM DOM ELEMENT is used as target for Popup */}
1717
<Popup
1818
target={this.state.popupTarget}
19-
trigger={<Icon name="question" circular bordered styles={{ cursor: 'pointer' }} />}
19+
trigger={<Button icon="question" circular styles={{ cursor: 'pointer' }} />}
2020
content="well, yes, I am just a garbish text ¯\_(ツ)_/¯"
2121
position="below"
2222
/>

docs/src/examples/components/Popup/Types/PopupCustomTargetExample.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { Popup, Divider, Icon, Text, Grid } from '@stardust-ui/react'
2+
import { Popup, Button, Divider, Text, Grid } from '@stardust-ui/react'
33
import { findDOMNode } from 'react-dom'
44

55
class PopupExample extends React.Component {
@@ -19,7 +19,7 @@ class PopupExample extends React.Component {
1919
content="well, yes, I am just a garbish text ¯\_(ツ)_/¯"
2020
position="below"
2121
>
22-
<Icon name="question" circular bordered styles={{ cursor: 'pointer' }} />
22+
<Button icon="question" circular styles={{ cursor: 'pointer' }} />
2323
</Popup>
2424

2525
<div style={{ marginLeft: 10 }}>

docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,23 @@
11
import React from 'react'
22
import { Button, Grid, Popup } from '@stardust-ui/react'
33

4-
class PopupWithButton extends React.Component<any, any> {
5-
state = { popupOpen: false }
4+
const PopupWithButton = props => {
5+
const { position, align, icon, padding } = props
66

7-
togglePopupState = () => {
8-
this.setState(prev => ({ popupOpen: !prev.popupOpen }))
9-
}
10-
11-
render = () => {
12-
const { position, align, icon, padding } = this.props
13-
14-
return (
15-
<Popup
16-
open={this.state.popupOpen}
17-
align={align}
18-
position={position}
19-
trigger={
20-
<Button
21-
onClick={() => this.togglePopupState()}
22-
onMouseLeave={() => this.setState({ popupOpen: false })}
23-
icon={icon}
24-
styles={{ padding, height: '38px', minWidth: '64px' }}
25-
/>
26-
}
27-
content={{
28-
content: (
29-
<p>
30-
The popup is rendered {position} the trigger<br />aligned to the {align}.
31-
</p>
32-
),
33-
}}
34-
/>
35-
)
36-
}
7+
return (
8+
<Popup
9+
align={align}
10+
position={position}
11+
trigger={<Button icon={icon} styles={{ padding, height: '38px', minWidth: '64px' }} />}
12+
content={{
13+
content: (
14+
<p>
15+
The popup is rendered {position} the trigger<br />aligned to the {align}.
16+
</p>
17+
),
18+
}}
19+
/>
20+
)
3721
}
3822

3923
const triggers = [

docs/src/examples/components/Popup/Variations/PopupExamplePosition.tsx

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,26 @@
11
import React from 'react'
22
import { Button, Grid, Popup } from '@stardust-ui/react'
33

4-
class PopupArrowExample extends React.Component<any, any> {
5-
state = { popupOpen: false }
6-
7-
togglePopupState = () => {
8-
this.setState(prev => ({ popupOpen: !prev.popupOpen }))
9-
}
10-
11-
render() {
12-
const { position, align, icon, padding } = this.props
13-
14-
const buttonStyles = { padding, height: '38px', minWidth: '64px' }
15-
16-
return (
17-
<Popup
18-
open={this.state.popupOpen}
19-
align={align}
20-
position={position}
21-
content={{
22-
content: (
23-
<p>
24-
The popup is rendered {position} the trigger<br />aligned to the {align}.
25-
</p>
26-
),
27-
}}
28-
>
29-
<Button
30-
onClick={() => this.togglePopupState()}
31-
onMouseLeave={() => this.setState({ popupOpen: false })}
32-
icon={icon}
33-
styles={buttonStyles}
34-
/>
35-
</Popup>
36-
)
37-
}
4+
const PopupArrowExample = props => {
5+
const { position, align, icon, padding } = props
6+
7+
const buttonStyles = { padding, height: '38px', minWidth: '64px' }
8+
9+
return (
10+
<Popup
11+
align={align}
12+
position={position}
13+
content={{
14+
content: (
15+
<p>
16+
The popup is rendered {position} the trigger<br />aligned to the {align}.
17+
</p>
18+
),
19+
}}
20+
>
21+
<Button icon={icon} styles={buttonStyles} />
22+
</Popup>
23+
)
3824
}
3925

4026
const triggers = [

0 commit comments

Comments
 (0)