Initial commit
This commit is contained in:
53
src/components/tag/Tag.tsx
Normal file
53
src/components/tag/Tag.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { useRive, Layout, Fit } from "@rive-app/react-canvas";
|
||||
import { useTagEffects } from "./useTagEffects";
|
||||
import { useRiveHoverInput } from "./useRiveHoverInput";
|
||||
|
||||
const STATE_MACHINE_NAME = "State Machine 1";
|
||||
const HOVER_INPUT_NAME = "Hover";
|
||||
|
||||
export const Tag = () => {
|
||||
const { shouldShow, handleMouseEnter, handleClick, buttonClassName } = useTagEffects();
|
||||
|
||||
const { rive, RiveComponent } = useRive({
|
||||
src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/default/watermark-bob2.riv",
|
||||
stateMachines: STATE_MACHINE_NAME,
|
||||
autoplay: true,
|
||||
layout: new Layout({
|
||||
fit: Fit.Contain,
|
||||
}),
|
||||
});
|
||||
|
||||
const setHover = useRiveHoverInput(rive, STATE_MACHINE_NAME, HOVER_INPUT_NAME);
|
||||
|
||||
const handleTagClick = () => {
|
||||
window.open("https://webild.io", "_blank", "noopener,noreferrer");
|
||||
};
|
||||
|
||||
const onMouseEnter = () => {
|
||||
handleMouseEnter();
|
||||
setHover(true);
|
||||
};
|
||||
|
||||
const onMouseLeave = () => {
|
||||
setHover(false);
|
||||
};
|
||||
|
||||
if (!shouldShow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Webild tag"
|
||||
className={`fixed z-[99999] bottom-6 right-6 w-[160px] h-[92px] cursor-pointer ${buttonClassName}`}
|
||||
onClick={(e) => handleClick(e, handleTagClick)}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<RiveComponent className="w-full h-full" />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tag;
|
||||
30
src/components/tag/useRiveHoverInput.ts
Normal file
30
src/components/tag/useRiveHoverInput.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
import { useStateMachineInput } from "@rive-app/react-canvas";
|
||||
|
||||
export function useRiveHoverInput(
|
||||
rive: unknown,
|
||||
stateMachineName: string,
|
||||
hoverInputName: string
|
||||
) {
|
||||
const hoverInput = useStateMachineInput(
|
||||
rive as never,
|
||||
stateMachineName,
|
||||
hoverInputName
|
||||
);
|
||||
|
||||
const hoverInputRef = useRef<typeof hoverInput | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
hoverInputRef.current = hoverInput ?? null;
|
||||
}, [hoverInput]);
|
||||
|
||||
return useCallback(
|
||||
(isHovering: boolean) => {
|
||||
const input = hoverInputRef.current;
|
||||
if (!input) return;
|
||||
input.value = isHovering;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
54
src/components/tag/useTagEffects.ts
Normal file
54
src/components/tag/useTagEffects.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { useRef, useEffect, useCallback, useState } from "react";
|
||||
|
||||
export function useTagEffects<T extends HTMLElement = HTMLButtonElement>() {
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||
const [shouldShow, setShouldShow] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
audioRef.current = new Audio("https://webuild-dev.s3.eu-north-1.amazonaws.com/default/audio/click.mp3");
|
||||
audioRef.current.volume = 0.75;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (window.self !== window.top) {
|
||||
try {
|
||||
const parentHostname = window.top?.location.hostname;
|
||||
if (parentHostname?.includes('webild.io')) {
|
||||
setShouldShow(false);
|
||||
}
|
||||
} catch {
|
||||
setShouldShow(true);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
const playSound = useCallback(() => {
|
||||
if (audioRef.current) {
|
||||
audioRef.current.currentTime = 0;
|
||||
audioRef.current.play().catch(() => {});
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleMouseEnter = useCallback(() => {
|
||||
if (window.innerWidth > 768) {
|
||||
playSound();
|
||||
}
|
||||
}, [playSound]);
|
||||
|
||||
const handleClick = useCallback(
|
||||
(e: React.MouseEvent<T>, onClick?: (e: React.MouseEvent<T>) => void) => {
|
||||
playSound();
|
||||
if (onClick) {
|
||||
onClick(e);
|
||||
}
|
||||
},
|
||||
[playSound]
|
||||
);
|
||||
|
||||
return {
|
||||
shouldShow,
|
||||
handleMouseEnter,
|
||||
handleClick,
|
||||
buttonClassName: "transition-all duration-200 hover:-translate-y-[3px]",
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user