diff --git a/src/components/ClipboardButton/ClipboardButton.tsx b/src/components/ClipboardButton/ClipboardButton.tsx deleted file mode 100644 index 71c454752c..0000000000 --- a/src/components/ClipboardButton/ClipboardButton.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import type {ButtonProps, CopyToClipboardStatus} from '@gravity-ui/uikit'; -import { - Button, - ClipboardIcon, - CopyToClipboard as CopyToClipboardUiKit, - Tooltip, -} from '@gravity-ui/uikit'; - -import {cn} from '../../utils/cn'; - -const b = cn('clipboard-button'); - -interface ClipboardButtonProps extends Pick { - className?: string; - text: string; -} - -/** - * An inner component required - * because `react-copy-to-clipboard` doesn't work with `Tooltip` otherwise. - */ -function InnerButton({ - className, - status, - title, - ...props -}: Omit & {status: CopyToClipboardStatus}) { - return ( - - - - ); -} - -export function ClipboardButton({text, ...props}: ClipboardButtonProps) { - return ( - - {(status) => } - - ); -} diff --git a/src/components/ClipboardButton/index.ts b/src/components/ClipboardButton/index.ts deleted file mode 100644 index 22aebf1cb9..0000000000 --- a/src/components/ClipboardButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ClipboardButton'; diff --git a/src/components/DeveloperUILinkButton/DeveloperUILinkButton.scss b/src/components/DeveloperUILinkButton/DeveloperUILinkButton.scss index 9bfd3fb965..33d9c7693f 100644 --- a/src/components/DeveloperUILinkButton/DeveloperUILinkButton.scss +++ b/src/components/DeveloperUILinkButton/DeveloperUILinkButton.scss @@ -1,12 +1,5 @@ -.developer-ui-link-button { - display: none; - - &_visible { - display: inline-block; - } +@import '../../styles/mixins.scss'; - .data-table__row:hover &, - .ydb-paginated-table__row:hover & { - display: inline-block; - } +.developer-ui-link-button { + @include table-hover-appearing-button(); } diff --git a/src/components/DeveloperUILinkButton/DeveloperUILinkButton.tsx b/src/components/DeveloperUILinkButton/DeveloperUILinkButton.tsx index b9126edba9..fc5041e900 100644 --- a/src/components/DeveloperUILinkButton/DeveloperUILinkButton.tsx +++ b/src/components/DeveloperUILinkButton/DeveloperUILinkButton.tsx @@ -1,22 +1,45 @@ import {ArrowUpRightFromSquare} from '@gravity-ui/icons'; +import type {ButtonSize} from '@gravity-ui/uikit'; import {Button, Icon} from '@gravity-ui/uikit'; import {cn} from '../../utils/cn'; +import i18n from './i18n'; + import './DeveloperUILinkButton.scss'; const b = cn('developer-ui-link-button'); +const buttonSizeToIconSize: Record = { + xs: 14, + s: 16, + m: 16, + l: 18, + xl: 18, +}; + interface DeveloperUiLinkProps { className?: string; visible?: boolean; href: string; + size?: ButtonSize; } -export function DeveloperUILinkButton({href, visible = false, className}: DeveloperUiLinkProps) { +export function DeveloperUILinkButton({ + href, + visible = false, + className, + size = 's', +}: DeveloperUiLinkProps) { return ( - ); } diff --git a/src/components/DeveloperUILinkButton/i18n/en.json b/src/components/DeveloperUILinkButton/i18n/en.json new file mode 100644 index 0000000000..47d941aadd --- /dev/null +++ b/src/components/DeveloperUILinkButton/i18n/en.json @@ -0,0 +1,3 @@ +{ + "action_go-to": "Go to {{href}}" +} diff --git a/src/components/DeveloperUILinkButton/i18n/index.ts b/src/components/DeveloperUILinkButton/i18n/index.ts new file mode 100644 index 0000000000..fc4abb3d22 --- /dev/null +++ b/src/components/DeveloperUILinkButton/i18n/index.ts @@ -0,0 +1,7 @@ +import {registerKeysets} from '../../../utils/i18n'; + +import en from './en.json'; + +const COMPONENT = 'ydb-developer-ui-button'; + +export default registerKeysets(COMPONENT, {en}); diff --git a/src/components/EntityStatus/EntityStatus.scss b/src/components/EntityStatus/EntityStatus.scss index 1e71601e0d..2e0b989d06 100644 --- a/src/components/EntityStatus/EntityStatus.scss +++ b/src/components/EntityStatus/EntityStatus.scss @@ -1,6 +1,8 @@ @import '../../styles/mixins.scss'; .entity-status { + position: relative; + display: inline-flex; align-items: center; @@ -14,24 +16,33 @@ } &__clipboard-button { + color: var(--g-color-text-secondary); + + @include table-hover-appearing-button(); + } + + &__controls-wrapper { + position: absolute; + top: 0; + right: 0; + display: flex; - flex-shrink: 0; + align-items: center; + gap: var(--g-spacing-1); - margin-left: var(--g-spacing-2); + width: 0; + height: 100%; - opacity: 0; - color: var(--g-color-text-secondary); + background-color: var(--g-color-base-float); - &_visible, - &:focus-visible { - opacity: 1; + .data-table__row:hover &, + .ydb-paginated-table__row:hover &, + .ydb-tree-view__item & { + width: min-content; + padding: var(--g-spacing-1); } } - &__additional-controls { - margin-left: var(--g-spacing-1); - } - &__label { margin-right: 2px; diff --git a/src/components/EntityStatus/EntityStatus.tsx b/src/components/EntityStatus/EntityStatus.tsx index 0f283067af..7866c92b2e 100644 --- a/src/components/EntityStatus/EntityStatus.tsx +++ b/src/components/EntityStatus/EntityStatus.tsx @@ -1,8 +1,7 @@ -import {Link as UIKitLink} from '@gravity-ui/uikit'; +import {ClipboardButton, Link as UIKitLink} from '@gravity-ui/uikit'; import {EFlag} from '../../types/api/enums'; import {cn} from '../../utils/cn'; -import {ClipboardButton} from '../ClipboardButton'; import {InternalLink} from '../InternalLink/InternalLink'; import {StatusIcon} from '../StatusIcon/StatusIcon'; import type {StatusIconMode, StatusIconSize} from '../StatusIcon/StatusIcon'; @@ -95,18 +94,21 @@ export function EntityStatus({ )} {renderLink()} - {hasClipboardButton && ( - - )} - {additionalControls && ( - {additionalControls} - )} +
+ {hasClipboardButton && ( + + )} + {additionalControls && ( + {additionalControls} + )} +
); } diff --git a/src/components/NodeHostWrapper/NodeHostWrapper.tsx b/src/components/NodeHostWrapper/NodeHostWrapper.tsx index 08f2a29a59..b185684d32 100644 --- a/src/components/NodeHostWrapper/NodeHostWrapper.tsx +++ b/src/components/NodeHostWrapper/NodeHostWrapper.tsx @@ -42,7 +42,9 @@ export const NodeHostWrapper = ({node, getNodeRef, database}: NodeHostWrapperPro }) : undefined; - const additionalControls = nodeHref ? : null; + const additionalControls = nodeHref ? ( + + ) : null; return ( = { hasClipboardButton showStatus={false} additionalControls={ - + } /> ); diff --git a/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx b/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx index 6e82fce557..32bb56c06e 100644 --- a/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx +++ b/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx @@ -2,13 +2,12 @@ import React from 'react'; import {DefinitionList, HelpPopover} from '@gravity-ui/components'; import type {DefinitionListSingleItem} from '@gravity-ui/components/build/esm/components/DefinitionList/types'; -import {Flex, Tabs} from '@gravity-ui/uikit'; +import {ClipboardButton, Flex, Tabs} from '@gravity-ui/uikit'; import qs from 'qs'; import {Link, useLocation} from 'react-router-dom'; import {StringParam, useQueryParam} from 'use-query-params'; import {AsyncReplicationState} from '../../../components/AsyncReplicationState'; -import {ClipboardButton} from '../../../components/ClipboardButton'; import {toFormattedSize} from '../../../components/FormattedBytes/utils'; import {LinkWithIcon} from '../../../components/LinkWithIcon/LinkWithIcon'; import SplitPane from '../../../components/SplitPane'; diff --git a/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx b/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx index d2b6b5d1b1..24174ae32a 100644 --- a/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx +++ b/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx @@ -1,10 +1,9 @@ import React from 'react'; import type {ControlGroupOption} from '@gravity-ui/uikit'; -import {RadioButton, Tabs, Text} from '@gravity-ui/uikit'; +import {ClipboardButton, RadioButton, Tabs, Text} from '@gravity-ui/uikit'; import JSONTree from 'react-json-inspector'; -import {ClipboardButton} from '../../../../components/ClipboardButton'; import Divider from '../../../../components/Divider/Divider'; import ElapsedTime from '../../../../components/ElapsedTime/ElapsedTime'; import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton'; diff --git a/src/containers/Tenant/Query/ExplainResult/ExplainResult.tsx b/src/containers/Tenant/Query/ExplainResult/ExplainResult.tsx index 8d0cc756ab..f9dd488f16 100644 --- a/src/containers/Tenant/Query/ExplainResult/ExplainResult.tsx +++ b/src/containers/Tenant/Query/ExplainResult/ExplainResult.tsx @@ -1,8 +1,7 @@ import React from 'react'; -import {RadioButton} from '@gravity-ui/uikit'; +import {ClipboardButton, RadioButton} from '@gravity-ui/uikit'; -import {ClipboardButton} from '../../../../components/ClipboardButton'; import Divider from '../../../../components/Divider/Divider'; import ElapsedTime from '../../../../components/ElapsedTime/ElapsedTime'; import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton'; diff --git a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.scss b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.scss index eab9045085..d3cf9f69cb 100644 --- a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.scss +++ b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.scss @@ -65,5 +65,9 @@ opacity: 0; color: var(--g-color-text-secondary); + .ydb-tree-view__item:hover &, + &:focus-visible { + opacity: 1; + } } } diff --git a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx index 2d28792ba7..12084b30a8 100644 --- a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx +++ b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx @@ -1,6 +1,5 @@ -import {Progress} from '@gravity-ui/uikit'; +import {ClipboardButton, Progress} from '@gravity-ui/uikit'; -import {ClipboardButton} from '../../../components/ClipboardButton'; import type {VersionValue} from '../../../types/versions'; import {cn} from '../../../utils/cn'; import type {PreparedNodeSystemState} from '../../../utils/nodes'; @@ -46,7 +45,12 @@ export const NodesTreeTitle = ({ {title ? ( {title} - + ) : null} diff --git a/src/styles/mixins.scss b/src/styles/mixins.scss index abb3bc7000..141e05df8b 100644 --- a/src/styles/mixins.scss +++ b/src/styles/mixins.scss @@ -368,3 +368,29 @@ --entity-state-border-color: var(--g-color-line-generic-hover); } } + +@mixin table-hover-appearing-button { + opacity: 0; + + &_visible, + &:focus-visible { + opacity: 1; + } + &:focus-visible { + position: absolute; + top: 2px; + right: 2px; + + background-color: var(--g-color-base-float); + } + .data-table__row:hover &, + .ydb-paginated-table__row:hover & { + opacity: 1; + } + .data-table__row:hover &:focus-visible, + .ydb-paginated-table__row:hover &:focus-visible { + position: static; + + background-color: unset; + } +}