Skip to content

Commit

Permalink
feat: add external handlers to either open or close a #modal
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Mar 27, 2019
1 parent 7c60630 commit 8d4b93f
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 13 deletions.
16 changes: 16 additions & 0 deletions packages/dnb-ui-lib/src/components/modal/Example.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ class Example extends PureComponent {
</p>
<br/>
<Input label="Focus:">Focus me with Tab key</Input>
</Modal>
`}
</ComponentBox>
<ComponentBox caption="Close Modal by handlers">
{/* @jsx */ `
<Modal
title="Auto close"
trigger_text="Click me"
// open_state="opened"
close_modal={close => {
setTimeout(close, 3e3)
}}
>
<p className="dnb-p">
This Modal will close in 3 seconds.
</p>
</Modal>
`}
</ComponentBox>
Expand Down
64 changes: 56 additions & 8 deletions packages/dnb-ui-lib/src/components/modal/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const renderProps = {
on_open: null,
on_close: null,
on_close_prevent: null,
open_modal: null,
close_modal: null,
modal_content: null
}

Expand All @@ -46,6 +48,7 @@ export const propTypes = {
PropTypes.bool
]),
prevent_close: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
open_state: PropTypes.oneOf(['opened', 'closed']),
class: PropTypes.string,

// React props
Expand All @@ -56,11 +59,15 @@ export const propTypes = {
PropTypes.func
]),

// Web Component props
preventSetTriggerRef: PropTypes.bool,
// Events and functions
on_open: PropTypes.func,
on_close: PropTypes.func,
on_close_prevent: PropTypes.func,
open_modal: PropTypes.func,
close_modal: PropTypes.func,

// Web Component props
preventSetTriggerRef: PropTypes.bool,
modal_content: PropTypes.oneOfType([
PropTypes.string,
PropTypes.node,
Expand Down Expand Up @@ -126,7 +133,23 @@ export default class Modal extends PureComponent {
}
}

static getDerivedStateFromProps(props, state) {
if (state._listenForPropChanges) {
switch (props.open_state) {
case 'opened':
state.modalActive = true
break
case 'closed':
state.modalActive = false
break
}
}
state._listenForPropChanges = true
return state
}

state = {
_listenForPropChanges: true,
modalActive: false
}

Expand All @@ -153,19 +176,38 @@ export default class Modal extends PureComponent {
}
}

componentDidMount() {
const { open_modal, open_state } = this.props
if (typeof open_modal === 'function') {
open_modal(() => {
this.toggleOpenClose(null, true)
}, this)
}
if (open_state) {
this.handleSideEffects(this.state.modalActive)
}
}
componentWillUnmount() {
this.toggleOpenClose(null, false)
}

toggleOpenClose = (event = null, showModal = null) => {
if (event && event.preventDefault) {
event.preventDefault()
}

Modal.insertModalRoot()

const modalActive =
showModal !== null ? showModal : !this.state.modalActive
this.setState({
modalActive
modalActive,
_listenForPropChanges: false
})

this.handleSideEffects(modalActive)
}
handleSideEffects = modalActive => {
Modal.insertModalRoot()

// prevent scrolling on the background
try {
document.body.setAttribute(
Expand All @@ -179,6 +221,15 @@ export default class Modal extends PureComponent {
)
}

if (modalActive) {
if (typeof this.props.close_modal === 'function') {
this.props.close_modal(() => {
this.isClosing = false
this.toggleOpenClose(null, false)
}, this)
}
}

const id = this._id
if (modalActive) {
dispatchCustomElementEvent(this, 'on_open', { id })
Expand Down Expand Up @@ -214,9 +265,6 @@ export default class Modal extends PureComponent {
this.toggleOpenClose(e, false)
}
}
componentWillUnmount() {
this.toggleOpenClose(null, false)
}
render() {
const {
id, // eslint-disable-line
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ exports[`Modal component have to match snapshot 1`] = `
"children": "children",
"class": "class",
"className": "className",
"close_modal": [Function],
"close_title": "close_title",
"content_id": "content_id",
"hide_close_button": "hide_close_button",
Expand All @@ -18,6 +19,8 @@ exports[`Modal component have to match snapshot 1`] = `
"on_close": [Function],
"on_close_prevent": [Function],
"on_open": [Function],
"open_modal": [Function],
"open_state": "'opened'",
"preventSetTriggerRef": true,
"prevent_close": "prevent_close",
"title": "title",
Expand Down Expand Up @@ -67,6 +70,7 @@ exports[`Modal component have to match snapshot 1`] = `
}
class={null}
className={null}
close_modal={null}
close_title="close_title"
content_id="modal_content_id"
hide_close_button={false}
Expand All @@ -76,6 +80,7 @@ exports[`Modal component have to match snapshot 1`] = `
on_close={null}
on_close_prevent={null}
on_open={null}
open_modal={null}
preventSetTriggerRef={true}
prevent_close={false}
title="modal_title"
Expand Down Expand Up @@ -191,6 +196,7 @@ exports[`Modal component have to match snapshot 1`] = `
"children": "children",
"class": "class",
"className": "className",
"close_modal": [Function],
"close_title": "close_title",
"content_id": "content_id",
"hide_close_button": "hide_close_button",
Expand All @@ -200,6 +206,8 @@ exports[`Modal component have to match snapshot 1`] = `
"on_close": [Function],
"on_close_prevent": [Function],
"on_open": [Function],
"open_modal": [Function],
"open_state": "'opened'",
"preventSetTriggerRef": true,
"prevent_close": "prevent_close",
"title": "title",
Expand Down Expand Up @@ -250,6 +258,7 @@ exports[`Modal component have to match snapshot 1`] = `
class={null}
className={null}
closeModal={[Function]}
close_modal={null}
close_title="close_title"
content_id="modal_content_id"
hide_close_button={false}
Expand All @@ -258,6 +267,7 @@ exports[`Modal component have to match snapshot 1`] = `
on_close={null}
on_close_prevent={null}
on_open={null}
open_modal={null}
prevent_close={false}
title="modal_title"
toggleOpenClose={[Function]}
Expand All @@ -270,6 +280,7 @@ exports[`Modal component have to match snapshot 1`] = `
"children": "children",
"class": "class",
"className": "className",
"close_modal": [Function],
"close_title": "close_title",
"content_id": "content_id",
"hide_close_button": "hide_close_button",
Expand All @@ -279,6 +290,8 @@ exports[`Modal component have to match snapshot 1`] = `
"on_close": [Function],
"on_close_prevent": [Function],
"on_open": [Function],
"open_modal": [Function],
"open_state": "'opened'",
"preventSetTriggerRef": true,
"prevent_close": "prevent_close",
"title": "title",
Expand Down Expand Up @@ -329,6 +342,7 @@ exports[`Modal component have to match snapshot 1`] = `
class={null}
className={null}
closeModal={[Function]}
close_modal={null}
close_title="close_title"
content_id="modal_content_id"
hide_close_button={false}
Expand All @@ -337,6 +351,7 @@ exports[`Modal component have to match snapshot 1`] = `
on_close={null}
on_close_prevent={null}
on_open={null}
open_modal={null}
prevent_close={false}
title="modal_title"
toggleOpenClose={[Function]}
Expand Down
3 changes: 3 additions & 0 deletions packages/dnb-ui-lib/src/components/modal/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
| `close_title` | _(optional)_ the title of the close button. Defaults to _Close Modal Window_ |
| `hide_close_button` | _(optional)_ if set to true, the close button will now be shown |
| `prevent_close` | _(optional)_ if set to `true` (boolean or string), then the user can't close the modal. |
| `open_state` | _(optional)_ use this prop to control the open/close state by setting either: `opened` or `closed` |
| `open_modal` | _(optional)_ set a function to call the callback function, once the modal should open: `open_modal={(open) => open()}` |
| `close_modal` | _(optional)_ set a function to call the callback function, once the modal should close: `close_modal={(close) => close()}` |

| Events | Description |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
Expand Down
64 changes: 59 additions & 5 deletions packages/dnb-ui-lib/stories/componentsStories.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,40 @@ stories.push([
)
])

stories.push([
'Modal',
() => (
<Wrapper>
<Modal trigger_text="Open Modal" title="Modal Title">
class ModalCloseExample extends React.PureComponent {
state = {
open_state: null
}

// constructor(props) {
// super(props)
//
// setTimeout(() => {
// this.setState({
// open_state: 'opened'
// })
// setTimeout(() => {
// this.setState({
// open_state: 'closed'
// })
// }, 3e3)
// }, 1e3)
// }

render() {
return (
<Modal
trigger_text="Open Modal and auto close"
title="Modal Title"
// open_state={this.state.open_state}
// open_modal={open => {
// setTimeout(open, 3e3)
// }}
close_modal={close => {
console.log('Modal was opened')
setTimeout(close, 3e3)
}}
>
<Hr />
<Box>
<H2>Some content</H2>
Expand All @@ -271,6 +300,31 @@ stories.push([
</P>
</Box>
</Modal>
)
}
}

stories.push([
'Modal',
() => (
<Wrapper>
<Box>
<Modal trigger_text="Open Modal" title="Modal Title">
<Hr />
<Box>
<H2>Some content</H2>
<Input>Focus me with Tab key</Input>
</Box>
<Box>
<P>
<Switch label="Checked:" checked />
</P>
</Box>
</Modal>
</Box>
<Box>
<ModalCloseExample />
</Box>
</Wrapper>
)
])
Expand Down

0 comments on commit 8d4b93f

Please sign in to comment.