Back

Как создать доступные формы с использованием ShadCN UI

Как создать доступные формы с использованием ShadCN UI

Создание форм, которые одновременно функциональны и доступны, может быть сложной задачей. Между управлением состоянием, обработкой валидации и обеспечением правильных ARIA-атрибутов разработчики часто тратят бесчисленные часы на то, что должно быть простыми задачами. ShadCN UI в сочетании с React Hook Form и Zod предлагает мощное решение, которое упрощает создание форм, сохраняя при этом стандарты доступности.

В этой статье демонстрируется, как создавать доступные формы с ShadCN UI, интегрировать ShadCN UI React Hook Form для управления состоянием и реализовывать паттерны валидации ShadCN UI Zod, которые останутся актуальными на годы вперед.

Ключевые выводы

  • ShadCN UI автоматически обрабатывает ARIA-атрибуты и паттерны доступности через свою композиционную систему форм
  • Интеграция React Hook Form обеспечивает эффективное управление состоянием с минимальными перерендерами
  • Валидация схем Zod обеспечивает типобезопасную валидацию форм с четкими сообщениями об ошибках
  • Встроенные компоненты обрабатывают ассоциации меток, объявления ошибок и навигацию с клавиатуры

Понимание архитектуры форм ShadCN UI

ShadCN UI предоставляет композиционную систему форм, построенную на примитивах React Hook Form и Radix UI. Архитектура следует последовательному паттерну:

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

Эта структура автоматически обрабатывает:

  • Генерацию уникальных ID с использованием React.useId()
  • Правильные атрибуты aria-describedby и aria-invalid
  • Ассоциации сообщений об ошибках
  • Связи метка-поле ввода

Настройка доступных форм с ShadCN UI

Сначала установите необходимые компоненты:

npx shadcn@latest add form input textarea checkbox label

Эта команда устанавливает компоненты ShadCN UI вместе с зависимостями React Hook Form и Zod.

Создание базовой схемы формы

Определите структуру вашей формы, используя Zod для типобезопасной валидации:

import { z } from "zod"

const formSchema = z.object({
  name: z.string().min(2, "Name must be at least 2 characters"),
  email: z.string().email("Invalid email address"),
  message: z.string().min(10, "Message must be at least 10 characters"),
  terms: z.boolean().refine((val) => val === true, {
    message: "You must accept the terms"
  })
})

type FormData = z.infer<typeof formSchema>

Реализация компонента формы

Вот как создать доступную контактную форму, используя интеграцию ShadCN UI React Hook Form:

import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescription } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { Checkbox } from "@/components/ui/checkbox"
import { Button } from "@/components/ui/button"

export function ContactForm() {
  const form = useForm<FormData>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      name: "",
      email: "",
      message: "",
      terms: false
    }
  })

  function onSubmit(data: FormData) {
    console.log(data)
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
        <FormField
          control={form.control}
          name="name"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Name</FormLabel>
              <FormControl>
                <Input placeholder="John Doe" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input type="email" placeholder="john@example.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        
        <FormField
          control={form.control}
          name="message"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Message</FormLabel>
              <FormControl>
                <Textarea 
                  placeholder="Your message here..." 
                  className="resize-none" 
                  {...field} 
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <FormField
          control={form.control}
          name="terms"
          render={({ field }) => (
            <FormItem className="flex flex-row items-start space-x-3 space-y-0">
              <FormControl>
                <Checkbox 
                  checked={field.value}
                  onCheckedChange={field.onChange}
                />
              </FormControl>
              <div className="space-y-1 leading-none">
                <FormLabel>
                  Accept terms and conditions
                </FormLabel>
              </div>
              <FormMessage />
            </FormItem>
          )}
        />

        <Button type="submit">Submit</Button>
      </form>
    </Form>
  )
}

Встроенные функции доступности

Компоненты форм ShadCN UI автоматически реализуют важнейшие паттерны доступности:

  1. Правильная разметка: Компонент FormLabel использует атрибут htmlFor для ассоциации с элементами управления формы
  2. Объявления ошибок: Компоненты FormMessage связаны через aria-describedby
  3. Недопустимые состояния: Поля автоматически получают aria-invalid="true" при сбое валидации
  4. Навигация с клавиатуры: Все компоненты поддерживают стандартные взаимодействия с клавиатурой

Расширенные паттерны валидации

Реализуйте сложные сценарии валидации ShadCN UI Zod:

const advancedSchema = z.object({
  password: z.string()
    .min(8, "Password must be at least 8 characters")
    .regex(/[A-Z]/, "Password must contain at least one uppercase letter")
    .regex(/[a-z]/, "Password must contain at least one lowercase letter")
    .regex(/[0-9]/, "Password must contain at least one number"),
  confirmPassword: z.string()
}).refine((data) => data.password === data.confirmPassword, {
  message: "Passwords don't match",
  path: ["confirmPassword"]
})

Лучшие практики для доступных форм

  1. Всегда используйте метки: Каждое поле ввода нуждается в видимой метке для пользователей программ чтения с экрана
  2. Предоставляйте четкие сообщения об ошибках: Будьте конкретны в том, что пошло не так и как это исправить
  3. Группируйте связанные поля: Используйте fieldset и legend для логических группировок
  4. Тестируйте с клавиатуры: Убедитесь, что все взаимодействия работают без мыши
  5. Валидируйте при отправке: Избегайте агрессивной встроенной валидации, которая прерывает пользователей

Заключение

ShadCN UI трансформирует разработку форм, объединяя мощь управления состоянием React Hook Form с типобезопасной валидацией Zod, при этом сохраняя доступность как основной принцип. Архитектура компонентов обеспечивает соответствие каждой создаваемой формы стандартам WCAG без необходимости ручного управления ARIA-атрибутами.

Следуя этим паттернам, вы создаете формы, которые работают для всех — независимо от их способностей или вспомогательных технологий. Красота этого подхода заключается в его простоте: доступные формы становятся стандартом по умолчанию, а не запоздалой мыслью.

Часто задаваемые вопросы

Хотя технически это возможно, компоненты форм ShadCN UI разработаны для работы с React Hook Form. Использование их без него означает потерю автоматической валидации, управления состоянием и функций доступности, которые делают библиотеку ценной.

ShadCN UI автоматически генерирует уникальные ID, ассоциирует метки с полями ввода через атрибуты htmlFor, связывает сообщения об ошибках через aria-describedby и устанавливает aria-invalid при ошибках валидации. Все компоненты поддерживают навигацию с клавиатуры по умолчанию.

Валидация Zod выполняется только при необходимости, обычно при событиях blur или submit. Влияние на производительность минимально, поскольку React Hook Form предотвращает ненужные перерендеры. Для форм с сотнями полей рассмотрите использование валидации на уровне полей вместо валидации на уровне схемы.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay