Graphical PDS migrator for AT Protocol
1import { JSX } from "preact";
2
3type ButtonBaseProps = {
4 color?: "blue" | "amber";
5 icon?: string;
6 iconAlt?: string;
7 label?: string;
8 className?: string;
9 condensed?: boolean;
10};
11
12type ButtonProps =
13 & ButtonBaseProps
14 & Omit<JSX.HTMLAttributes<HTMLButtonElement>, keyof ButtonBaseProps>;
15type AnchorProps =
16 & ButtonBaseProps
17 & Omit<JSX.HTMLAttributes<HTMLAnchorElement>, keyof ButtonBaseProps>
18 & { href: string };
19
20/**
21 * The button props or anchor props for a button or link.
22 * @type {Props}
23 */
24type Props = ButtonProps | AnchorProps;
25
26/**
27 * Styled button component.
28 * @param props - The button props
29 * @returns The button component
30 * @component
31 */
32export function Button(props: Props) {
33 const {
34 color = "blue",
35 icon,
36 iconAlt,
37 label,
38 className = "",
39 condensed = false,
40 ...rest
41 } = props;
42 const isAnchor = "href" in props;
43
44 const baseStyles = "airport-sign flex items-center [transition:none]";
45 const paddingStyles = condensed ? "px-2 py-1.5" : "px-3 py-2 sm:px-6 sm:py-3";
46 const transformStyles =
47 "translate-y-0 hover:translate-y-1 hover:transition-transform hover:duration-200 hover:ease-in-out";
48 const colorStyles = {
49 blue:
50 "bg-gradient-to-r from-blue-400 to-blue-500 text-white hover:from-blue-500 hover:to-blue-600",
51 amber:
52 "bg-gradient-to-r from-amber-400 to-amber-500 text-slate-900 hover:from-amber-500 hover:to-amber-600",
53 };
54
55 const buttonContent = (
56 <>
57 {icon && (
58 <img
59 src={icon}
60 alt={iconAlt || ""}
61 className={`${condensed ? "w-4 h-4" : "w-6 h-6"} mr-2`}
62 style={{
63 filter: color === "blue"
64 ? "brightness(0) invert(1)"
65 : "brightness(0)",
66 }}
67 />
68 )}
69 {label && (
70 <span className="font-mono font-bold tracking-wider">
71 {label}
72 </span>
73 )}
74 </>
75 );
76
77 const buttonStyles = `${baseStyles} ${paddingStyles} ${transformStyles} ${
78 colorStyles[color]
79 } ${className}`;
80
81 if (isAnchor) {
82 return (
83 <a
84 href={props.href}
85 className={buttonStyles}
86 {...rest as JSX.HTMLAttributes<HTMLAnchorElement>}
87 >
88 {buttonContent}
89 </a>
90 );
91 }
92
93 const buttonProps = rest as JSX.HTMLAttributes<HTMLButtonElement>;
94 return (
95 <button
96 {...buttonProps}
97 className={buttonStyles}
98 >
99 {buttonContent}
100 </button>
101 );
102}