Skip to content

Commit 9d68de8

Browse files
committed
Update Button component with iconBefore and iconAfter, clean up Icons component
1 parent f359dce commit 9d68de8

File tree

7 files changed

+71
-49
lines changed

7 files changed

+71
-49
lines changed

Diff for: client/common/Button.jsx

+26-4
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,10 @@ const StyledIconButton = styled.button`
150150
* A Button performs an primary action
151151
*/
152152
const Button = ({
153-
children, href, kind, 'aria-label': ariaLabel, to, type, ...props
153+
children, href, kind, iconBefore, iconAfter, 'aria-label': ariaLabel, to, type, ...props
154154
}) => {
155+
const hasChildren = React.Children.count(children) > 0;
156+
const content = <>{iconBefore}{hasChildren && <span>{children}</span>}{iconAfter}</>;
155157
let StyledComponent = StyledButton;
156158

157159
if (kind === kinds.inline) {
@@ -161,19 +163,31 @@ const Button = ({
161163
}
162164

163165
if (href) {
164-
return <StyledComponent kind={kind} as="a" aria-label={ariaLabel} href={href} {...props}>{children}</StyledComponent>;
166+
return (
167+
<StyledComponent
168+
kind={kind}
169+
as="a"
170+
aria-label={ariaLabel}
171+
href={href}
172+
{...props}
173+
>
174+
{content}
175+
</StyledComponent>
176+
);
165177
}
166178

167179
if (to) {
168-
return <StyledComponent kind={kind} as={Link} aria-label={ariaLabel} to={to} {...props}>{children}</StyledComponent>;
180+
return <StyledComponent kind={kind} as={Link} aria-label={ariaLabel} to={to} {...props}>{content}</StyledComponent>;
169181
}
170182

171-
return <StyledComponent kind={kind} aria-label={ariaLabel} type={type} {...props}>{children}</StyledComponent>;
183+
return <StyledComponent kind={kind} aria-label={ariaLabel} type={type} {...props}>{content}</StyledComponent>;
172184
};
173185

174186
Button.defaultProps = {
175187
'children': null,
176188
'disabled': false,
189+
'iconAfter': null,
190+
'iconBefore': null,
177191
'kind': kinds.block,
178192
'href': null,
179193
'aria-label': null,
@@ -193,6 +207,14 @@ Button.propTypes = {
193207
If the button can be activated or not
194208
*/
195209
'disabled': PropTypes.bool,
210+
/**
211+
* SVG icon to place after child content
212+
*/
213+
'iconAfter': PropTypes.element,
214+
/**
215+
* SVG icon to place before child content
216+
*/
217+
'iconBefore': PropTypes.element,
196218
/**
197219
* The kind of button - determines how it appears visually
198220
*/

Diff for: client/common/Button.stories.jsx

+19-15
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import { action } from '@storybook/addon-actions';
33
import { boolean, text } from '@storybook/addon-knobs';
44

55
import Button from './Button';
6-
import Icons from './Icons';
7-
8-
const { Github, DropdownArrow, Plus } = Icons;
6+
import { GithubIcon, DropdownArrowIcon, PlusIcon } from './Icons';
97

108
export default {
119
title: 'Common/Button',
@@ -39,28 +37,34 @@ export const ReactRouterLink = () => (
3937
);
4038

4139
export const ButtonWithIconBefore = () => (
42-
<Button>
43-
<Github aria-label="Github logo" />
44-
<span>Create</span>
40+
<Button
41+
iconBefore={<GithubIcon aria-label="Github logo" />}
42+
>
43+
Create
4544
</Button>
4645
);
4746

4847
export const ButtonWithIconAfter = () => (
49-
<Button>
50-
<span>Create</span>
51-
<Github aria-label="Github logo" />
48+
<Button
49+
iconAfter={<GithubIcon aria-label="Github logo" />}
50+
>
51+
Create
5252
</Button>
5353
);
5454

5555
export const InlineButtonWithIconAfter = () => (
56-
<Button kind={Button.kinds.inline}>
57-
<span>File name</span>
58-
<DropdownArrow />
56+
<Button
57+
iconAfter={<DropdownArrowIcon />}
58+
kind={Button.kinds.inline}
59+
>
60+
File name
5961
</Button>
6062
);
6163

6264
export const InlineIconOnlyButton = () => (
63-
<Button kind={Button.kinds.inline} aria-label="Add to collection">
64-
<Plus />
65-
</Button>
65+
<Button
66+
aria-label="Add to collection"
67+
iconBefore={<PlusIcon />}
68+
kind={Button.kinds.inline}
69+
/>
6670
);

Diff for: client/common/Icons.jsx

+14-18
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,39 @@ import DropdownArrow from '../images/down-filled-triangle.svg';
1313

1414
// could also give these a default size, color, etc. based on the theme
1515
// Need to add size to these - like small icon, medium icon, large icon. etc.
16-
function withLabel(Icon) {
17-
const render = (props) => {
16+
function withLabel(SvgComponent) {
17+
const Icon = (props) => {
1818
const { 'aria-label': ariaLabel } = props;
1919
if (ariaLabel) {
20-
return (<Icon
20+
return (<SvgComponent
2121
{...props}
2222
aria-label={ariaLabel}
2323
role="img"
2424
focusable="false"
2525
/>);
2626
}
27-
return (<Icon
27+
return (<SvgComponent
2828
{...props}
2929
aria-hidden
3030
focusable="false"
3131
/>);
3232
};
3333

34-
render.propTypes = {
34+
Icon.propTypes = {
3535
'aria-label': PropTypes.string
3636
};
3737

38-
render.defaultProps = {
38+
Icon.defaultProps = {
3939
'aria-label': null
4040
};
4141

42-
return render;
42+
return Icon;
4343
}
4444

45-
const Icons = {
46-
SortArrowUp: withLabel(SortArrowUp),
47-
SortArrowDown: withLabel(SortArrowDown),
48-
Github: withLabel(Github),
49-
Google: withLabel(Google),
50-
Plus: withLabel(Plus),
51-
Close: withLabel(Close),
52-
DropdownArrow: withLabel(DropdownArrow)
53-
};
54-
55-
export default Icons;
45+
export const SortArrowUpIcon = withLabel(SortArrowUp);
46+
export const SortArrowDownIcon = withLabel(SortArrowDown);
47+
export const GithubIcon = withLabel(Github);
48+
export const GoogleIcon = withLabel(Google);
49+
export const PlusIcon = withLabel(Plus);
50+
export const CloseIcon = withLabel(Close);
51+
export const DropdownArrowIcon = withLabel(DropdownArrow);

Diff for: client/common/Icons.stories.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { select } from '@storybook/addon-knobs';
33

4-
import Icons from './Icons';
4+
import * as Icons from './Icons';
55

66
export default {
77
title: 'Common/Icons',

Diff for: client/modules/User/components/APIKeyForm.jsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33

44
import Button from '../../../common/Button';
5-
import Icons from '../../../common/Icons';
5+
import { PlusIcon } from '../../../common/Icons';
66
import CopyableInput from '../../IDE/components/CopyableInput';
77

88
import APIKeyList from './APIKeyList';
@@ -82,11 +82,11 @@ class APIKeyForm extends React.Component {
8282
/>
8383
<Button
8484
disabled={this.state.keyLabel === ''}
85-
type="submit"
85+
iconBefore={<PlusIcon />}
8686
label="Create new key"
87+
type="submit"
8788
>
88-
<Icons.Plus />
89-
<span>Create</span>
89+
Create
9090
</Button>
9191
</form>
9292

Diff for: client/modules/User/components/Collection.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { bindActionCreators } from 'redux';
88
import classNames from 'classnames';
99

1010
import Button from '../../../common/Button';
11-
import Icons from '../../../common/Icons';
11+
import { DropdownArrowIcon } from '../../../common/Icons';
1212
import * as ProjectActions from '../../IDE/actions/project';
1313
import * as ProjectsActions from '../../IDE/actions/projects';
1414
import * as CollectionsActions from '../../IDE/actions/collections';
@@ -54,9 +54,9 @@ const ShareURL = ({ value }) => {
5454
<div className="collection-share" ref={node}>
5555
<Button
5656
onClick={() => setShowURL(!showURL)}
57+
iconAfter={<DropdownArrowIcon />}
5758
>
5859
Share
59-
<Icons.DropdownArrow />
6060
</Button>
6161
{ showURL &&
6262
<div className="collection__share-dropdown">

Diff for: client/modules/User/components/SocialAuthButton.jsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import styled from 'styled-components';
44

55
import { remSize } from '../../../theme';
66

7-
import Icons from '../../../common/Icons';
7+
import { GithubIcon, GoogleIcon } from '../../../common/Icons';
88
import Button from '../../../common/Button';
99

1010
const authUrls = {
@@ -18,8 +18,8 @@ const labels = {
1818
};
1919

2020
const icons = {
21-
github: Icons.Github,
22-
google: Icons.Google
21+
github: GithubIcon,
22+
google: GoogleIcon
2323
};
2424

2525
const services = {
@@ -35,10 +35,10 @@ function SocialAuthButton({ service }) {
3535
const ServiceIcon = icons[service];
3636
return (
3737
<StyledButton
38+
iconBefore={<ServiceIcon aria-label={`${service} logo`} />}
3839
href={authUrls[service]}
3940
>
40-
<ServiceIcon aria-label={`${service} logo`} />
41-
<span>{labels[service]}</span>
41+
{labels[service]}
4242
</StyledButton>
4343
);
4444
}

0 commit comments

Comments
 (0)