Skip to content

Commit

Permalink
feat(Popup): add eventsEnabled prop (#3715)
Browse files Browse the repository at this point in the history
* feat(Popup): add `eventsEnabled` prop

* fix UT

* fix styles on Knobs
  • Loading branch information
layershifter authored Jul 24, 2019
1 parent 048bd35 commit c86e198
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { KnobProvider } from '@stardust-ui/docs-components'
import cx from 'classnames'
import copyToClipboard from 'copy-to-clipboard'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import VisibilitySensor from 'react-visibility-sensor'
import { Grid } from 'semantic-ui-react'
import { Checkbox, Grid, Label } from 'semantic-ui-react'

import { examplePathToHash, scrollToAnchor } from 'docs/src/utils'
import CarbonAdNative from 'docs/src/components/CarbonAd/CarbonAdNative'
import formatCode from 'docs/src/utils/formatCode'
import ComponentControls from '../ComponentControls'
import ExampleEditor from '../ExampleEditor'
import ComponentDocContext from '../ComponentDocContext'
import ComponentExampleKnobs from './ComponentExampleKnobs'
import ComponentExampleTitle from './ComponentExampleTitle'

const childrenStyle = {
Expand All @@ -23,6 +25,29 @@ const componentControlsStyle = {
width: 'auto',
}

/* eslint-disable react/prop-types */
const knobComponents = {
KnobControl: (props) => (
<div style={{ display: 'flex', alignItems: 'center', flexGrow: 1, marginLeft: 5 }}>
{props.children}
</div>
),
KnobBoolean: (props) => (
<Checkbox
checked={props.value}
onChange={(e, data) => props.setValue(data.checked)}
type='checkbox'
value={props.value}
/>
),
KnobLabel: (props) => (
<Label size='small' style={{ fontFamily: 'monospace' }}>
{props.name}
</Label>
),
}
/* eslint-enable react/prop-types */

/**
* Renders a `component` and the raw `code` that produced it.
* Allows toggling the the raw `code` code block.
Expand Down Expand Up @@ -78,9 +103,7 @@ class ComponentExample extends Component {
if (wasCodeChanged) {
/* eslint-disable-next-line no-console */
console.warn(
`[HMR] the code of example (${
props.examplePath
}) was not reload because it was modified, please reset your changes.`,
`[HMR] the code of example (${props.examplePath}) was not reload because it was modified, please reset your changes.`,
)
} else {
derivedState.originalSourceCode = props.sourceCode
Expand Down Expand Up @@ -173,27 +196,31 @@ class ComponentExample extends Component {
/>
</Grid.Column>
</Grid.Row>
<KnobProvider components={knobComponents}>
<ComponentExampleKnobs />

{children && (
<Grid.Row columns={1} style={childrenStyle}>
<Grid.Column>{children}</Grid.Column>
{children && (
<Grid.Row columns={1} style={childrenStyle}>
<Grid.Column>{children}</Grid.Column>
</Grid.Row>
)}

<Grid.Row style={{ paddingBottom: wasEverVisible && 0 }}>
<ExampleEditor
examplePath={examplePath}
hasCodeChanged={originalSourceCode !== sourceCode}
onCodeChange={this.handleCodeChange}
onCodeFormat={this.handleCodeFormat}
onCodeReset={this.handleCodeReset}
renderHtml={renderHtml}
showCode={showCode}
sourceCode={sourceCode}
title={title}
visible={wasEverVisible}
/>
</Grid.Row>
)}

<Grid.Row style={{ paddingBottom: wasEverVisible && 0 }}>
<ExampleEditor
examplePath={examplePath}
hasCodeChanged={originalSourceCode !== sourceCode}
onCodeChange={this.handleCodeChange}
onCodeFormat={this.handleCodeFormat}
onCodeReset={this.handleCodeReset}
renderHtml={renderHtml}
showCode={showCode}
sourceCode={sourceCode}
title={title}
visible={wasEverVisible}
/>
</Grid.Row>
</KnobProvider>

{isActiveHash && <CarbonAdNative inverted={showCode} />}
</Grid>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CodeSnippet, KnobInspector, useKnobValues } from '@stardust-ui/docs-components'
import _ from 'lodash'
import React from 'react'
import { Grid } from 'semantic-ui-react'

const columnStyles = {
padding: 0,
}

const knobsStyles = {
background: 'whitesmoke',
color: '#777',
lineHeight: '1.5',
padding: '1rem',
}

const rowStyles = {
padding: 0,
}

const ComponentExampleKnobs = () => {
const knobValues = useKnobValues()
const values = _.fromPairs(knobValues.map((knob) => [knob.name, knob.value]))

return (
<KnobInspector>
{(knobs) =>
knobs && (
<Grid.Row columns={2} stretched style={rowStyles}>
<Grid.Column style={columnStyles}>
<div style={knobsStyles}> {knobs}</div>
</Grid.Column>
<Grid.Column style={columnStyles}>
<CodeSnippet copyable={false} fitted label='Knobs' mode='json' value={values} />
</Grid.Column>
</Grid.Row>
)
}
</KnobInspector>
)
}

export default ComponentExampleKnobs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as docsComponents from '@stardust-ui/docs-components'
import faker from 'faker'
import React from 'react'
import PropTypes from 'prop-types'
Expand All @@ -16,6 +17,7 @@ export const babelConfig = {
}

export const externals = {
'@stardust-ui/docs-components': docsComponents,
faker,
lodash: require('lodash'),
react: React,
Expand Down
5 changes: 3 additions & 2 deletions docs/src/components/ExternalExampleLayout.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { KnobProvider } from '@stardust-ui/docs-components'
import PropTypes from 'prop-types'
import { createElement } from 'react'
import React, { createElement } from 'react'
import { withRouteData } from 'react-static'

const ExternalExampleLayout = (props) => {
const exampleComponent = require(`docs/src/examples/${props.path}`).default

return createElement(exampleComponent)
return <KnobProvider>{createElement(exampleComponent)}</KnobProvider>
}

ExternalExampleLayout.propTypes = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const PopupExampleActions = () => (
</Grid.Column>
<Grid.Column>
<Popup
trigger={<Button icon>Click me or Hover me</Button>}
trigger={<Button>Click me or Hover me</Button>}
header='Movie Search'
content='Multiple events can trigger a popup'
on={['hover', 'click']}
Expand Down
25 changes: 25 additions & 0 deletions docs/src/examples/modules/Popup/Usage/PopupExampleEventsEnabled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useBooleanKnob } from '@stardust-ui/docs-components'
import React from 'react'
import { Button, Popup } from 'semantic-ui-react'

const PopupExampleEventsEnabled = () => {
const [eventsEnabled] = useBooleanKnob({
name: 'eventsEnabled',
initialValue: true,
})
const [open, setOpen] = useBooleanKnob({ name: 'open' })

return (
<Popup
content='Hello'
eventsEnabled={eventsEnabled}
on='click'
onClose={() => setOpen(false)}
onOpen={() => setOpen(true)}
open={open}
trigger={<Button content='A trigger' />}
/>
)
}

export default PopupExampleEventsEnabled
47 changes: 28 additions & 19 deletions docs/src/examples/modules/Popup/Usage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,34 @@ const PopupUsageExamples = () => (
target='_blank'
/>
</ComponentExample>
<ComponentExample
title={<code>eventsEnabled</code>}
description={
<span>
Enables the <code>Popper.js</code> event listeners.
</span>
}
examplePath='modules/Popup/Usage/PopupExampleEventsEnabled'
/>
<ComponentExample
title='Popper Dependencies'
description={
<span>
A popup can have dependencies which update will schedule a position
update. Should be used in cases when content is changing, behaves like{' '}
<a
href='https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect'
rel='noopener noreferrer'
target='_blank'
>
<code>dependencies</code>
</a>{' '}
in React Hooks.
</span>
}
examplePath='modules/Popup/Usage/PopupExamplePopperDependencies'
renderHtml={false}
/>
<ComponentExample
title='Actions'
description='A popup can be triggered on hover, click, focus or multiple actions.'
Expand Down Expand Up @@ -79,25 +107,6 @@ const PopupUsageExamples = () => (
examplePath='modules/Popup/Usage/PopupExampleDefaultOpen'
renderHtml={false}
/>
<ComponentExample
title='Popper Dependencies'
description={
<span>
A popup can have dependencies which update will schedule a position
update. Should be used in cases when content is changing, behaves like{' '}
<a
href='https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect'
rel='noopener noreferrer'
target='_blank'
>
<code>dependencies</code>
</a>{' '}
in React Hooks.
</span>
}
examplePath='modules/Popup/Usage/PopupExamplePopperDependencies'
renderHtml={false}
/>
</ExampleSection>
)

Expand Down
3 changes: 3 additions & 0 deletions src/modules/Popup/Popup.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export interface StrictPopupProps extends StrictPortalProps {
/** A disabled popup only renders its trigger. */
disabled?: boolean

/** Enables the Popper.js event listeners. */
eventsEnabled?: boolean

/** A flowing Popup has no maximum width and continues to flow to fit its content. */
flowing?: boolean

Expand Down
16 changes: 15 additions & 1 deletion src/modules/Popup/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ export default class Popup extends Component {
/** A disabled popup only renders its trigger. */
disabled: PropTypes.bool,

/** Enables the Popper.js event listeners. */
eventsEnabled: PropTypes.bool,

/** A flowing Popup has no maximum width and continues to flow to fit its content. */
flowing: PropTypes.bool,

Expand Down Expand Up @@ -145,6 +148,7 @@ export default class Popup extends Component {

static defaultProps = {
disabled: false,
eventsEnabled: true,
offset: 0,
on: 'hover',
pinned: false,
Expand Down Expand Up @@ -319,7 +323,16 @@ export default class Popup extends Component {
}

render() {
const { context, disabled, offset, pinned, popperModifiers, position, trigger } = this.props
const {
context,
disabled,
eventsEnabled,
offset,
pinned,
popperModifiers,
position,
trigger,
} = this.props
const { closed, portalRestProps } = this.state

if (closed || disabled) return trigger
Expand Down Expand Up @@ -351,6 +364,7 @@ export default class Popup extends Component {
triggerRef={this.triggerRef}
>
<Popper
eventsEnabled={eventsEnabled}
modifiers={modifiers}
placement={positionsMapping[position]}
referenceElement={referenceElement}
Expand Down
14 changes: 14 additions & 0 deletions test/specs/modules/Popup/Popup-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,20 @@ describe('Popup', () => {
})
})

describe('eventsEnabled ', () => {
it(`is "true" by default`, () => {
wrapperMount(<Popup open />)

wrapper.should.have.prop('eventsEnabled', true)
wrapper.find('Popper').should.have.prop('eventsEnabled', true)
})

it(`can be set to "false"`, () => {
wrapperMount(<Popup eventsEnabled={false} open />)
wrapper.find('Popper').should.have.prop('eventsEnabled', false)
})
})

describe('flowing', () => {
it('adds flowing to the popup className', () => {
wrapperMount(<Popup flowing open />)
Expand Down

0 comments on commit c86e198

Please sign in to comment.