Skip to content

Commit

Permalink
feat(Divider): add the Divider component (#1322)
Browse files Browse the repository at this point in the history
  • Loading branch information
v4dyar4 authored Mar 28, 2024
1 parent eb1f5d9 commit 9a19806
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
/src/components/CopyToClipboard @SeqviriouM
#/src/components/Dialog
/src/components/Disclosure @Raubzeug
/src/components/Divider @v4dyar4
/src/components/DropdownMenu @axtk
/src/components/Hotkey @d3m1d0v
/src/components/Icon @amje
Expand Down
15 changes: 15 additions & 0 deletions src/components/Divider/Divider.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@use '../variables';

$block: '.#{variables.$ns}divider';

#{$block} {
&_orientation {
&_vertical {
border-inline-start: 1px solid var(--g-divider-color, var(--g-color-line-generic));
}

&_horizontal {
border-block-start: 1px solid var(--g-divider-color, var(--g-color-line-generic));
}
}
}
29 changes: 29 additions & 0 deletions src/components/Divider/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';

import type {DOMProps, QAProps} from '../types';
import {block} from '../utils/cn';

import './Divider.scss';

export type DividerOrientation = 'vertical' | 'horizontal';

export interface DividerProps extends DOMProps, QAProps {
orientation?: DividerOrientation;
}

const b = block('divider');

export const Divider = React.forwardRef<HTMLDivElement, DividerProps>(function Divider(props, ref) {
const {orientation = 'horizontal', className, style, qa} = props;

return (
<div
className={b({orientation}, className)}
ref={ref}
style={style}
data-qa={qa}
role="separator"
aria-orientation={orientation === 'vertical' ? 'vertical' : undefined}
/>
);
});
148 changes: 148 additions & 0 deletions src/components/Divider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<!--GITHUB_BLOCK-->

# Divider

<!--/GITHUB_BLOCK-->

```tsx
import {Divider} from '@gravity-ui/uikit';
```

The `Divider` component is used as a thin line for delimiting and grouping elements to reinforce visual hierarchy.

```tsx
<Divider className="custom-divider" direction="horizontal" />
```

### Orientation

To control the orientation of the `Divider`, use the `orientation` property. The default orientation is `horizontal`.

#### Horizontal

<!--LANDING_BLOCK
<ExampleBlock
code={`
<Container>
<Text>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
</Text>
<Divider direction="horizontal"/>
<Text>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
</Text>
</Container>
`}
>
<UIKit.Container>
<UIKit.Text>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
</UIKit.Text>
<UIKit.Divider direction="horizontal"/>
<UIKit.Text>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
</UIKit.Text>
</UIKit.Container>
</ExampleBlock>
LANDING_BLOCK-->

<!--GITHUB_BLOCK-->

```tsx
import {Container, Text, Divider} from '@gravity-ui/uikit';

<Container>
<Text>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
</Text>
<Divider orientation="horizontal" />
<Text>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
</Text>
</Container>;
```

<!--/GITHUB_BLOCK-->

#### Vertical

<!--LANDING_BLOCK
<ExampleBlock
code={`
<Container>
<Flex gap={3}>
<Label>Label</Label>
<Divider orientation="vertical"/>
<Label>Label</Label>
<Divider orientation="vertical"/>
<Label>Label</Label>
<Divider orientation="vertical"/>
<Label>Label</Label>
</Flex>
</Container>
`}
>
<UIKit.Container>
<UIKit.Flex gap={3}>
<UIKit.Label>Label</UIKit.Label>
<UIKit.Divider orientation="vertical"/>
<UIKit.Label>Label</UIKit.Label>
<UIKit.Divider orientation="vertical"/>
<UIKit.Label>Label</UIKit.Label>
<UIKit.Divider orientation="vertical"/>
<UIKit.Label>Label</UIKit.Label>
</UIKit.Flex>
</UIKit.Container>
</ExampleBlock>
LANDING_BLOCK-->

<!--GITHUB_BLOCK-->

```tsx
import {Flex, Label, Divider} from '@gravity-ui/uikit';

<Container>
<Flex gap={3}>
<Label>Label</Label>
<Divider orientation="vertical" />
<Label>Label</Label>
<Divider orientation="vertical" />
<Label>Label</Label>
<Divider orientation="vertical" />
<Label>Label</Label>
</Flex>
</Container>;
```

<!--/GITHUB_BLOCK-->

### Properties

| Name | Description | Type | Default |
| :---------- | :-------------------------------------- | :---------------------- | :----------- |
| className | HTML `class` attribute | `string` | - |
| orientation | Sets the direction of divider | `horizontal - vertical` | `horizontal` |
| style | HTML `style` attribute | `React.CSSProperties` | |
| qa | HTML `data-qa` attribute, used in tests | `string` | |

### CSS API

| Name | Description |
| :------------------ | :------------ |
| `--g-divider-color` | Divider color |
137 changes: 137 additions & 0 deletions src/components/Divider/__stories__/Divider.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React from 'react';

import type {Meta, StoryObj} from '@storybook/react';

import {Showcase} from '../../../demo/Showcase';
import {Card} from '../../Card';
import {ListItem} from '../../List';
import {Flex} from '../../layout';
import {Divider} from '../Divider';

const meta: Meta<typeof Divider> = {
title: 'Components/Utils/Divider',
component: Divider,
};

export default meta;

type Story = StoryObj<typeof Divider>;

const listItems = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight'];

const disabledControl = {
table: {
disable: true,
},
};

const listItemStyle: React.CSSProperties = {
padding: '0.5rem',
textAlign: 'center',
width: '60px',
};

export const Horizontal: Story = {
args: {
orientation: 'horizontal',
},
argTypes: {
orientation: disabledControl,
style: disabledControl,
qa: disabledControl,
className: disabledControl,
},
render: (args) => {
return (
<Showcase>
<Card theme="normal" type="container">
<Flex direction="column">
{listItems.map((value, index) => (
<React.Fragment key={index}>
<ListItem
item={value}
itemIndex={index}
active={false}
selected={false}
onActivate={() => {}}
style={listItemStyle}
/>

{index < listItems.length - 1 && <Divider {...args} />}
</React.Fragment>
))}
</Flex>
</Card>
</Showcase>
);
},
};

export const Vertical: Story = {
args: {
orientation: 'vertical',
},
argTypes: {
orientation: disabledControl,
style: disabledControl,
qa: disabledControl,
className: disabledControl,
},
render: (args) => (
<Showcase>
<Card theme="normal" type="container">
<Flex>
{listItems.map((value, index) => (
<React.Fragment key={index}>
<ListItem
item={value}
itemIndex={index}
active={false}
selected={false}
onActivate={() => {}}
style={listItemStyle}
/>

{index < listItems.length - 1 && <Divider {...args} />}
</React.Fragment>
))}
</Flex>
</Card>
</Showcase>
),
};

export const Custom: Story = {
args: {
orientation: 'vertical',
className: 'custom-divider',
style: {borderWidth: '2px'},
},
render: (args) => (
<Showcase>
<style>
{`.g-root {
--g-divider-color: #027bf3;
}`}
</style>
<Card theme="normal" type="container">
<Flex direction={args.orientation === 'vertical' ? 'row' : 'column'}>
{listItems.map((value, index) => (
<React.Fragment key={index}>
<ListItem
item={value}
itemIndex={index}
active={false}
selected={false}
onActivate={() => {}}
style={listItemStyle}
/>

{index < listItems.length - 1 && <Divider {...args} />}
</React.Fragment>
))}
</Flex>
</Card>
</Showcase>
),
};
7 changes: 7 additions & 0 deletions src/components/Divider/__stories__/Docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {Meta, Markdown} from '@storybook/addon-docs';
import * as Stories from './Divider.stories';
import Readme from '../README.md?raw';

<Meta of={Stories} />

<Markdown>{Readme}</Markdown>
39 changes: 39 additions & 0 deletions src/components/Divider/__tests__/Divider.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';

import {render, screen} from '../../../../test-utils/utils';
import {block} from '../../utils/cn';
import {Divider} from '../Divider';

const b = block('custom-divider');
const qa = 'divider';

describe('Divider', () => {
test('Should passed className', () => {
render(<Divider className={b()} qa={qa} />);

expect(screen.getByTestId(qa)).toHaveClass('g-custom-divider');
});
test('Should passed style', () => {
render(<Divider style={{borderWidth: '2px'}} qa={qa} />);

expect(screen.getByTestId(qa)).toHaveStyle({borderWidth: '2px'});
});
test('Should render with orientation=horizontal', () => {
render(<Divider qa={qa} />);

const element = screen.getByTestId(qa);

expect(element).not.toHaveAttribute('aria-orientation');
expect(element).toHaveAttribute('role', 'separator');
expect(element).toHaveClass('g-divider_orientation_horizontal');
});
test('Should render with orientation=vertical', () => {
render(<Divider orientation="vertical" qa={qa} />);

const element = screen.getByTestId(qa);

expect(element).toHaveAttribute('aria-orientation', 'vertical');
expect(element).toHaveAttribute('role', 'separator');
expect(element).toHaveClass('g-divider_orientation_vertical');
});
});
1 change: 1 addition & 0 deletions src/components/Divider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Divider';

0 comments on commit 9a19806

Please sign in to comment.