File size: 3,832 Bytes
9b906ea | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import React from "react";
import { useTranslation } from "react-i18next";
import PlusIcon from "#/icons/u-plus.svg?react";
import CheckmarkIcon from "#/icons/checkmark.svg?react";
import RemoveIcon from "#/icons/x-mark.svg?react";
import { StyledTooltip } from "#/components/shared/buttons/styled-tooltip";
import { I18nKey } from "#/i18n/declaration";
import { cn } from "#/utils/utils";
interface CirclePlusCheckToggleProps {
testId?: string;
isSelected: boolean;
onToggle: (selected: boolean) => void;
isDisabled?: boolean;
className?: string;
enableLabelKey?: I18nKey;
disableLabelKey?: I18nKey;
enableTooltipKey?: I18nKey;
disableTooltipKey?: I18nKey;
removeTooltipKey?: I18nKey;
}
export function CirclePlusBadge({
className,
testId,
tooltipKey = I18nKey.AUTOMATIONS$ADD_AUTOMATION,
}: {
className?: string;
testId?: string;
tooltipKey?: I18nKey;
}) {
const { t } = useTranslation("openhands");
return (
<StyledTooltip content={t(tooltipKey)} placement="top">
<span
aria-hidden="true"
data-testid={testId}
className={cn(
"inline-flex size-7 shrink-0 items-center justify-center rounded-full bg-surface-raised text-white transition-colors hover:bg-[var(--oh-interactive-hover)]",
className,
)}
>
<PlusIcon className="size-3" />
</span>
</StyledTooltip>
);
}
export function CirclePlusCheckToggle({
testId,
isSelected,
onToggle,
isDisabled = false,
className,
enableLabelKey = I18nKey.SETTINGS$SKILLS_ENABLE_SKILL,
disableLabelKey = I18nKey.SETTINGS$SKILLS_DISABLE_SKILL,
enableTooltipKey = I18nKey.COMMON$ENABLE,
disableTooltipKey,
removeTooltipKey = I18nKey.COMMON$REMOVE,
}: CirclePlusCheckToggleProps) {
const { t } = useTranslation("openhands");
const [isPointerOver, setIsPointerOver] = React.useState(false);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
if (isDisabled) {
return;
}
onToggle(!isSelected);
event.currentTarget.blur();
};
const showRemoveIcon = isSelected && isPointerOver;
const selectedTooltipKey = disableTooltipKey ?? removeTooltipKey;
const tooltipLabel = t(isSelected ? selectedTooltipKey : enableTooltipKey);
const ariaLabel = t(isSelected ? disableLabelKey : enableLabelKey);
return (
<StyledTooltip content={tooltipLabel} placement="top">
<button
type="button"
role="switch"
aria-checked={isSelected}
data-testid={testId}
data-showing-remove={showRemoveIcon ? "true" : "false"}
disabled={isDisabled}
aria-label={ariaLabel}
onClick={handleClick}
onPointerEnter={() => setIsPointerOver(true)}
onPointerLeave={() => setIsPointerOver(false)}
className={cn(
"inline-flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-full p-0 transition-colors",
isSelected &&
(showRemoveIcon
? "border-0 bg-[rgba(248,113,113,0.14)] text-[#ef4444] hover:bg-[rgba(248,113,113,0.24)]"
: "border border-white bg-transparent text-white [&_path]:fill-current"),
!isSelected &&
"border-0 bg-surface-raised text-white hover:bg-[var(--oh-interactive-hover)]",
isDisabled && "cursor-not-allowed opacity-50",
className,
)}
>
{isSelected ? (
showRemoveIcon ? (
<RemoveIcon
aria-hidden
width={14}
height={14}
className="stroke-[2.5]"
/>
) : (
<CheckmarkIcon aria-hidden width={14} height={14} />
)
) : (
<PlusIcon aria-hidden className="size-3" />
)}
</button>
</StyledTooltip>
);
}
|