first commit
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import { cn } from "../utils/cn";
|
||||
import Icon from "./Icon.astro";
|
||||
|
||||
type Variant = "solid" | "outline" | "ghost" | "soft" | "link";
|
||||
type Color =
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "tertiary"
|
||||
| "accent"
|
||||
| "info"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "danger"
|
||||
| "neutral";
|
||||
type Size = "sm" | "md" | "lg" | "icon";
|
||||
|
||||
interface Props extends HTMLAttributes<"button"> {
|
||||
variant?: Variant;
|
||||
color?: Color;
|
||||
size?: Size;
|
||||
pill?: boolean;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
variant = "solid",
|
||||
color = "primary",
|
||||
size = "md",
|
||||
pill = false,
|
||||
icon = "",
|
||||
class: className,
|
||||
...rest
|
||||
}: Props = Astro.props;
|
||||
|
||||
const base =
|
||||
"inline-flex items-center justify-center gap-2 font-medium transition-colors " +
|
||||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 " +
|
||||
"disabled:opacity-50 disabled:pointer-events-none";
|
||||
|
||||
const sizeClass: Record<Size, string> = {
|
||||
sm: "h-8 px-3 text-sm",
|
||||
md: "h-10 px-4 text-sm",
|
||||
lg: "h-11 px-5 text-base",
|
||||
icon: "h-10 w-10 p-0",
|
||||
};
|
||||
|
||||
const radius = pill ? "rounded-full" : "rounded-md";
|
||||
|
||||
const styles: Record<Color, Record<Variant, string>> = {
|
||||
primary: {
|
||||
solid: "bg-primary text-primary-foreground hover:bg-primary/90 border border-transparent focus-visible:ring-primary/40",
|
||||
outline:
|
||||
"border border-primary text-primary hover:bg-primary/10 focus-visible:ring-primary/40",
|
||||
ghost: "text-primary hover:bg-primary/10 border border-transparent focus-visible:ring-primary/30",
|
||||
soft: "bg-primary/15 text-primary hover:bg-primary/20 border border-transparent focus-visible:ring-primary/30",
|
||||
link: "text-primary underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-primary/40",
|
||||
},
|
||||
secondary: {
|
||||
solid: "bg-secondary text-secondary-foreground hover:bg-secondary/90 border border-transparent focus-visible:ring-secondary/40",
|
||||
outline:
|
||||
"border border-secondary text-secondary hover:bg-secondary/10 focus-visible:ring-secondary/40",
|
||||
ghost: "text-secondary hover:bg-secondary/10 border border-transparent focus-visible:ring-secondary/30",
|
||||
soft: "bg-secondary/15 text-secondary hover:bg-secondary/20 border border-transparent focus-visible:ring-secondary/30",
|
||||
link: "text-secondary underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-secondary/40",
|
||||
},
|
||||
tertiary: {
|
||||
solid: "bg-tertiary text-tertiary-foreground hover:bg-tertiary/90 border border-transparent focus-visible:ring-tertiary/40",
|
||||
outline:
|
||||
"border border-tertiary text-tertiary hover:bg-tertiary/10 focus-visible:ring-tertiary/40",
|
||||
ghost: "text-tertiary hover:bg-tertiary/10 border border-transparent focus-visible:ring-tertiary/30",
|
||||
soft: "bg-tertiary/15 text-tertiary hover:bg-tertiary/20 border border-transparent focus-visible:ring-tertiary/30",
|
||||
link: "text-tertiary underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-tertiary/40",
|
||||
},
|
||||
accent: {
|
||||
solid: "bg-accent text-accent-foreground hover:bg-accent/90 border border-transparent focus-visible:ring-accent/40",
|
||||
outline:
|
||||
"border border-accent text-accent hover:bg-accent/10 focus-visible:ring-accent/40",
|
||||
ghost: "text-accent hover:bg-accent/10 border border-transparent focus-visible:ring-accent/30",
|
||||
soft: "bg-accent/15 text-accent hover:bg-accent/20 border border-transparent focus-visible:ring-accent/30",
|
||||
link: "text-accent underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-accent/40",
|
||||
},
|
||||
info: {
|
||||
solid: "bg-info text-info-foreground hover:bg-info/90 border border-transparent focus-visible:ring-info/40",
|
||||
outline:
|
||||
"border border-info text-info hover:bg-info/10 focus-visible:ring-info/40",
|
||||
ghost: "text-info hover:bg-info/10 border border-transparent focus-visible:ring-info/30",
|
||||
soft: "bg-info/15 text-info hover:bg-info/20 border border-transparent focus-visible:ring-info/30",
|
||||
link: "text-info underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-info/40",
|
||||
},
|
||||
success: {
|
||||
solid: "bg-success text-success-foreground hover:bg-success/90 border border-transparent focus-visible:ring-success/40",
|
||||
outline:
|
||||
"border border-success text-success hover:bg-success/10 focus-visible:ring-success/40",
|
||||
ghost: "text-success hover:bg-success/10 border border-transparent focus-visible:ring-success/30",
|
||||
soft: "bg-success/15 text-success hover:bg-success/20 border border-transparent focus-visible:ring-success/30",
|
||||
link: "text-success underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-success/40",
|
||||
},
|
||||
warning: {
|
||||
solid: "bg-warning text-warning-foreground hover:bg-warning/90 border border-transparent focus-visible:ring-warning/40",
|
||||
outline:
|
||||
"border border-warning text-warning hover:bg-warning/10 focus-visible:ring-warning/40",
|
||||
ghost: "text-warning hover:bg-warning/10 border border-transparent focus-visible:ring-warning/30",
|
||||
soft: "bg-warning/14 text-warning hover:bg-warning/20 border border-transparent focus-visible:ring-warning/30",
|
||||
link: "text-warning underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-warning/40",
|
||||
},
|
||||
danger: {
|
||||
solid: "bg-danger text-danger-foreground hover:bg-danger/90 border border-transparent focus-visible:ring-danger/40",
|
||||
outline:
|
||||
"border border-danger text-danger hover:bg-danger/10 focus-visible:ring-danger/40",
|
||||
ghost: "text-danger hover:bg-danger/10 border border-transparent focus-visible:ring-danger/30",
|
||||
soft: "bg-danger/15 text-danger hover:bg-danger/20 border border-transparent focus-visible:ring-danger/30",
|
||||
link: "text-danger underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-danger/40",
|
||||
},
|
||||
neutral: {
|
||||
solid: "bg-neutral text-neutral-foreground hover:bg-neutral/90 border border-transparent focus-visible:ring-neutral/40",
|
||||
outline:
|
||||
"border border-neutral text-neutral hover:bg-neutral/10 focus-visible:ring-neutral/40",
|
||||
ghost: "text-neutral hover:bg-neutral/10 border border-transparent focus-visible:ring-neutral/30",
|
||||
soft: "bg-neutral/15 text-neutral hover:bg-neutral/20 border border-transparent focus-visible:ring-neutral/30",
|
||||
link: "text-neutral underline underline-offset-4 p-0 h-auto border-0 focus-visible:ring-neutral/40",
|
||||
},
|
||||
};
|
||||
|
||||
const variantColor = styles[color][variant];
|
||||
const sizeKls = variant === "link" ? "" : sizeClass[size];
|
||||
const iconSize = size === "sm" ? "size-4" : size === "lg" ? "size-5" : "size-5";
|
||||
---
|
||||
|
||||
<button class={cn(base, radius, sizeKls, variantColor, className)} {...rest}>
|
||||
{icon && <Icon name={icon} class={cn(iconSize, "shrink-0")} />}
|
||||
<slot />
|
||||
</button>
|
||||
Reference in New Issue
Block a user