|
| 1 | +import * as Headless from '@headlessui/react' |
| 2 | +import clsx from 'clsx' |
| 3 | +import React, { forwardRef } from 'react' |
| 4 | +import { TouchTarget } from './button' |
| 5 | +import { Link } from './link' |
| 6 | + |
| 7 | +const colors = { |
| 8 | + red: 'bg-red-500/15 text-red-700 group-data-[hover]:bg-red-500/25 dark:bg-red-500/10 dark:text-red-400 dark:group-data-[hover]:bg-red-500/20', |
| 9 | + orange: |
| 10 | + 'bg-orange-500/15 text-orange-700 group-data-[hover]:bg-orange-500/25 dark:bg-orange-500/10 dark:text-orange-400 dark:group-data-[hover]:bg-orange-500/20', |
| 11 | + amber: |
| 12 | + 'bg-amber-400/20 text-amber-700 group-data-[hover]:bg-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400 dark:group-data-[hover]:bg-amber-400/15', |
| 13 | + yellow: |
| 14 | + 'bg-yellow-400/20 text-yellow-700 group-data-[hover]:bg-yellow-400/30 dark:bg-yellow-400/10 dark:text-yellow-300 dark:group-data-[hover]:bg-yellow-400/15', |
| 15 | + lime: 'bg-lime-400/20 text-lime-700 group-data-[hover]:bg-lime-400/30 dark:bg-lime-400/10 dark:text-lime-300 dark:group-data-[hover]:bg-lime-400/15', |
| 16 | + green: |
| 17 | + 'bg-green-500/15 text-green-700 group-data-[hover]:bg-green-500/25 dark:bg-green-500/10 dark:text-green-400 dark:group-data-[hover]:bg-green-500/20', |
| 18 | + emerald: |
| 19 | + 'bg-emerald-500/15 text-emerald-700 group-data-[hover]:bg-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-400 dark:group-data-[hover]:bg-emerald-500/20', |
| 20 | + teal: 'bg-teal-500/15 text-teal-700 group-data-[hover]:bg-teal-500/25 dark:bg-teal-500/10 dark:text-teal-300 dark:group-data-[hover]:bg-teal-500/20', |
| 21 | + cyan: 'bg-cyan-400/20 text-cyan-700 group-data-[hover]:bg-cyan-400/30 dark:bg-cyan-400/10 dark:text-cyan-300 dark:group-data-[hover]:bg-cyan-400/15', |
| 22 | + sky: 'bg-sky-500/15 text-sky-700 group-data-[hover]:bg-sky-500/25 dark:bg-sky-500/10 dark:text-sky-300 dark:group-data-[hover]:bg-sky-500/20', |
| 23 | + blue: 'bg-blue-500/15 text-blue-700 group-data-[hover]:bg-blue-500/25 dark:text-blue-400 dark:group-data-[hover]:bg-blue-500/25', |
| 24 | + indigo: |
| 25 | + 'bg-indigo-500/15 text-indigo-700 group-data-[hover]:bg-indigo-500/25 dark:text-indigo-400 dark:group-data-[hover]:bg-indigo-500/20', |
| 26 | + violet: |
| 27 | + 'bg-violet-500/15 text-violet-700 group-data-[hover]:bg-violet-500/25 dark:text-violet-400 dark:group-data-[hover]:bg-violet-500/20', |
| 28 | + purple: |
| 29 | + 'bg-purple-500/15 text-purple-700 group-data-[hover]:bg-purple-500/25 dark:text-purple-400 dark:group-data-[hover]:bg-purple-500/20', |
| 30 | + fuchsia: |
| 31 | + 'bg-fuchsia-400/15 text-fuchsia-700 group-data-[hover]:bg-fuchsia-400/25 dark:bg-fuchsia-400/10 dark:text-fuchsia-400 dark:group-data-[hover]:bg-fuchsia-400/20', |
| 32 | + pink: 'bg-pink-400/15 text-pink-700 group-data-[hover]:bg-pink-400/25 dark:bg-pink-400/10 dark:text-pink-400 dark:group-data-[hover]:bg-pink-400/20', |
| 33 | + rose: 'bg-rose-400/15 text-rose-700 group-data-[hover]:bg-rose-400/25 dark:bg-rose-400/10 dark:text-rose-400 dark:group-data-[hover]:bg-rose-400/20', |
| 34 | + zinc: 'bg-zinc-600/10 text-zinc-700 group-data-[hover]:bg-zinc-600/20 dark:bg-white/5 dark:text-zinc-400 dark:group-data-[hover]:bg-white/10', |
| 35 | +} |
| 36 | + |
| 37 | +type BadgeProps = { color?: keyof typeof colors } |
| 38 | + |
| 39 | +export function Badge({ color = 'zinc', className, ...props }: BadgeProps & React.ComponentPropsWithoutRef<'span'>) { |
| 40 | + return ( |
| 41 | + <span |
| 42 | + {...props} |
| 43 | + className={clsx( |
| 44 | + className, |
| 45 | + 'inline-flex items-center gap-x-1.5 rounded-md px-1.5 py-0.5 text-sm/5 font-medium sm:text-xs/5 forced-colors:outline', |
| 46 | + colors[color] |
| 47 | + )} |
| 48 | + /> |
| 49 | + ) |
| 50 | +} |
| 51 | + |
| 52 | +export const BadgeButton = forwardRef(function BadgeButton( |
| 53 | + { |
| 54 | + color = 'zinc', |
| 55 | + className, |
| 56 | + children, |
| 57 | + ...props |
| 58 | + }: BadgeProps & { className?: string; children: React.ReactNode } & ( |
| 59 | + | Omit<Headless.ButtonProps, 'as' | 'className'> |
| 60 | + | Omit<React.ComponentPropsWithoutRef<typeof Link>, 'className'> |
| 61 | + ), |
| 62 | + ref: React.ForwardedRef<HTMLElement> |
| 63 | +) { |
| 64 | + let classes = clsx( |
| 65 | + className, |
| 66 | + 'group relative inline-flex rounded-md focus:outline-none data-[focus]:outline data-[focus]:outline-2 data-[focus]:outline-offset-2 data-[focus]:outline-blue-500' |
| 67 | + ) |
| 68 | + |
| 69 | + return 'href' in props ? ( |
| 70 | + <Link {...props} className={classes} ref={ref as React.ForwardedRef<HTMLAnchorElement>}> |
| 71 | + <TouchTarget> |
| 72 | + <Badge color={color}>{children}</Badge> |
| 73 | + </TouchTarget> |
| 74 | + </Link> |
| 75 | + ) : ( |
| 76 | + <Headless.Button {...props} className={classes} ref={ref}> |
| 77 | + <TouchTarget> |
| 78 | + <Badge color={color}>{children}</Badge> |
| 79 | + </TouchTarget> |
| 80 | + </Headless.Button> |
| 81 | + ) |
| 82 | +}) |
0 commit comments