---
title: Button
description: A versatile button component that supports multiple visual styles, sizes, and can render as a button, anchor, or custom element
---

```tsx
'use client';

import { Button } from '@/ui/buttons/Button';

export function ButtonDemo() {
  return (
    <div>
      Primary
      <Button color="saffron" theme="solid" variant="pill">
        Click me
      </Button>
      Secondary
      <Button color="saffron" size="secondary" theme="solid" variant="pill">
        Click me
      </Button>
      Tertiary
      <Button color="saffron" size="tertiary" theme="solid" variant="pill">
        Click me
      </Button>
    </div>
  );
}
```

## Installation

Using the CLI:

```bash
npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/button.json
```

Or manually, copy the following code into `/ui/button.tsx`:

```tsx
'use client';
import { clsx } from 'clsx';
import type {
  ComponentProps,
  ElementType,
  FunctionComponent,
  PropsWithChildren,
  ReactElement,
  ReactPortal,
} from 'react';

import { type ButtonProps as Btn, getButtonClasses } from './Button.type';
import { ButtonContent } from './ButtonContent';

export interface ButtonProps extends Btn, Omit<ComponentProps<'button'>, 'color'> {
  component?: 'button';
}

export interface ButtonAnchorProps extends Btn, Omit<ComponentProps<'a'>, 'color'> {
  component: 'a';
  disabled?: boolean;
}

export interface FakeButtonProps extends Btn, Omit<ComponentProps<'span'>, 'color'> {
  component: 'span' | 'div';
  disabled?: boolean;
}
// For Button with React Router Link or similar components
export interface ReactButtonProps extends Btn, Omit<ComponentProps<'a'>, 'href' | 'color'> {
  component?: ReactElement | ReactPortal;
  disabled?: boolean;
}

export type AnyButtonProps = PropsWithChildren<
  ButtonProps | ButtonAnchorProps | FakeButtonProps | ReactButtonProps
>;

export function useButton({ component, disabled, ...props }: AnyButtonProps): {
  attrs: Record<string, unknown>;
  Cmp: ElementType;
} {
  if (component === 'a' || 'href' in props || typeof component === 'object') {
    return {
      attrs: {
        'data-name': 'ButtonAnchor',
        'aria-disabled': disabled ? 'true' : undefined,
        ...props,
      },
      Cmp: 'a',
    };
  }

  if (component === 'span' || component === 'div') {
    return {
      attrs: {
        'data-name': 'FakeButton',
        'aria-disabled': disabled ? 'true' : undefined,
        ...props,
      },
      Cmp: 'span' as ElementType,
    };
  }

  return {
    attrs: {
      'data-name': 'Button',
      type: 'button',
      disabled,
      ...props,
    },
    Cmp: 'button' as ElementType,
  };
}

// Main Button component that handles both button and anchor functionality
export const Button: FunctionComponent<AnyButtonProps> = ({
  className,
  children,
  color = 'saffron',
  icon,
  iconWidth,
  size = 'medium',
  theme = 'solid',
  variant = 'pill',
  ...props
}) => {
  const { Cmp, attrs } = useButton(props);

  return (
    <Cmp {...attrs} className={clsx(getButtonClasses({ color, size, theme, variant }), className)}>
      <ButtonContent icon={icon} iconWidth={iconWidth}>
        {children}
      </ButtonContent>
    </Cmp>
  );
};

Button.displayName = 'Button';
```

## Usage

```tsx showLineNumbers
import { Button } from '@/docs/lib/ui/Button';

export function Component() {
  return (
    <Button color="saffron" size="medium" theme="solid" variant="pill">
      Click me
    </Button>
  );
}
```

## API Reference

### Button

| Prop        | Type                                                                                                                                                                                                                   | Default     | Description                                                                                 |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------- |
| `color`     | `"black" \| "darkGrey" \| "green" \| "lavender" \| "lightGrey" \| "lightSand" \| "marygold" \| "orange" \| "red" \| "saffron" \| "sand" \| "sienna" \| "ultramarine" \| "verdigris" \| "wave" \| "white" \| "current"` | `"saffron"` | The color theme of the button                                                               |
| `icon`      | `IconicNames`                                                                                                                                                                                                          | `undefined` | Optional icon name from the Trident Icons library                                           |
| `iconType`  | `IconicTypes`                                                                                                                                                                                                          | `undefined` | Force the icon type to be svg, font or default                                              |
| `iconWidth` | `string`                                                                                                                                                                                                               | `undefined` | Custom width for the icon (e.g., "24px")                                                    |
| `size`      | `"small" \| "medium" \| "large"`                                                                                                                                                                                       | `"medium"`  | The size of the button                                                                      |
| `theme`     | `"outline" \| "solid"`                                                                                                                                                                                                 | `"solid"`   | The visual style of the button - solid for filled background, outline for border only       |
| `variant`   | `"circle" \| "pill"`                                                                                                                                                                                                   | `"pill"`    | The shape of the button - circle for circular buttons, pill for rounded rectangular buttons |
| `component` | `"button" \| "a" \| "span" \| "div" \| ReactElement`                                                                                                                                                                   | `"button"`  | The underlying HTML element or React component to render                                    |
| `disabled`  | `boolean`                                                                                                                                                                                                              | `false`     | Whether the button is disabled (sets `disabled` attribute or `aria-disabled` for anchors)   |
| `children`  | `ReactNode`                                                                                                                                                                                                            | `undefined` | The content to display inside the button                                                    |

## Examples

```tsx
'use client';

import { Button } from '@/ui/buttons/Button';

export function ButtonOutlineDemo() {
  return (
    <Button color="saffron" size="medium" theme="outline" variant="pill">
      Learn more
    </Button>
  );
}
```

```tsx
'use client';

import { Button } from '@/ui/buttons/Button';

export function ButtonSmallDemo() {
  return (
    <Button color="ultramarine" size="small" theme="solid" variant="circle">
      hi!
    </Button>
  );
}
```

```tsx
'use client';

import { Button } from '@/ui/buttons/Button';

export function ButtonLargeDemo() {
  return (
    <Button color="saffron" size="large" theme="solid" variant="circle">
      Get started
    </Button>
  );
}
```

```tsx
'use client';

import { Button } from '@/ui/buttons/Button';

export function ButtonIconDemo() {
  return (
    <Button color="saffron" size="medium" theme="solid" variant="pill" icon="ArrowDefaultRight">
      Continue
    </Button>
  );
}
```

```tsx
'use client';

import { Button } from '@/ui/buttons/Button';

export function ButtonDisabledDemo() {
  return (
    <Button color="saffron" size="medium" theme="solid" variant="pill" disabled>
      Submit
    </Button>
  );
}
```

```tsx
'use client';

import { Button } from '@/ui/buttons/Button';

export function ButtonCircleDemo() {
  return (
    <Button color="saffron" size="medium" theme="solid" variant="circle" icon="HeartOutlined">
      <span className="sr-only">Add to favorites</span>
    </Button>
  );
}
```

## Notes

- The Button component is polymorphic and can render as a `<button>`, `<a>`, `<span>`, `<div>`, or any custom React component
- When `component="a"` or an `href` prop is provided, the button renders as an anchor element with appropriate accessibility attributes
- The `disabled` prop sets the native `disabled` attribute on button elements and `aria-disabled` on anchor and fake button elements
- All standard HTML button attributes (onClick, onFocus, etc.) are supported and forwarded to the underlying element
- The component automatically handles button type, defaulting to `type="button"` to prevent form submission
