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