- Published on
How to properly style shadcn/ui library Button component?
- Authors
- Name
- Ripal & Zalak
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
- Maintain Reusability: Avoid repeating similar styles across components. Use variants and sizes to centralize styles.
- Consistency: Ensure your customizations align with the rest of your design system.
- 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.