mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-08 22:38:05 -05:00
fix: prevent nested buttons in tooltip button (#12177)
Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { TooltipButton } from "#/components/shared/buttons/tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
|
||||
interface ChatActionTooltipProps {
|
||||
children: React.ReactNode;
|
||||
tooltip: string | React.ReactNode;
|
||||
ariaLabel: string;
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
export function ChatActionTooltip({
|
||||
@@ -12,14 +12,12 @@ export function ChatActionTooltip({
|
||||
ariaLabel,
|
||||
}: ChatActionTooltipProps) {
|
||||
return (
|
||||
<TooltipButton
|
||||
tooltip={tooltip}
|
||||
ariaLabel={ariaLabel}
|
||||
disabled={false}
|
||||
<StyledTooltip
|
||||
content={tooltip}
|
||||
placement="bottom"
|
||||
tooltipClassName="bg-white text-black text-xs font-medium leading-5"
|
||||
>
|
||||
{children}
|
||||
</TooltipButton>
|
||||
<span data-aria-label={ariaLabel}>{children}</span>
|
||||
</StyledTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { cn } from "#/utils/utils";
|
||||
import { CopyToClipboardButton } from "#/components/shared/buttons/copy-to-clipboard-button";
|
||||
import { OpenHandsSourceType } from "#/types/core/base";
|
||||
import { TooltipButton } from "#/components/shared/buttons/tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
import { MarkdownRenderer } from "../markdown/markdown-renderer";
|
||||
|
||||
interface ChatMessageProps {
|
||||
@@ -53,7 +53,7 @@ export function ChatMessage({
|
||||
className={cn(
|
||||
"rounded-xl relative w-fit max-w-full last:mb-4",
|
||||
"flex flex-col gap-2",
|
||||
type === "user" && " p-4 bg-tertiary self-end",
|
||||
type === "user" && "p-4 bg-tertiary self-end",
|
||||
type === "agent" && "mt-6 w-full max-w-full bg-transparent",
|
||||
isFromPlanningAgent && "border border-[#597ff4] bg-tertiary p-4",
|
||||
)}
|
||||
@@ -67,21 +67,16 @@ export function ChatMessage({
|
||||
>
|
||||
{actions?.map((action, index) =>
|
||||
action.tooltip ? (
|
||||
<TooltipButton
|
||||
key={index}
|
||||
tooltip={action.tooltip}
|
||||
ariaLabel={action.tooltip}
|
||||
placement="top"
|
||||
>
|
||||
<StyledTooltip key={index} content={action.tooltip} placement="top">
|
||||
<button
|
||||
type="button"
|
||||
onClick={action.onClick}
|
||||
className="button-base p-1 cursor-pointer"
|
||||
aria-label={`Action ${index + 1}`}
|
||||
aria-label={action.tooltip}
|
||||
>
|
||||
{action.icon}
|
||||
</button>
|
||||
</TooltipButton>
|
||||
</StyledTooltip>
|
||||
) : (
|
||||
<button
|
||||
key={index}
|
||||
@@ -112,6 +107,7 @@ export function ChatMessage({
|
||||
>
|
||||
<MarkdownRenderer includeStandard>{message}</MarkdownRenderer>
|
||||
</div>
|
||||
|
||||
{children}
|
||||
</article>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TooltipButton } from "#/components/shared/buttons/tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
|
||||
interface GitControlBarTooltipWrapperProps {
|
||||
tooltipMessage: string;
|
||||
@@ -18,16 +18,15 @@ export function GitControlBarTooltipWrapper({
|
||||
}
|
||||
|
||||
return (
|
||||
<TooltipButton
|
||||
tooltip={tooltipMessage}
|
||||
ariaLabel={tooltipMessage}
|
||||
testId={testId}
|
||||
<StyledTooltip
|
||||
content={tooltipMessage}
|
||||
placement="top"
|
||||
className="hover:opacity-100"
|
||||
tooltipClassName="bg-white text-black"
|
||||
showArrow
|
||||
tooltipClassName="bg-white text-black"
|
||||
>
|
||||
{children}
|
||||
</TooltipButton>
|
||||
<span data-testid={testId} className="hover:opacity-100">
|
||||
{children}
|
||||
</span>
|
||||
</StyledTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { ConversationStatus } from "#/types/conversation-status";
|
||||
import { cn, getConversationStatusLabel } from "#/utils/utils";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { TooltipButton } from "#/components/shared/buttons/tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
|
||||
interface ConversationStatusIndicatorProps {
|
||||
conversationStatus: ConversationStatus;
|
||||
@@ -17,7 +17,7 @@ export function ConversationStatusIndicator({
|
||||
const conversationStatusBackgroundColor = useMemo(() => {
|
||||
switch (conversationStatus) {
|
||||
case "STOPPED":
|
||||
return "bg-[#3C3C49]"; // Inactive/stopped - grey
|
||||
return "bg-[#3C3C49]";
|
||||
case "RUNNING":
|
||||
return "bg-[#1FBD53]"; // Running/online - green
|
||||
case "STARTING":
|
||||
@@ -34,13 +34,10 @@ export function ConversationStatusIndicator({
|
||||
);
|
||||
|
||||
return (
|
||||
<TooltipButton
|
||||
tooltip={statusLabel}
|
||||
ariaLabel={statusLabel}
|
||||
<StyledTooltip
|
||||
content={statusLabel}
|
||||
placement="right"
|
||||
showArrow
|
||||
asSpan
|
||||
className="p-0 border-0 bg-transparent hover:opacity-100"
|
||||
tooltipClassName="bg-[#1a1a1a] text-white text-xs shadow-lg"
|
||||
>
|
||||
<div
|
||||
@@ -49,6 +46,6 @@ export function ConversationStatusIndicator({
|
||||
conversationStatusBackgroundColor,
|
||||
)}
|
||||
/>
|
||||
</TooltipButton>
|
||||
</StyledTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { GitProviderIcon } from "#/components/shared/git-provider-icon";
|
||||
import { GitRepository } from "#/types/git";
|
||||
import { MicroagentManagementAddMicroagentButton } from "./microagent-management-add-microagent-button";
|
||||
import { TooltipButton } from "#/components/shared/buttons/tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
|
||||
interface MicroagentManagementAccordionTitleProps {
|
||||
repository: GitRepository;
|
||||
@@ -14,17 +14,17 @@ export function MicroagentManagementAccordionTitle({
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<GitProviderIcon gitProvider={repository.git_provider} />
|
||||
<TooltipButton
|
||||
tooltip={repository.full_name}
|
||||
ariaLabel={repository.full_name}
|
||||
testId="repository-name-tooltip"
|
||||
placement="bottom"
|
||||
asSpan
|
||||
className="text-white text-base font-normal bg-transparent p-0 min-w-0 h-auto cursor-pointer truncate max-w-[194px] translate-y-[-1px]"
|
||||
>
|
||||
<span>{repository.full_name}</span>
|
||||
</TooltipButton>
|
||||
|
||||
<StyledTooltip content={repository.full_name} placement="bottom">
|
||||
<span
|
||||
className="text-white text-base font-normal bg-transparent p-0 min-w-0 h-auto cursor-pointer truncate max-w-[194px] translate-y-[-1px]"
|
||||
data-testid="repository-name-tooltip"
|
||||
>
|
||||
{repository.full_name}
|
||||
</span>
|
||||
</StyledTooltip>
|
||||
</div>
|
||||
|
||||
<MicroagentManagementAddMicroagentButton repository={repository} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import ListIcon from "#/icons/list.svg?react";
|
||||
import { TooltipButton } from "./tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
import { cn } from "#/utils/utils";
|
||||
|
||||
interface ConversationPanelButtonProps {
|
||||
@@ -17,23 +17,28 @@ export function ConversationPanelButton({
|
||||
}: ConversationPanelButtonProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const label = t(I18nKey.SIDEBAR$CONVERSATIONS);
|
||||
|
||||
return (
|
||||
<TooltipButton
|
||||
testId="toggle-conversation-panel"
|
||||
tooltip={t(I18nKey.SIDEBAR$CONVERSATIONS)}
|
||||
ariaLabel={t(I18nKey.SIDEBAR$CONVERSATIONS)}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
<ListIcon
|
||||
width={24}
|
||||
height={24}
|
||||
className={cn(
|
||||
"cursor-pointer",
|
||||
isOpen ? "text-white" : "text-[#B1B9D3]",
|
||||
disabled && "opacity-50",
|
||||
)}
|
||||
/>
|
||||
</TooltipButton>
|
||||
<StyledTooltip content={label}>
|
||||
<button
|
||||
type="button"
|
||||
data-testid="toggle-conversation-panel"
|
||||
aria-label={label}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
className="p-0 bg-transparent border-0"
|
||||
>
|
||||
<ListIcon
|
||||
width={24}
|
||||
height={24}
|
||||
className={cn(
|
||||
"cursor-pointer",
|
||||
isOpen ? "text-white" : "text-[#B1B9D3]",
|
||||
disabled && "opacity-50",
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NavLink } from "react-router";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { TooltipButton } from "./tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
import RobotIcon from "#/icons/robot.svg?react";
|
||||
|
||||
interface MicroagentManagementButtonProps {
|
||||
@@ -15,14 +16,21 @@ export function MicroagentManagementButton({
|
||||
const microagentManagement = t(I18nKey.MICROAGENT_MANAGEMENT$TITLE);
|
||||
|
||||
return (
|
||||
<TooltipButton
|
||||
tooltip={microagentManagement}
|
||||
ariaLabel={microagentManagement}
|
||||
navLinkTo="/microagent-management"
|
||||
testId="microagent-management-button"
|
||||
disabled={disabled}
|
||||
>
|
||||
<RobotIcon width={28} height={28} />
|
||||
</TooltipButton>
|
||||
<StyledTooltip content={microagentManagement}>
|
||||
<NavLink
|
||||
to="/microagent-management"
|
||||
data-testid="microagent-management-button"
|
||||
aria-label={microagentManagement}
|
||||
tabIndex={disabled ? -1 : 0}
|
||||
onClick={(e) => {
|
||||
if (disabled) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
className={disabled ? "pointer-events-none opacity-50" : undefined}
|
||||
>
|
||||
<RobotIcon width={28} height={28} />
|
||||
</NavLink>
|
||||
</StyledTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,41 @@
|
||||
import { useLocation } from "react-router";
|
||||
import { NavLink } from "react-router";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { TooltipButton } from "./tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
import PlusIcon from "#/icons/u-plus.svg?react";
|
||||
import { cn } from "#/utils/utils";
|
||||
|
||||
interface NewProjectButtonProps {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export function NewProjectButton({ disabled = false }: NewProjectButtonProps) {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const startNewProject = t(I18nKey.CONVERSATION$START_NEW);
|
||||
|
||||
return (
|
||||
<TooltipButton
|
||||
tooltip={startNewProject}
|
||||
ariaLabel={startNewProject}
|
||||
navLinkTo="/"
|
||||
testId="new-project-button"
|
||||
disabled={disabled}
|
||||
<StyledTooltip
|
||||
content={startNewProject}
|
||||
placement="right"
|
||||
tooltipClassName="bg-transparent"
|
||||
>
|
||||
<PlusIcon
|
||||
width={24}
|
||||
height={24}
|
||||
color={pathname === "/" ? "#ffffff" : "#B1B9D3"}
|
||||
/>
|
||||
</TooltipButton>
|
||||
<NavLink
|
||||
to="/"
|
||||
data-testid="new-project-button"
|
||||
aria-label={startNewProject}
|
||||
tabIndex={disabled ? -1 : 0}
|
||||
onClick={(e) => {
|
||||
if (disabled) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
className={cn("inline-flex items-center justify-center", {
|
||||
"pointer-events-none opacity-50": disabled,
|
||||
})}
|
||||
>
|
||||
<PlusIcon width={24} height={24} />
|
||||
</NavLink>
|
||||
</StyledTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import { NavLink } from "react-router";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import OpenHandsLogo from "#/assets/branding/openhands-logo.svg?react";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { TooltipButton } from "./tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
|
||||
export function OpenHandsLogoButton() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const tooltipText = t(I18nKey.BRANDING$OPENHANDS);
|
||||
const ariaLabel = t(I18nKey.BRANDING$OPENHANDS_LOGO);
|
||||
|
||||
return (
|
||||
<TooltipButton
|
||||
tooltip={t(I18nKey.BRANDING$OPENHANDS)}
|
||||
ariaLabel={t(I18nKey.BRANDING$OPENHANDS_LOGO)}
|
||||
navLinkTo="/"
|
||||
>
|
||||
<OpenHandsLogo width={46} height={30} />
|
||||
</TooltipButton>
|
||||
<StyledTooltip content={tooltipText}>
|
||||
<NavLink to="/" aria-label={ariaLabel}>
|
||||
<OpenHandsLogo width={46} height={30} />
|
||||
</NavLink>
|
||||
</StyledTooltip>
|
||||
);
|
||||
}
|
||||
|
||||
32
frontend/src/components/shared/buttons/styled-tooltip.tsx
Normal file
32
frontend/src/components/shared/buttons/styled-tooltip.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Tooltip, TooltipProps } from "@heroui/react";
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
export interface StyledTooltipProps {
|
||||
children: ReactNode;
|
||||
content: string | ReactNode;
|
||||
tooltipClassName?: React.HTMLAttributes<HTMLDivElement>["className"];
|
||||
placement?: TooltipProps["placement"];
|
||||
showArrow?: boolean;
|
||||
closeDelay?: number;
|
||||
}
|
||||
|
||||
export function StyledTooltip({
|
||||
children,
|
||||
content,
|
||||
tooltipClassName,
|
||||
placement = "right",
|
||||
showArrow = false,
|
||||
closeDelay = 100,
|
||||
}: StyledTooltipProps) {
|
||||
return (
|
||||
<Tooltip
|
||||
content={content}
|
||||
closeDelay={closeDelay}
|
||||
placement={placement}
|
||||
className={tooltipClassName}
|
||||
showArrow={showArrow}
|
||||
>
|
||||
<div className="inline-flex">{children}</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
import { Tooltip, TooltipProps } from "@heroui/react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { NavLink } from "react-router";
|
||||
import { cn } from "#/utils/utils";
|
||||
|
||||
export interface TooltipButtonProps {
|
||||
children: ReactNode;
|
||||
tooltip: string | ReactNode;
|
||||
onClick?: () => void;
|
||||
href?: string;
|
||||
navLinkTo?: string;
|
||||
ariaLabel: string;
|
||||
testId?: string;
|
||||
className?: React.HTMLAttributes<HTMLButtonElement>["className"];
|
||||
tooltipClassName?: React.HTMLAttributes<HTMLDivElement>["className"];
|
||||
disabled?: boolean;
|
||||
placement?: TooltipProps["placement"];
|
||||
showArrow?: boolean;
|
||||
asSpan?: boolean;
|
||||
}
|
||||
|
||||
export function TooltipButton({
|
||||
children,
|
||||
tooltip,
|
||||
onClick,
|
||||
href,
|
||||
navLinkTo,
|
||||
ariaLabel,
|
||||
testId,
|
||||
className,
|
||||
tooltipClassName,
|
||||
disabled = false,
|
||||
placement = "right",
|
||||
showArrow = false,
|
||||
asSpan = false,
|
||||
}: TooltipButtonProps) {
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
if (onClick && !disabled) {
|
||||
onClick();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
const isClickable = !!onClick && !disabled;
|
||||
let buttonContent: React.ReactNode;
|
||||
if (asSpan) {
|
||||
if (isClickable) {
|
||||
buttonContent = (
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId}
|
||||
onClick={handleClick}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
onClick();
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"hover:opacity-80",
|
||||
disabled && "opacity-50 cursor-not-allowed",
|
||||
className,
|
||||
)}
|
||||
aria-disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
buttonContent = (
|
||||
<span
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId}
|
||||
className={cn(
|
||||
"hover:opacity-80",
|
||||
disabled && "opacity-50 cursor-not-allowed",
|
||||
className,
|
||||
)}
|
||||
aria-disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
buttonContent = (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId}
|
||||
onClick={handleClick}
|
||||
className={cn(
|
||||
"hover:opacity-80",
|
||||
disabled && "opacity-50 cursor-not-allowed",
|
||||
className,
|
||||
)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
let content;
|
||||
|
||||
if (navLinkTo && !disabled) {
|
||||
content = (
|
||||
<NavLink
|
||||
to={navLinkTo}
|
||||
onClick={handleClick}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
"hover:opacity-80",
|
||||
isActive ? "text-white" : "text-[#9099AC]",
|
||||
className,
|
||||
)
|
||||
}
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId}
|
||||
>
|
||||
{children}
|
||||
</NavLink>
|
||||
);
|
||||
} else if (navLinkTo && disabled) {
|
||||
// If disabled and has navLinkTo, render a button that looks like a NavLink but doesn't navigate
|
||||
content = (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId}
|
||||
className={cn(
|
||||
"text-[#9099AC]",
|
||||
"opacity-50 cursor-not-allowed",
|
||||
className,
|
||||
)}
|
||||
disabled
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
} else if (href && !disabled) {
|
||||
content = (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className={cn("hover:opacity-80", className)}
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
} else if (href && disabled) {
|
||||
// If disabled and has href, render a button that looks like a link but doesn't navigate
|
||||
content = (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId}
|
||||
className={cn("opacity-50 cursor-not-allowed", className)}
|
||||
disabled
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
content = buttonContent;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
content={tooltip}
|
||||
closeDelay={100}
|
||||
placement={placement}
|
||||
className={tooltipClassName}
|
||||
showArrow={showArrow}
|
||||
>
|
||||
{content}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { useSettings } from "#/hooks/query/use-settings";
|
||||
import { hasAdvancedSettingsSet } from "#/utils/has-advanced-settings-set";
|
||||
import { useSaveSettings } from "#/hooks/mutation/use-save-settings";
|
||||
import { SettingsSwitch } from "#/components/features/settings/settings-switch";
|
||||
import { TooltipButton } from "#/components/shared/buttons/tooltip-button";
|
||||
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
|
||||
import QuestionCircleIcon from "#/icons/question-circle.svg?react";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { SettingsInput } from "#/components/features/settings/settings-input";
|
||||
@@ -693,13 +693,13 @@ function LlmSettingsScreen() {
|
||||
>
|
||||
{t(I18nKey.SETTINGS$CONFIRMATION_MODE)}
|
||||
</SettingsSwitch>
|
||||
<TooltipButton
|
||||
tooltip={t(I18nKey.SETTINGS$CONFIRMATION_MODE_TOOLTIP)}
|
||||
ariaLabel={t(I18nKey.SETTINGS$CONFIRMATION_MODE)}
|
||||
className="text-[#9099AC] hover:text-white cursor-help"
|
||||
<StyledTooltip
|
||||
content={t(I18nKey.SETTINGS$CONFIRMATION_MODE_TOOLTIP)}
|
||||
>
|
||||
<QuestionCircleIcon width={16} height={16} />
|
||||
</TooltipButton>
|
||||
<span className="text-[#9099AC] hover:text-white cursor-help">
|
||||
<QuestionCircleIcon width={16} height={16} />
|
||||
</span>
|
||||
</StyledTooltip>
|
||||
</div>
|
||||
|
||||
{confirmationModeEnabled && (
|
||||
|
||||
Reference in New Issue
Block a user