Published on

How to properly style shadcn/ui library Button component?

Authors
  • Name
    Ripal & Zalak
    Twitter

How to Properly Style ShadCN/UI Button Component

The ShadCN/UI library provides flexible and powerful UI components. However, customizing these components, such as the Button component, can sometimes be confusing. This guide explains best practices to style and extend the ShadCN/UI Button component effectively.

Overview of the ShadCN Button Component

The default Button component is built using class-variance-authority (CVA) for styling and supports multiple variants and sizes:

const buttonVariants = cva(
  'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-zinc-950 dark:focus-visible:ring-zinc-300',
  {
    variants: {
      variant: {
        default:
          'bg-zinc-900 text-zinc-50 hover:bg-zinc-900/90 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-50/90',
        destructive:
          'bg-red-500 text-zinc-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-zinc-50 dark:hover:bg-red-900/90',
        outline:
          'border border-zinc-200 bg-white hover:bg-zinc-100 hover:text-zinc-900 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-50',
        secondary:
          'bg-zinc-100 text-zinc-900 hover:bg-zinc-100/80 dark:bg-zinc-800 dark:text-zinc-50 dark:hover:bg-zinc-800/80',
        ghost:
          'hover:bg-zinc-100 hover:text-zinc-900 dark:hover:bg-zinc-800 dark:hover:text-zinc-50',
        link: 'text-zinc-900 underline-offset-4 hover:underline dark:text-zinc-50',
      },
      size: {
        default: 'h-10 px-4 py-2',
        sm: 'h-9 rounded-md px-3',
        lg: 'h-11 rounded-md px-8',
        icon: 'h-10 w-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
)

Best Practices for Customization

1. Adding New Variants and Sizes

The most straightforward approach is to extend the existing buttonVariants with new styles.

const buttonVariants = cva(
  '...', // Existing styles
  {
    variants: {
      ...existingVariants,
      size: {
        ...existingSizes,
        xl: 'h-14 rounded-2xl px-12 py-4', // New XL size
      },
      variant: {
        ...existingVariants,
        cta: 'bg-red-600 text-white hover:bg-red-700 focus-visible:ring-red-500',
      },
    },
  }
)

You can then use these variants like this:

<Button variant="cta" size="xl">
  Call to Action
</Button>

2. Creating a Wrapper Component

If you need frequent use of a customized button, consider creating a wrapper component:

import React from 'react'
import { Button } from '@/components/ui/shadcn/button'

type StyledButtonProps = React.ComponentProps<typeof Button>

function StyledButton({ children, ...props }: StyledButtonProps) {
  return (
    <Button
      {...props}
      className="rounded-full bg-red-500 px-10 py-4 text-white hover:bg-red-600 focus-visible:ring-2 focus-visible:ring-red-500"
    >
      {children}
    </Button>
  )
}

export default StyledButton

3. Using Class Names for Specific Cases

For one-off customizations, directly override the className prop:

<Button className="rounded-lg bg-blue-500 px-8 py-3 text-white hover:bg-blue-600 focus-visible:ring-blue-400">
  Custom Button
</Button>

Key Considerations

  1. Maintain Reusability: Avoid repeating similar styles across components. Use variants and sizes to centralize styles.
  2. Consistency: Ensure your customizations align with the rest of your design system.
  3. Understand CVA: Learn how class-variance-authority works to leverage its full potential.

FAQs

Can I apply this approach to other ShadCN components?

Yes! Many ShadCN components use similar structures, so you can extend them with additional variants and sizes.

Should I always use wrapper components?

Not necessarily. For frequent and consistent customizations, wrapper components are helpful. For one-off use cases, customizing directly with className works fine.

How do I debug styling issues?

Use browser developer tools to inspect applied classes and adjust your configurations accordingly.

Conclusion

Customizing ShadCN components, like the Button, is flexible and straightforward when leveraging class-variance-authority. Whether adding new variants, creating wrapper components, or applying direct class overrides, choose an approach that best fits your project’s needs.