Build websites 10x faster with HextaUI Blocks — Learn more
UI/UI

Label

Displays a label element with enhanced styling and accessibility features for form controls.

Usage

import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";

<div className="grid w-full max-w-sm items-center gap-1.5">
  <Label htmlFor="email">Email</Label>
  <Input id="email" type="email" placeholder="Enter your email" />
</div>;

Installation

Install following dependencies:

npm install class-variance-authority
pnpm add class-variance-authority
yarn add class-variance-authority
bun add class-variance-authority

Copy and paste the following code into your project.

components/ui/label.tsx
"use client";

import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const labelVariants = cva(
  "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
  {
    variants: {
      variant: {
        default: "text-[hsl(var(--hu-foreground))]",
        destructive: "text-[hsl(var(--hu-destructive))]",
        muted: "text-[hsl(var(--hu-muted-foreground))]",
      },
      size: {
        default: "text-sm",
        sm: "text-xs",
        lg: "text-base",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  },
);

export interface LabelProps
  extends React.LabelHTMLAttributes<HTMLLabelElement>,
    VariantProps<typeof labelVariants> {
  required?: boolean;
  optional?: boolean;
}

const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
  (
    { className, variant, size, required, optional, children, ...props },
    ref,
  ) => {
    return (
      <label
        ref={ref}
        className={cn(labelVariants({ variant, size, className }))}
        {...props}
      >
        {children}
        {required && (
          <span
            className="text-[hsl(var(--hu-destructive))] ml-1"
            aria-label="required"
          >
            *
          </span>
        )}
        {optional && !required && (
          <span className="text-[hsl(var(--hu-muted-foreground))] ml-1 font-normal">
            (optional)
          </span>
        )}
      </label>
    );
  },
);

Label.displayName = "Label";

export { Label, labelVariants };
npx hextaui@latest add label
pnpm dlx hextaui@latest add label
yarn dlx hextaui@latest add label
bun x hextaui@latest add label

Usage

import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
<div className="grid w-full max-w-sm items-center gap-1.5">
  <Label htmlFor="email">Email</Label>
  <Input id="email" type="email" placeholder="Enter your email" />
</div>

Examples

Sizes

<div className="grid w-full items-center gap-1.5">
  <Label size="sm" htmlFor="small">Small Label</Label>
  <Input id="small" placeholder="Small input" size="sm" />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="default">Default Label</Label>
  <Input id="default" placeholder="Default input" />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label size="lg" htmlFor="large">Large Label</Label>
  <Input id="large" placeholder="Large input" size="lg" />
</div>

Variants

<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="default-variant">Default Label</Label>
  <Input id="default-variant" placeholder="Enter text" />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label variant="destructive" htmlFor="error-variant">Error Label</Label>
  <Input id="error-variant" placeholder="Enter text" error />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label variant="muted" htmlFor="muted-variant">Muted Label</Label>
  <Input id="muted-variant" placeholder="Enter text" />
</div>

Required and Optional Labels

<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="required-field" required>Required Field</Label>
  <Input id="required-field" placeholder="This field is required" />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="optional-field" optional>Optional Field</Label>
  <Input id="optional-field" placeholder="This field is optional" />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="normal-field">Normal Field</Label>
  <Input id="normal-field" placeholder="Normal field" />
</div>

With Icons and Complex Inputs

import { Mail, Lock, User } from "lucide-react";

<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="email-with-icon" required>Email Address</Label>
  <Input
    id="email-with-icon"
    type="email"
    placeholder="Enter your email"
    leftIcon={<Mail />}
    clearable
  />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="password-with-icon" required>Password</Label>
  <Input
    id="password-with-icon"
    type="password"
    placeholder="Enter your password"
    leftIcon={<Lock />}
  />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="username-with-icon" optional>Username</Label>
  <Input
    id="username-with-icon"
    type="text"
    placeholder="Choose a username"
    leftIcon={<User />}
    clearable
  />
</div>

Form Layout Examples

<form className="space-y-4">
  <div className="grid w-full items-center gap-1.5">
    <Label htmlFor="form-email" required>
      Email
    </Label>
    <Input
      id="form-email"
      type="email"
      placeholder="Enter your email"
      leftIcon={<Mail />}
      clearable
    />
  </div>
  <div className="grid w-full items-center gap-1.5">
    <Label htmlFor="form-password" required>
      Password
    </Label>
    <Input
      id="form-password"
      type="password"
      placeholder="Enter your password"
      leftIcon={<Lock />}
    />
  </div>
  <div className="grid w-full items-center gap-1.5">
    <Label htmlFor="form-confirm" required>
      Confirm Password
    </Label>
    <Input
      id="form-confirm"
      type="password"
      placeholder="Confirm your password"
      leftIcon={<Lock />}
    />
  </div>
  <div className="grid w-full items-center gap-1.5">
    <Label htmlFor="form-bio" optional>
      Bio
    </Label>
    <Input id="form-bio" placeholder="Tell us about yourself" clearable />
  </div>
</form>

Disabled State

<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="disabled-input">Disabled Field</Label>
  <Input id="disabled-input" placeholder="Disabled input" disabled />
</div>
<div className="grid w-full items-center gap-1.5">
  <Label htmlFor="disabled-required" required>Disabled Required Field</Label>
  <Input id="disabled-required" placeholder="Disabled required input" disabled />
</div>

Form Association

The Label component works seamlessly with form controls:

// Proper association using htmlFor
<Label htmlFor="email">Email Address</Label>
<Input id="email" type="email" />

// Required field indication
<Label htmlFor="password" required>Password</Label>
<Input id="password" type="password" />

// Optional field indication
<Label htmlFor="bio" optional>Biography</Label>
<Input id="bio" />

Props

PropTypeDefault
className?
string
undefined
optional?
boolean
false
required?
boolean
false
size?
"default" | "sm" | "lg"
"default"
variant?
"default" | "destructive" | "muted"
"default"
Edit on GitHub

Last updated on