Skip to content

Commit 97c94f2

Browse files
committed
fix: migrate input and field to base-ui
1 parent a1c6d82 commit 97c94f2

File tree

7 files changed

+119
-114
lines changed

7 files changed

+119
-114
lines changed

packages/ui-react/.storybook/style.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
@layer base {
55
html {
6-
/* @apply text-gray-dark; */
7-
@apply text-red;
6+
/* Use a bold color to clearly show cases where we've forgotten to set text color. */
7+
color: #ff00ff;
88
}
99
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { Meta, Preview } from "@storybook/react";
2+
import * as Input from "../input/input.js";
3+
import * as Field from "./field.js";
4+
5+
export default {
6+
title: "Components/Field",
7+
component: Field.Field,
8+
argTypes: {
9+
children: {
10+
control: false,
11+
},
12+
},
13+
} satisfies Meta;
14+
15+
export const WithInput = {
16+
args: {
17+
children: (
18+
<>
19+
<Field.Label>Name</Field.Label>
20+
<Input.Input />
21+
</>
22+
),
23+
},
24+
} satisfies Preview;
25+
26+
export const WithValidation = {
27+
args: {
28+
validate: () => "Please enter a valid email address.",
29+
children: (
30+
<>
31+
<Field.Label>Email</Field.Label>
32+
<Input.Input />
33+
34+
<Field.Error />
35+
<Field.Description>
36+
This field will always fail validation on blur.
37+
</Field.Description>
38+
</>
39+
),
40+
},
41+
} satisfies Preview;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Field } from "@base-ui-components/react/field";
2+
import { cn } from "../../lib/utils.js";
3+
4+
export type FieldProps = React.HTMLAttributes<HTMLDivElement> & {
5+
asChild?: boolean;
6+
label: string;
7+
labelFor: string;
8+
};
9+
10+
const Root = Field.Root;
11+
const Control = Field.Control;
12+
const Validity = Field.Validity;
13+
14+
const FieldError = ({ className, ...props }: Field.Error.Props) => {
15+
return (
16+
<Field.Error className={cn("text-sm text-red", className)} {...props} />
17+
);
18+
};
19+
20+
const Description = ({ className, ...props }: Field.Description.Props) => {
21+
return (
22+
<Field.Description
23+
className={cn("text-sm text-gray-800", className)}
24+
{...props}
25+
/>
26+
);
27+
};
28+
29+
const Label = ({ className, ...props }: Field.Label.Props) => {
30+
return (
31+
<Field.Label
32+
className={cn("font-bold text-sm text-gray-dark", className)}
33+
{...props}
34+
/>
35+
);
36+
};
37+
38+
export {
39+
Root as Field,
40+
Control,
41+
Validity,
42+
FieldError as Error,
43+
Description,
44+
Label,
45+
};

packages/ui-react/src/components/form-field/form-field.stories.tsx

Lines changed: 0 additions & 24 deletions
This file was deleted.

packages/ui-react/src/components/form-field/form-field.tsx

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,34 @@
1-
import { forwardRef } from "react";
1+
import { Input as InputPrimitive } from "@base-ui-components/react/input";
22
import { cn } from "../../lib/utils.js";
33

4-
export type InputProps = Omit<
5-
React.InputHTMLAttributes<HTMLInputElement>,
6-
"placeholder"
7-
> & {
8-
// Make id required
9-
id: string;
10-
};
4+
export type InputProps = Omit<InputPrimitive.Props, "placeholder">;
115

12-
const Input = forwardRef<HTMLInputElement, InputProps>(
13-
({ className, type = "text", ...props }, ref) => {
14-
return (
15-
<input
16-
type={type}
17-
className={cn(
18-
`
19-
flex
20-
h-10 w-full px-3 py-2
21-
rounded-lg
22-
border border-gray-300
23-
bg-gray-100 text-gray-dark
24-
text-base
25-
file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground
26-
focus-visible:outline-none
27-
focus-visible:border-gray-500
28-
disabled:cursor-not-allowed
29-
disabled:opacity-50
30-
`,
31-
className,
32-
)}
33-
ref={ref}
34-
{...props}
35-
// Explicitly set placeholder to empty string to avoid users ignoring
36-
// the types and passing placeholder anyways.
37-
placeholder=""
38-
/>
39-
);
40-
},
41-
);
42-
Input.displayName = "Input";
6+
const Input = ({ className, type = "text", ...props }: InputProps) => {
7+
return (
8+
<InputPrimitive
9+
type={type}
10+
className={cn(
11+
`
12+
flex
13+
h-10 w-full px-3 py-2
14+
rounded-lg
15+
border border-gray-300
16+
bg-gray-100 text-gray-dark
17+
text-base
18+
file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground
19+
focus-visible:outline-none
20+
focus-visible:border-gray-500
21+
disabled:cursor-not-allowed
22+
disabled:opacity-50
23+
`,
24+
className,
25+
)}
26+
{...props}
27+
// Explicitly set placeholder to empty string to prevent users from
28+
// ignoring the types and passing placeholder anyways.
29+
placeholder=""
30+
/>
31+
);
32+
};
4333

4434
export { Input };

packages/ui-react/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export * as Button from "./components/button/button.js";
2+
export * as Callout from "./components/callout/callout.js";
23
export * as Checkbox from "./components/checkbox/checkbox.js";
3-
export * as FormField from "./components/form-field/form-field.js";
4+
export * as Field from "./components/field/field.js";
45
export * as Input from "./components/input/input.js";
56
export * as Select from "./components/select/select.js";
67
export * as Toast from "./components/toast/toast.js";
7-
export * as Callout from "./components/callout/callout.js";

0 commit comments

Comments
 (0)