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 colorStyles = {
47 blue: "bg-blue-500 text-white hover:bg-blue-500",
48 amber: "bg-amber-400 text-slate-900 hover:bg-amber-500",
49 };
50
51 const buttonContent = (
52 <>
53 {icon && (
54 <img
55 src={icon}
56 alt={iconAlt || ""}
57 className={`${condensed ? "w-4 h-4" : "w-6 h-6"} mr-2`}
58 style={{
59 filter: color === "blue"
60 ? "brightness(0) invert(1)"
61 : "brightness(0)",
62 }}
63 />
64 )}
65 {label && (
66 <span className="font-mono font-bold tracking-wider">
67 {label}
68 </span>
69 )}
70 </>
71 );
72
73 const buttonStyles = `${baseStyles} ${paddingStyles} ${
74 colorStyles[color]
75 } ${className}`;
76
77 if (isAnchor) {
78 return (
79 <a
80 href={props.href}
81 className={buttonStyles}
82 {...rest as JSX.HTMLAttributes<HTMLAnchorElement>}
83 >
84 {buttonContent}
85 </a>
86 );
87 }
88
89 const buttonProps = rest as JSX.HTMLAttributes<HTMLButtonElement>;
90 return (
91 <button
92 {...buttonProps}
93 className={buttonStyles}
94 >
95 {buttonContent}
96 </button>
97 );
98}