# Button with Icon

> Button with a leading or trailing icon; position is switchable.

- Author: Atelier UI
- License: MIT
- Page: https://chromotion.dev/en/components/button-with-icon
- Site: Atelier UI (https://chromotion.dev)

## Install

```bash
npx shadcn@latest add https://chromotion.dev/r/button-with-icon.json
```

Stack: React + TypeScript + Tailwind CSS v4, shadcn/ui conventions. `cn` comes from `@/lib/utils`.

## Dependencies

```bash
npm install lucide-react
```

## Usage

```tsx title="components/button-with-icon-demo.tsx"
import { ArrowRight, Download, Mail } from "lucide-react"

import { ButtonWithIcon } from "@/components/button-with-icon"

export default function ButtonWithIconDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3 p-8">
      <ButtonWithIcon icon={<Mail />}>Login with email</ButtonWithIcon>
      <ButtonWithIcon icon={<ArrowRight />} iconPosition="right">
        Continue
      </ButtonWithIcon>
      <ButtonWithIcon icon={<Download />} className="bg-secondary text-secondary-foreground hover:bg-secondary/80">
        Download
      </ButtonWithIcon>
    </div>
  )
}
```

## Source

```tsx title="components/button-with-icon.tsx"
import * as React from "react"
import { Mail } from "lucide-react"

import { cn } from "@/lib/utils"

export interface ButtonWithIconProps extends React.ComponentProps<"button"> {
  icon?: React.ReactNode
  iconPosition?: "left" | "right"
}

export function ButtonWithIcon({ icon, iconPosition = "left", className, children, ...props }: ButtonWithIconProps) {
  const iconNode = <span className="inline-flex shrink-0 [&_svg]:size-4">{icon ?? <Mail />}</span>

  return (
    <button
      className={cn(
        "inline-flex h-10 items-center justify-center gap-2 rounded-lg bg-primary px-5 text-sm font-medium text-primary-foreground shadow-xs",
        "transition-[background-color,transform] hover:bg-primary/90 active:scale-[0.98]",
        "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:outline-none",
        "disabled:pointer-events-none disabled:opacity-50",
        className
      )}
      {...props}
    >
      {iconPosition === "left" && iconNode}
      {children}
      {iconPosition === "right" && iconNode}
    </button>
  )
}
```
