ph/components

Button

Solid, outline or ghost.

Code

Copy into src/components/ph/ .

Button.astro
---
import type { HTMLAttributes } from "astro/types";
import Icon from "./Icon.astro";
import type { IconName } from "./icons";

type Props = Omit<HTMLAttributes<"a"> & HTMLAttributes<"button">, "type"> & {
  href?: string;
  type?: "button" | "submit" | "reset";
  variant?: "solid" | "outline" | "ghost";
  size?: "sm" | "md" | "lg";
  icon?: IconName;
  iconEnd?: IconName;
};

const { href, type = "button", variant = "solid", size = "md", icon, iconEnd, class: className, ...rest } = Astro.props;
const Tag = href ? "a" : "button";

const variants = {
  solid: "bg-foreground text-background hover:bg-primary hover:text-primary-foreground",
  outline: "border border-foreground text-foreground hover:bg-foreground hover:text-background",
  ghost: "text-foreground hover:bg-foreground/[0.08]",
};
const sizes = {
  sm: "h-8 gap-1.5 px-3 text-[13px]",
  md: "h-10 gap-2 px-4 text-[15px]",
  lg: "h-[52px] gap-2.5 px-6 text-xl",
};
---

<Tag
  href={href}
  type={href ? undefined : type}
  class:list={[
    "inline-flex w-fit shrink-0 cursor-pointer items-center justify-center font-mono font-semibold tracking-wide whitespace-nowrap uppercase no-underline transition-[color,background-color,transform] duration-150 ease-quint active:scale-[0.97] disabled:pointer-events-none disabled:opacity-40",
    variants[variant],
    sizes[size],
    className,
  ]}
  {...rest}
>
  {icon && <Icon name={icon} />}
  <slot />
  {iconEnd && <Icon name={iconEnd} />}
</Tag>

Also needs