form-refactorer | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / tools / form-refactorer

form-refactorer

maintained by redpanda-data

star 4.2k account_tree 412 verified_user MIT License
bolt View GitHub

name: form-refactorer description: Refactor legacy forms to use modern Redpanda UI Registry Field components with react-hook-form and Zod validation. Use when user requests: (1) Form refactoring or modernization, (2) Converting Chakra UI or @redpanda-data/ui forms, (3) Updating forms to use Field components, (4) Migrating from legacy form patterns, (5) Implementing forms with react-hook-form and Zod validation.

Form Refactorer

Refactor legacy forms to modern Redpanda UI Registry Field components with react-hook-form and Zod validation.

Core Requirements

MUST USE (Modern Pattern)

import {
  FieldSet,
  FieldLegend,
  FieldGroup,
  Field,
  FieldLabel,
  FieldContent,
  FieldDescription,
  FieldError,
  FieldSeparator
} from "components/redpanda-ui/components/field";
  • react-hook-form for form state management
  • Zod for validation schemas via zodResolver
  • Field component family for all form layouts

FORBIDDEN (Legacy Patterns)

See no-legacy for prohibited patterns.

// ❌ Also never import legacy form components
import { Form } from "components/redpanda-ui/components/form";

Refactoring Workflow

Step 1: Identify Legacy Patterns

Scan the form file for these indicators:

Legacy imports to remove:

  • @chakra-ui/react form components (FormControl, FormLabel, FormErrorMessage, FormHelperText)
  • @redpanda-data/ui Form component
  • components/redpanda-ui/components/form (legacy)
  • Yup validation imports

Legacy patterns to replace:

  • <FormControl isInvalid={...}><Field data-invalid={...}>
  • <FormLabel><FieldLabel htmlFor="...">
  • <FormErrorMessage><FieldError>
  • <FormHelperText><FieldDescription>
  • Yup schemas → Zod schemas

Step 2: Set Up Modern Dependencies

Add required imports:

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import {
  FieldSet,
  FieldLegend,
  FieldGroup,
  Field,
  FieldLabel,
  FieldError,
  FieldDescription
} from "components/redpanda-ui/components/field";

Create Zod schema replacing Yup:

// Replace Yup schema
const schema = z.object({
  name: z.string().min(1, "Name is required"),
  email: z.string().email("Invalid email address"),
  age: z.number().min(18, "Must be 18 or older"),
});

// Use with react-hook-form
const { register, handleSubmit, formState: { errors } } = useForm({
  resolver: zodResolver(schema),
});

Step 3: Restructure Form Layout

Replace legacy structure with Field components:

Pattern: Simple vertical field

<Field data-invalid={!!errors.fieldName}>
  <FieldLabel htmlFor="fieldName">Field Label</FieldLabel>
  <Input
    id="fieldName"
    {...register("fieldName")}
    aria-invalid={!!errors.fieldName}
  />
  <FieldDescription>Optional helper text</FieldDescription>
  {errors.fieldName && <FieldError>{errors.fieldName.message}</FieldError>}
</Field>

Pattern: Horizontal field (switch/checkbox)

<Field orientation="horizontal">
  <Switch id="toggle" {...register("toggle")} />
  <FieldContent>
    <FieldLabel htmlFor="toggle">Enable Feature</FieldLabel>
    <FieldDescription>This enables the feature</FieldDescription>
  </FieldContent>
</Field>

Pattern: Multiple fields in group

<FieldSet>
  <FieldLegend>Section Title</FieldLegend>
  <FieldDescription>Section description (optional)</FieldDescription>
  <FieldGroup>
    <Field>...</Field>
    <Field>...</Field>
    <FieldSeparator />  {/* Optional visual divider */}
    <Field>...</Field>
  </FieldGroup>
</FieldSet>

Step 4: Handle Validation Errors

Apply error states to both Field and Input:

<Field data-invalid={!!errors.email}>
  <FieldLabel htmlFor="email">Email</FieldLabel>
  <Input
    id="email"
    {...register("email")}
    aria-invalid={!!errors.email}  // For assistive technologies
  />
  {errors.email && <FieldError>{errors.email.message}</FieldError>}
</Field>

Step 5: Ensure Accessibility

Required accessibility attributes:

  1. Label association: Use htmlFor on FieldLabel matching Input id
  2. Error state: Add data-invalid to Field when error exists
  3. ARIA invalid: Add aria-invalid to Input when error exists
  4. Semantic grouping: Use FieldSet + FieldLegend for related fields
// ✅ Correct accessibility
<Field data-invalid={!!errors.name}>
  <FieldLabel htmlFor="name">Name</FieldLabel>
  <Input id="name" {...register("name")} aria-invalid={!!errors.name} />
  {errors.name && <FieldError>{errors.name.message}</FieldError>}
</Field>

Quick Reference

Component Hierarchy

FieldSet              - Semantic fieldset container for related fields
├─ FieldLegend        - Title for the fieldset
├─ FieldDescription   - Description for entire fieldset
└─ FieldGroup         - Layout wrapper that stacks fields
   ├─ Field           - Individual field wrapper
   │  ├─ FieldLabel       - Label for input (use htmlFor)
   │  ├─ Input/Select/... - Form control
   │  ├─ FieldDescription - Helper text
   │  └─ FieldError       - Error message
   ├─ FieldSeparator  - Visual divider between fields
   └─ Field           - Another field

Common Zod Patterns

// String validations
z.string().min(1, "Required")
z.string().email("Invalid email")
z.string().url("Invalid URL")
z.string().regex(/^[A-Z]/, "Must start with capital")

// Number validations
z.number().min(0, "Must be positive")
z.number().max(100, "Max 100")
z.number().int("Must be integer")

// Optional fields
z.string().optional()
z.string().nullable()

// Arrays
z.array(z.string()).min(1, "At least one required")

// Objects
z.object({
  nested: z.string(),
})

// Conditional validation
z.object({
  type: z.enum(["a", "b"]),
  value: z.string(),
}).refine((data) => {
  if (data.type === "a") return data.value.length > 5;
  return true;
}, "Value must be longer than 5 for type A")

Advanced Scenarios

For complex patterns (dynamic fields, field arrays, multi-section forms), see:

Checklist

Before completing refactoring, verify:

  • All legacy form imports removed (Chakra, @redpanda-data/ui, legacy Form)
  • Field components used for all fields
  • FieldLabel has htmlFor matching Input id
  • Errors show data-invalid on Field and aria-invalid on Input
  • Yup replaced with Zod + zodResolver
  • FieldSet + FieldLegend used for semantic grouping
  • FieldError conditionally rendered: {errors.field && <FieldError>...
  • No inline styling or className for layout (use Field orientation/FieldGroup)
  • Form submission handled via react-hook-form handleSubmit

Documentation

Full Field component documentation: https://redpanda-ui-registry.netlify.app/docs/field

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 4.2k
GitHub Forks 412
Created Jan 2026
Last Updated 4个月前
tools tools frontend

Related Skills

ui-ux-pro-max
chevron_right
ui-ux-pro-max
chevron_right
tailwind-setup
chevron_right
api-routes
chevron_right
data-fetching
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.