Skip to content

Commit

Permalink
docs(Link): impoving Link docs (#328)
Browse files Browse the repository at this point in the history
Co-authored-by: LakeVostok <[email protected]>
  • Loading branch information
LakeVostok and nskulikov authored Oct 27, 2022
1 parent fedde3b commit 4eab994
Show file tree
Hide file tree
Showing 10 changed files with 659 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/src/components/DropdownMenu @axtk
/src/components/Icon @amje
/src/components/Label @amje
/src/components/Link @LakeVostok
/src/components/List @korvin89
/src/components/Loader @SeqviriouM
/src/components/Modal @amje
Expand Down
67 changes: 67 additions & 0 deletions src/components/Link/__stories__/Link.docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {ArgsTable} from '@storybook/addon-docs';
import {DocsSource} from '../../../demo/DocsSource/DocsSource';
import {
LinkExampleViewNormal,
LinkExampleViewPrimary,
LinkExampleViewSecondary,
LinkExampleHref,
LinkExampleUsage,
} from './examples/LinkExampleView/LinkExampleView';
import {Link} from '../Link';

# Link

```ts
import {Link} from '@gravity-ui/uikit';
```

[Description](#description)

[Appearance](#appearance)

- [Normal](#normal)
- [Primary](#primary)
- [Secondary](#secondary)

[Href](#href)

[Usage](#usage)

## Description
Link - is a part of the text, that, when clicked, takes the user to another part of the page, another page inside the service, or to a page of another external service.

The main difference from the [Buttons](/docs/components-button) is the navigation function. Links more often lead to other pages or open new browser tabs.

## Appearance
There can be three types: `normal`(the usual blue), `primary`(black), `secondary`(gray). it is controlled by the view property.

### Normal
The most familiar and well-established pattern of use for users. It is used to visually highlight an element inside a text, table, and as part of navigation. It is used to navigate to pages inside the service and to external sources, including documentation. Also, they are used on error pages and zero states.

<DocsSource language="tsx" code={LinkExampleViewNormal.code}/>
<LinkExampleViewNormal/>

### Primary
They are used when it is natively clear to the user that it is possible to interact with an element, but visually using blue links will overload the interface and disrupt the balance of accents on the page.

<DocsSource language="tsx" code={LinkExampleViewPrimary.code}/>
<LinkExampleViewPrimary/>

### Secondary
Like primary links, they are used when it is natively clear to the user that an element can be interacted with, and the need to navigate through them is secondary and affects a small number of scenarios. The main task is not to argue with the accents on the page. It is more often used in bread crumbs or when displaying secondary attributes.

<DocsSource language="tsx" code={LinkExampleViewSecondary.code}/>
<LinkExampleViewSecondary/>

## Href
`href` property is optional. If it is absent, then Link wil act like Button.
<DocsSource language="tsx" code={LinkExampleHref.code}/>
<LinkExampleHref/>

## Usage
Сan be used as an independent text element, or as part of the text
<DocsSource language="tsx" code={LinkExampleUsage.code}/>
<LinkExampleUsage/>

## Properties
<ArgsTable of={Link}/>
51 changes: 51 additions & 0 deletions src/components/Link/__stories__/Link.new.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import {Meta, Story} from '@storybook/react';
import {Link} from '../Link';
import Docs from './Link.docs.mdx';

export default {
title: 'Components/Basic/Link',
id: 'components/Link',
argTypes: {
view: {
options: ['normal', 'primary', 'secondary', 'normal-visitable'],
control: {type: 'select'},
defaultValue: 'normal',
description: 'test',
},
children: {
control: {type: 'text'},
defaultValue: 'Link',
},
href: {
control: {type: 'text'},
defaultValue: '#',
},
target: {
control: {type: 'text'},
if: {arg: 'href', truthy: true},
},
rel: {
control: {type: 'text'},
if: {arg: 'href', truthy: true},
},
title: {
control: {type: 'text'},
defaultValue: 'title',
},
id: {
control: {type: 'text'},
},
},
parameters: {
order: -100,
docs: {
page: Docs,
},
},
} as Meta;

export const Playground: Story = (args) => {
return <Link {...args} />;
};
Playground.storyName = 'Link';
4 changes: 4 additions & 0 deletions src/components/Link/__stories__/Link.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import {Meta, Story} from '@storybook/react';
import {Link, LinkProps} from '../Link';
import {LinkShowcase} from '../__stories__/LinkShowcase';

export default {
title: 'Components/Link',
Expand All @@ -9,3 +10,6 @@ export default {

const DefaultTemplate: Story<LinkProps> = (args) => <Link {...args}>Link</Link>;
export const Default = DefaultTemplate.bind({});

const ShowcaseTemplate: Story = () => <LinkShowcase />;
export const Showcase = ShowcaseTemplate.bind({});
59 changes: 59 additions & 0 deletions src/components/Link/__stories__/LinkShowcase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';

import {Link} from '../Link';
import {Showcase} from '../../../demo/Showcase';
import {ShowcaseGrid} from '../../../demo/ShowcaseGrid/ShowcaseGrid';

export function LinkShowcase() {
return (
<Showcase title="Link">
<ShowcaseGrid
rowKey="href"
component={Link}
propsCombinations={{
view: [
{
name: 'View normal',
value: 'normal',
},
{
name: 'View primary',
value: 'primary',
},
{
name: 'View secondary',
value: 'secondary',
},
{
name: 'View normal-visitable',
value: 'normal-visitable',
},
],
href: [
{
name: 'With href',
value: '#',
},
{
name: 'Without href',
value: undefined,
},
],
target: [
{
name: 'blank',
value: '_blank',
},
{
name: 'top',
value: '_top',
},
],
}}
staticProps={{
children: 'Link',
}}
/>
</Showcase>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';

import {Link} from '../../..';
import {Text} from '../../../../Text';
import {DocsExample} from '../../../../../demo/DocsExample/DocsExample';

export function LinkExampleViewNormal() {
return (
<DocsExample>
<Link view="normal" href="#">
Link
</Link>
</DocsExample>
);
}
LinkExampleViewNormal.code = `
<Link view="normal" href="#">
Link
</Link>
`.trim();

export function LinkExampleViewPrimary() {
return (
<DocsExample>
<Link view="primary" href="#">
Link
</Link>
</DocsExample>
);
}
LinkExampleViewPrimary.code = `
<Link view="primary" href="#">
Link
</Link>
`.trim();

export function LinkExampleViewSecondary() {
return (
<DocsExample>
<Link view="secondary" href="#">
Link
</Link>
</DocsExample>
);
}
LinkExampleViewSecondary.code = `
<Link view="secondary" href="#">
Link
</Link>
`.trim();

export function LinkExampleHref() {
return (
<DocsExample>
<Link href="#">Link with href</Link>
<Link>Link without href</Link>
</DocsExample>
);
}
LinkExampleHref.code = `
<Link href="#">Link with href</Link>
<Link>Link without href</Link>
`.trim();

export function LinkExampleUsage() {
return (
<ul>
<li>
<Text>
<Link>what roles are active in the service</Link>
</Text>
</li>
<li>
<Text>
Currently, this role can only be assigned to a <Link>folder</Link> or{' '}
<Link>cloud</Link>
</Text>
</li>
</ul>
);
}
LinkExampleUsage.code = `
<Text>
<Link>what roles are active in the service</Link>
</Text>
<Text>
Currently, this role can only be assigned to a <Link>folder</Link> or <Link>cloud</Link>
</Text>
`.trim();
30 changes: 30 additions & 0 deletions src/components/Link/__tests__/Link.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import {render, screen} from '@testing-library/react';
import {Link} from '../Link';

describe('Link', () => {
test('Link is anchor', () => {
render(<Link href="#" />);

const link = screen.getByRole('link');

expect(link).toBeInTheDocument();
});

test('Link is span', () => {
render(<Link qa="test" />);

// btw there should be role attribute at span
const link = screen.getByTestId('test');

expect(link.tagName).toBe('SPAN');
});

test('rel attribute is present', () => {
render(<Link href="#" target="_blank" />);

const link = screen.getByRole('link');

expect(link).toHaveAttribute('rel', 'noopener noreferrer');
});
});
Loading

0 comments on commit 4eab994

Please sign in to comment.