Field
Apto para servidorLayout wrapper that groups a label, control, description, and error text.
Vista previa en vivo
Renderizado desde el código fuente instalado de VEXA — los mismos archivos que recibes.
Escritorio
Account notifications only.
Lowercase letters and dashes only.
Instalación
Añade el código del componente a tu proyecto. Las dependencias del registry se resuelven automáticamente.
npx shadcn@latest add https://vexa.valfiguer.com/r/field.jsonSe instala en components/vexa/field.tsx
Dependencias npm
Sin dependencias npm externas.
Dependencias del registry
- @vexa/utils
- @vexa/label
Otros items de VEXA que necesita este componente. Instálalos primero — la CLI los resuelve automáticamente.
Código
Cópialo a su ruta destino, o instálalo con el comando de arriba.
components/vexa/field.tsx
import type * as React from "react";
import { cn } from "@/lib/utils";
/**
* Field — a vertical layout wrapper that groups a `Label`, a control, and its
* description / error text with consistent spacing.
*
* RSC-safe by design: it uses no React context or hooks, so the accessible
* wiring stays explicit and server-renderable. Associate parts by id:
*
* ```tsx
* <Field>
* <Label htmlFor="email">Email</Label>
* <Input id="email" aria-describedby="email-hint" aria-invalid={hasError} />
* <FieldDescription id="email-hint">Work address preferred.</FieldDescription>
* {hasError ? <FieldError id="email-error">Enter a valid email.</FieldError> : null}
* </Field>
* ```
*/
export function Field({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="field"
className={cn("flex flex-col gap-2", className)}
{...props}
/>
);
}
/**
* FieldDescription — supplementary help text. Reference its `id` from the
* control's `aria-describedby`.
*/
export function FieldDescription({
className,
...props
}: React.ComponentProps<"p">) {
return (
<p
data-slot="field-description"
className={cn("text-sm text-vexa-muted-foreground", className)}
{...props}
/>
);
}
/**
* FieldError — an error message. Reference its `id` from the control's
* `aria-describedby` (or `aria-errormessage`) and set `aria-invalid` on the
* control. Errors should name both the problem and the recovery action.
* A leading icon or `"Error:"` prefix keeps meaning from relying on color.
*/
export function FieldError({
className,
children,
...props
}: React.ComponentProps<"p">) {
if (children == null || children === false) return null;
return (
<p
data-slot="field-error"
className={cn(
"flex items-center gap-1.5 text-sm font-medium text-vexa-danger",
"[&_svg]:size-4 [&_svg]:shrink-0",
className,
)}
{...props}
>
{children}
</p>
);
}
JSON del registryr/field.json
r/field.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "field",
"type": "registry:ui",
"title": "Field",
"description": "Layout wrapper that groups a label, control, description, and error text.",
"registryDependencies": [
"@vexa/utils",
"@vexa/label"
],
"files": [
{
"path": "registry/default/ui/field.tsx",
"type": "registry:ui",
"target": "components/vexa/field.tsx",
"content": "import type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Field — a vertical layout wrapper that groups a `Label`, a control, and its\n * description / error text with consistent spacing.\n *\n * RSC-safe by design: it uses no React context or hooks, so the accessible\n * wiring stays explicit and server-renderable. Associate parts by id:\n *\n * ```tsx\n * <Field>\n * <Label htmlFor=\"email\">Email</Label>\n * <Input id=\"email\" aria-describedby=\"email-hint\" aria-invalid={hasError} />\n * <FieldDescription id=\"email-hint\">Work address preferred.</FieldDescription>\n * {hasError ? <FieldError id=\"email-error\">Enter a valid email.</FieldError> : null}\n * </Field>\n * ```\n */\nexport function Field({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n />\n );\n}\n\n/**\n * FieldDescription — supplementary help text. Reference its `id` from the\n * control's `aria-describedby`.\n */\nexport function FieldDescription({\n className,\n ...props\n}: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\"text-sm text-vexa-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\n/**\n * FieldError — an error message. Reference its `id` from the control's\n * `aria-describedby` (or `aria-errormessage`) and set `aria-invalid` on the\n * control. Errors should name both the problem and the recovery action.\n * A leading icon or `\"Error:\"` prefix keeps meaning from relying on color.\n */\nexport function FieldError({\n className,\n children,\n ...props\n}: React.ComponentProps<\"p\">) {\n if (children == null || children === false) return null;\n return (\n <p\n data-slot=\"field-error\"\n className={cn(\n \"flex items-center gap-1.5 text-sm font-medium text-vexa-danger\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n >\n {children}\n </p>\n );\n}\n"
}
],
"meta": {
"frameworks": [
"react",
"next"
],
"rsc": "server-safe",
"exports": [
"Field",
"FieldDescription",
"FieldError"
],
"cssVars": [
"--vexa-muted-foreground",
"--vexa-danger"
],
"a11y": "No context/hooks — accessible wiring stays explicit (id + aria-describedby). Errors name the problem and recovery; not color-only.",
"example": "<Field><Label htmlFor=\"n\">Name</Label><Input id=\"n\" /></Field>",
"tests": "planned — see docs/README.md#roadmap"
}
}Detalles
Accesibilidad
No context/hooks — accessible wiring stays explicit (id + aria-describedby). Errors name the problem and recovery; not color-only.