Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

now EuiBadge render anchor tags too #3009

Merged
merged 11 commits into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)

- `EuiBadge` allows for `href` ([#3009](https://github.com/elastic/eui/pull/3009))
anishagg17 marked this conversation as resolved.
Show resolved Hide resolved
- 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>
);
30 changes: 30 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,16 @@ const badgeButtonSnippet = [
</EuiBadge>`,
];

import BadgeHref from './badge_href';
const badgeHrefSource = require('!!raw-loader!./badge_href');
const badgeHrefHtml = renderToHtml(BadgeHref);
const badgeHrefSnippet = [
`<EuiBadgeGroup gutterSize="s">
<EuiBadge href="https://elastic.github.io/" />
<EuiBadge href="https://elastic.github.io/" target="blank/>
</EuiBadgeGroup>`,
];

import BadgeTruncate from './badge_truncate';
const badgeTruncateSource = require('!!raw-loader!./badge_truncate');
const badgeTruncateHtml = renderToHtml(BadgeTruncate);
Expand Down Expand Up @@ -177,6 +187,26 @@ 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 have href attributes also the target attribute.</p>
</div>
),
snippet: badgeHrefSnippet,
demo: <BadgeHref />,
},
{
title: 'Badge groups and truncation',
source: [
Expand Down
56 changes: 56 additions & 0 deletions src-docs/src/views/badge/badge_href.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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"
onClickAriaLabel="Example of href badge"
data-test-sub="testExample3">
href on text within badge
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge
color="#0000FF"
href="/#/display/badge"
target="blank"
onClickAriaLabel="Example of href badge with target=blank"
data-test-sub="testExample4">
an anchor badge with target=blank
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge
color="accent"
iconType="bolt"
iconSide="right"
href="/#/display/badge"
onClickAriaLabel="Example of href event for the badge"
iconOnClick={() => window.alert('Icon inside badge clicked')}
iconOnClickAriaLabel="Example of onClick event for icon within the anchor"
data-test-sub="testExample5">
href on both text and icon within badge
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge
color="secondary"
isDisabled={true}
href="/#/display/badge"
onClickAriaLabel="Example of disabled badge"
iconOnClick={() => window.alert('Icon inside badge clicked')}
iconOnClickAriaLabel="Example disabled anchor"
data-test-sub="testExample5">
disabled anchor badge
</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
);
10 changes: 5 additions & 5 deletions src/components/badge/__snapshots__/badge.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,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
48 changes: 36 additions & 12 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'>;

interface WithAnchorProps {
href: string;
target?: string;
}

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 @@ -172,6 +183,19 @@ export const EuiBadge: FunctionComponent<EuiBadgeProps> = ({
'euiBadge__icon',
closeButtonProps && closeButtonProps.className
);
const Element = href && !isDisabled ? 'a' : 'button';
const relObj: {
href?: string;
target?: string;
onClick?: MouseEventHandler<HTMLButtonElement>;
} = {};

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 +233,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
anishagg17 marked this conversation as resolved.
Show resolved Hide resolved
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