"use client";
import {
motion,
useReducedMotion,
type HTMLMotionProps,
} from "motion/react";
import {
forwardRef,
useState,
type FocusEvent,
type MouseEvent,
type ReactNode,
} from "react";
import { EASE_OUT, SPRING_LAYOUT, SPRING_PRESS } from "@/lib/ease";
import { useHoverCapable } from "@/lib/hooks/use-hover-capable";
import { cn } from "@/lib/utils";
export interface ExpandingArrowButtonProps extends Omit<
HTMLMotionProps<"button">,
"children"
> {
children: ReactNode;
accentClassName?: string;
labelClassName?: string;
}
const ARROW_OPACITY = [1, 0.78, 0.54, 0.32, 0.16] as const;
function DottedChevron({ className }: { className?: string }) {
return (
);
}
export const ExpandingArrowButton = forwardRef<
HTMLButtonElement,
ExpandingArrowButtonProps
>(function ExpandingArrowButton(
{
children,
className,
accentClassName,
labelClassName,
disabled,
onMouseEnter,
onMouseLeave,
onFocus,
onBlur,
...rest
},
ref,
) {
const reduce = useReducedMotion();
const canHover = useHoverCapable();
const [hovered, setHovered] = useState(false);
const [focused, setFocused] = useState(false);
const active = !disabled && ((canHover && hovered) || focused);
const layoutTransition = reduce ? { duration: 0 } : SPRING_LAYOUT;
const handleMouseEnter = (event: MouseEvent) => {
setHovered(true);
onMouseEnter?.(event);
};
const handleMouseLeave = (event: MouseEvent) => {
setHovered(false);
onMouseLeave?.(event);
};
const handleFocus = (event: FocusEvent) => {
setFocused(true);
onFocus?.(event);
};
const handleBlur = (event: FocusEvent) => {
setFocused(false);
onBlur?.(event);
};
return (
{ARROW_OPACITY.map((opacity, index) => (
))}
{children}
);
});