File size: 3,067 Bytes
aa01edd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
123
124
import type { MantineTheme } from "@mantine/core";
import { Button } from "@mantine/core";
import React from "react";

interface ExpandableLinkProps {
  href: string;
  children: React.ReactNode;
}

export default function ExpandableLink({
  href,
  children,
}: ExpandableLinkProps) {
  const childContent = children?.toString() || "";
  const firstChar = childContent.charAt(0);
  const [isExpanded, setIsExpanded] = React.useState(true);
  const timerRef = React.useRef<number | null>(null);

  React.useEffect(() => {
    timerRef.current = window.setTimeout(() => {
      setIsExpanded(false);
      timerRef.current = null;
    }, 3000);

    return () => {
      if (timerRef.current) {
        clearTimeout(timerRef.current);
      }
    };
  }, []);

  const handleMouseEnter = () => {
    if (timerRef.current) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
    setIsExpanded(true);
  };

  const handleMouseLeave = () => {
    timerRef.current = window.setTimeout(() => {
      setIsExpanded(false);
      timerRef.current = null;
    }, 3000);
  };

  const fullTextRef = React.useRef<HTMLDivElement>(null);
  const [fullTextWidth, setFullTextWidth] = React.useState(0);

  React.useEffect(() => {
    const measureText = () => {
      if (fullTextRef.current) {
        setFullTextWidth(fullTextRef.current.scrollWidth);
      }
    };

    measureText();

    window.addEventListener("resize", measureText);
    return () => {
      window.removeEventListener("resize", measureText);
    };
  }, []);

  return (
    <Button
      component="a"
      href={href}
      target="_blank"
      rel="nofollow noopener noreferrer"
      variant="light"
      color="gray"
      size="compact-xs"
      radius="xl"
      style={(theme: MantineTheme) => ({
        textDecoration: "none",
        transform: "translateY(-2px)",
        overflow: "hidden",
        position: "relative",
        width: isExpanded ? `${fullTextWidth + theme.spacing.md}px` : "2em",
        transition: "width 0.3s ease-in-out",
        textAlign: "center",
      })}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
      onFocus={handleMouseEnter}
      onBlur={handleMouseLeave}
    >
      <span
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          opacity: isExpanded ? 0 : 1,
          transition: "opacity 0.2s ease-in-out",
        }}
      >
        {firstChar}
      </span>
      <span
        ref={fullTextRef}
        style={{
          opacity: isExpanded ? 1 : 0,
          transition: "opacity 0.3s ease-in-out",
          visibility: isExpanded ? "visible" : "hidden",
          whiteSpace: "nowrap",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          height: "100%",
          position: "relative",
        }}
      >
        {children}
      </span>
    </Button>
  );
}