Skip to content

Commit a74b52c

Browse files
committed
implement TagButton component
1 parent d79bbe1 commit a74b52c

File tree

2 files changed

+80
-31
lines changed

2 files changed

+80
-31
lines changed
Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Meta, StoryObj } from "@storybook/react"
22

33
import { HStack, VStack } from "../flex"
4-
import { Tag } from "../tag"
4+
import { Tag, TagButton } from "../tag"
55

66
const meta = {
77
title: "Molecules / Display Content / New Tags",
@@ -18,20 +18,34 @@ const statusArray = ["normal", "tag", "success", "error", "warning"] as const
1818
// "subtle" is default variant
1919
const variantArray = ["subtle", "highContrast", "solid", "outline"] as const
2020

21-
const StyleVariantList = () => (
22-
<HStack>
23-
{statusArray.map((status) => (
24-
<VStack key={status}>
25-
{variantArray.map((variant) => (
26-
<Tag key={variant} status={status} variant={variant}>
27-
Tag Name
28-
</Tag>
29-
))}
30-
</VStack>
31-
))}
32-
</HStack>
33-
)
34-
3521
export const StyleVariantsBasic: Story = {
36-
render: (args) => <StyleVariantList {...args} />,
22+
render: () => (
23+
<HStack>
24+
{statusArray.map((status) => (
25+
<VStack key={status}>
26+
{variantArray.map((variant) => (
27+
<Tag key={variant} status={status} variant={variant}>
28+
Tag Name
29+
</Tag>
30+
))}
31+
</VStack>
32+
))}
33+
</HStack>
34+
),
35+
}
36+
37+
export const StyleVariantsButton: Story = {
38+
render: () => (
39+
<HStack>
40+
{statusArray.map((status) => (
41+
<VStack key={status}>
42+
{variantArray.map((variant) => (
43+
<TagButton key={variant} status={status} variant={variant}>
44+
Tag Name
45+
</TagButton>
46+
))}
47+
</VStack>
48+
))}
49+
</HStack>
50+
),
3751
}

src/components/ui/tag.tsx

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import { forwardRef } from "react"
12
import { cva, VariantProps } from "class-variance-authority"
23
import { Slot } from "@radix-ui/react-slot"
34

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

67
const tagVariants = cva(
7-
"inline-flex items-center rounded-full border px-2 py-0.5 min-h-8 text-xs uppercase transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8+
"inline-flex items-center rounded-full border px-2 py-0.5 min-h-8 text-xs uppercase transition-colors",
89
{
910
variants: {
1011
status: {
@@ -25,27 +26,31 @@ const tagVariants = cva(
2526
{
2627
variant: "solid",
2728
status: "normal",
28-
className: "bg-body-medium",
29+
className:
30+
"bg-body-medium focus-visible:outline-body hover:shadow-body",
2931
},
3032
{
3133
variant: "solid",
3234
status: "tag",
33-
className: "bg-primary",
35+
className:
36+
"bg-primary focus-visible:outline-primary-high-contrast hover:shadow-primary-low-contrast",
3437
},
3538
{
3639
variant: "solid",
3740
status: "success",
38-
className: "bg-success text-success-light",
41+
className:
42+
"bg-success text-success-light focus-visible:outline-success-dark",
3943
},
4044
{
4145
variant: "solid",
4246
status: "error",
43-
className: "bg-error text-error-light",
47+
className: "bg-error text-error-light focus-visible:outline-error-dark",
4448
},
4549
{
4650
variant: "solid",
4751
status: "warning",
48-
className: "bg-warning text-warning-dark",
52+
className:
53+
"bg-warning text-warning-dark focus-visible:outline-warning-border",
4954
},
5055
{
5156
variant: "highContrast",
@@ -96,14 +101,44 @@ export interface TagProps
96101
asChild?: boolean
97102
}
98103

99-
function Tag({ className, asChild, variant, status, ...props }: TagProps) {
100-
const Comp = asChild ? Slot : "div"
101-
return (
102-
<Comp
103-
className={cn(tagVariants({ variant, status }), className)}
104-
{...props}
105-
/>
106-
)
104+
const Tag = forwardRef<HTMLDivElement, TagProps>(
105+
({ className, asChild, variant, status, ...props }, ref) => {
106+
const Comp = asChild ? Slot : "div"
107+
return (
108+
<Comp
109+
ref={ref}
110+
className={cn(tagVariants({ variant, status }), className)}
111+
{...props}
112+
/>
113+
)
114+
}
115+
)
116+
117+
Tag.displayName = "Tag"
118+
119+
export interface TagButtonProps
120+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
121+
VariantProps<typeof tagVariants> {
122+
asChild?: boolean
107123
}
108124

109-
export { Tag }
125+
const TagButton = forwardRef<HTMLButtonElement, TagButtonProps>(
126+
({ className, asChild, variant, status, ...props }, ref) => {
127+
const Comp = asChild ? Slot : "button"
128+
return (
129+
<Comp
130+
ref={ref}
131+
className={cn(
132+
"hover:shadow-[2px_2px] focus-visible:outline focus-visible:outline-4 focus-visible:-outline-offset-1 focus-visible:outline-inherit",
133+
tagVariants({ variant, status }),
134+
className
135+
)}
136+
{...props}
137+
/>
138+
)
139+
}
140+
)
141+
142+
TagButton.displayName = "TagButton"
143+
144+
export { Tag, TagButton }

0 commit comments

Comments
 (0)