Files
community-rule/app/components/ToggleGroup.tsx
T
adilallo f6a0673082
CI Pipeline / test (20) (pull_request) Failing after 1m17s
CI Pipeline / test (18) (pull_request) Failing after 1m28s
CI Pipeline / e2e (chromium) (pull_request) Failing after 1m33s
CI Pipeline / e2e (firefox) (pull_request) Failing after 1m27s
CI Pipeline / e2e (webkit) (pull_request) Failing after 1m34s
CI Pipeline / visual-regression (pull_request) Failing after 2m9s
CI Pipeline / storybook (pull_request) Failing after 1m5s
CI Pipeline / performance (pull_request) Failing after 1m42s
CI Pipeline / lint (pull_request) Failing after 49s
CI Pipeline / build (pull_request) Failing after 1m29s
Convert from JSX to TSX
2025-12-10 22:14:17 -07:00

155 lines
4.1 KiB
TypeScript

import React, { memo, useCallback, useId, forwardRef } from "react";
interface ToggleGroupProps
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange"> {
children?: React.ReactNode;
className?: string;
position?: "left" | "middle" | "right";
state?: "default" | "hover" | "focus" | "selected";
showText?: boolean;
ariaLabel?: string;
onChange?: (
e:
| React.MouseEvent<HTMLButtonElement>
| React.KeyboardEvent<HTMLButtonElement>
) => void;
onFocus?: (e: React.FocusEvent<HTMLButtonElement>) => void;
onBlur?: (e: React.FocusEvent<HTMLButtonElement>) => void;
}
const ToggleGroup = memo(
forwardRef<HTMLButtonElement, ToggleGroupProps>((props, ref) => {
const {
children,
className = "",
position = "left",
state = "default",
showText = true,
ariaLabel,
onChange,
onFocus,
onBlur,
...rest
} = props;
const groupId = useId();
// Position-based styling for border radius
const getPositionStyles = useCallback((pos: string): string => {
switch (pos) {
case "left":
return "rounded-l-[var(--measures-radius-medium)] rounded-r-none";
case "middle":
return "rounded-none";
case "right":
return "rounded-r-[var(--measures-radius-medium)] rounded-l-none";
default:
return "rounded-[var(--measures-radius-medium)]";
}
}, []);
// State-based styling
const getStateStyles = useCallback((state: string): string => {
switch (state) {
case "hover":
return "bg-[var(--color-magenta-magenta100)] text-[var(--color-content-default-primary)]";
case "focus":
return "bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] shadow-[0_0_5px_1px_#3281F8]";
case "selected":
return "bg-[var(--color-magenta-magenta100)] text-[var(--color-content-default-primary)] shadow-[inset_0_0_0_1px_var(--color-border-default-secondary)]";
case "default":
default:
return "bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)]";
}
}, []);
const positionStyles = getPositionStyles(position);
const stateStyles = getStateStyles(state);
const handleClick = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
if (onChange) {
onChange(e);
}
},
[onChange]
);
const handleFocus = useCallback(
(e: React.FocusEvent<HTMLButtonElement>) => {
if (onFocus) {
onFocus(e);
}
},
[onFocus]
);
const handleBlur = useCallback(
(e: React.FocusEvent<HTMLButtonElement>) => {
if (onBlur) {
onBlur(e);
}
},
[onBlur]
);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLButtonElement>) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
if (onChange) {
onChange(e);
}
}
},
[onChange]
);
const toggleClasses = `
${positionStyles}
${stateStyles}
py-[var(--measures-spacing-008)]
px-[var(--measures-spacing-008)]
gap-[var(--measures-spacing-008)]
font-inter
font-medium
text-[12px]
leading-[12px]
cursor-pointer
transition-all
duration-200
focus:outline-none
focus-visible:shadow-[0_0_5px_1px_#3281F8]
hover:bg-[var(--color-magenta-magenta100)]
flex
items-center
justify-center
${className}
`
.trim()
.replace(/\s+/g, " ");
return (
<button
ref={ref}
id={groupId}
type="button"
role="button"
aria-label={ariaLabel || (showText ? undefined : "Toggle option")}
onClick={handleClick}
onKeyDown={handleKeyDown}
onFocus={handleFocus}
onBlur={handleBlur}
className={toggleClasses}
{...rest}
>
{showText ? children : children || "☰"}
</button>
);
})
);
ToggleGroup.displayName = "ToggleGroup";
export default ToggleGroup;