diff --git a/src/components/HelpPopover/HelpPopover.scss b/src/components/HelpPopover/HelpPopover.scss new file mode 100644 index 00000000..b9639ee4 --- /dev/null +++ b/src/components/HelpPopover/HelpPopover.scss @@ -0,0 +1,15 @@ +@use '../variables'; +@use '@gravity-ui/uikit/styles/mixins'; + +$block: '.#{variables.$ns}help-popover'; + +#{$block} { + &__button { + @include mixins.button-reset(); + } + + &__button:focus-visible { + outline: 2px solid var(--g-color-line-generic-active); + border-radius: 50%; + } +} diff --git a/src/components/HelpPopover/HelpPopover.tsx b/src/components/HelpPopover/HelpPopover.tsx index ec9e1d50..04c86acb 100644 --- a/src/components/HelpPopover/HelpPopover.tsx +++ b/src/components/HelpPopover/HelpPopover.tsx @@ -7,6 +7,8 @@ import {block} from '../utils/cn'; import {QuestionMarkIcon} from './QuestionMarkIcon'; +import './HelpPopover.scss'; + const b = block('help-popover'); /** @@ -14,12 +16,24 @@ const b = block('help-popover'); */ type DistributiveOmit = T extends unknown ? Omit : never; -export type HelpPopoverProps = DistributiveOmit & QAProps; +export interface AriaProps { + buttonAriaAttributes?: React.AriaAttributes; + buttonRole?: React.AriaRole; + buttonRef?: React.RefObject; +} +export type HelpPopoverProps = DistributiveOmit & QAProps & AriaProps; export function HelpPopover(props: HelpPopoverProps) { return ( - + ); } diff --git a/src/components/HelpPopover/README.md b/src/components/HelpPopover/README.md index a47f951b..83682945 100644 --- a/src/components/HelpPopover/README.md +++ b/src/components/HelpPopover/README.md @@ -4,19 +4,22 @@ Component to display popover with tips ### PropTypes -| Property | Type | Required | Values | Default | Description | -| :------------ | :---------- | :------- | :---------------- | :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- | -| theme | `String` | | `info`, `special` | `info` | Appearance | -| className | `String` | | | | Control class name | -| placement | `Array` | | | [`right`, `bottom`] | Allowed popover positions | -| autoclosable | `Boolean` | | | `true` | Close popover when pointer is outside of control | -| delayClosing | `Number` | | | `300` | Timeout before closing popover (see `autoclosable`) | -| title | `String` | | | | Popover title | -| content | `ReactNode` | | | | Popover content | -| htmlContent | `String` | | | | Render HTML via `dangerouslySetInnerHTML` | -| links | `Array` | | | [] | Links below content, could be
`{ text: 'Link 1', href: 'https://example.com'}` or
`{ text: 'Link 2', onClick: () => onLinkClick() }` | -| tooltipButton | `Object` | | | | Render button with this value
`{ text: 'Button', onClick: () => onClick() }` | -| offset | `Object` | | | `{ left: 4 }` | Control popup toggle position offset
`{ top: 0, left: 0 }` | +| Property | Type | Required | Values | Default | Description | +| :------------------- | :----------------------------------- | :------- | :---------------- | :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- | +| theme | `String` | | `info`, `special` | `info` | Appearance | +| className | `String` | | | | Control class name | +| placement | `Array` | | | [`right`, `bottom`] | Allowed popover positions | +| autoclosable | `Boolean` | | | `true` | Close popover when pointer is outside of control | +| delayClosing | `Number` | | | `300` | Timeout before closing popover (see `autoclosable`) | +| title | `String` | | | | Popover title | +| content | `ReactNode` | | | | Popover content | +| htmlContent | `String` | | | | Render HTML via `dangerouslySetInnerHTML` | +| links | `Array` | | | [] | Links below content, could be
`{ text: 'Link 1', href: 'https://example.com'}` or
`{ text: 'Link 2', onClick: () => onLinkClick() }` | +| tooltipButton | `Object` | | | | Render button with this value
`{ text: 'Button', onClick: () => onClick() }` | +| offset | `Object` | | | `{ left: 4 }` | Control popup toggle position offset
`{ top: 0, left: 0 }` | +| buttonAriaAttributes | `React.AriaAttributes` | | | | Set aria attributes to the underlying button element | +| buttonRole | `React.AriaRole` | | | | Set aria role to the underlying button element | +| buttonRef | `React.RefObject` | | | | Ref to the underlying button element | ### Examples diff --git a/src/components/HelpPopover/__stories__/HelpPopover.stories.tsx b/src/components/HelpPopover/__stories__/HelpPopover.stories.tsx index ff2b6189..ccb16d9d 100644 --- a/src/components/HelpPopover/__stories__/HelpPopover.stories.tsx +++ b/src/components/HelpPopover/__stories__/HelpPopover.stories.tsx @@ -2,9 +2,14 @@ import React from 'react'; import type {Meta, StoryFn} from '@storybook/react'; +import {cn} from '../../utils/cn'; import {HelpPopover} from '../HelpPopover'; import type {HelpPopoverProps} from '../HelpPopover'; +import './HelpPopoverShowcase.scss'; + +const b = cn('help-popover-showcase'); + export default { title: 'Components/HelpPopover', component: HelpPopover, @@ -15,3 +20,46 @@ export const Default = DefaultTemplate.bind({}); Default.args = { content: 'Some content', }; + +export const Accessible: StoryFn = (args) => { + const helpPopoverWithoutActionsId = 'helpPopoverWithoutActionsId'; + const helpPopoverWithActionsId = 'helpPopoverWithActionsId'; + const [openPopover, setOpenPopover] = React.useState(false); + const ref = React.useRef(null); + return ( +
+
+ Without actions: + +
+
+ With actions: + Some link} + openOnHover={false} + onOpenChange={setOpenPopover} + focusTrap + autoFocus + restoreFocusRef={ref} + buttonAriaAttributes={{ + 'aria-expanded': openPopover, + 'aria-controls': helpPopoverWithActionsId, + 'aria-label': 'More info', + }} + buttonRef={ref} + /> +
+
+ ); +}; diff --git a/src/components/HelpPopover/__stories__/HelpPopoverShowcase.scss b/src/components/HelpPopover/__stories__/HelpPopoverShowcase.scss new file mode 100644 index 00000000..25e3931a --- /dev/null +++ b/src/components/HelpPopover/__stories__/HelpPopoverShowcase.scss @@ -0,0 +1,9 @@ +.help-popover-showcase { + &__container { + display: flex; + margin-bottom: 10px; + } + &__container-title { + margin-right: 5px; + } +}