Skip to content

Commit

Permalink
Styled Link (#154)
Browse files Browse the repository at this point in the history
* migrate Link to styled-components

* remove empty class

* use color from theme

* use appropriate assertion method
  • Loading branch information
tkanzakic authored Oct 23, 2020
1 parent ab545b9 commit 31ab759
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';
import styled from 'styled-components';
import { Icon, favorite as Favorite } from 'components/primitives/Icon';
import { Link } from '.';
import { Typography } from 'components/primitives/Typography';
import { text, select } from '@storybook/addon-knobs';

export default {
title: 'Primitives/Link',
component: Link,
};

export const Text = () => (
<Link url="#">
<Typography tag={Typography.Tags.Span} type={Typography.Types.Link}>
Text Link
</Typography>
</Link>
);

const FlexContainer = styled.div`
display: flex;
align-items: center;
`;

export const Icons = () => (
<Link url="#">
<FlexContainer>
<Typography tag={Typography.Tags.Span} type={Typography.Types.Link}>
Text & Icon
</Typography>
<Icon className="fill-current" width={20} height={20}>
<Favorite type="filled" />
</Icon>
</FlexContainer>
</Link>
);

export const Primary = () => (
<Link url="#" type={Link.Types.Primary}>
Primary Link
</Link>
);

export const Secondary = () => (
<Link url="#" type={Link.Types.Secondary}>
Secondary Link
</Link>
);

export const Playground = () => (
<Link
url={text('Url', 'https://impulsum.vc')}
type={select('Type', Link.Types, Link.Types.Text)}
target={select('Target', Link.Target, Link.Target.Blank)}
>
{text('Title', 'Link title')}
</Link>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import styled from 'styled-components';
import { getTheme } from 'utils/getTheme';

interface Props {
theme: any;
}

export const StyledLink = styled.a<Props>`
color: ${(props) => getTheme(props).colors.fillBlack500};
flex-grow: 0;
&.image {
display: flex;
justify-content: center;
}
&.primary {
color: ${(props) => getTheme(props).colors.fillWhite};
background-color: ${(props) => getTheme(props).colors.fillPrimary900};
text-align: center;
user-select: none;
font-weight: 500;
padding: 1rem 2rem;
display: flex;
align-items: center;
justify-content: center;
}
&.secondary {
color: ${(props) => getTheme(props).colors.fillPrimary900};
background-color: ${(props) => getTheme(props).colors.fillWhite};
text-align: center;
user-select: none;
font-weight: 500;
padding: 1rem 2rem;
display: flex;
align-items: center;
justify-content: center;
border-style: solid;
border-width: 1px;
border-color: ${(props) => getTheme(props).colors.fillPrimary900};
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { Link } from './Link';

describe('Link', () => {
const testId = 'link';
it('should render correctly with children', () => {
render(
<Link route={{ slug: 'link_test' }}>
<div>Link test</div>
</Link>
);
const link = screen.getByTestId(testId);
expect(link.children).toHaveLength(1);
});
it('should render correctly without slug', () => {
render(<Link>Link test</Link>);
screen.getByText('Link test');
});
it('should render class', () => {
render(<Link className="foo">Link test</Link>);
const link = screen.getByTestId(testId);
expect(link).toHaveClass('foo');
});
it('should render Image type', () => {
render(<Link type={Link.Types.Image}>Link test</Link>);
const link = screen.getByTestId(testId);
expect(link).toHaveClass('image');
});
it('should render Text type', () => {
render(<Link type={Link.Types.Text}>Link test</Link>);
const link = screen.getByTestId(testId);
expect(link).toHaveClass('text');
});
it('should render Primary type', () => {
render(<Link type={Link.Types.Primary}>Link test</Link>);
const link = screen.getByTestId(testId);
expect(link).toHaveClass('primary');
});
it('should render Secondary type', () => {
render(<Link type={Link.Types.Secondary}>Link test</Link>);
const link = screen.getByTestId(testId);
expect(link).toHaveClass('secondary');
});
it('should render href', () => {
render(<Link route={{ slug: 'link_test' }}>Link test</Link>);
const link = screen.getByTestId(testId);
expect(link).toHaveAttribute('href', 'link_test');
});
it('should render target', () => {
render(<Link target={Link.Target.Blank} />);
const link = screen.getByTestId(testId);
expect(link).toHaveAttribute('target', '_blank');
});
});
26 changes: 26 additions & 0 deletions packages/styled-components/src/components/primitives/Link/Link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import cn from 'classnames';
import { Props, Types, Target } from './Link.types';
import { StyledLink } from './Link.styled';

export const Link = ({
children,
className,
route,
type = Types.Text,
url,
testId = 'link',
target,
}: Props) => (
<StyledLink
target={target}
href={route ? route.slug : url}
className={cn(type, className)}
data-testid={testId}
>
{children}
</StyledLink>
);

Link.Types = Types;
Link.Target = Target;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ReactNode } from 'react';

export type Props = {
children?: ReactNode;
className?: string;
textClassName?: string;
route?: { slug: string };
url?: string;
type?: Types;
testId?: string;
target?: Target;
};

export enum Types {
Image = 'image',
Text = 'text',
Primary = 'primary',
Secondary = 'secondary',
}

export enum Target {
Blank = '_blank',
Parent = '_parent',
Top = '_top',
FrameName = 'framename',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Link';
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './Button';
export * from './Icon';
export * from './Link';
export * from './Typography';

0 comments on commit 31ab759

Please sign in to comment.