Files
kycnotme/web/src/components/BadgeSmall.astro
2025-05-19 10:23:36 +00:00

163 lines
6.2 KiB
Plaintext

---
import { Icon } from 'astro-icon/components'
import { tv, type VariantProps } from 'tailwind-variants'
import type { Polymorphic } from 'astro/types'
const badge = tv({
slots: {
base: 'inline-flex h-4 items-center justify-center gap-0.75 rounded-full px-1.25 text-[10px] font-medium',
icon: 'size-3 shrink-0',
text: 'mx-0.25 overflow-hidden text-ellipsis whitespace-nowrap',
},
variants: {
color: {
red: '',
orange: '',
amber: '',
yellow: '',
lime: '',
green: '',
emerald: '',
teal: '',
cyan: '',
sky: '',
blue: '',
indigo: '',
violet: '',
purple: '',
fuchsia: '',
pink: '',
rose: '',
slate: '',
gray: '',
zinc: '',
neutral: '',
stone: '',
white: '',
black: '',
},
variant: {
solid: '',
faded: '',
},
},
compoundVariants: [
// Red
{ color: 'red', variant: 'solid', class: { base: 'bg-red-500 text-white' } },
{ color: 'red', variant: 'faded', class: { base: 'bg-red-500/30 text-red-300' } },
// Orange
{ color: 'orange', variant: 'solid', class: { base: 'bg-orange-500 text-white' } },
{ color: 'orange', variant: 'faded', class: { base: 'bg-orange-500/30 text-orange-300' } },
// Amber
{ color: 'amber', variant: 'solid', class: { base: 'bg-amber-500 text-black' } },
{ color: 'amber', variant: 'faded', class: { base: 'bg-amber-500/30 text-amber-300' } },
// Yellow
{ color: 'yellow', variant: 'solid', class: { base: 'bg-yellow-500 text-black' } },
{ color: 'yellow', variant: 'faded', class: { base: 'bg-yellow-500/30 text-yellow-300' } },
// Lime
{ color: 'lime', variant: 'solid', class: { base: 'bg-lime-500 text-black' } },
{ color: 'lime', variant: 'faded', class: { base: 'bg-lime-500/30 text-lime-300' } },
// Green
{ color: 'green', variant: 'solid', class: { base: 'bg-green-500 text-black' } },
{ color: 'green', variant: 'faded', class: { base: 'bg-green-500/30 text-green-300' } },
// Emerald
{ color: 'emerald', variant: 'solid', class: { base: 'bg-emerald-500 text-white' } },
{ color: 'emerald', variant: 'faded', class: { base: 'bg-emerald-500/30 text-emerald-300' } },
// Teal
{ color: 'teal', variant: 'solid', class: { base: 'bg-teal-500 text-white' } },
{ color: 'teal', variant: 'faded', class: { base: 'bg-teal-500/30 text-teal-300' } },
// Cyan
{ color: 'cyan', variant: 'solid', class: { base: 'bg-cyan-500 text-white' } },
{ color: 'cyan', variant: 'faded', class: { base: 'bg-cyan-500/30 text-cyan-300' } },
// Sky
{ color: 'sky', variant: 'solid', class: { base: 'bg-sky-500 text-white' } },
{ color: 'sky', variant: 'faded', class: { base: 'bg-sky-500/30 text-sky-300' } },
// Blue
{ color: 'blue', variant: 'solid', class: { base: 'bg-blue-500 text-white' } },
{ color: 'blue', variant: 'faded', class: { base: 'bg-blue-500/30 text-blue-300' } },
// Indigo
{ color: 'indigo', variant: 'solid', class: { base: 'bg-indigo-500 text-white' } },
{ color: 'indigo', variant: 'faded', class: { base: 'bg-indigo-500/30 text-indigo-300' } },
// Violet
{ color: 'violet', variant: 'solid', class: { base: 'bg-violet-500 text-white' } },
{ color: 'violet', variant: 'faded', class: { base: 'bg-violet-500/30 text-violet-300' } },
// Purple
{ color: 'purple', variant: 'solid', class: { base: 'bg-purple-500 text-white' } },
{ color: 'purple', variant: 'faded', class: { base: 'bg-purple-500/30 text-purple-300' } },
// Fuchsia
{ color: 'fuchsia', variant: 'solid', class: { base: 'bg-fuchsia-500 text-white' } },
{ color: 'fuchsia', variant: 'faded', class: { base: 'bg-fuchsia-500/30 text-fuchsia-300' } },
// Pink
{ color: 'pink', variant: 'solid', class: { base: 'bg-pink-500 text-white' } },
{ color: 'pink', variant: 'faded', class: { base: 'bg-pink-500/30 text-pink-300' } },
// Rose
{ color: 'rose', variant: 'solid', class: { base: 'bg-rose-500 text-white' } },
{ color: 'rose', variant: 'faded', class: { base: 'bg-rose-500/30 text-rose-300' } },
// Slate
{ color: 'slate', variant: 'solid', class: { base: 'bg-slate-500 text-white' } },
{ color: 'slate', variant: 'faded', class: { base: 'bg-slate-500/30 text-slate-300' } },
// Gray
{ color: 'gray', variant: 'solid', class: { base: 'bg-gray-500 text-white' } },
{ color: 'gray', variant: 'faded', class: { base: 'bg-gray-500/30 text-gray-300' } },
// Zinc
{ color: 'zinc', variant: 'solid', class: { base: 'bg-zinc-500 text-white' } },
{ color: 'zinc', variant: 'faded', class: { base: 'bg-zinc-500/30 text-zinc-300' } },
// Neutral
{ color: 'neutral', variant: 'solid', class: { base: 'bg-neutral-500 text-white' } },
{ color: 'neutral', variant: 'faded', class: { base: 'bg-neutral-500/30 text-neutral-300' } },
// Stone
{ color: 'stone', variant: 'solid', class: { base: 'bg-stone-500 text-white' } },
{ color: 'stone', variant: 'faded', class: { base: 'bg-stone-500/30 text-stone-300' } },
// White
{ color: 'white', variant: 'solid', class: { base: 'bg-white text-black' } },
{ color: 'white', variant: 'faded', class: { base: 'bg-white-500/30 text-white-300' } },
// Black
{ color: 'black', variant: 'solid', class: { base: 'bg-black text-white' } },
{ color: 'black', variant: 'faded', class: { base: 'bg-black-500/30 text-black-300' } },
],
defaultVariants: {
color: 'gray',
variant: 'solid',
},
})
type Props<Tag extends 'a' | 'div' | 'li' = 'div'> = Polymorphic<
VariantProps<typeof badge> & {
as: Tag
icon?: string
text: string
inlineIcon?: boolean
classNames?: {
icon?: string
text?: string
}
}
>
const {
as: Tag = 'div',
icon: iconName,
text: textContent,
inlineIcon,
classNames,
color,
variant,
class: className,
...props
} = Astro.props
const { base, icon: iconSlot, text: textSlot } = badge({ color, variant })
---
<Tag {...props} class={base({ class: className })}>
{
!!iconName && (
<Icon name={iconName} class={iconSlot({ class: classNames?.icon })} is:inline={inlineIcon} />
)
}
<span class={textSlot({ class: classNames?.text })}>{textContent}</span>
</Tag>