Skip to content

Commit

Permalink
feat(components): add polymorphic support with asChild and ref forwar…
Browse files Browse the repository at this point in the history
…ding to Badge
  • Loading branch information
anstapol committed Jan 4, 2025
1 parent 1081536 commit 72ad2b5
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 22 deletions.
6 changes: 6 additions & 0 deletions apps/www/content/docs/components/badge.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ npx shadcn@latest add badge

<Steps>

<Step>Install the following dependencies:</Step>

```bash
npm install @radix-ui/react-slot
```

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="badge" />
Expand Down
2 changes: 1 addition & 1 deletion apps/www/public/r/styles/default/badge.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"files": [
{
"path": "ui/badge.tsx",
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"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\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground hover:bg-primary/80\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive:\n \"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80\",\n outline: \"text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }\n",
"content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"focus:ring-ring 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-offset-2\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground hover:bg-primary/80 border-transparent\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent\",\n outline: \"text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {\n asChild?: boolean\n}\n\nconst Badge = React.forwardRef<HTMLDivElement, BadgeProps>(\n ({ className, variant, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"div\"\n return (\n <Comp\n className={cn(badgeVariants({ variant }), className)}\n ref={ref}\n {...props}\n />\n )\n }\n)\n\nBadge.displayName = \"Badge\"\n\nexport { Badge, badgeVariants }\n",
"type": "registry:ui",
"target": ""
}
Expand Down
2 changes: 1 addition & 1 deletion apps/www/public/r/styles/new-york/badge.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"files": [
{
"path": "ui/badge.tsx",
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-md 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\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive:\n \"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80\",\n outline: \"text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }\n",
"content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"focus:ring-ring inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow\",\n outline: \"text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {\n asChild?: boolean // Enable polymorphism\n}\n\nconst Badge = React.forwardRef<HTMLDivElement, BadgeProps>(\n ({ className, variant, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"div\"\n return (\n <Comp\n className={cn(badgeVariants({ variant }), className)}\n ref={ref}\n {...props}\n />\n )\n }\n)\n\nBadge.displayName = \"Badge\"\n\nexport { Badge, badgeVariants }\n",
"type": "registry:ui",
"target": ""
}
Expand Down
32 changes: 22 additions & 10 deletions apps/www/registry/default/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

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

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",
"focus:ring-ring 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-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
"bg-primary text-primary-foreground hover:bg-primary/80 border-transparent",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
"bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent",
outline: "text-foreground",
},
},
Expand All @@ -25,12 +26,23 @@ const badgeVariants = cva(

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

function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
VariantProps<typeof badgeVariants> {
asChild?: boolean
}

const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
({ className, variant, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "div"
return (
<Comp
className={cn(badgeVariants({ variant }), className)}
ref={ref}
{...props}
/>
)
}
)

Badge.displayName = "Badge"

export { Badge, badgeVariants }
32 changes: 22 additions & 10 deletions apps/www/registry/new-york/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

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

const badgeVariants = cva(
"inline-flex items-center rounded-md 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",
"focus:ring-ring inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
"bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
destructive:
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
"bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow",
outline: "text-foreground",
},
},
Expand All @@ -25,12 +26,23 @@ const badgeVariants = cva(

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

function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
VariantProps<typeof badgeVariants> {
asChild?: boolean // Enable polymorphism
}

const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
({ className, variant, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "div"
return (
<Comp
className={cn(badgeVariants({ variant }), className)}
ref={ref}
{...props}
/>
)
}
)

Badge.displayName = "Badge"

export { Badge, badgeVariants }

0 comments on commit 72ad2b5

Please sign in to comment.