Skip to content

Commit b0ea1ab

Browse files
authored
feat: add Label component
1 parent e9f22ba commit b0ea1ab

File tree

7 files changed

+135
-2
lines changed

7 files changed

+135
-2
lines changed

package-lock.json

+47-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"vitest": "^3.0.4"
6464
},
6565
"dependencies": {
66+
"@radix-ui/react-label": "^2.1.1",
6667
"@radix-ui/react-slot": "^1.1.1",
6768
"class-variance-authority": "^0.7.1",
6869
"clsx": "^2.1.1",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`Label component > renders correctly 1`] = `
4+
<div>
5+
<label
6+
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
7+
for="email"
8+
>
9+
Email
10+
</label>
11+
</div>
12+
`;

src/components/input.stories.tsx

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Meta, StoryObj } from "@storybook/react";
22

33
import { Button } from "./button";
44
import { Input } from "./input";
5+
import { Label } from "./label";
56

67
const meta = {
78
title: "Input",
@@ -48,3 +49,14 @@ export const WithButton: Story = {
4849
);
4950
},
5051
};
52+
53+
export const WithLabel: Story = {
54+
render() {
55+
return (
56+
<div className="grid w-full max-w-sm items-center gap-2">
57+
<Label htmlFor="email">Email</Label>
58+
<Input id="email" type="email" placeholder="Email" />
59+
</div>
60+
);
61+
},
62+
};

src/components/label.spec.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { render } from "@testing-library/react";
2+
import { describe, expect, it } from "vitest";
3+
import { Label } from "./label";
4+
5+
describe("Label component", () => {
6+
it("renders correctly", () => {
7+
const { container } = render(<Label htmlFor="email">Email</Label>);
8+
expect(container).toMatchSnapshot();
9+
});
10+
});

src/components/label.stories.tsx

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
3+
import { Input } from "./input";
4+
import { Label } from "./label";
5+
6+
const meta = {
7+
title: "Label",
8+
component: Label,
9+
parameters: {
10+
layout: "centered",
11+
},
12+
} satisfies Meta<typeof Label>;
13+
14+
export default meta;
15+
type Story = StoryObj<typeof meta>;
16+
17+
export const WithInput: Story = {
18+
render() {
19+
return (
20+
<div className="grid w-full max-w-sm items-center gap-1.5">
21+
<Label htmlFor="email">Email</Label>
22+
<Input id="email" type="email" placeholder="Email" />
23+
</div>
24+
);
25+
},
26+
};

src/components/label.tsx

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"use client";
2+
3+
import * as LabelPrimitive from "@radix-ui/react-label";
4+
import { cva, type VariantProps } from "class-variance-authority";
5+
import * as React from "react";
6+
7+
import { cn } from "@/lib/utils";
8+
9+
const labelVariants = cva(
10+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11+
);
12+
13+
const Label = React.forwardRef<
14+
React.ElementRef<typeof LabelPrimitive.Root>,
15+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
16+
VariantProps<typeof labelVariants>
17+
>(({ className, ...props }, ref) => (
18+
<LabelPrimitive.Root
19+
ref={ref}
20+
className={cn(labelVariants(), className)}
21+
{...props}
22+
/>
23+
));
24+
25+
Label.displayName = LabelPrimitive.Root.displayName;
26+
27+
export { Label };

0 commit comments

Comments
 (0)