Skip to content

Commit 860f58a

Browse files
authored
feat: Badge component (#937)
1 parent 2f1951f commit 860f58a

File tree

5 files changed

+163
-0
lines changed

5 files changed

+163
-0
lines changed

.changeset/khaki-buttons-impress.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@obosbbl/grunnmuren-react': minor
3+
---
4+
5+
add `<Badge />` component
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
import { cx } from 'cva';
3+
import { Fragment } from 'react';
4+
import { PaintRoller } from '@obosbbl/grunnmuren-icons-react';
5+
6+
import { Badge } from './Badge';
7+
8+
const meta: Meta<typeof Badge> = {
9+
title: 'Badge',
10+
component: Badge,
11+
render: (props) => {
12+
return (
13+
<div className="space-x-4">
14+
<Badge {...props} size="small">
15+
Small
16+
</Badge>
17+
<Badge {...props} size="medium">
18+
Medium
19+
</Badge>
20+
<Badge {...props} size="large">
21+
Large
22+
</Badge>
23+
</div>
24+
);
25+
},
26+
};
27+
28+
export default meta;
29+
30+
type Story = StoryObj<typeof Badge>;
31+
32+
export const Sandbox = () => {
33+
const colors = [
34+
'mint',
35+
'sky',
36+
'blue-dark',
37+
'green-dark',
38+
'gray-dark',
39+
'white',
40+
] as const;
41+
42+
return colors.map((color) => (
43+
<Fragment key={color}>
44+
<h2 className="font-medium">{color}</h2>
45+
<div className={cx('space-x-4 p-2', color === 'white' && 'bg-gray')}>
46+
<Badge color={color} size="small">
47+
small
48+
</Badge>
49+
<Badge color={color} size="medium">
50+
medium
51+
</Badge>
52+
<Badge color={color} size="large">
53+
large
54+
</Badge>
55+
</div>
56+
</Fragment>
57+
));
58+
};
59+
60+
export const WithIcon = () => {
61+
const colors = [
62+
'mint',
63+
'sky',
64+
'blue-dark',
65+
'green-dark',
66+
'gray-dark',
67+
'white',
68+
] as const;
69+
70+
return colors.map((color) => (
71+
<Fragment key={color}>
72+
<h2 className="font-medium">{color}</h2>
73+
<div className={cx('space-x-4 p-2', color === 'white' && 'bg-gray')}>
74+
<Badge color={color} size="small">
75+
<PaintRoller />
76+
small
77+
</Badge>
78+
<Badge color={color} size="medium">
79+
<PaintRoller />
80+
medium
81+
</Badge>
82+
<Badge color={color} size="large">
83+
<PaintRoller />
84+
large
85+
</Badge>
86+
</div>
87+
</Fragment>
88+
));
89+
};
90+
91+
export const Sizes: Story = {
92+
args: {
93+
color: 'mint',
94+
},
95+
render: (props) => {
96+
return (
97+
<div className="space-x-4">
98+
<Badge {...props} size="small">
99+
Small
100+
</Badge>
101+
<Badge {...props} size="medium">
102+
Medium
103+
</Badge>
104+
<Badge {...props} size="large">
105+
Large
106+
</Badge>
107+
</div>
108+
);
109+
},
110+
};

packages/react/src/badge/Badge.tsx

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { type VariantProps, cva } from 'cva';
2+
import { type Ref, forwardRef } from 'react';
3+
4+
type BadgeProps = VariantProps<typeof badgeVariants> & {
5+
children?: React.ReactNode;
6+
className?: string;
7+
};
8+
9+
const badgeVariants = cva({
10+
base: [
11+
'inline-flex w-fit items-center justify-center gap-1.5 rounded-lg [&_svg]:shrink-0',
12+
],
13+
variants: {
14+
color: {
15+
'gray-dark': 'bg-gray-dark text-white',
16+
mint: 'bg-mint',
17+
sky: 'bg-sky',
18+
white: 'bg-white',
19+
'blue-dark': 'bg-blue-dark text-white',
20+
'green-dark': 'bg-green-dark text-white',
21+
},
22+
size: {
23+
small: 'description px-2 py-0.5 [&_svg]:h-4 [&_svg]:w-4',
24+
medium: 'description px-2.5 py-1.5 [&_svg]:h-4 [&_svg]:w-4',
25+
large: 'paragraph px-3 py-2 [&_svg]:h-5 [&_svg]:w-5',
26+
},
27+
},
28+
defaultVariants: {
29+
size: 'medium',
30+
},
31+
});
32+
33+
function Badge(props: BadgeProps, ref: Ref<HTMLSpanElement>) {
34+
const { className: _className, color, size, ...restProps } = props;
35+
36+
const className = badgeVariants({
37+
className: _className,
38+
color,
39+
size,
40+
});
41+
42+
return <span className={className} {...restProps} ref={ref} />;
43+
}
44+
45+
const _Badge = forwardRef(Badge);
46+
export { _Badge as Badge, type BadgeProps };

packages/react/src/badge/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Badge';

packages/react/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export { Form } from 'react-aria-components';
33

44
export * from './GrunnmurenProvider';
55
export * from './accordion';
6+
export * from './badge';
67
export * from './button';
78
export * from './checkbox';
89
export * from './combobox';

0 commit comments

Comments
 (0)