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

Added external prop to EuiLink #2442

Merged
merged 11 commits into from
Oct 17, 2019
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## [`master`](https://github.com/elastic/eui/tree/master)

- Added ability for `EuiColorStops` to accept user-defined range bounds ([#2396](https://github.com/elastic/eui/pull/2396))
- Added `external` prop to `EuiLink` ([#2442](https://github.com/elastic/eui/pull/2410))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link is pointing to the wrong PR


## [`14.6.0`](https://github.com/elastic/eui/tree/v14.6.0)

Expand Down
39 changes: 21 additions & 18 deletions src-docs/src/views/link/link.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
import React from 'react';

import { EuiLink, EuiText } from '../../../../src/components';
import { EuiCode, EuiLink, EuiText } from '../../../../src/components';

export default () => (
<EuiText>
<p>
Open the{' '}
{
<EuiLink href="http://www.elastic.co" target="_blank">
Elastic website
</EuiLink>
}{' '}
<EuiLink href="http://www.elastic.co" target="_blank">
Elastic website
</EuiLink>{' '}
in a new tab.
</p>
<p>
This{' '}
<EuiLink href="http://www.elastic.co" external target="_blank">
link
</EuiLink>{' '}
has the <EuiCode>external</EuiCode> prop set to true.
</p>
<p>
This link is actually a{' '}
{<EuiLink onClick={() => window.alert('Button clicked')}>button</EuiLink>}{' '}
<EuiLink onClick={() => window.alert('Button clicked')}>button</EuiLink>{' '}
with an onClick handler.
</p>
<p>
Here is an example of a{' '}
{
<EuiLink
href="https://github.com/elastic/eui"
onClick={e => {
if (!window.confirm('Are you sure you want to see the eui repo?')) {
e.preventDefault();
}
}}>
link
</EuiLink>
}{' '}
<EuiLink
href="https://github.com/elastic/eui"
onClick={e => {
if (!window.confirm('Are you sure you want to see the eui repo?')) {
e.preventDefault();
}
}}>
link
</EuiLink>{' '}
with both an href and an onClick handler.
</p>
<p>Links can be colored as well.</p>
Expand Down
18 changes: 18 additions & 0 deletions src/components/link/__snapshots__/link.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ exports[`EuiLink if href is not specified, it renders a button of type=button 1`
/>
`;

exports[`EuiLink it is an external link 1`] = `
<a
class="euiLink euiLink--primary"
href="/baz/bing"
rel="noreferrer"
>
<svg
aria-label="External link"
class="euiIcon euiIcon--small euiIcon-isLoading euiLink__externalIcon"
focusable="false"
height="16"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
/>
</a>
`;

exports[`EuiLink it passes the default props through 1`] = `
<button
aria-label="aria-label"
Expand Down
4 changes: 4 additions & 0 deletions src/components/link/_link.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
.euiLink {
@include euiLink;

.euiLink__externalIcon {
margin-left: $euiSizeXS;
}
}

$textColors: (
Expand Down
5 changes: 5 additions & 0 deletions src/components/link/link.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ describe('EuiLink', () => {
expect(component).toMatchSnapshot();
});

test('it is an external link', () => {
const component = render(<EuiLink external href="/baz/bing" />);
expect(component).toMatchSnapshot();
});

test('supports href', () => {
const component = render(<EuiLink href="/baz/bing" />);
expect(component).toMatchSnapshot();
Expand Down
30 changes: 27 additions & 3 deletions src/components/link/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React, {
AnchorHTMLAttributes,
ButtonHTMLAttributes,
MouseEventHandler,
forwardRef,
} from 'react';
import classNames from 'classnames';

import { EuiIcon } from '../icon';
import { EuiI18n } from '../i18n';
import { CommonProps, ExclusiveUnion, keysOf } from '../common';
import { getSecureRelForTarget } from '../../services';

Expand Down Expand Up @@ -46,6 +46,10 @@ export type EuiLinkButtonProps = CommonProps &
export interface LinkAnchorProps {
type?: EuiLinkType;
color?: EuiLinkColor;
/**
* Set to true to show an icon indicating that it is an external link.
*/
external?: boolean;
}

export type EuiLinkAnchorProps = CommonProps &
Expand All @@ -57,13 +61,17 @@ export type EuiLinkProps = ExclusiveUnion<
EuiLinkAnchorProps
>;

const EuiLink = forwardRef<HTMLAnchorElement | HTMLButtonElement, EuiLinkProps>(
const EuiLink = React.forwardRef<
HTMLAnchorElement | HTMLButtonElement,
EuiLinkProps
>(
(
{
children,
color = 'primary',
className,
href,
external,
target,
rel,
type = 'button',
Expand All @@ -78,6 +86,21 @@ const EuiLink = forwardRef<HTMLAnchorElement | HTMLButtonElement, EuiLinkProps>(
className
);

const externalLinkIcon = external ? (
<EuiI18n token="euiLink.external.ariaLabel" default="External link">
{(ariaLabel: string) => (
<EuiIcon
aria-label={ariaLabel}
size="s"
className="euiLink__externalIcon"
type="popout"
/>
)}
</EuiI18n>
) : (
undefined
);

if (href === undefined) {
const buttonProps = {
className: classes,
Expand Down Expand Up @@ -111,6 +134,7 @@ const EuiLink = forwardRef<HTMLAnchorElement | HTMLButtonElement, EuiLinkProps>(
ref={ref as React.Ref<HTMLAnchorElement>}
{...anchorProps as EuiLinkAnchorProps}>
{children}
{externalLinkIcon}
</a>
);
}
Expand Down