Skip to content

Commit

Permalink
now EuiBadge renders anchor tags too (#3009)
Browse files Browse the repository at this point in the history
* fixed errors

* updated changelog

* Update CHANGELOG.md

* added preview in docs-section

* Update CHANGELOG.md

* added example file

* Fixing anchor and disabled styles, updating example (#2)

Thanks @cchaos

* added tests

* Update CHANGELOG.md

Co-Authored-By: Caroline Horn <549577+cchaos@users.noreply.github.com>

Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com>
  • Loading branch information
anishagg17 and cchaos authored Mar 16, 2020
1 parent a8a4063 commit 8ea32fe
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## [`master`](https://github.com/elastic/eui/tree/master)

- Added `href` prop to `EuiBadge` ([#3009](https://github.com/elastic/eui/pull/3009))
- Added props descriptions for `EuiComboBox` ([#3007](https://github.com/elastic/eui/pull/3007))
- Exported `dateFormatAliases` as a part of the public API ([#3043](https://github.com/elastic/eui/pull/3043))
- Exported `EuiTextProps` type definition ([#3039](https://github.com/elastic/eui/pull/3039))
Expand Down
12 changes: 12 additions & 0 deletions src-docs/src/views/badge/badge_button.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,17 @@ export default () => (
onClick on both text and icon within badge
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge
isDisabled={true}
color="danger"
onClick={() => window.alert('Badge clicked')}
onClickAriaLabel="Example of disabled button badge"
iconOnClick={() => window.alert('Disabled badge clicked')}
iconOnClickAriaLabel="Example of disabled button badge"
data-test-sub="testExample4">
disabled button badge
</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
);
28 changes: 28 additions & 0 deletions src-docs/src/views/badge/badge_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ const badgeButtonSnippet = [
</EuiBadge>`,
];

import BadgeHref from './badge_href';
const badgeHrefSource = require('!!raw-loader!./badge_href');
const badgeHrefHtml = renderToHtml(BadgeHref);
const badgeHrefSnippet = ['<EuiBadge href="#" />'];

import BadgeTruncate from './badge_truncate';
const badgeTruncateSource = require('!!raw-loader!./badge_truncate');
const badgeTruncateHtml = renderToHtml(BadgeTruncate);
Expand Down Expand Up @@ -177,6 +182,29 @@ export const BadgeExample = {
snippet: badgeButtonSnippet,
demo: <BadgeButton />,
},
{
title: 'Badge with href',
source: [
{
type: GuideSectionTypes.JS,
code: badgeHrefSource,
},
{
type: GuideSectionTypes.HTML,
code: badgeHrefHtml,
},
],
text: (
<div>
<p>
Badges can also be made to render anchor tags by passing an{' '}
<EuiCode>href</EuiCode>.
</p>
</div>
),
snippet: badgeHrefSnippet,
demo: <BadgeHref />,
},
{
title: 'Badge groups and truncation',
source: [
Expand Down
38 changes: 38 additions & 0 deletions src-docs/src/views/badge/badge_href.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import {
EuiBadge,
EuiFlexGroup,
EuiFlexItem,
} from '../../../../src/components';

export default () => (
<EuiFlexGroup wrap responsive={false} gutterSize="xs">
<EuiFlexItem grow={false}>
<EuiBadge color="#BADA55" href="/#/display/badge">
badge as an anchor
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge color="hollow" href="/#/display/badge" target="blank">
anchor with target specified
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge
color="accent"
href="/#/display/badge"
iconType="bolt"
iconSide="right"
iconOnClick={() => window.alert('Icon inside badge clicked')}
iconOnClickAriaLabel="Example of onClick event for icon within the anchor">
anchor with an icon and iconOnClick
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge color="secondary" href="/#/display/badge" isDisabled={true}>
disabled anchor badge
</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
);
50 changes: 45 additions & 5 deletions src/components/badge/__snapshots__/badge.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,46 @@ exports[`EuiBadge is rendered 1`] = `
</span>
`;

exports[`EuiBadge is rendered with href provided 1`] = `
<a
aria-label="aria-label"
class="euiBadge euiBadge-isClickable euiBadge--iconLeft testClass1 testClass2"
data-test-subj="test subject string"
href="/#/"
style="background-color:#d3dae6;color:#000"
>
<span
class="euiBadge__content"
>
<span
class="euiBadge__text"
>
Content
</span>
</span>
</a>
`;

exports[`EuiBadge is rendered with iconOnClick and href provided 1`] = `
<span
class="euiBadge euiBadge--iconLeft testClass1 testClass2"
style="background-color:#d3dae6;color:#000"
>
<span
class="euiBadge__content"
>
<a
aria-label="aria-label"
class="euiBadge__childButton"
data-test-subj="test subject string"
href="/#/"
>
Content
</a>
</span>
</span>
`;

exports[`EuiBadge is rendered with iconOnClick and onClick provided 1`] = `
<span
class="euiBadge euiBadge--iconLeft testClass1 testClass2"
Expand All @@ -59,19 +99,19 @@ exports[`EuiBadge is rendered with iconOnClick and onClick provided 1`] = `

exports[`EuiBadge is rendered with iconOnClick provided 1`] = `
<span
aria-label="aria-label"
class="euiBadge euiBadge--iconLeft testClass1 testClass2"
data-test-subj="test subject string"
style="background-color:#d3dae6;color:#000"
>
<span
class="euiBadge__content"
>
<span
class="euiBadge__text"
<button
aria-label="aria-label"
class="euiBadge__childButton"
data-test-subj="test subject string"
>
Content
</span>
</button>
</span>
</span>
`;
Expand Down
3 changes: 2 additions & 1 deletion src/components/badge/_badge.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
&.euiBadge-isDisabled {
// sass-lint:disable-block no-important
// Using !important to override inline styles
color: makeHighContrastColor($euiButtonColorDisabled, $euiButtonColorDisabled, 2) !important;
background-color: $euiButtonColorDisabled !important;
color: $euiButtonColorDisabledText !important;
}

&:focus-within {
Expand All @@ -46,6 +46,7 @@
text-align: inherit;
font-weight: inherit;
line-height: inherit;
color: inherit;

&:disabled {
cursor: not-allowed;
Expand Down
24 changes: 24 additions & 0 deletions src/components/badge/badge.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ describe('EuiBadge', () => {
expect(component).toMatchSnapshot();
});

test('is rendered with href provided', () => {
const component = render(
<EuiBadge {...requiredProps} href="/#/">
Content
</EuiBadge>
);

expect(component).toMatchSnapshot();
});

test('is rendered with iconOnClick provided', () => {
const component = render(
<EuiBadge
Expand Down Expand Up @@ -62,6 +72,20 @@ describe('EuiBadge', () => {
expect(component).toMatchSnapshot();
});

test('is rendered with iconOnClick and href provided', () => {
const component = render(
<EuiBadge
{...requiredProps}
iconOnClick={jest.fn()}
iconOnClickAriaLabel="Example of onclick event for icon within the anchor"
href="/#/">
Content
</EuiBadge>
);

expect(component).toMatchSnapshot();
});

describe('props', () => {
describe('iconType', () => {
it('is rendered', () => {
Expand Down
52 changes: 39 additions & 13 deletions src/components/badge/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, {
HTMLAttributes,
MouseEventHandler,
ReactNode,
Ref,
} from 'react';
import classNames from 'classnames';
import { CommonProps, ExclusiveUnion, keysOf, PropsOf } from '../common';
Expand All @@ -26,6 +27,11 @@ type WithButtonProps = {
onClickAriaLabel: AriaAttributes['aria-label'];
} & Omit<HTMLAttributes<HTMLButtonElement>, 'onClick' | 'color'>;

type WithAnchorProps = {
href: string;
target?: string;
} & Omit<HTMLAttributes<HTMLAnchorElement>, 'href' | 'color'>;

type WithSpanProps = Omit<HTMLAttributes<HTMLSpanElement>, 'onClick' | 'color'>;

interface WithIconOnClick {
Expand Down Expand Up @@ -66,7 +72,10 @@ export type EuiBadgeProps = {
closeButtonProps?: Partial<PropsOf<EuiIcon>>;
} & CommonProps &
ExclusiveUnion<WithIconOnClick, {}> &
ExclusiveUnion<WithSpanProps, WithButtonProps>;
ExclusiveUnion<
ExclusiveUnion<WithButtonProps, WithAnchorProps>,
WithSpanProps
>;

// TODO - replace with variables once https://github.com/elastic/eui/issues/2731 is closed
const colorInk = '#000';
Expand Down Expand Up @@ -108,6 +117,8 @@ export const EuiBadge: FunctionComponent<EuiBadgeProps> = ({
onClickAriaLabel,
iconOnClickAriaLabel,
closeButtonProps,
href,
target,
...rest
}) => {
checkValidColor(color);
Expand Down Expand Up @@ -160,7 +171,7 @@ export const EuiBadge: FunctionComponent<EuiBadgeProps> = ({
const classes = classNames(
'euiBadge',
{
'euiBadge-isClickable': onClick && !iconOnClick,
'euiBadge-isClickable': (onClick || href) && !iconOnClick,
'euiBadge-isDisabled': isDisabled,
'euiBadge--hollow': color === 'hollow',
},
Expand All @@ -172,6 +183,21 @@ export const EuiBadge: FunctionComponent<EuiBadgeProps> = ({
'euiBadge__icon',
closeButtonProps && closeButtonProps.className
);
const Element = href && !isDisabled ? 'a' : 'button';
const relObj: {
href?: string;
target?: string;
onClick?:
| ((event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void)
| ((event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void);
} = {};

if (href && !isDisabled) {
relObj.href = href;
relObj.target = target;
} else if (onClick) {
relObj.onClick = onClick;
}

let optionalIcon: ReactNode = null;
if (iconType) {
Expand Down Expand Up @@ -209,46 +235,46 @@ export const EuiBadge: FunctionComponent<EuiBadgeProps> = ({
);
}

if (onClick && iconOnClick) {
if (iconOnClick) {
return (
<span className={classes} style={optionalCustomStyles}>
<span className="euiBadge__content">
<EuiInnerText>
{(ref, innerText) => (
<button
<Element
className="euiBadge__childButton"
disabled={isDisabled}
aria-label={onClickAriaLabel}
onClick={onClick}
ref={ref}
title={innerText}
{...rest}>
{...relObj as HTMLAttributes<HTMLElement>}
{...rest as HTMLAttributes<HTMLElement>}>
{children}
</button>
</Element>
)}
</EuiInnerText>
{optionalIcon}
</span>
</span>
);
} else if (onClick) {
} else if (onClick || href) {
return (
<EuiInnerText>
{(ref, innerText) => (
<button
<Element
disabled={isDisabled}
aria-label={onClickAriaLabel}
className={classes}
onClick={onClick}
style={optionalCustomStyles}
ref={ref}
ref={ref as Ref<HTMLButtonElement & HTMLAnchorElement>}
title={innerText}
{...rest}>
{...relObj as HTMLAttributes<HTMLElement>}
{...rest as HTMLAttributes<HTMLElement>}>
<span className="euiBadge__content">
<span className="euiBadge__text">{children}</span>
{optionalIcon}
</span>
</button>
</Element>
)}
</EuiInnerText>
);
Expand Down

0 comments on commit 8ea32fe

Please sign in to comment.