diff --git a/package-lock.json b/package-lock.json index 60042df6..360d4f23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "@gravity-ui/prettier-config": "^1.0.1", "@gravity-ui/stylelint-config": "^2.0.0", "@gravity-ui/tsconfig": "^1.0.0", - "@gravity-ui/uikit": "^5.10.0", + "@gravity-ui/uikit": "^5.17.0", "@storybook/addon-essentials": "^7.1.1", "@storybook/cli": "^7.1.1", "@storybook/preset-scss": "^1.0.3", @@ -61,7 +61,7 @@ "typescript": "^4.9.5" }, "peerDependencies": { - "@gravity-ui/uikit": "^5.10.0", + "@gravity-ui/uikit": "^5.12.0", "react": "^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" } @@ -3321,9 +3321,9 @@ "dev": true }, "node_modules/@gravity-ui/uikit": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/@gravity-ui/uikit/-/uikit-5.16.0.tgz", - "integrity": "sha512-zxQNXItQ60nPXaHw7CtUWR106VdUG3ONEf5ZRPnDHHVe+cuQFm0mCg6nFw3R5mUSWyOHKvHbkEoY44gnMC+fDQ==", + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@gravity-ui/uikit/-/uikit-5.17.0.tgz", + "integrity": "sha512-Q59Rq4AV4J9j6TKX7GayvcNE68kcxqTHPUgbETLUC2IIwhGGrm2TvJtzifY9RkJrFIJ1xNs6MiRAsjKPm73dfA==", "dev": true, "dependencies": { "@bem-react/classname": "^1.6.0", diff --git a/package.json b/package.json index 73c18411..2ba21524 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@gravity-ui/prettier-config": "^1.0.1", "@gravity-ui/stylelint-config": "^2.0.0", "@gravity-ui/tsconfig": "^1.0.0", - "@gravity-ui/uikit": "^5.10.0", + "@gravity-ui/uikit": "^5.17.0", "@storybook/addon-essentials": "^7.1.1", "@storybook/cli": "^7.1.1", "@storybook/preset-scss": "^1.0.3", @@ -88,7 +88,7 @@ "typescript": "^4.9.5" }, "peerDependencies": { - "@gravity-ui/uikit": "^5.10.0", + "@gravity-ui/uikit": "^5.12.0", "react": "^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" }, diff --git a/src/components/HelpPopover/HelpPopover.tsx b/src/components/HelpPopover/HelpPopover.tsx index 60991db8..4be8a1dd 100644 --- a/src/components/HelpPopover/HelpPopover.tsx +++ b/src/components/HelpPopover/HelpPopover.tsx @@ -10,6 +10,7 @@ import {QuestionMarkIcon} from './QuestionMarkIcon'; import './HelpPopover.scss'; const b = block('help-popover'); +const ICON_SIZE = 16; export interface HelpPopoverProps extends Omit, QAProps { buttonProps?: React.ButtonHTMLAttributes; @@ -25,7 +26,7 @@ export function HelpPopover(props: HelpPopoverProps) { {...props.buttonProps} className={b('button', props.buttonProps?.className)} > - + ); diff --git a/src/components/SharePopover/SharePopover.scss b/src/components/SharePopover/SharePopover.scss index f51141ca..7eed228d 100644 --- a/src/components/SharePopover/SharePopover.scss +++ b/src/components/SharePopover/SharePopover.scss @@ -1,4 +1,5 @@ @use '../variables'; +@use '../mixins'; $block: '.#{variables.$ns}share-popover'; @@ -11,11 +12,14 @@ $block: '.#{variables.$ns}share-popover'; } &__container { + @include mixins.button-reset(); + @include mixins.focusable(); display: flex; flex-wrap: nowrap; cursor: pointer; color: var(--g-color-text-secondary); + border-radius: var(--g-focus-border-radius); &:hover { color: var(--g-color-text-primary); diff --git a/src/components/SharePopover/SharePopover.tsx b/src/components/SharePopover/SharePopover.tsx index ef861bc0..a11b808d 100644 --- a/src/components/SharePopover/SharePopover.tsx +++ b/src/components/SharePopover/SharePopover.tsx @@ -1,7 +1,7 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import {NodesRight} from '@gravity-ui/icons'; -import {Icon, Popover} from '@gravity-ui/uikit'; +import {Icon, Popover, useUniqId} from '@gravity-ui/uikit'; import type {IconData, PopupPlacement} from '@gravity-ui/uikit'; import {block} from '../utils/cn'; @@ -13,6 +13,21 @@ import {LayoutDirection} from './constants'; import './SharePopover.scss'; const b = block('share-popover'); +const DEFAULT_ICON_SIZE = 16; // px +const DEFAULT_CLOSE_DELAY = 300; // ms +const DEFAULT_PLACEMENT = 'bottom-end'; + +export const sharePopoverDefaultProps: SharePopoverDefaultProps = { + iconSize: DEFAULT_ICON_SIZE, + shareOptions: ShareList.defaultProps.shareOptions, + withCopyLink: true, + useWebShareApi: false, + placement: [DEFAULT_PLACEMENT], + openByHover: true, + autoclosable: true, + closeDelay: DEFAULT_CLOSE_DELAY, + direction: LayoutDirection.Row, +}; interface SharePopoverDefaultProps extends ShareListDefaultProps { /** Web Share API setting (share options can be specified for non supported api case) */ @@ -60,51 +75,37 @@ export interface SharePopoverProps extends ShareListProps, Partial React.ReactElement; } -type SharePopoverInnerProps = Omit & - Required>; - -export const sharePopoverDefaultProps: SharePopoverDefaultProps = { - iconSize: 16, - shareOptions: ShareList.defaultProps.shareOptions, - withCopyLink: true, - useWebShareApi: false, - placement: ['bottom-end'], - openByHover: true, - autoclosable: true, - closeDelay: 300, - direction: LayoutDirection.Row, -}; - -export class SharePopover extends React.PureComponent { - static defaultProps = sharePopoverDefaultProps; - - render() { - const { - url, - title, - text, - shareOptions, - withCopyLink, - useWebShareApi, - placement, - openByHover, - autoclosable, - closeDelay, - iconSize, - iconClass, - tooltipClassName, - switcherClassName, - className, - direction, - customIcon, - buttonTitle, - copyTitle, - copyIcon, - renderCopy, - children, - } = this.props; - - const content = ( +export const SharePopover = (props: SharePopoverProps) => { + const { + url, + title, + text, + shareOptions = sharePopoverDefaultProps.shareOptions, + withCopyLink = sharePopoverDefaultProps.withCopyLink, + useWebShareApi = sharePopoverDefaultProps.useWebShareApi, + placement = sharePopoverDefaultProps.placement, + openByHover = sharePopoverDefaultProps.openByHover, + autoclosable = sharePopoverDefaultProps.autoclosable, + closeDelay = sharePopoverDefaultProps.closeDelay, + iconSize = sharePopoverDefaultProps.iconSize, + iconClass, + tooltipClassName, + switcherClassName, + className, + direction = sharePopoverDefaultProps.direction, + customIcon, + buttonTitle, + copyTitle, + copyIcon, + renderCopy, + children, + onClick, + } = props; + const [isOpen, setIsOpen] = React.useState(false); + const tooltipId = useUniqId(); + + const content = useMemo( + () => ( { > {children} - ); - - return ( - -
+ ), + [ + children, + copyIcon, + copyTitle, + direction, + renderCopy, + shareOptions, + text, + title, + url, + withCopyLink, + ], + ); + + const handleClick = React.useCallback( + async (event: React.MouseEvent) => { + if (onClick) { + onClick(event); + } + + if (useWebShareApi && navigator && typeof navigator.share === 'function') { + await navigator.share({url, title, text}); + event.preventDefault(); + return false; + } + return true; + }, + [onClick, text, title, url, useWebShareApi], + ); + + return ( + + {({onClick: onClickInner}) => ( +
-
- ); - } - - private handleClick = async (event: React.MouseEvent) => { - const {url, title, text, useWebShareApi, onClick} = this.props; - - if (onClick) { - onClick(event); - } - - if (useWebShareApi && navigator && typeof navigator.share === 'function') { - await navigator.share({url, title, text}); - event.preventDefault(); - return false; - } - return true; - }; -} + + )} + + ); +}; diff --git a/src/components/mixins.scss b/src/components/mixins.scss new file mode 100644 index 00000000..1640e361 --- /dev/null +++ b/src/components/mixins.scss @@ -0,0 +1,10 @@ +@import '@gravity-ui/uikit/styles/mixins'; + +@mixin focusable() { + &:focus { + outline: 2px solid var(--g-color-line-focus); + } + &:focus:not(:focus-visible) { + outline: 0; + } +}