Arrow Fill Button
vault-hyperiux/arrow-fill-buttonFreeComponent
Button with expanding circle fill and animated arrow icon on hover
Install it
npx shadcn@latest add https://vault.hyperiux.com/r/arrow-fill-button.jsonSource
1// Built using Hyperiux Vault: https://vault.hyperiux.com23"use client";45import { useEffect, useRef, useState } from "react";6import { ArrowRight } from "lucide-react";78const DEFAULT_HREF = "#";9const COMPACT_LAYOUT_BREAKPOINT = 1280;10const ANIMATION_DURATION_MS = 450;1112function ArrowFillButton({13 btnText="Hover Me",14 href = DEFAULT_HREF,15 className = "",1617 bgColor = "#ff5f00",18 textColor = "#ffffff",1920 fillBgColor = "#ffffff",21 fillTextColor = "#ff5f00",2223 hoverFillBgColor = "#ffffff",24 hoverFillTextColor = "#ff5f00",2526 arrowColor,27 hoverArrowColor,2829 ...props30}) {31 const [isReady, setIsReady] = useState(false);32 const [isCompactLayout, setIsCompactLayout] = useState(false);33 const [isPressed, setIsPressed] = useState(false);34 const releaseTimeoutRef = useRef(null);3536 const usesUtilityBackground =37 className.includes("bg-") ||38 className.includes("from-") ||39 className.includes("via-") ||40 className.includes("to-");4142 useEffect(() => {43 const frame = window.requestAnimationFrame(() => {44 setIsReady(true);45 });4647 return () => window.cancelAnimationFrame(frame);48 }, []);4950 useEffect(() => {51 const mediaQuery = window.matchMedia(52 `(max-width: ${COMPACT_LAYOUT_BREAKPOINT - 1}px)`53 );5455 const syncCompactLayout = (event) => {56 const matches = "matches" in event ? event.matches : event.currentTarget.matches;57 setIsCompactLayout(matches);5859 if (!matches) {60 setIsPressed(false);61 }62 };6364 syncCompactLayout(mediaQuery);65 mediaQuery.addEventListener("change", syncCompactLayout);6667 return () => {68 mediaQuery.removeEventListener("change", syncCompactLayout);69 };70 }, []);7172 useEffect(() => {73 return () => {74 if (releaseTimeoutRef.current) {75 window.clearTimeout(releaseTimeoutRef.current);76 }77 };78 }, []);7980 const clearPressedState = () => {81 if (releaseTimeoutRef.current) {82 window.clearTimeout(releaseTimeoutRef.current);83 }8485 releaseTimeoutRef.current = window.setTimeout(() => {86 setIsPressed(false);87 releaseTimeoutRef.current = null;88 }, ANIMATION_DURATION_MS);89 };9091 const handlePointerDown = (event) => {92 props.onPointerDown?.(event);9394 if (!isCompactLayout || event.pointerType === "mouse") {95 return;96 }9798 if (releaseTimeoutRef.current) {99 window.clearTimeout(releaseTimeoutRef.current);100 releaseTimeoutRef.current = null;101 }102103 setIsPressed(true);104 };105106// … truncated
What it pulls in
npm packages
More from vault-hyperiux
All 115 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| 3D Portfolio Slider3d-portfolio-slider | vault-hyperiux | Components | Free | 3 deps | |
| Animated FAQanimated-faq | vault-hyperiux | Components | Free | 2 deps | |
| Animated Formanimated-form | vault-hyperiux | Components | Free | 1 dep | |
| Animated Modalanimated-modal | vault-hyperiux | Components | Free | 1 dep | |
| Tabsanimated-tabs | vault-hyperiux | Components | Free | 1 dep | |
| Animated Toggleanimated-toggle | vault-hyperiux | Components | Free | no deps | |
| Block Transitionblock-transition | vault-hyperiux | Components | Free | 2 deps | |
| Blur Textblur-text | vault-hyperiux | Components | Free | 1 dep |
