Release 2025-05-19
This commit is contained in:
@@ -1,176 +0,0 @@
|
||||
---
|
||||
import { Icon } from 'astro-icon/components'
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
|
||||
import type { HTMLAttributes, Polymorphic } from 'astro/types'
|
||||
|
||||
type Props<Tag extends 'a' | 'button' | 'label' = 'button'> = Polymorphic<
|
||||
Required<Pick<HTMLAttributes<'label'>, Tag extends 'label' ? 'for' : never>> &
|
||||
VariantProps<typeof button> & {
|
||||
as: Tag
|
||||
label?: string
|
||||
icon?: string
|
||||
endIcon?: string
|
||||
classNames?: {
|
||||
label?: string
|
||||
icon?: string
|
||||
endIcon?: string
|
||||
}
|
||||
dataAstroReload?: boolean
|
||||
children?: never
|
||||
disabled?: boolean
|
||||
}
|
||||
>
|
||||
|
||||
export type ButtonProps<Tag extends 'a' | 'button' | 'label' = 'button'> = Props<Tag>
|
||||
|
||||
const button = tv({
|
||||
slots: {
|
||||
base: 'inline-flex 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',
|
||||
},
|
||||
},
|
||||
color: {
|
||||
black: {
|
||||
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',
|
||||
},
|
||||
white: {
|
||||
base: 'border-day-300 bg-day-100 hover:bg-day-200 text-black focus-visible:ring-green-500',
|
||||
},
|
||||
gray: {
|
||||
base: 'border-day-500 bg-day-400 hover:bg-day-500 text-black focus-visible:ring-white',
|
||||
},
|
||||
success: {
|
||||
base: 'border-green-600 bg-green-500 text-black hover:bg-green-600',
|
||||
},
|
||||
error: {
|
||||
base: 'border-red-600 bg-red-500 text-white hover:bg-red-600',
|
||||
},
|
||||
warning: {
|
||||
base: 'border-yellow-600 bg-yellow-500 text-white hover:bg-yellow-600',
|
||||
},
|
||||
info: {
|
||||
base: 'border-blue-600 bg-blue-500 text-white hover:bg-blue-600',
|
||||
},
|
||||
},
|
||||
shadow: {
|
||||
true: {
|
||||
base: 'shadow-lg',
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
true: {
|
||||
base: 'cursor-not-allowed',
|
||||
},
|
||||
},
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
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: 'error',
|
||||
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',
|
||||
},
|
||||
],
|
||||
defaultVariants: {
|
||||
size: 'md',
|
||||
color: 'black',
|
||||
shadow: false,
|
||||
disabled: false,
|
||||
},
|
||||
})
|
||||
|
||||
const {
|
||||
as: Tag = 'button' as 'a' | 'button' | 'label',
|
||||
label,
|
||||
icon,
|
||||
endIcon,
|
||||
size,
|
||||
color,
|
||||
shadow,
|
||||
class: className,
|
||||
classNames,
|
||||
role,
|
||||
dataAstroReload,
|
||||
disabled,
|
||||
...htmlProps
|
||||
} = Astro.props
|
||||
|
||||
const {
|
||||
base,
|
||||
icon: iconSlot,
|
||||
label: labelSlot,
|
||||
endIcon: endIconSlot,
|
||||
} = button({ size, color, shadow, disabled })
|
||||
|
||||
const ActualTag = disabled && Tag === 'a' ? 'span' : Tag
|
||||
---
|
||||
|
||||
<ActualTag
|
||||
class={base({ class: className })}
|
||||
role={role ??
|
||||
(ActualTag === 'button' || ActualTag === 'label' || ActualTag === 'span' ? undefined : 'button')}
|
||||
aria-disabled={disabled}
|
||||
{...dataAstroReload && { 'data-astro-reload': dataAstroReload }}
|
||||
{...htmlProps}
|
||||
>
|
||||
{!!icon && <Icon name={icon} class={iconSlot({ class: classNames?.icon })} />}
|
||||
{!!label && <span class={labelSlot({ class: classNames?.label })}>{label}</span>}
|
||||
{
|
||||
!!endIcon && (
|
||||
<Icon name={endIcon} class={endIconSlot({ class: classNames?.endIcon })}>
|
||||
{endIcon}
|
||||
</Icon>
|
||||
)
|
||||
}
|
||||
</ActualTag>
|
||||
Reference in New Issue
Block a user