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