Skip to content
VEXA
Forms

Label

Server-safe

An accessible caption for a form control.

Live preview

Rendered from the installed VEXA source — the same files you receive.

Desktop

Installation

Adds the component source to your project. Registry dependencies are pulled in automatically.

npx shadcn@latest add https://vexa.valfiguer.com/r/label.json

Installs to components/vexa/label.tsx

npm dependencies

No external npm dependencies.

Registry dependencies

  • @vexa/utils

Other VEXA items this component needs. Install them first — they are resolved automatically by the CLI.

Source

Copy this into its target path, or install it with the command above.

components/vexa/label.tsx
import type * as React from "react";

import { cn } from "@/lib/utils";

/**
 * Label — an accessible caption for a form control.
 *
 * RSC-safe. Uses the native `<label>` element; associate it with a control via
 * `htmlFor` matching the control's `id`. When the associated control is
 * disabled, add `data-disabled` (or rely on a `group`/`peer`) to dim the label.
 */
export function Label({ className, ...props }: React.ComponentProps<"label">) {
  return (
    <label
      data-slot="label"
      className={cn(
        "inline-flex items-center gap-1 text-sm font-medium leading-none text-vexa-foreground select-none",
        "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-60",
        className,
      )}
      {...props}
    />
  );
}
Registry JSONr/label.json
r/label.json
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "label",
  "type": "registry:ui",
  "title": "Label",
  "description": "An accessible caption for a form control.",
  "registryDependencies": [
    "@vexa/utils"
  ],
  "files": [
    {
      "path": "registry/default/ui/label.tsx",
      "type": "registry:ui",
      "target": "components/vexa/label.tsx",
      "content": "import type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Label — an accessible caption for a form control.\n *\n * RSC-safe. Uses the native `<label>` element; associate it with a control via\n * `htmlFor` matching the control's `id`. When the associated control is\n * disabled, add `data-disabled` (or rely on a `group`/`peer`) to dim the label.\n */\nexport function Label({ className, ...props }: React.ComponentProps<\"label\">) {\n  return (\n    <label\n      data-slot=\"label\"\n      className={cn(\n        \"inline-flex items-center gap-1 text-sm font-medium leading-none text-vexa-foreground select-none\",\n        \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-60\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n"
    }
  ],
  "meta": {
    "frameworks": [
      "react",
      "next"
    ],
    "rsc": "server-safe",
    "cssVars": [
      "--vexa-foreground"
    ],
    "a11y": "Native <label>; associate via htmlFor matching the control id.",
    "example": "<Label htmlFor=\"email\">Email</Label>",
    "tests": "planned — see docs/README.md#roadmap"
  }
}

Details

Accessibility

Native <label>; associate via htmlFor matching the control id.

Usage

The accessible caption for a form control. Clicking it moves focus to the associated control.

Anatomy

Label
A native `<label>` element.

Accessibility

Native `<label>`. Associate via `htmlFor` matching the control `id`.

Focus: Not focusable; clicking forwards focus to its control.

  • Give every control a programmatic label (WCAG 1.3.1 / 3.3.2 / 4.1.2). Mark required in text, not color.

Guidelines

Do

  • Set `htmlFor` to the control's `id`.
  • Keep the label text visible.
  • Indicate required state in text.

Don't

  • Don't wrap unrelated content in a Label.
  • Don't rely on a placeholder instead of a Label.
  • Don't visually hide the label without an accessible alternative.
Edit this page

Was this page helpful?

Stored locally in this browser. No account or server needed.