Sitemap
Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Conditional Hover Effects in shadcn Badge Component

2 min readJun 17, 2024

--

Background

Our project manager noticed some badges had hover effects, making them look like buttons, which caused confusion. We needed to remove hover effects for non-button badges while keeping them for actual buttons. We use the shadcn badge component.

Initial Setup

Here’s the default setup using class-variance-authority (CVA):

import { cva, type VariantProps } from "class-variance-authority";
import cn from "@/utils/cn";

const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);

export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}

function Badge({ className, variant, ...props }: BadgeProps) {
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
}

export { Badge, badgeVariants };

Solution

I conditionally apply hover effects based on the role attribute:

const hoverVariants = cva("", {
variants: {
variant: {
default: "hover:bg-primary/80",
secondary: "hover:bg-secondary/80",
destructive: "hover:bg-destructive/80",
outline: "",
},
},
defaultVariants: {
variant: "default",
},
});

function Badge({ className, variant, role, ...props }: BadgeProps) {
const isRoleButton = role === "button";
return (
<div
className={cn(
badgeVariants({ variant }),
isRoleButton && hoverVariants({ variant }),
className
)}
role={role}
{...props}
/>
);
}

Explanation

1.Separated Styles:

  • badgeVariants: Base styles.
  • hoverVariants: Hover styles.

2.Conditional Application:

  • Check if role is "button".
  • Apply hoverVariants only if true.

Usage Example

import React from 'react';
import { Badge } from './path/to/Badge';

const Example = () => (
<div>
<Badge role="button" variant="default">Default Button Badge</Badge>
<Badge role="button" variant="secondary">Secondary Button Badge</Badge>
<Badge variant="destructive">Non-Button Destructive Badge</Badge>
<Badge variant="outline">Non-Button Outline Badge</Badge>
</div>
);

export default Example;

Conclusion

This method ensures flexibility by conditionally applying hover effects based on the role attribute. It keeps the component logic clean and maintainable.

Get Dobinshin’s stories in your inbox

Join Medium for free to get updates from this writer.

If you have a better idea, feel free to leave a comment below.

--

--

Dev Genius
Dev Genius