सामग्री पर जाएँ

फ़ील्ड

सेटिंग्स पैनलों, चेकआउट फ़ॉर्मों और साइनअप फ़्लो के लिए लेबल, नियंत्रण, सहायता पाठ और त्रुटि स्लॉट — नियोब्रूटलिस्ट फ़ॉर्म ट्रीटमेंट के साथ।

import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {

फ़ील्ड लेबल, कंट्रोल, हेल्पर टेक्स्ट और एरर मैसेज को एक संरेखित ब्लॉक में लपेटता है, और FieldGroup तथा FieldSet से समूहित सेक्शन तक बढ़ता है। नीचे कोई प्रिमिटिव नहीं — सादा fieldset, legend और role="group" सेमेंटिक्स, Label और Separator के साथ, नियोब्रूटलिस्ट रेसिपी: लेजेंड और लेबल पर बोल्ड हेडिंग टाइप; लपेटे कंट्रोल मोटे बॉर्डर और कठोर छायाएँ लाते हैं।

इसे इन स्थितियों में चुनें:

  • सेटिंग्स पेजFieldSet लेजेंड और ग्रुपों के बीच FieldSeparator से प्रोफ़ाइल, नोटिफ़िकेशन, बिलिंग स्टैक करें।
  • चेकआउट और साइनअप फ़ॉर्म — इनपुट, सेलेक्ट और स्विच पर लेबल, विवरण और एरर अलाइनमेंट एक जैसा रखें।
  • चॉइस कार्ड — प्लान पिकर और प्रेफ़रेंस पैनल के लिए रेडियो, चेकबॉक्स या स्विच को चुनने योग्य FieldLabel कार्ड में लपेटें।

इंस्टॉलेशन

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/field.json
npx shadcn@latest add https://neobrutalism.com/r/base/field.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/field.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/field.json

निम्नलिखित कोड को अपने प्रोजेक्ट में कॉपी और पेस्ट करें.

components/ui/field.tsx
"use client"

import { useMemo } from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"
import { Label } from "@/components/ui/label"
import { Separator } from "@/components/ui/separator"

function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
  return (
    <fieldset
      data-slot="field-set"
      className={cn(
        "flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
        className
      )}
      {...props}
    />
  )
}

function FieldLegend({
  className,
  variant = "legend",
  ...props
}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) {
  return (
    <legend
      data-slot="field-legend"
      data-variant={variant}
      className={cn(
        "mb-1.5 font-head font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base",
        className
      )}
      {...props}
    />
  )
}

function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="field-group"
      className={cn(
        "group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4",
        className
      )}
      {...props}
    />
  )
}

const fieldVariants = cva(
  "group/field flex w-full gap-2 data-[invalid=true]:text-destructive",
  {
    variants: {
      orientation: {
        vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
        horizontal:
          "flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
        responsive:
          "flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
      },
    },
    defaultVariants: {
      orientation: "vertical",
    },
  }
)

function Field({
  className,
  orientation = "vertical",
  ...props
}: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) {
  return (
    <div
      role="group"
      data-slot="field"
      data-orientation={orientation}
      className={cn(fieldVariants({ orientation }), className)}
      {...props}
    />
  )
}

function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="field-content"
      className={cn(
        "group/field-content flex flex-1 flex-col gap-0.5 leading-snug",
        className
      )}
      {...props}
    />
  )
}

function FieldLabel({
  className,
  ...props
}: React.ComponentProps<typeof Label>) {
  return (
    <Label
      data-slot="field-label"
      className={cn(
        "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded has-[>[data-slot=field]]:border-2 *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
        "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
        className
      )}
      {...props}
    />
  )
}

function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="field-label"
      className={cn(
        "flex w-fit items-center gap-2 text-sm font-head font-medium group-data-[disabled=true]/field:opacity-50",
        className
      )}
      {...props}
    />
  )
}

function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
  return (
    <p
      data-slot="field-description"
      className={cn(
        "text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5",
        "last:mt-0 nth-last-2:-mt-1",
        "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
        className
      )}
      {...props}
    />
  )
}

function FieldSeparator({
  children,
  className,
  ...props
}: React.ComponentProps<"div"> & {
  children?: React.ReactNode
}) {
  return (
    <div
      data-slot="field-separator"
      data-content={!!children}
      className={cn(
        "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
        className
      )}
      {...props}
    >
      <Separator className="absolute inset-0 top-1/2" />
      {children && (
        <span
          className="relative mx-auto block w-fit bg-background px-2 text-muted-foreground"
          data-slot="field-separator-content"
        >
          {children}
        </span>
      )}
    </div>
  )
}

function FieldError({
  className,
  children,
  errors,
  ...props
}: React.ComponentProps<"div"> & {
  errors?: Array<{ message?: string } | undefined>
}) {
  const content = useMemo(() => {
    if (children) {
      return children
    }

    if (!errors?.length) {
      return null
    }

    const uniqueErrors = [
      ...new Map(errors.map((error) => [error?.message, error])).values(),
    ]

    if (uniqueErrors?.length == 1) {
      return uniqueErrors[0]?.message
    }

    return (
      <ul className="ml-4 flex list-disc flex-col gap-1">
        {uniqueErrors.map(
          (error, index) =>
            error?.message && <li key={index}>{error.message}</li>
        )}
      </ul>
    )
  }, [children, errors])

  if (!content) {
    return null
  }

  return (
    <div
      role="alert"
      data-slot="field-error"
      className={cn("text-sm font-normal text-destructive", className)}
      {...props}
    >
      {content}
    </div>
  )
}

export {
  Field,
  FieldLabel,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLegend,
  FieldSeparator,
  FieldSet,
  FieldContent,
  FieldTitle,
}

अपने प्रोजेक्ट सेटअप के अनुसार इंपोर्ट पाथ अपडेट करें.

उपयोग

import {
  Field,
  FieldContent,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSeparator,
  FieldSet,
  FieldTitle,
} from "@/components/ui/field"
<FieldSet>
  <FieldLegend>Profile</FieldLegend>
  <FieldDescription>This appears on invoices and emails.</FieldDescription>
  <FieldGroup>
    <Field>
      <FieldLabel htmlFor="name">Full name</FieldLabel>
      <Input id="name" autoComplete="off" placeholder="Evil Rabbit" />
      <FieldDescription>This appears on invoices and emails.</FieldDescription>
    </Field>
    <Field>
      <FieldLabel htmlFor="username">Username</FieldLabel>
      <Input id="username" autoComplete="off" aria-invalid />
      <FieldError>Choose another username.</FieldError>
    </Field>
    <Field orientation="horizontal">
      <Switch id="newsletter" />
      <FieldLabel htmlFor="newsletter">Subscribe to the newsletter</FieldLabel>
    </Field>
  </FieldGroup>
</FieldSet>

कंपोज़िशन

Field

लेबल, हेल्पर टेक्स्ट और वैलिडेशन के साथ एक अकेला कंट्रोल.

Field
├── FieldLabel
├── Input / Textarea / Switch / Select
├── FieldDescription
└── FieldError

FieldGroup

एक ही समूह में संबंधित फ़ील्ड. जरूरत पड़ने पर सेक्शन के बीच FieldSeparator का उपयोग करें.

FieldGroup
├── Field
│   ├── FieldLabel
│   ├── Input / Textarea / Switch / Select
│   ├── FieldDescription
│   └── FieldError
├── FieldSeparator
└── Field
    ├── FieldLabel
    └── Input / Textarea / Switch / Select

FieldSet

एक लेजेंड और विवरण के साथ सिमेंटिक समूह, जिसमें आमतौर पर एक FieldGroup होता है.

FieldSet
├── FieldLegend
├── FieldDescription
└── FieldGroup
    ├── Field
    │   ├── FieldLabel
    │   ├── Input / Textarea / Switch / Select
    │   ├── FieldDescription
    │   └── FieldError
    └── Field
        ├── FieldLabel
        └── Input / Textarea / Switch / Select

एनाटॉमी

Field फ़ैमिली सुलभ फ़ॉर्म बनाने के लिए डिज़ाइन की गई है. एक सामान्य फ़ील्ड इस तरह संरचित होता है:

<Field>
  <FieldLabel htmlFor="input-id">Label</FieldLabel>
  {/* Input, Select, Switch, etc. */}
  <FieldDescription>Optional helper text.</FieldDescription>
  <FieldError>Validation message.</FieldError>
</Field>
  • Field एक अकेले फ़ील्ड का मुख्य रैपर है.
  • FieldContent एक flex कॉलम है जो लेबल और विवरण को समूहबद्ध करता है. अगर आपके पास कोई विवरण नहीं है तो इसकी जरूरत नहीं है.
  • संबंधित फ़ील्ड को FieldGroup से रैप करें, और सिमेंटिक समूह के लिए FieldLegend के साथ FieldSet का उपयोग करें.

फ़ॉर्म

Field कंपोनेंट के साथ और React Hook Form, Tanstack Form, या Formisch के साथ फ़ॉर्म बनाने के लिए Form डॉक्युमेंटेशन देखें.

उदाहरण

Input

import {
  Field,
  FieldDescription,

Textarea

import {
  Field,
  FieldDescription,

Select

import {
  Field,
  FieldDescription,

Slider

"use client"

import * as React from "react"

Fieldset

import {
  Field,
  FieldDescription,

Checkbox

import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,

Radio

import {
  Field,
  FieldDescription,

Switch

import { Field, FieldLabel } from "@/components/ui/field"
import { Switch } from "@/components/ui/switch"

Choice Card

चयन योग्य फ़ील्ड समूह बनाने के लिए Field कंपोनेंट्स को FieldLabel के अंदर रैप करें. यह RadioItem, Checkbox और Switch कंपोनेंट्स के साथ काम करता है.

import {
  Field,
  FieldContent,

Field Group

FieldGroup के साथ Field कंपोनेंट्स को स्टैक करें. उन्हें अलग करने के लिए FieldSeparator जोड़ें.

import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,

RTL

Neobrutalism में RTL सपोर्ट सक्षम करने के लिए, RTL कॉन्फ़िगरेशन गाइड देखें.

"use client"

import * as React from "react"

रिस्पॉन्सिव लेआउट

  • वर्टिकल फ़ील्ड: डिफ़ॉल्ट ओरिएंटेशन लेबल, कंट्रोल और हेल्पर टेक्स्ट को एक के ऊपर एक स्टैक करता है—मोबाइल-फ़र्स्ट लेआउट के लिए आदर्श.
  • हॉरिज़ॉन्टल फ़ील्ड: लेबल और कंट्रोल को अगल-बगल संरेखित करने के लिए Field पर orientation="horizontal" सेट करें. विवरण को संरेखित रखने के लिए इसे FieldContent के साथ जोड़ें.
  • रिस्पॉन्सिव फ़ील्ड: कंटेनर-अवेयर पैरेंट के अंदर स्वचालित कॉलम लेआउट के लिए orientation="responsive" सेट करें. विशिष्ट ब्रेकपॉइंट्स पर ओरिएंटेशन बदलने के लिए FieldGroup पर @container/field-group क्लासेस लागू करें.
import { Button } from "@/components/ui/button"
import {
  Field,

वैलिडेशन और एरर

  • पूरे ब्लॉक को एरर स्टेट में बदलने के लिए Field पर data-invalid जोड़ें.
  • सहायक तकनीकों के लिए इनपुट पर ही aria-invalid जोड़ें.
  • एरर संदेशों को फ़ील्ड के साथ संरेखित रखने के लिए FieldError को कंट्रोल के तुरंत बाद या FieldContent के अंदर रेंडर करें.
<Field data-invalid>
  <FieldLabel htmlFor="email">Email</FieldLabel>
  <Input id="email" type="email" aria-invalid />
  <FieldError>Enter a valid email address.</FieldError>
</Field>

एक्सेसिबिलिटी

  • FieldSet और FieldLegend कीबोर्ड और सहायक तकनीक उपयोगकर्ताओं के लिए संबंधित कंट्रोल्स को समूहबद्ध रखते हैं.
  • Field, role="group" आउटपुट करता है, इसलिए नेस्टेड कंट्रोल्स संयोजित होने पर FieldLabel और FieldLegend से लेबलिंग प्राप्त करते हैं.
  • FieldSeparator का उपयोग संयम से करें ताकि स्क्रीन रीडर्स को स्पष्ट सेक्शन सीमाएं मिलें.

एक्सेसिबिलिटी

फ़ील्ड परिवार सेमेंटिक्स-पहले है: FieldSet और FieldLegend नेटिव fieldset/legend रेंडर करते हैं, Field role="group" रेंडर करता है, और FieldError role="alert" रेंडर करता है ताकि वैलिडेशन संदेश दिखते ही घोषित हों।

  • हर FieldLabel को कंट्रोल से htmlFor/id से जोड़ें — लेबल पर क्लिक फ़ोकस/टॉगल करता है और स्क्रीन रीडर संबंध घोषित करते हैं।
  • अमान्य इनपुट पर कंट्रोल पर ही aria-invalid सेट करें; Field पर data-invalid सिर्फ़ एरर स्टाइल चलाता है।
  • कीबोर्ड व्यवहार अंदर के कंट्रोल का है — रैपर अपना कोई फ़ोकस स्टॉप या की बाइंडिंग नहीं जोड़ते।

API रेफ़रेंस

FieldSet

एक कंटेनर जो स्पेसिंग प्रीसेट के साथ एक सिमेंटिक fieldset रेंडर करता है.

PropTypeDefault
classNamestring
<FieldSet>
  <FieldLegend>Delivery</FieldLegend>
  <FieldGroup>{/* Fields */}</FieldGroup>
</FieldSet>

FieldLegend

FieldSet के लिए लेजेंड एलिमेंट. लेबल आकार के साथ संरेखित करने के लिए label वैरिएंट पर स्विच करें.

PropTypeDefault
variant"legend" | "label""legend"
classNamestring
<FieldLegend variant="label">Notification Preferences</FieldLegend>

FieldLegend के दो वैरिएंट हैं: legend और label. label वैरिएंट लेबल का आकार और संरेखण लागू करता है. नेस्टेड FieldSet होने पर उपयोगी.

FieldGroup

लेआउट रैपर जो Field कंपोनेंट्स को स्टैक करता है और रिस्पॉन्सिव ओरिएंटेशन के लिए container queries सक्षम करता है.

PropTypeDefault
classNamestring
<FieldGroup className="@container/field-group flex flex-col gap-6">
  <Field>{/* ... */}</Field>
  <Field>{/* ... */}</Field>
</FieldGroup>

Field

एक अकेले फ़ील्ड का मुख्य रैपर. ओरिएंटेशन कंट्रोल, अमान्य स्टेट स्टाइलिंग और स्पेसिंग प्रदान करता है.

PropTypeDefault
orientation"vertical" | "horizontal" | "responsive""vertical"
classNamestring
data-invalidboolean
<Field orientation="horizontal">
  <FieldLabel htmlFor="remember">Remember me</FieldLabel>
  <Switch id="remember" />
</Field>

FieldContent

flex कॉलम जो कंट्रोल और विवरणों को समूहबद्ध करता है जब लेबल कंट्रोल के बगल में होता है. अगर आपके पास कोई विवरण नहीं है तो इसकी जरूरत नहीं है.

PropTypeDefault
classNamestring
<Field>
  <Checkbox id="notifications" />
  <FieldContent>
    <FieldLabel htmlFor="notifications">Notifications</FieldLabel>
    <FieldDescription>Email, SMS, and push options.</FieldDescription>
  </FieldContent>
</Field>

FieldLabel

लेबल जो सीधे इनपुट और नेस्टेड Field चिल्ड्रन दोनों के लिए स्टाइल किया गया है.

PropTypeDefault
classNamestring
asChildbooleanfalse
<FieldLabel htmlFor="email">Email</FieldLabel>

FieldTitle

FieldContent के अंदर लेबल स्टाइलिंग के साथ एक टाइटल रेंडर करता है.

PropTypeDefault
classNamestring
<FieldContent>
  <FieldTitle>Enable Touch ID</FieldTitle>
  <FieldDescription>Unlock your device faster.</FieldDescription>
</FieldContent>

FieldDescription

हेल्पर टेक्स्ट स्लॉट जो हॉरिज़ॉन्टल लेआउट में लंबी लाइनों को स्वचालित रूप से संतुलित करता है.

PropTypeDefault
classNamestring
<FieldDescription>We never share your email with anyone.</FieldDescription>

FieldSeparator

FieldGroup के अंदर सेक्शन अलग करने के लिए विज़ुअल डिवाइडर. वैकल्पिक इनलाइन कंटेंट स्वीकार करता है.

PropTypeDefault
classNamestring
<FieldSeparator>Or continue with</FieldSeparator>

FieldError

सुलभ एरर कंटेनर जो चिल्ड्रन या एक errors array (उदाहरण के लिए, react-hook-form से) स्वीकार करता है.

PropTypeDefault
errorsArray<{ message?: string } | undefined>
classNamestring
<FieldError errors={errors.username} />

जब errors array में कई संदेश होते हैं, तो कंपोनेंट स्वचालित रूप से एक सूची रेंडर करता है.

FieldError, Standard Schema लागू करने वाले किसी भी वैलिडेटर द्वारा उत्पन्न issues भी स्वीकार करता है, जिसमें Zod, Valibot और ArkType शामिल हैं. विभिन्न लाइब्रेरीज़ में एकीकृत एरर सूची रेंडर करने के लिए स्कीमा परिणाम से issues array सीधे पास करें.