Skip to content

Commit

Permalink
feat(Modal): Add closeIcon (#932)
Browse files Browse the repository at this point in the history
* feat(Modal): Add closeIcon

* Default closeIcon to `close` if closeIcon=true
  • Loading branch information
jeffcarbs authored and levithomason committed Nov 23, 2016
1 parent bd2e1da commit c222ba7
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import { Button, Modal } from 'semantic-ui-react'

class ModalCloseConfigExample extends Component {
class ModalExampleCloseConfig extends Component {
state = { open: false }

closeConfigShow = (closeOnEscape, closeOnRootNodeClick) => () => {
Expand Down Expand Up @@ -40,4 +40,4 @@ class ModalCloseConfigExample extends Component {
}
}

export default ModalCloseConfigExample
export default ModalExampleCloseConfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import { Button, Header, Icon, Modal } from 'semantic-ui-react'

const ModalExampleCloseIcon = () => (
<Modal trigger={<Button>Show Modal</Button>} closeIcon='close'>
<Header icon='archive' content='Archive Old Messages' />
<Modal.Content>
<p>Your inbox is getting full, would you like us to enable automatic archiving of old messages?</p>
</Modal.Content>
<Modal.Actions>
<Button color='red'>
<Icon name='remove' /> No
</Button>
<Button color='green'>
<Icon name='checkmark' /> Yes
</Button>
</Modal.Actions>
</Modal>
)

export default ModalExampleCloseIcon
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import { Popup, Button, Header, Image, Modal } from 'semantic-ui-react'

class ModalDimmerExample extends Component {
class ModalExampleDimmer extends Component {
state = { open: false }

show = (dimmer) => () => this.setState({ dimmer, open: true })
Expand Down Expand Up @@ -47,5 +47,5 @@ class ModalDimmerExample extends Component {
}
}

export default ModalDimmerExample
export default ModalExampleDimmer

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import { Button, Modal } from 'semantic-ui-react'

class ModalSizeExample extends Component {
class ModalExampleSize extends Component {
state = { open: false }

show = (size) => () => this.setState({ size, open: true })
Expand Down Expand Up @@ -35,4 +35,4 @@ class ModalSizeExample extends Component {
}
}

export default ModalSizeExample
export default ModalExampleSize
4 changes: 4 additions & 0 deletions docs/app/Examples/modules/Modal/Variations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const ModalExamples = () => (
description='Modal can config not to close by escape or dimmer click.'
examplePath='modules/Modal/Variations/ModalExampleCloseConfig'
/>
<ComponentExample
description='A Modal can have a close icon.'
examplePath='modules/Modal/Variations/ModalExampleCloseIcon'
/>
</ExampleSection>
)

Expand Down
32 changes: 30 additions & 2 deletions src/modules/Modal/Modal.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import _ from 'lodash'
import React, { PropTypes, Component } from 'react'
import React, { PropTypes } from 'react'
import cx from 'classnames'

import ModalHeader from './ModalHeader'
import ModalContent from './ModalContent'
import ModalActions from './ModalActions'
import ModalDescription from './ModalDescription'
import Icon from '../../elements/Icon'
import Portal from '../../addons/Portal'

import {
AutoControlledComponent as Component,
customPropTypes,
getElementType,
getUnhandledProps,
Expand Down Expand Up @@ -45,9 +47,19 @@ class Modal extends Component {
/** Additional classes. */
className: PropTypes.string,

/** Icon */
closeIcon: PropTypes.oneOfType([
PropTypes.node,
PropTypes.object,
PropTypes.bool,
]),

/** A modal can reduce its complexity */
basic: PropTypes.bool,

/** Initial value of open. */
defaultOpen: PropTypes.bool,

/** A modal can appear in a dimmer */
dimmer: PropTypes.oneOfType([
PropTypes.bool,
Expand Down Expand Up @@ -87,6 +99,10 @@ class Modal extends Component {
mountNode: isBrowser ? document.body : null,
}

static autoControlledProps = [
'open',
]

static _meta = _meta
static Header = ModalHeader
static Content = ModalContent
Expand All @@ -101,13 +117,21 @@ class Modal extends Component {
}

handleClose = (e) => {
debug('close()')

const { onClose } = this.props
if (onClose) onClose(e, this.props)

this.trySetState({ open: false })
}

handleOpen = (e) => {
debug('open()')

const { onOpen } = this.props
if (onOpen) onOpen(e, this.props)

this.trySetState({ open: true })
}

handlePortalMount = (e) => {
Expand Down Expand Up @@ -172,7 +196,8 @@ class Modal extends Component {
}

render() {
const { basic, children, className, dimmer, mountNode, open, size } = this.props
const { open } = this.state
const { basic, children, className, closeIcon, dimmer, mountNode, size } = this.props

// Short circuit when server side rendering
if (!isBrowser) return null
Expand All @@ -193,8 +218,11 @@ class Modal extends Component {
const portalProps = _.pick(unhandled, portalPropNames)
const ElementType = getElementType(Modal, this.props)

const closeIconName = closeIcon === true ? 'close' : closeIcon

const modalJSX = (
<ElementType {...rest} className={classes} style={{ marginTop }} ref={c => (this._modalNode = c)}>
{Icon.create(closeIconName, { onClick: this.handleClose })}
{children}
</ElementType>
)
Expand Down
25 changes: 25 additions & 0 deletions test/specs/modules/Modal/Modal-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,31 @@ describe('Modal', () => {
})
})

describe('closeIcon', () => {
it('is not present by default', () => {
wrapperMount(<Modal open>foo</Modal>)
assertBodyContains('.ui.modal .icon', false)
})

it('defaults to `close` when boolean', () => {
wrapperMount(<Modal open closeIcon>foo</Modal>)
assertBodyContains('.ui.modal .icon.close')
})

it('is present when passed', () => {
wrapperMount(<Modal open closeIcon='bullseye'>foo</Modal>)
assertBodyContains('.ui.modal .icon.bullseye')
})

it('triggers onClose when clicked', () => {
const spy = sandbox.spy()

wrapperMount(<Modal onClose={spy} open closeIcon='bullseye'>foo</Modal>)
domEvent.click('.ui.modal .icon.bullseye')
spy.should.have.been.calledOnce()
})
})

describe('scrolling', () => {
afterEach(() => {
document.body.classList.remove('scrolling')
Expand Down

0 comments on commit c222ba7

Please sign in to comment.