Back to list
keidsondesigner

create-form

by keidsondesigner

0🍴 0📅 Jan 16, 2026

SKILL.md


name: create-form description: Cria formulários com React Hook Form, validação Zod e shadcn/ui. Use quando precisar criar ou modificar formulários seguindo os padrões Bewear. tools: Read, Write, Edit, Glob, Grep

Create Form Skill

Esta skill cria formulários seguindo o padrão estabelecido no projeto Bewear com React Hook Form, Zod e shadcn/ui.

Quando Usar

  • Criar novos formulários
  • Adicionar validação a formulários existentes
  • Implementar formulários com feedback de erro

Regras Obrigatórias

1. Stack de Formulários

SEMPRE use:

  • React Hook Form v7.62.0 para gerenciamento de formulários
  • Zod v4.0.17 para validação de schema
  • @hookform/resolvers para integração
  • shadcn/ui Form components

2. Estrutura do Formulário

Arquivo de referência obrigatório: src/app/auth/components/sign-in-form.tsx

"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import z from "zod";
import { Button } from "@/components/ui/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { toast } from "sonner";

// 1. Definir schema Zod
const formSchema = z.object({
  email: z.string().email("Email inválido"),
  password: z.string().min(8, "Senha deve ter pelo menos 8 caracteres"),
});

// 2. Inferir tipo do schema
type FormValues = z.infer<typeof formSchema>;

const FormComponent = () => {
  // 3. Inicializar form com zodResolver
  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      email: "",
      password: "",
    },
  });

  // 4. Função de submit assíncrona
  async function onSubmit(values: FormValues) {
    try {
      toast.success("Sucesso!");
    } catch (error) {
      toast.error("Erro ao processar");
      form.setError("email", {
        message: "Mensagem de erro",
      });
    }
  }

  // 5. Renderizar Form
  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input type="email" placeholder="Digite seu email" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <Button type="submit" disabled={form.formState.isSubmitting}>
          {form.formState.isSubmitting ? "Enviando..." : "Enviar"}
        </Button>
      </form>
    </Form>
  );
};

export default FormComponent;

3. Validações Zod Comuns

// Email
email: z.string().email("Email inválido")

// String com mínimo
password: z.string().min(8, "Mínimo 8 caracteres")

// String obrigatória
name: z.string().min(1, "Nome obrigatório")

// Número
quantity: z.number().min(1, "Quantidade mínima 1")

// UUID
id: z.uuid("ID inválido")

// CPF/CNPJ
cpfOrCnpj: z.string().regex(/^\d{11}|\d{14}$/, "CPF/CNPJ inválido")

// CEP
zipCode: z.string().regex(/^\d{5}-?\d{3}$/, "CEP inválido")

// Telefone
phone: z.string().regex(/^\(\d{2}\)\s?\d{4,5}-?\d{4}$/, "Telefone inválido")

// Opcional
complement: z.string().optional()

4. Componentes shadcn/ui Form

SEMPRE use estes componentes na ordem:

<FormField
  control={form.control}
  name="fieldName"
  render={({ field }) => (
    <FormItem>
      <FormLabel>Label</FormLabel>
      <FormControl>
        <Input {...field} />
      </FormControl>
      <FormMessage />
    </FormItem>
  )}
/>

5. Toast Notifications

import { toast } from "sonner";

// Sucesso
toast.success("Operação concluída com sucesso");

// Erro
toast.error("Erro ao processar operação");

// Info
toast.info("Informação importante");

6. Tratamento de Erros

// Erro específico em campo
form.setError("email", {
  message: "Este email já está cadastrado",
});

// Múltiplos erros
if (error.code === "USER_NOT_FOUND") {
  toast.error("Usuário não encontrado");
  return form.setError("email", {
    message: "Usuário não encontrado",
  });
}

7. Estados de Loading

// Desabilitar botão durante submit
<Button type="submit" disabled={form.formState.isSubmitting}>
  {form.formState.isSubmitting ? "Carregando..." : "Enviar"}
</Button>

// Verificar se form está válido
form.formState.isValid

// Verificar erros
form.formState.errors

Tipos de Input Comuns

// Text
<Input type="text" placeholder="Nome" {...field} />

// Email
<Input type="email" placeholder="email@example.com" {...field} />

// Password
<Input type="password" placeholder="Senha" {...field} />

// Number
<Input type="number" min={1} {...field}
  onChange={e => field.onChange(parseInt(e.target.value))} />

// Textarea (se precisar adicionar component)
<Textarea placeholder="Descrição" {...field} />

// Select (usar shadcn/ui Select component)
<Select onValueChange={field.onChange} defaultValue={field.value}>
  <SelectTrigger>
    <SelectValue placeholder="Selecione" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="valor1">Opção 1</SelectItem>
  </SelectContent>
</Select>

Integração com Server Actions

import { serverAction } from "@/actions/server-action";

async function onSubmit(values: FormValues) {
  try {
    await serverAction(values);
    toast.success("Sucesso!");
  } catch (error) {
    toast.error("Erro ao processar");
  }
}

Integração com React Query Mutation

import { useCreateMutation } from "@/hooks/mutations/use-create-mutation";

const FormComponent = () => {
  const createMutation = useCreateMutation();

  async function onSubmit(values: FormValues) {
    try {
      await createMutation.mutateAsync(values);
      toast.success("Criado com sucesso!");
    } catch (error) {
      toast.error("Erro ao criar");
    }
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <Button
          type="submit"
          disabled={form.formState.isSubmitting || createMutation.isPending}
        >
          {createMutation.isPending ? "Salvando..." : "Salvar"}
        </Button>
      </form>
    </Form>
  );
};

Formulário com Card

import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";

return (
  <Card>
    <CardHeader>
      <CardTitle>Título</CardTitle>
      <CardDescription>Descrição do formulário</CardDescription>
    </CardHeader>
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <CardContent className="grid gap-6">
          {/* FormFields aqui */}
        </CardContent>
        <CardFooter>
          <Button type="submit">Enviar</Button>
        </CardFooter>
      </form>
    </Form>
  </Card>
);

Arquivos de Referência

  • Sign In Form: src/app/auth/components/sign-in-form.tsx
  • Sign Up Form: src/app/auth/components/sign-up-form.tsx
  • Add Address Form: src/app/cart/identification/components/add-address-form.tsx
  • Form Component: src/components/ui/form.tsx

Processo de Criação

  1. Definir schema Zod com validações apropriadas
  2. Inferir tipo com z.infer
  3. Inicializar useForm com zodResolver
  4. Criar FormFields com componentes shadcn/ui
  5. Implementar onSubmit com tratamento de erros
  6. Adicionar toast notifications para feedback
  7. Testar validações e estados de loading

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon