Patterns
Explicit Label And Input Id
When to use:
- the label and control are rendered as separate siblings
Composition notes:
- give the control a stable
id - connect
LabelwithhtmlFor
Trade-offs:
- clear and explicit
- requires id management
import { Label, TextField, TextFieldInput } from '@vega-ui/react';
import { useId } from 'react';
export default function FieldLabel() {
const id = useId();
return (
<div style={{ display: 'grid', gap: 'var(--spacing-3)', width: '100%' }}>
<Label htmlFor={id}>Company name</Label>
<TextField>
<TextFieldInput id={id} name='company' autoComplete='organization' />
</TextField>Wrapping Label
When to use:
- the label and a single-element control (
TextArea,Radio) should form one click target without managing ids
Composition notes:
- wrap the control inside
Label; nohtmlFororidis needed - do not wrap
TextField(its root is a<div>) orCheckbox/Switch(their roots are already<label>elements)
Trade-offs:
- improves hit area
- less suitable for complex nested layouts
import { Label, Radio, TextArea } from '@vega-ui/react';
export default function WrappingLabel() {
return (
<div style={{ display: 'grid', gap: 'var(--spacing-8)', width: '100%' }}>
<Label style={{ display: 'grid', gap: 'var(--spacing-3)' }}>
Delivery instructions
<TextArea name='instructions' rows={3} fullWidth placeholder='Gate code, floor, where to leave the parcel' />
</Label>
<div style={{ display: 'grid', gap: 'var(--spacing-3)' }}>
<Label fontWeight={400} style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-4)' }}>
<Radio name='window' value='morning' defaultChecked />Label With Helper Copy
When to use:
- the field needs visible labeling plus secondary guidance
Composition notes:
- keep the actual label separate from helper text
- place helper copy below the control or nearby
Trade-offs:
- preserves clear semantics
- requires an extra text element for guidance
import { Button, HelperText, Label, TextField, TextFieldInput } from '@vega-ui/react';
import { FormEvent, useId, useState } from 'react';
export default function RequiredFieldError() {
const id = useId();
const messageId = `${id}-message`;
const [taxId, setTaxId] = useState('');
const [submitted, setSubmitted] = useState(false);
const invalid = submitted && taxId.trim() === '';
const onSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();Comparison
Quick Decision Rule
Use Label for form control labeling. Use Text or Heading for copy that does not name an input.
Label vs Text
Use Label when:
- the text names a form control
Use Text when:
- the content is body copy, helper text, or static content
Label vs Heading
Use Label when:
- the text names one control
Use Heading when:
- the text defines section or page structure
Label vs FieldsetLegend
Use Label when:
- one field needs a visible semantic label
Use FieldsetLegend when:
- a group of related controls needs one shared semantic label
Choose This Component When
- one field needs a visible semantic label
- native label click behavior matters
- the naming text should remain tightly coupled to one control
Do Not Choose This Component When
- the content is a heading or paragraph
- you need to label a whole group rather than one control
Troubleshooting
Clicking The Label Does Not Focus The Control
Symptom
The label renders, but clicking it does not move focus to the intended field.
Likely Cause
htmlFor does not match the control id, or the control is not wrapped by the label.
How To Verify
- inspect the rendered
forattribute - confirm the target control has the matching
id
Fix
Use a matching htmlFor and id, or wrap the control directly inside Label.
The Label Reads Like Helper Text
Symptom
The field has copy nearby, but the primary label is visually too weak or ambiguous.
Likely Cause
Typography overrides made the label look like secondary text.
How To Verify
- compare label weight and color with nearby helper text
- confirm there is one obvious visible label
Fix
Keep the primary label visually distinct and move secondary guidance into separate helper copy.
One Label Appears To Control Multiple Inputs
Symptom
Several inputs look grouped under one label, and click behavior feels inconsistent.
Likely Cause
Multiple unrelated controls were wrapped in one label.
How To Verify
- inspect the label contents
- confirm whether one label contains more than one independent control
Fix
Use one Label per control, or switch to Fieldset and FieldsetLegend for grouped controls.