-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Idea: support for wrapped Redwood field components #3
Comments
This is great @Benjamin-Lee! Thank you so much for contributing 😀 I've had more people asking for better forms support, but haven't had a chance to look into it yet. And to be honest it might still be a few days/weeks/years until I do. |
Happy to help. I ended up changing my strategy for doing this to something so much easier: using import { cva } from "class-variance-authority"
import { cn } from "src/lib/utils"
export const inputVariants = cva(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
)
export const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
{
variants: {
error: {
true: "text-destructive",
},
},
}
)
export const fieldErrorVariants = cva(
"block text-[0.8rem] font-medium text-destructive"
)
export const FormItem = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
return <div ref={ref} className={cn("space-y-2", className)} {...props} />
})
FormItem.displayName = "FormItem" Then, building a form is as easy as: <Form onSubmit={onSubmit} className="space-y-6">
<div className="flex justify-between">
<FormItem>
<Label
name="email"
className={labelVariants()}
errorClassName={labelVariants({ error: true })}
>
First Name
</Label>
<TextField
name="firstName"
className={inputVariants()}
validation={{
required: {
value: true,
message: 'First name is required',
},
}}
autoComplete="given-name"
/>
<FieldError name="firstName" className={fieldErrorVariants()} />
</FormItem>
<FormItem>
<Label
name="lastName"
className={labelVariants()}
errorClassName={labelVariants({ error: true })}
>
Last Name
</Label>
<TextField
name="lastName"
className={inputVariants()}
validation={{
required: {
value: true,
message: 'Last name is required',
},
}}
autoComplete="family-name"
/>
<FieldError name="email" className={fieldErrorVariants()} />
</FormItem>
</div>
<FormItem>
<Label
name="email"
className={labelVariants()}
errorClassName={labelVariants({ error: true })}
>
Email address
</Label>
<EmailField
name="email"
className={inputVariants()}
ref={emailRef}
validation={{
required: {
value: true,
message: 'Email is required',
},
}}
/>
<FieldError name="email" className={fieldErrorVariants()} />
</FormItem>
<FormItem>
<Label
name="password"
className={labelVariants()}
errorClassName={labelVariants({ error: true })}
>
Password
</Label>
<PasswordField
name="password"
className={inputVariants()}
autoComplete="current-password"
validation={{
required: {
value: true,
message: 'Password is required',
},
minLength: {
value: 8,
message: 'Password must be at least 8 characters',
},
}}
/>
<FieldError name="password" className={fieldErrorVariants()} />
</FormItem>
<div>
<Submit className={cn(buttonVariants(), 'w-full')}>Login</Submit>
</div>
</Form> |
Hello, I was wondering if you have a solution for the Checkbox and Switch components? |
@Quelu I've just used shad's
It works, but you don't get the full RW form integration with its error handling unfortunately I want a better experience, but haven't prioritized that yet |
Thank you so much for the response! However, it doesn't work with the Checkbox component when it's set up to have multiple values other than a boolean. Based on what you provided, I was able to better understand how Shadcn works with react-hook-form. I was then able to create these components, which I can now directly use in my Redwood forms: export const CheckboxField = ({
label,
value,
name,
}: InputFieldProps & {
label: React.ReactNode;
value: string;
}) => {
return (
<Controller
name={name}
render={({ field }) => (
<div className="flex gap-4" key={name}>
<Checkbox
id={`checkbox-${value}`}
checked={field.value?.includes(value)}
onCheckedChange={(checked) => {
return checked
? field.onChange([...(field?.value || []), value])
: field.onChange(
field.value?.filter((newValue) => newValue !== value)
);
}}
/>
<ShadLabel htmlFor={`checkbox-${value}`}>{label}</ShadLabel>
</div>
)}
/>
);
};
export const CheckboxGroupField = ({
name,
options,
validation,
}: InputFieldProps & {
options: { label: React.ReactNode; value: string }[];
}) => {
return (
<Controller
name={name}
rules={validation}
render={() => (
<>
{options.map((option) => (
<CheckboxField
key={option.value}
label={option.label}
value={option.value}
name={name}
/>
))}
</>
)}
/>
);
};
export const SwitchField = ({
label,
name,
validation,
defaultValue,
}: InputFieldProps & {
label?: React.ReactNode;
}) => {
return (
<Controller
name={name}
rules={validation}
defaultValue={defaultValue}
render={({ field }) => (
<div className="flex gap-4" key={name}>
<Switch
id={`switch-${name}`}
checked={field.value}
onCheckedChange={field.onChange}
/>
{label && <ShadLabel htmlFor={`switch-${name}`}>{label}</ShadLabel>}
</div>
)}
/>
);
}; |
I'm trying to use shadcn/ui inside a Redwood project while also using Redwood Forms. It would be great if there were a way for the
<Input>
component from shadcn/ui to wrap the Redwood<TextField>
and its siblings. Here's my first pass at it if it's of any help:The text was updated successfully, but these errors were encountered: