From 4ccdea447f4da12a94a5040cfdbc78afb323e58d Mon Sep 17 00:00:00 2001 From: Andrey Morozov Date: Mon, 20 May 2024 14:20:06 +0300 Subject: [PATCH] feat(Link): allow to pass all corresponding html props --- src/components/Link/Link.tsx | 68 +++++++++---------- src/components/Link/README.md | 27 +++----- .../Link/__stories__/Link.new.stories.tsx | 63 ----------------- .../Link/__stories__/Link.stories.tsx | 40 ++++++++--- 4 files changed, 75 insertions(+), 123 deletions(-) delete mode 100644 src/components/Link/__stories__/Link.new.stories.tsx diff --git a/src/components/Link/Link.tsx b/src/components/Link/Link.tsx index 7118386124..3b5f07b9de 100644 --- a/src/components/Link/Link.tsx +++ b/src/components/Link/Link.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type {DOMProps, QAProps} from '../types'; +import type {QAProps} from '../types'; import {block} from '../utils/cn'; import {eventBroker} from '../utils/event-broker'; @@ -8,18 +8,13 @@ import './Link.scss'; export type LinkView = 'normal' | 'primary' | 'secondary'; -export interface LinkProps extends DOMProps, QAProps { +export interface LinkProps extends React.AnchorHTMLAttributes, QAProps { view?: LinkView; visitable?: boolean; - title?: string; href: string; - target?: string; - rel?: string; - id?: string; - children?: React.ReactNode; - onClick?: React.MouseEventHandler; - onFocus?: React.FocusEventHandler; - onBlur?: React.FocusEventHandler; + /** + * @deprecated + */ extraProps?: React.AnchorHTMLAttributes; } @@ -31,44 +26,49 @@ export const Link = React.forwardRef(function Link visitable, href, target, - rel, - title, + rel: relProp, children, - extraProps, - onClick, - onFocus, - onBlur, - id, - style, - className, qa, + onClickCapture, + className, + extraProps, + ...restProps }, ref, ) { - const handleClickCapture = React.useCallback((event: React.SyntheticEvent) => { - eventBroker.publish({ - componentId: 'Link', - eventId: 'click', - domEvent: event, - }); - }, []); + const handleClickCapture = React.useCallback( + (event: React.MouseEvent) => { + eventBroker.publish({ + componentId: 'Link', + eventId: 'click', + domEvent: event, + }); + + if (onClickCapture) { + onClickCapture(event); + } + }, + [onClickCapture], + ); const commonProps = { - title, - onClick, onClickCapture: handleClickCapture, - onFocus, - onBlur, - id, - style, className: b({view, visitable}, className), 'data-qa': qa, }; - const relProp = target === '_blank' && !rel ? 'noopener noreferrer' : rel; + const rel = target === '_blank' && !relProp ? 'noopener noreferrer' : relProp; return ( - + {children} ); diff --git a/src/components/Link/README.md b/src/components/Link/README.md index ea9f8017d2..9a37f27fa9 100644 --- a/src/components/Link/README.md +++ b/src/components/Link/README.md @@ -167,21 +167,12 @@ LANDING_BLOCK--> ## Properties -| Name | Description | Type | Default | -| :--------- | :----------------------------------------- | :-------------------------------------------------------: | :--------: | -| view | Link appearance | `"normal" \| "primary" \| "secondary"` | `"normal"` | -| visitable | Display `:visitable` CSS state | `boolean \| undefined` | -| href | HTML `href` attribute | `string` | -| target | HTML `target` attribute | `string \| undefined` | -| rel | HTML `rel` attribute | `string \| undefined` | -| title | HTML `title` attribute | `string \| undefined` | -| children | Link content | `React.ReactNode` | -| extraProps | Any additional props | `Record \| undefined` | -| onClick | `click` event handler | `React.MouseEventHandler \| undefined` | -| onFocus | `focus` event handler | `React.FocusEventHandler \| undefined` | -| onBlur | `blur` event handler | `React.FocusEventHandler \| undefined` | -| id | HTML `id` attribute | `string \| undefined` | -| style | HTML `style` attribute | `React.CSSProperties \| undefined` | -| className | HTML `class` attribute | `string \| undefined` | -| qa | HTML `data-qa` attribute, used for testing | `string \| undefined` | -| ref | React ref to Link DOM node | `React.ForwardedRef \| undefined` | +`LinkProps` extends `React.HTMLAnchorElement`. + +| Name | Description | Type | Default | +| :-------- | :----------------------------------------- | :----------------------------------: | :--------: | +| children | Link content | `React.ReactNode` | | +| href | HTML `href` attribute | `string` | | +| qa | HTML `data-qa` attribute, used for testing | `string` | | +| view | Link appearance | `"normal"` `"primary"` `"secondary"` | `"normal"` | +| visitable | Display `:visitable` CSS state | `boolean` | | diff --git a/src/components/Link/__stories__/Link.new.stories.tsx b/src/components/Link/__stories__/Link.new.stories.tsx deleted file mode 100644 index cd6deaa11e..0000000000 --- a/src/components/Link/__stories__/Link.new.stories.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react'; - -import type {Meta, StoryFn} from '@storybook/react'; - -import {Link} from '../Link'; -import type {LinkProps} from '../Link'; - -export default { - title: 'Components/Navigation/Link', - id: 'components/navigation/Link', - args: { - view: 'normal', - children: 'Link', - href: '#', - title: 'title', - }, - argTypes: { - view: { - options: ['normal', 'primary', 'secondary'], - control: {type: 'select'}, - description: 'test', - }, - children: { - control: {type: 'text'}, - }, - href: { - control: {type: 'text'}, - }, - target: { - control: {type: 'text'}, - if: {arg: 'href', truthy: true}, - }, - rel: { - control: {type: 'text'}, - if: {arg: 'href', truthy: true}, - }, - title: { - control: {type: 'text'}, - }, - id: { - control: {type: 'text'}, - }, - }, - parameters: { - order: -100, - a11y: { - element: '#storybook-root', - config: { - rules: [ - { - id: 'color-contrast', - enabled: false, - }, - ], - }, - }, - }, -} as Meta; - -export const Playground: StoryFn = (args) => { - return ; -}; -Playground.storyName = 'Link'; diff --git a/src/components/Link/__stories__/Link.stories.tsx b/src/components/Link/__stories__/Link.stories.tsx index 00f4c0f7cb..6433ad25c2 100644 --- a/src/components/Link/__stories__/Link.stories.tsx +++ b/src/components/Link/__stories__/Link.stories.tsx @@ -1,10 +1,9 @@ import React from 'react'; -import type {Meta, StoryFn} from '@storybook/react'; +import type {Meta, StoryObj} from '@storybook/react'; +import {Showcase} from '../../../demo/Showcase'; import {Link} from '../Link'; -import type {LinkProps} from '../Link'; -import {LinkShowcase} from '../__stories__/LinkShowcase'; export default { title: 'Components/Navigation/Link', @@ -22,10 +21,35 @@ export default { }, }, }, -} as Meta; +} as Meta; -const DefaultTemplate: StoryFn = (args) => Link; -export const Default = DefaultTemplate.bind({}); +type Story = StoryObj; -const ShowcaseTemplate: StoryFn = () => ; -export const Showcase = ShowcaseTemplate.bind({}); +export const Default: Story = {args: {href: '#', children: 'Link'}}; + +export const View: Story = { + args: { + ...Default.args, + }, + render: (args) => ( + + + Normal + + + Primary + + + Secondary + + + ), +}; + +export const Visitable = { + args: { + ...Default.args, + visitable: true, + href: '.', + }, +};