Skip to content

Commit e9f22ba

Browse files
authored
feat: add Input component
1 parent ab75b52 commit e9f22ba

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`Input component > renders correctly 1`] = `
4+
<div>
5+
<input
6+
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-dodger-blue focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
7+
placeholder="Email"
8+
/>
9+
</div>
10+
`;

src/components/input.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 { Input } from "./input";
4+
5+
describe("Input component", () => {
6+
it("renders correctly", () => {
7+
const { container } = render(<Input placeholder="Email" />);
8+
expect(container).toMatchSnapshot();
9+
});
10+
});

src/components/input.stories.tsx

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
3+
import { Button } from "./button";
4+
import { Input } from "./input";
5+
6+
const meta = {
7+
title: "Input",
8+
component: Input,
9+
parameters: {
10+
layout: "centered",
11+
},
12+
argTypes: {
13+
disabled: {
14+
control: "boolean",
15+
},
16+
},
17+
} satisfies Meta<typeof Input>;
18+
19+
export default meta;
20+
type Story = StoryObj<typeof meta>;
21+
22+
export const Default: Story = {
23+
args: {
24+
placeholder: "Email",
25+
},
26+
};
27+
28+
export const File: Story = {
29+
args: {
30+
type: "file",
31+
},
32+
};
33+
34+
export const Disabled: Story = {
35+
args: {
36+
placeholder: "Email",
37+
disabled: true,
38+
},
39+
};
40+
41+
export const WithButton: Story = {
42+
render() {
43+
return (
44+
<div className="flex w-full max-w-sm items-center space-x-2">
45+
<Input type="email" placeholder="Email" />
46+
<Button type="submit">Subscribe</Button>
47+
</div>
48+
);
49+
},
50+
};

src/components/input.tsx

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { InputHTMLAttributes } from "react";
2+
import * as React from "react";
3+
4+
import { cn } from "@/lib/utils";
5+
6+
export type InputProps = InputHTMLAttributes<HTMLInputElement>;
7+
8+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
9+
({ className, type, ...props }, ref) => {
10+
return (
11+
<input
12+
type={type}
13+
className={cn(
14+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-dodger-blue focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
15+
className
16+
)}
17+
ref={ref}
18+
{...props}
19+
/>
20+
);
21+
}
22+
);
23+
24+
Input.displayName = "Input";
25+
26+
export { Input };

0 commit comments

Comments
 (0)