SPB Git

spb/phi-conseil

Public
2.5 KB · 89 lines tsx
1import Link from "next/link";2import type { ComponentPropsWithoutRef, ReactNode } from "react";34type Variant = "primary" | "ivory" | "outline" | "ghost";5type Size = "md" | "lg";67const base =8  "inline-flex items-center justify-center gap-2 rounded-pill font-medium transition-[background-color,color,box-shadow,transform] duration-[var(--duration-base)] ease-[var(--ease-out)] focus-visible:outline-3 focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-60 motion-safe:hover:-translate-y-px";910const variants: Record<Variant, string> = {11  primary: "bg-slate-500 text-white shadow-sm hover:bg-slate-700 focus-visible:outline-navy-900",12  ivory: "bg-ivory-200 text-navy-900 hover:bg-ivory-100 focus-visible:outline-white",13  outline:14    "border border-navy-800/50 bg-transparent text-navy-900 hover:border-navy-900 hover:bg-white/60",15  ghost: "text-navy-900 hover:bg-navy-900/5",16};1718const sizes: Record<Size, string> = {19  md: "px-5 py-2 text-sm",20  lg: "px-6 py-3 text-[0.95rem]",21};2223export function Arrow({ className = "h-4 w-4" }: { className?: string }) {24  return (25    <svg26      className={className}27      viewBox="0 0 16 16"28      fill="none"29      stroke="currentColor"30      strokeWidth="1.6"31      strokeLinecap="round"32      strokeLinejoin="round"33      aria-hidden="true"34    >35      <path d="M2.5 8h11M9 3.5 13.5 8 9 12.5" />36    </svg>37  );38}3940type CommonProps = {41  variant?: Variant;42  size?: Size;43  arrow?: boolean;44  className?: string;45  children: ReactNode;46};4748type LinkProps = CommonProps & { href: string } & Omit<49    ComponentPropsWithoutRef<typeof Link>,50    "href" | "children" | "className"51  >;52type ButtonProps = CommonProps & { href?: undefined } & Omit<53    ComponentPropsWithoutRef<"button">,54    "children" | "className"55  >;5657export function Button(props: LinkProps | ButtonProps) {58  const {59    variant = "primary",60    size = "md",61    arrow = true,62    className = "",63    children,64    ...rest65  } = props;66  const cls = `${base} ${variants[variant]} ${sizes[size]} ${className}`;67  const content = (68    <>69      {children}70      {arrow ? <Arrow /> : null}71    </>72  );73  if (rest.href !== undefined) {74    const { href, ...linkRest } = rest as Omit<LinkProps, keyof CommonProps>;75    return (76      <Link href={href} className={cls} {...linkRest}>77        {content}78      </Link>79    );80  }81  const { href: _unused, ...buttonRest } = rest as Omit<ButtonProps, keyof CommonProps>;82  void _unused;83  return (84    <button type="button" className={cls} {...buttonRest}>85      {content}86    </button>87  );88}89
Files · main
Menu

Theme