Skip to content

Commit

Permalink
EuiButton, EuiButtonEmpty and EuiButtonIcon can now take an HREF (#316)
Browse files Browse the repository at this point in the history
Buttons now switch to anchor tags if an href is present.
  • Loading branch information
snide authored Jan 18, 2018
1 parent b59cf36 commit 687cfab
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 35 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# [`master`](https://github.com/elastic/eui/tree/master)

No public interface changes since `0.0.13`.
- EuiButton, EuiButtonEmpty and EuiButtonIcon can now take an `href` [(#316)](https://github.com/elastic/eui/pull/316)

**Bug fixes**

- Set `EuiFlexGroup` to `flex-grow: 1` to be more friendly with IE11 [(#315)](https://github.com/elastic/eui/pull/315)

# [`0.0.13`](https://github.com/elastic/eui/tree/v0.0.13)

Expand Down
28 changes: 28 additions & 0 deletions src-docs/src/views/button/button_as_link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

import {
EuiButton,
EuiButtonEmpty,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
} from '../../../../src/components';

export default () => (
<EuiFlexGroup gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton href="http://www.elastic.co">
Link to elastic.co
</EuiButton>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiButtonEmpty href="http://www.elastic.co">
Link to elastic.co
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonIcon href="http://www.elastic.co" iconType="link" aria-label="This is a link" />
</EuiFlexItem>
</EuiFlexGroup>
);
20 changes: 20 additions & 0 deletions src-docs/src/views/button/button_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ import ButtonGhost from './button_ghost';
const buttonGhostSource = require('!!raw-loader!./button_ghost');
const buttonGhostHtml = renderToHtml(ButtonGhost);

import ButtonAsLink from './button_as_link';
const buttonAsLinkSource = require('!!raw-loader!./button_as_link');
const buttonAsLinkHtml = renderToHtml(ButtonAsLink);

export const ButtonExample = {
title: 'Button',
sections: [{
Expand All @@ -52,6 +56,22 @@ export const ButtonExample = {
</p>
),
demo: <Button />,
}, {
title: 'Buttons can also be links',
source: [{
type: GuideSectionTypes.JS,
code: buttonAsLinkSource,
}, {
type: GuideSectionTypes.HTML,
code: buttonAsLinkHtml,
}],
text: (
<p>
Buttons will use an <EuiCode>{'<a>'}</EuiCode> tag
if there is a <EuiCode>href</EuiCode> prop present.
</p>
),
demo: <ButtonAsLink />,
}, {
title: 'Button with Icon',
source: [{
Expand Down
47 changes: 34 additions & 13 deletions src/components/button/button.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';

import classNames from 'classnames';

import checkHrefAndOnClick from '../../services/prop_types/check_href_and_onclick';

import {
ICON_TYPES,
EuiIcon,
Expand Down Expand Up @@ -41,6 +42,8 @@ export const EuiButton = ({
size,
fill,
isDisabled,
href,
onClick,
...rest
}) => {

Expand Down Expand Up @@ -69,18 +72,34 @@ export const EuiButton = ({
);
}

return (
<button
disabled={isDisabled}
className={classes}
{...rest}
>
<span className="euiButton__content">
{buttonIcon}
<span>{children}</span>
</span>
</button>
);
if (href) {
return (
<a
className={classes}
href={href}
{...rest}
>
<span className="euiButton__content">
{buttonIcon}
<span>{children}</span>
</span>
</a>
);
} else {
return (
<button
disabled={isDisabled}
className={classes}
onClick={onClick}
{...rest}
>
<span className="euiButton__content">
{buttonIcon}
<span>{children}</span>
</span>
</button>
);
}
};

EuiButton.propTypes = {
Expand All @@ -92,6 +111,8 @@ EuiButton.propTypes = {
color: PropTypes.oneOf(COLORS),
size: PropTypes.oneOf(SIZES),
isDisabled: PropTypes.bool,
href: checkHrefAndOnClick,
onClick: PropTypes.func,
};

EuiButton.defaultProps = {
Expand Down
46 changes: 34 additions & 12 deletions src/components/button/button_empty/button_empty.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import checkHrefAndOnClick from '../../../services/prop_types/check_href_and_onclick';

import {
ICON_TYPES,
EuiIcon,
Expand Down Expand Up @@ -48,6 +50,8 @@ export const EuiButtonEmpty = ({
size,
flush,
isDisabled,
href,
onClick,
...rest
}) => {

Expand All @@ -74,18 +78,34 @@ export const EuiButtonEmpty = ({
);
}

return (
<button
disabled={isDisabled}
className={classes}
{...rest}
>
<span className="euiButtonEmpty__content">
{buttonIcon}
<span>{children}</span>
</span>
</button>
);
if (href) {
return (
<a
className={classes}
href={href}
{...rest}
>
<span className="euiButtonEmpty__content">
{buttonIcon}
<span>{children}</span>
</span>
</a>
);
} else {
return (
<button
disabled={isDisabled}
className={classes}
onClick={onClick}
{...rest}
>
<span className="euiButtonEmpty__content">
{buttonIcon}
<span>{children}</span>
</span>
</button>
);
}
};

EuiButtonEmpty.propTypes = {
Expand All @@ -97,6 +117,8 @@ EuiButtonEmpty.propTypes = {
size: PropTypes.oneOf(SIZES),
flush: PropTypes.oneOf(FLUSH_TYPES),
isDisabled: PropTypes.bool,
href: checkHrefAndOnClick,
onClick: PropTypes.func,
};

EuiButtonEmpty.defaultProps = {
Expand Down
1 change: 1 addition & 0 deletions src/components/button/button_icon/_button_icon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
box-shadow: none;
height: $euiSizeL;
width: $euiSizeL;
line-height: $euiSizeL;
border-radius: $euiBorderRadius;

// Account for border.
Expand Down
37 changes: 28 additions & 9 deletions src/components/button/button_icon/button_icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import checkHrefAndOnClick from '../../../services/prop_types/check_href_and_onclick';

import {
ICON_TYPES,
EuiIcon,
Expand Down Expand Up @@ -37,6 +39,8 @@ export const EuiButtonIcon = ({
iconType,
color,
isDisabled,
href,
onClick,
...rest
}) => {

Expand All @@ -60,15 +64,28 @@ export const EuiButtonIcon = ({
);
}

return (
<button
disabled={isDisabled}
className={classes}
{...rest}
>
{buttonIcon}
</button>
);
if (href) {
return (
<a
className={classes}
href={href}
{...rest}
>
{buttonIcon}
</a>
);
} else {
return (
<button
disabled={isDisabled}
className={classes}
onClick={onClick}
{...rest}
>
{buttonIcon}
</button>
);
}
};

EuiButtonIcon.propTypes = {
Expand All @@ -78,6 +95,8 @@ EuiButtonIcon.propTypes = {
color: PropTypes.oneOf(COLORS),
isDisabled: PropTypes.bool,
'aria-label': accessibleButtonIcon,
href: checkHrefAndOnClick,
onClick: PropTypes.func,
};

EuiButtonIcon.defaultProps = {
Expand Down
8 changes: 8 additions & 0 deletions src/services/prop_types/check_href_and_onclick.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default function checkHrefAndOnClick(props, propName, componentName) {
if (props.href && props.onClick) {
throw new Error(
`${componentName} must either specify an href property (if it should be a link) ` +
`or an onClick property (if it should be a button), but not both.`
);
}
}

0 comments on commit 687cfab

Please sign in to comment.