Skip to content

Commit 1c47dae

Browse files
committed
feat(Button): add "animated" and "or"
1 parent 1750249 commit 1c47dae

File tree

13 files changed

+190
-36
lines changed

13 files changed

+190
-36
lines changed

docs/app/Examples/elements/Button/Content/ButtonConditionalsExample.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Button } from 'stardust'
44
const ButtonConditionalsExample = () => (
55
<Button.Group>
66
<Button>Cancel</Button>
7-
<div className='or' />
7+
<Button.Or />
88
<Button positive>Save</Button>
99
</Button.Group>
1010
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react'
2+
import { Button } from 'stardust'
3+
4+
const ButtonMultipleConditionalsExample = () => (
5+
<Button.Group>
6+
<Button>One</Button>
7+
<Button.Or />
8+
<Button>Two</Button>
9+
<Button.Or />
10+
<Button>Three</Button>
11+
</Button.Group>
12+
)
13+
14+
export default ButtonMultipleConditionalsExample

docs/app/Examples/elements/Button/Content/index.js

+4-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import React from 'react'
22
import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
33
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'
4-
import { Message } from 'stardust'
54

65
const ButtonContentExamples = () => (
76
<ExampleSection title='Content'>
87
<ComponentExample
98
title='Conditionals'
109
description='Button groups can contain conditionals'
1110
examplePath='elements/Button/Content/ButtonConditionalsExample'
12-
>
13-
<Message warning>
14-
Or buttons can have their text localized, or adjusted by using the data-text attribute.
15-
If the size of the conditional changes you will need to adjust @orCircleSize.
16-
</Message>
17-
</ComponentExample>
11+
/>
12+
<ComponentExample
13+
examplePath='elements/Button/Content/ButtonMultipleConditionalsExample'
14+
/>
1815
</ExampleSection>
1916
)
2017

docs/app/Examples/elements/Button/GroupVariations/ButtonGroupOrSizeExample.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Button } from 'stardust'
44
const ButtonGroupOrSizeExample = () => (
55
<Button.Group size='large'>
66
<Button>One</Button>
7-
<div className='or' />
7+
<Button.Or />
88
<Button>Three</Button>
99
</Button.Group>
1010
)

docs/app/Examples/elements/Button/Types/ButtonAnimatedExample.js

+24-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,30 @@ import React from 'react'
22
import { Button, Icon } from 'stardust'
33

44
const ButtonAnimatedExample = () => (
5-
<Button animated>
6-
<div className='visible content'>Next</div>
7-
<div className='hidden content'>
8-
<Icon name='right arrow' />
9-
</div>
10-
</Button>
5+
<div>
6+
<Button animated>
7+
<Button.Content visible>Next</Button.Content>
8+
<Button.Content hidden>
9+
<Icon name='right arrow' />
10+
</Button.Content>
11+
</Button>
12+
13+
<Button animated='vertical'>
14+
<Button.Content hidden>Shop</Button.Content>
15+
<Button.Content visible>
16+
<Icon name='shop' />
17+
</Button.Content>
18+
</Button>
19+
20+
<Button animated='fade'>
21+
<Button.Content visible>
22+
Sign-up for a Pro account
23+
</Button.Content>
24+
<Button.Content hidden>
25+
$12.99 a month
26+
</Button.Content>
27+
</Button>
28+
</div>
1129
)
1230

1331
export default ButtonAnimatedExample

docs/app/Examples/elements/Button/Variations/ButtonCircularExample.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react'
22
import { Button } from 'stardust'
33

44
const ButtonCircularExample = () => (
5-
<Button circular color='settings' icon='settings' />
5+
<Button circular icon='settings' />
66
)
77

88
export default ButtonCircularExample

docs/app/Examples/elements/Button/Variations/ButtonSocialExample.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
import React from 'react'
2-
import { Button } from 'stardust'
2+
import { Button, Icon } from 'stardust'
33

44
const ButtonSocialExample = () => (
55
<div>
6-
<Button color='facebook' icon='facebook'>
7-
Facebook
6+
<Button color='facebook'>
7+
<Icon name='facebook' /> Facebook
88
</Button>
9-
<Button color='twitter' icon='twitter'>
10-
Twitter
9+
<Button color='twitter'>
10+
<Icon name='twitter' /> Twitter
1111
</Button>
12-
<Button color='google plus' icon='google plus'>
13-
Google Plus
12+
<Button color='google plus'>
13+
<Icon name='google plus' /> Google Plus
1414
</Button>
15-
<Button color='vk' icon='vk'>
16-
VK
15+
<Button color='vk'>
16+
<Icon name='vk' /> VK
1717
</Button>
18-
<Button color='linkedin' icon='linkedin'>
19-
LinkedIn
18+
<Button color='linkedin'>
19+
<Icon name='linkedin' /> LinkedIn
2020
</Button>
21-
<Button color='instagram' icon='instagram'>
22-
Instagram
21+
<Button color='instagram'>
22+
<Icon name='instagram' /> Instagram
2323
</Button>
24-
<Button color='youtube' icon='youtube'>
25-
YouTube
24+
<Button color='youtube'>
25+
<Icon name='youtube' /> YouTube
2626
</Button>
2727
</div>
2828
)

src/elements/Button/Button.js

+17-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import {
1313
useValueAndKey,
1414
} from '../../lib'
1515
import { createIcon, createLabel } from '../../factories'
16+
import ButtonContent from './ButtonContent'
1617
import ButtonGroup from './ButtonGroup'
18+
import ButtonOr from './ButtonOr'
1719

1820
const debug = makeDebugger('button')
1921

@@ -37,7 +39,7 @@ function Button(props) {
3739
color,
3840
size,
3941
useKeyOnly(active, 'active'),
40-
useKeyOnly(animated, 'animated'),
42+
useKeyOrValueAndKey(animated, 'animated'),
4143
useKeyOrValueAndKey(attached, 'attached'),
4244
useKeyOnly(basic, 'basic'),
4345
useKeyOnly(circular, 'circular'),
@@ -110,12 +112,15 @@ function Button(props) {
110112
)
111113
}
112114

115+
Button.Content = ButtonContent
113116
Button.Group = ButtonGroup
117+
Button.Or = ButtonOr
114118

115119
Button._meta = {
116120
name: 'Button',
117121
type: META.TYPES.ELEMENT,
118122
props: {
123+
animated: ['fade', 'vertical'],
119124
attached: ['left', 'right', 'top', 'bottom'],
120125
color: [
121126
...SUI.COLORS,
@@ -144,7 +149,10 @@ Button.propTypes = {
144149
active: PropTypes.bool,
145150

146151
/** A button can animate to show hidden content */
147-
animated: PropTypes.bool,
152+
animated: PropTypes.oneOfType([
153+
PropTypes.bool,
154+
PropTypes.oneOf(Button._meta.props.animated),
155+
]),
148156

149157
/** A button can be attached to the top or bottom of other content */
150158
attached: PropTypes.oneOf(Button._meta.props.attached),
@@ -157,7 +165,13 @@ Button.propTypes = {
157165
PropTypes.node,
158166
customPropTypes.disallow(['label']),
159167
customPropTypes.givenProps(
160-
{ icon: PropTypes.bool.isRequired },
168+
{
169+
icon: PropTypes.oneOfType([
170+
PropTypes.string.isRequired,
171+
PropTypes.object.isRequired,
172+
PropTypes.element.isRequired,
173+
]),
174+
},
161175
customPropTypes.disallow(['icon']),
162176
),
163177
]),

src/elements/Button/ButtonContent.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import cx from 'classnames'
2+
import React, { PropTypes } from 'react'
3+
4+
import {
5+
getElementType,
6+
getUnhandledProps,
7+
META,
8+
useKeyOnly,
9+
} from '../../lib'
10+
11+
/**
12+
* Used in some Button types, such as `animated`
13+
*/
14+
function ButtonContent(props) {
15+
const { children, className, hidden, visible } = props
16+
const classes = cx(
17+
useKeyOnly(visible, 'visible'),
18+
useKeyOnly(hidden, 'hidden'),
19+
'content',
20+
className,
21+
)
22+
23+
const rest = getUnhandledProps(ButtonContent, props)
24+
const ElementType = getElementType(ButtonContent, props)
25+
26+
return (
27+
<ElementType className={classes} {...rest}>
28+
{children}
29+
</ElementType>
30+
)
31+
}
32+
33+
ButtonContent._meta = {
34+
name: 'ButtonContent',
35+
parent: 'Button',
36+
type: META.TYPES.ELEMENT,
37+
}
38+
39+
ButtonContent.propTypes = {
40+
/** An element type to render as (string or function). */
41+
as: PropTypes.oneOfType([
42+
PropTypes.string,
43+
PropTypes.func,
44+
]),
45+
46+
/** Initially visible, hidden on hover */
47+
visible: PropTypes.bool,
48+
49+
/** Initially hidden, visible on hover */
50+
hidden: PropTypes.bool,
51+
52+
/** Additional classes */
53+
className: PropTypes.string,
54+
55+
/** Primary content, intended to the Button children */
56+
children: PropTypes.any,
57+
}
58+
59+
export default ButtonContent

src/elements/Button/ButtonOr.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import cx from 'classnames'
2+
import React, { PropTypes } from 'react'
3+
4+
import { getElementType, getUnhandledProps, META } from '../../lib'
5+
6+
/**
7+
* Used in some Button types, such as `animated`
8+
*/
9+
function ButtonOr(props) {
10+
const { className } = props
11+
const classes = cx('or', className)
12+
const rest = getUnhandledProps(ButtonOr, props)
13+
const ElementType = getElementType(ButtonOr, props)
14+
15+
return <ElementType className={classes} {...rest} />
16+
}
17+
18+
ButtonOr._meta = {
19+
name: 'ButtonOr',
20+
parent: 'Button',
21+
type: META.TYPES.ELEMENT,
22+
}
23+
24+
ButtonOr.propTypes = {
25+
/** An element type to render as (string or function). */
26+
as: PropTypes.oneOfType([
27+
PropTypes.string,
28+
PropTypes.func,
29+
]),
30+
31+
/** Additional classes */
32+
className: PropTypes.string,
33+
}
34+
35+
export default ButtonOr

test/specs/elements/Button/Button-test.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import React from 'react'
22

33
import Button from 'src/elements/Button/Button'
4+
import ButtonContent from 'src/elements/Button/ButtonContent'
45
import ButtonGroup from 'src/elements/Button/ButtonGroup'
6+
import ButtonOr from 'src/elements/Button/ButtonOr'
57
import * as common from 'test/specs/commonTests'
68
import { sandbox } from 'test/utils'
79

810
describe('Button', () => {
911
common.isConformant(Button)
1012
common.hasUIClassName(Button)
11-
common.hasSubComponents(Button, [ButtonGroup])
13+
common.hasSubComponents(Button, [ButtonContent, ButtonGroup, ButtonOr])
1214
common.implementsIconProp(Button)
1315
common.implementsLabelProp(Button)
1416

1517
common.propKeyOnlyToClassName(Button, 'active')
16-
common.propKeyOnlyToClassName(Button, 'animated')
18+
common.propKeyOrValueToClassName(Button, 'animated')
1719
common.propKeyOrValueToClassName(Button, 'attached')
1820
common.propKeyOnlyToClassName(Button, 'basic')
1921
common.propKeyOnlyToClassName(Button, 'circular')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import ButtonContent from 'src/elements/Button/ButtonContent'
2+
import * as common from 'test/specs/commonTests'
3+
4+
describe('ButtonContent', () => {
5+
common.isConformant(ButtonContent)
6+
common.propKeyOnlyToClassName(ButtonContent, 'hidden')
7+
common.propKeyOnlyToClassName(ButtonContent, 'visible')
8+
common.rendersChildren(ButtonContent)
9+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import ButtonOr from 'src/elements/Button/ButtonOr'
2+
import * as common from 'test/specs/commonTests'
3+
4+
describe('ButtonOr', () => {
5+
common.isConformant(ButtonOr)
6+
})

0 commit comments

Comments
 (0)