Skip to content

Commit

Permalink
feat(component): add external prop to link component
Browse files Browse the repository at this point in the history
  • Loading branch information
chanceaclark committed Nov 11, 2019
1 parent e6fce3e commit 2acee91
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 9 deletions.
19 changes: 15 additions & 4 deletions packages/big-design/src/components/Link/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { OpenInNewIcon } from '@bigcommerce/big-design-icons';
import React, { memo, Ref } from 'react';

import { MarginProps } from '../../mixins';

import { StyledLink } from './styled';

export type LinkProps = React.AnchorHTMLAttributes<HTMLAnchorElement> & MarginProps;
export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement>, MarginProps {
external?: boolean;
}

interface PrivateProps {
forwardedRef: Ref<HTMLAnchorElement>;
isExternal?: boolean;
}

const StyleableLink: React.FC<LinkProps & PrivateProps> = memo(props => <StyledLink {...props} />);

export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => (
<StyleableLink {...props} forwardedRef={ref} />
));
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(({ children, external, ...props }, ref) => {
const isExternal = external && props.target === '_blank';

return (
<StyleableLink {...props} isExternal={isExternal} forwardedRef={ref}>
{isExternal ? <span>{children}</span> : children}
{isExternal && <OpenInNewIcon size="medium" />}
</StyleableLink>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,60 @@ exports[`render link 1`] = `
Link
</a>
`;

exports[`renders with external icon 1`] = `
.c1 {
vertical-align: middle;
height: 1rem;
width: 1rem;
}
.c0 {
color: #3C64F4;
cursor: pointer;
font-size: 1rem;
font-weight: 400;
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c0 svg {
margin-left: 0.25rem;
}
<a
class="c0"
href="#"
target="_blank"
>
<span>
Link
</span>
<svg
class="c1"
fill="currentColor"
height="24"
stroke="currentColor"
stroke-width="0"
viewBox="0 0 24 24"
width="24"
>
<title />
<path
d="M0 0h24v24H0V0z"
fill="none"
/>
<path
d="M18 19H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h5c.55 0 1-.45 1-1s-.45-1-1-1H5a2 2 0 00-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-6c0-.55-.45-1-1-1s-1 .45-1 1v5c0 .55-.45 1-1 1zM14 4c0 .55.45 1 1 1h2.59l-9.13 9.13a.996.996 0 101.41 1.41L19 6.41V9c0 .55.45 1 1 1s1-.45 1-1V4c0-.55-.45-1-1-1h-5c-.55 0-1 .45-1 1z"
/>
</svg>
</a>
`;
10 changes: 10 additions & 0 deletions packages/big-design/src/components/Link/spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ test('render link', () => {
expect(container.firstChild).toMatchSnapshot();
});

test('renders with external icon', () => {
const { container } = render(
<Link href="#" external target="_blank">
Link
</Link>,
);

expect(container.firstChild).toMatchSnapshot();
});

test('forwards styles', () => {
const { container } = render(
<Link href="#" className="test" style={{ background: 'red' }}>
Expand Down
15 changes: 13 additions & 2 deletions packages/big-design/src/components/Link/styled.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import { theme as defaultTheme } from '@bigcommerce/big-design-theme';
import styled from 'styled-components';
import styled, { css } from 'styled-components';

import { withMargins } from '../../mixins';

import { LinkProps } from './Link';

export const StyledLink = styled.a<LinkProps>`
export const StyledLink = styled.a<LinkProps & { isExternal?: boolean }>`
${withMargins()};
color: ${({ theme }) => theme.colors.primary};
cursor: pointer;
font-size: ${({ theme }) => theme.typography.fontSize.medium};
font-weight: ${({ theme }) => theme.typography.fontWeight.regular};
text-decoration: none;
${({ isExternal, theme }) =>
isExternal &&
css`
display: inline-flex;
align-items: center;
svg {
margin-left: ${theme.spacing.xxSmall};
}
`}
`;

StyledLink.defaultProps = { theme: defaultTheme };
17 changes: 17 additions & 0 deletions packages/docs/PropTables/LinkPropTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Code, NextLink, Prop, PropTable, PropTableWrapper } from '../components';

const linkProps: Prop[] = [
{
name: 'external',
types: 'boolean',
description: (
<>
Shows and external icons When the <Code primary>external</Code> flag is set and target="_blank".
</>
),
},
];

export const LinkPropTable: React.FC<PropTableWrapper> = props => (
<PropTable title="Link" propList={linkProps} {...props} />
);
1 change: 1 addition & 0 deletions packages/docs/PropTables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from './FormPropTable';
export * from './GridPropTable';
export * from './IconPropTable';
export * from './InputPropTable';
export * from './LinkPropTable';
export * from './MarginPropTable';
export * from './ModalPropTable';
export * from './PaddingPropTable';
Expand Down
21 changes: 18 additions & 3 deletions packages/docs/pages/Link/LinkPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { H0, H2, Link, Text } from '@bigcommerce/big-design';
import { H0, H1, H2, Link, Text } from '@bigcommerce/big-design';
import { OpenInNewIcon } from '@bigcommerce/big-design-icons';
import React from 'react';

import { CodePreview } from '../../components';
import { MarginPropTable } from '../../PropTables';
import { Code, CodePreview } from '../../components';
import { LinkPropTable, MarginPropTable } from '../../PropTables';

export default () => (
<>
Expand All @@ -22,6 +23,20 @@ export default () => (
{/* jsx-to-string:end */}
</CodePreview>

<Text>You can also include and external icon.</Text>

<CodePreview>
{/* jsx-to-string:start */}
<Link href="#" target="_blank" external>
Learn More
</Link>
{/* jsx-to-string:end */}
</CodePreview>

<H1>API</H1>

<LinkPropTable />

<H2>Inherited Props</H2>
<MarginPropTable collapsible />
</>
Expand Down

0 comments on commit 2acee91

Please sign in to comment.