From 9a198065d40466f43eedb4f479140f43e231ee8f Mon Sep 17 00:00:00 2001 From: Vadim Polyakov <108093658+v4dyar4@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:49:04 +0300 Subject: [PATCH] feat(Divider): add the Divider component (#1322) --- CODEOWNERS | 1 + src/components/Divider/Divider.scss | 15 ++ src/components/Divider/Divider.tsx | 29 ++++ src/components/Divider/README.md | 148 ++++++++++++++++++ .../Divider/__stories__/Divider.stories.tsx | 137 ++++++++++++++++ src/components/Divider/__stories__/Docs.mdx | 7 + .../Divider/__tests__/Divider.test.tsx | 39 +++++ src/components/Divider/index.ts | 1 + 8 files changed, 377 insertions(+) create mode 100644 src/components/Divider/Divider.scss create mode 100644 src/components/Divider/Divider.tsx create mode 100644 src/components/Divider/README.md create mode 100644 src/components/Divider/__stories__/Divider.stories.tsx create mode 100644 src/components/Divider/__stories__/Docs.mdx create mode 100644 src/components/Divider/__tests__/Divider.test.tsx create mode 100644 src/components/Divider/index.ts diff --git a/CODEOWNERS b/CODEOWNERS index 4117511b0b..a46ad0f852 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -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 diff --git a/src/components/Divider/Divider.scss b/src/components/Divider/Divider.scss new file mode 100644 index 0000000000..4139723fe8 --- /dev/null +++ b/src/components/Divider/Divider.scss @@ -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)); + } + } +} diff --git a/src/components/Divider/Divider.tsx b/src/components/Divider/Divider.tsx new file mode 100644 index 0000000000..8ac333c182 --- /dev/null +++ b/src/components/Divider/Divider.tsx @@ -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(function Divider(props, ref) { + const {orientation = 'horizontal', className, style, qa} = props; + + return ( +
+ ); +}); diff --git a/src/components/Divider/README.md b/src/components/Divider/README.md new file mode 100644 index 0000000000..330a69476b --- /dev/null +++ b/src/components/Divider/README.md @@ -0,0 +1,148 @@ + + +# Divider + + + +```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 + +``` + +### Orientation + +To control the orientation of the `Divider`, use the `orientation` property. The default orientation is `horizontal`. + +#### Horizontal + + + + + +```tsx +import {Container, Text, Divider} from '@gravity-ui/uikit'; + + + + 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? + + + + 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? + +; +``` + + + +#### Vertical + + + + + +```tsx +import {Flex, Label, Divider} from '@gravity-ui/uikit'; + + + + + + + + + + + +; +``` + + + +### 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 | diff --git a/src/components/Divider/__stories__/Divider.stories.tsx b/src/components/Divider/__stories__/Divider.stories.tsx new file mode 100644 index 0000000000..ed948837e7 --- /dev/null +++ b/src/components/Divider/__stories__/Divider.stories.tsx @@ -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 = { + title: 'Components/Utils/Divider', + component: Divider, +}; + +export default meta; + +type Story = StoryObj; + +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 ( + + + + {listItems.map((value, index) => ( + + {}} + style={listItemStyle} + /> + + {index < listItems.length - 1 && } + + ))} + + + + ); + }, +}; + +export const Vertical: Story = { + args: { + orientation: 'vertical', + }, + argTypes: { + orientation: disabledControl, + style: disabledControl, + qa: disabledControl, + className: disabledControl, + }, + render: (args) => ( + + + + {listItems.map((value, index) => ( + + {}} + style={listItemStyle} + /> + + {index < listItems.length - 1 && } + + ))} + + + + ), +}; + +export const Custom: Story = { + args: { + orientation: 'vertical', + className: 'custom-divider', + style: {borderWidth: '2px'}, + }, + render: (args) => ( + + + + + {listItems.map((value, index) => ( + + {}} + style={listItemStyle} + /> + + {index < listItems.length - 1 && } + + ))} + + + + ), +}; diff --git a/src/components/Divider/__stories__/Docs.mdx b/src/components/Divider/__stories__/Docs.mdx new file mode 100644 index 0000000000..fe1c86a9ef --- /dev/null +++ b/src/components/Divider/__stories__/Docs.mdx @@ -0,0 +1,7 @@ +import {Meta, Markdown} from '@storybook/addon-docs'; +import * as Stories from './Divider.stories'; +import Readme from '../README.md?raw'; + + + +{Readme} diff --git a/src/components/Divider/__tests__/Divider.test.tsx b/src/components/Divider/__tests__/Divider.test.tsx new file mode 100644 index 0000000000..5351c1dd5f --- /dev/null +++ b/src/components/Divider/__tests__/Divider.test.tsx @@ -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(); + + expect(screen.getByTestId(qa)).toHaveClass('g-custom-divider'); + }); + test('Should passed style', () => { + render(); + + expect(screen.getByTestId(qa)).toHaveStyle({borderWidth: '2px'}); + }); + test('Should render with orientation=horizontal', () => { + render(); + + 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(); + + const element = screen.getByTestId(qa); + + expect(element).toHaveAttribute('aria-orientation', 'vertical'); + expect(element).toHaveAttribute('role', 'separator'); + expect(element).toHaveClass('g-divider_orientation_vertical'); + }); +}); diff --git a/src/components/Divider/index.ts b/src/components/Divider/index.ts new file mode 100644 index 0000000000..1f84888dc7 --- /dev/null +++ b/src/components/Divider/index.ts @@ -0,0 +1 @@ +export * from './Divider';