DesignX
Core@paxeer/core/buttonimplemented

Button

shadcn Button restyled to MD3. Aliases: filled=default, error=destructive, tonal=secondary.

Install

$pnpm exec designx add @paxeer/core/button

Preview

Loading preview...

Source code

components/designx/core/button.tsxtsx
"use client";

import { cva, type VariantProps } from "class-variance-authority";
import { type ComponentProps } from "react";
import { Slot } from "radix-ui";
import { cn } from "../lib/cn";

/**
 * Adapted from shadcn/ui Button. Variants map to MD3 roles:
 * default/filled → primary, destructive/error → error,
 * secondary/tonal → secondary-container, outline → outline.
 */
const buttonVariants = cva(
  "dx-focus-ring inline-flex shrink-0 items-center justify-center gap-2 rounded-[var(--md-sys-shape-corner-small)] text-[length:var(--md-sys-typescale-label-large-size)] font-medium whitespace-nowrap transition-colors disabled:pointer-events-none disabled:opacity-38 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
  {
    variants: {
      variant: {
        default: "bg-primary text-on-primary hover:brightness-110",
        filled: "bg-primary text-on-primary hover:brightness-110",
        destructive: "bg-error text-on-error hover:brightness-110",
        error: "bg-error text-on-error hover:brightness-110",
        outline:
          "border border-outline bg-transparent text-primary hover:bg-secondary-container hover:text-on-secondary-container",
        outlined:
          "border border-outline bg-transparent text-primary hover:bg-secondary-container hover:text-on-secondary-container",
        secondary: "bg-secondary-container text-on-secondary-container hover:brightness-110",
        tonal: "bg-secondary-container text-on-secondary-container hover:brightness-110",
        ghost: "bg-transparent text-primary hover:bg-secondary-container hover:text-on-secondary-container",
        text: "bg-transparent text-primary hover:bg-secondary-container hover:text-on-secondary-container",
        elevated: "bg-surface-container-low text-primary shadow-sm hover:bg-surface-container",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-10 px-4 has-[>svg]:px-3",
        xs: "h-6 gap-1 px-2 text-xs has-[>svg]:px-1.5",
        sm: "h-8 gap-1.5 px-3 has-[>svg]:px-2.5",
        dense: "h-8 gap-1.5 px-3 has-[>svg]:px-2.5",
        lg: "h-12 rounded-[var(--md-sys-shape-corner-medium)] px-5",
        large: "h-12 rounded-[var(--md-sys-shape-corner-medium)] px-5",
        icon: "size-10",
        "icon-sm": "size-8",
        "icon-lg": "size-12",
      },
    },
    defaultVariants: {
      variant: "filled",
      size: "default",
    },
  },
);

export interface ButtonProps
  extends ComponentProps<"button">, VariantProps<typeof buttonVariants> {
  asChild?: boolean;
}

export function Button({
  className,
  variant = "filled",
  size = "default",
  asChild = false,
  type = "button",
  ...props
}: ButtonProps) {
  const Comp = asChild ? Slot.Root : "button";

  return (
    <Comp
      data-slot="button"
      data-variant={variant}
      data-size={size}
      type={asChild ? undefined : type}
      className={cn(buttonVariants({ variant, size }), className)}
      {...props}
    />
  );
}

export { buttonVariants };

Dependencies

npm packages

class-variance-authorityradix-ui

Registry dependencies