--- import { Icon } from 'astro-icon/components' import { tv, type VariantProps } from 'tailwind-variants' import { cn } from '../lib/cn' import type { HTMLAttributes, Polymorphic } from 'astro/types' type Props = Polymorphic< Required, Tag extends 'label' ? 'for' : never>> & VariantProps & { as: Tag label: string icon?: string endIcon?: string classNames?: { label?: string icon?: string endIcon?: string } dataAstroReload?: boolean children?: never disabled?: boolean inlineIcon?: boolean } > export type ButtonProps = Props const button = tv({ slots: { base: 'inline-flex shrink-0 items-center justify-center gap-2 rounded-lg border transition-colors duration-100 focus-visible:ring-2 focus-visible:ring-current focus-visible:ring-offset-2 focus-visible:ring-offset-black focus-visible:outline-hidden', icon: 'size-4 shrink-0', label: 'text-left whitespace-nowrap', endIcon: 'size-4 shrink-0', }, variants: { size: { sm: { base: 'h-8 px-3 text-sm', icon: 'size-4', endIcon: 'size-4', }, md: { base: 'h-9 px-4 text-sm', icon: 'size-4', endIcon: 'size-4', label: 'font-medium', }, lg: { base: 'h-10 px-5 text-base', icon: 'size-5', endIcon: 'size-5', label: 'font-bold tracking-wider uppercase', }, }, iconOnly: { true: { base: 'p-0', label: 'sr-only', }, }, color: { black: '', white: '', gray: '', success: '', danger: '', warning: '', info: '', }, variant: { solid: '', faded: '', }, shadow: { true: { base: 'shadow-lg', }, }, disabled: { true: { base: 'cursor-not-allowed', }, }, }, compoundVariants: [ // Color variants - solid { color: 'black', variant: 'solid', class: { base: 'border-night-500 bg-night-800 hover:bg-night-900 hover:text-day-200 focus-visible:bg-night-500 text-white/50 focus-visible:text-white focus-visible:ring-white', }, }, { color: 'white', variant: 'solid', class: { base: 'border-day-300 bg-day-100 hover:bg-day-200 text-black focus-visible:ring-green-500', }, }, { color: 'gray', variant: 'solid', class: { base: 'border-day-500 bg-day-400 hover:bg-day-500 text-black focus-visible:ring-white', }, }, { color: 'success', variant: 'solid', class: { base: 'border-green-600 bg-green-500 text-black hover:bg-green-600', }, }, { color: 'danger', variant: 'solid', class: { base: 'border-red-600 bg-red-500 text-white hover:bg-red-600', }, }, { color: 'warning', variant: 'solid', class: { base: 'border-yellow-600 bg-yellow-500 text-white hover:bg-yellow-600', }, }, { color: 'info', variant: 'solid', class: { base: 'border-blue-600 bg-blue-500 text-white hover:bg-blue-600', }, }, // Color variants - faded { color: 'black', variant: 'faded', class: { base: 'bg2night-800/15 hover:bg-night-700/30 border-current/30 text-white/70 hover:text-white/90 focus-visible:ring-white/50', }, }, { color: 'white', variant: 'faded', class: { base: 'b2-day-100/15 hover:bg-day-200/30 border-current/30 text-white/70 hover:text-white/90 focus-visible:ring-white/50', }, }, { color: 'gray', variant: 'faded', class: { base: 'b2-day-400/15 hover:bg-day-500/30 text-day-300 hover:text-day-100 border-current/30 focus-visible:ring-white/50', }, }, { color: 'success', variant: 'faded', class: { base: 'border-current/20 bg-green-500/15 text-green-300 hover:bg-green-500/30 hover:text-green-100', }, }, { color: 'danger', variant: 'faded', class: { base: 'border-current/20 bg-red-500/15 text-red-300 hover:bg-red-500/30 hover:text-red-100', }, }, { color: 'warning', variant: 'faded', class: { base: 'border-current/20 bg-yellow-500/15 text-yellow-300 hover:bg-yellow-500/30 hover:text-yellow-100', }, }, { color: 'info', variant: 'faded', class: { base: 'border-current/20 bg-blue-500/15 text-blue-300 hover:bg-blue-500/30 hover:text-blue-100', }, }, // Shadow variants { color: 'black', shadow: true, class: 'shadow-black/30', }, { color: 'white', shadow: true, class: 'shadow-white/30', }, { color: 'gray', shadow: true, class: 'shadow-day-500/30', }, { color: 'success', shadow: true, class: 'shadow-green-500/30', }, { color: 'danger', shadow: true, class: 'shadow-red-500/30', }, { color: 'warning', shadow: true, class: 'shadow-yellow-500/30', }, { color: 'info', shadow: true, class: 'shadow-blue-500/30', }, // Icon only variants { iconOnly: true, size: 'sm', class: 'w-8', }, { iconOnly: true, size: 'md', class: 'w-9', }, { iconOnly: true, size: 'lg', class: 'w-10', }, ], defaultVariants: { size: 'md', color: 'black', variant: 'solid', shadow: false, disabled: false, iconOnly: false, }, }) const { as: Tag = 'button' as 'a' | 'button' | 'label', label, icon, endIcon, size, color, variant, shadow, class: className, classNames, role, dataAstroReload, disabled, inlineIcon, iconOnly, ...htmlProps } = Astro.props const { base, icon: iconSlot, label: labelSlot, endIcon: endIconSlot, } = button({ size, color, variant, shadow, disabled, iconOnly: iconOnly ?? (!label && !(!!icon && !!endIcon)), }) const ActualTag = disabled && Tag === 'a' ? 'span' : Tag --- {!!icon && } {label} { !!endIcon && ( {endIcon} ) }