1"use client";
2
3import React from "react";
4
5interface CloseButtonProps {
6 onClick?: () => void;
7 label?: string;
8 size?: "sm" | "md";
9 tone?: "light" | "dark";
10 className?: string;
11}
12
13const sizes = {
14 sm: { box: "w-6 h-6 rounded-[7px]", icon: 9 },
15 md: { box: "w-7 h-7 rounded-[8px]", icon: 10 },
16};
17
18/* Quiet until hovered, then it rises into a raised face like every other
19 pressable thing — so it reads as a control, not decoration. */
20export function CloseButton({
21 onClick,
22 label = "Close",
23 size = "md",
24 tone = "light",
25 className = "",
26}: CloseButtonProps) {
27 const dark = tone === "dark";
28 const s = sizes[size];
29
30 return (
31 <button
32 type="button"
33 onClick={onClick}
34 aria-label={label}
35 className={[
36 "group/close relative shrink-0 flex items-center justify-center cursor-pointer",
37 "transition-[color,background,scale] duration-150 active:scale-95",
38 "focus-visible:outline-2 focus-visible:outline-offset-2",
39 dark
40 ? "text-white/45 hover:text-white focus-visible:outline-white"
41 : "text-neutral-400 hover:text-neutral-900 focus-visible:outline-neutral-900",
42 s.box,
43 className,
44 ].join(" ")}
45 >
46 <span
47 aria-hidden
48 className={[
49 "absolute inset-0 rounded-[inherit] opacity-0 group-hover/close:opacity-100 transition-opacity duration-150",
50 dark
51 ? "[background:var(--tile-dark)] [box-shadow:var(--tile-dark-shadow)]"
52 : "[background:var(--face-light)] [box-shadow:var(--face-light-shadow)]",
53 ].join(" ")}
54 />
55 <svg
56 className="relative"
57 width={s.icon}
58 height={s.icon}
59 fill="none"
60 stroke="currentColor"
61 strokeWidth="2.5"
62 viewBox="0 0 24 24"
63 >
64 <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
65 </svg>
66 </button>
67 );
68}