An enterprise-grade form field component based on BrConfigProvider for global theme configuration. It supports multi-control integration, state linkage, and customizable layouts, making it seamless to integrate with inline forms like BrForm and BrTable.
Component Features
- 🎨 Theme Configuration: Inherits global theme settings (colors, rounded corners, sizes) via
BrConfigProvider.
- 🔄 State Linkage: Automatically links label, border, and message colors based on the field's state (e.g., error, success).
- 📐 Flexible Layout: Supports positioning labels on the top, left, or right, along with customizable label widths.
- 🛠️ Customization: Easy to override default styles using TailwindCSS or custom class names.
Basic Usage
Displays a basic form field containing a label, control, and description.
<script setup lang="ts">
import { ref } from 'vue'
import { BrFormField } from '@breeze-ui/vue'
const value = ref('')
</script>
<template>
<div class="max-w-sm">
<BrFormField
label="Username"
description="This is your public display name."
name="username"
>
<template #default="{ id, disabled, readonly, state }">
<input
:id="id"
v-model="value"
:disabled="disabled"
:readonly="readonly"
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
:class="{ 'border-[var(--destructive)]': state === 'error' }"
placeholder="Enter username"
/>
</template>
</BrFormField>
</div>
</template>
Error State
Shows the coordinated color change effect of the label, border, and hint text when validation fails.
<script setup lang="ts">
import { ref } from 'vue'
import { BrFormField } from '@breeze-ui/vue'
const email = ref('invalid-email')
</script>
<template>
<div class="max-w-sm">
<BrFormField
label="Email Address"
required
error="Please enter a valid email address."
state="error"
>
<template #default="{ id, state }">
<input
:id="id"
v-model="email"
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors"
:class="state === 'error' ? 'border-[var(--destructive)] focus-visible:ring-[var(--destructive)]' : ''"
/>
</template>
</BrFormField>
</div>
</template>
Custom Layout
Supports displaying the label on the left or right side, and customizing the label width.
<script setup lang="ts">
import { ref } from 'vue'
import { BrFormField } from '@breeze-ui/vue'
const notification = ref(false)
const agreement = ref(false)
</script>
<template>
<div class="space-y-6 max-w-sm">
<!-- Label on the left -->
<BrFormField
label="Push Notifications"
description="Receive updates via email."
label-position="left"
label-width="120px"
>
<template #default="{ id }">
<input :id="id" v-model="notification" type="checkbox" class="w-4 h-4" />
</template>
</BrFormField>
<!-- Label on the right -->
<BrFormField
label="I have read and agree to the terms."
label-position="right"
>
<template #default="{ id }">
<input :id="id" v-model="agreement" type="checkbox" class="w-4 h-4" />
</template>
</BrFormField>
</div>
</template>
State Linkage
Demonstrates disabled, readonly, and loading states. The label and description will automatically adjust their styles to match the state.
<script setup lang="ts">
import { ref } from 'vue'
import { BrFormField } from '@breeze-ui/vue'
const value1 = ref('Some value')
const value2 = ref('Cannot edit this')
const value3 = ref('')
</script>
<template>
<div class="space-y-6 max-w-sm">
<!-- Disabled State -->
<BrFormField
label="Disabled Field"
description="This field and its label are disabled."
disabled
>
<template #default="{ id, disabled }">
<input
:id="id"
v-model="value1"
:disabled="disabled"
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
/>
</template>
</BrFormField>
<!-- Readonly State -->
<BrFormField
label="Readonly Field"
description="This field cannot be modified."
readonly
>
<template #default="{ id, readonly }">
<input
:id="id"
v-model="value2"
:readonly="readonly"
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 read-only:bg-muted read-only:cursor-default"
/>
</template>
</BrFormField>
<!-- Loading State -->
<BrFormField
label="Loading Field"
description="Verifying availability..."
loading
>
<template #default="{ id }">
<input
:id="id"
v-model="value3"
placeholder="Checking..."
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 pr-10"
/>
</template>
</BrFormField>
</div>
</template>
API Reference
Common attributes: Supports passing class for style overriding, and automatically injects state from formFieldContext.
A singleton utility for managing global form field layering.
import { formFieldManager } from '@breeze-ui/vue/form-field'
// Get the next auto-incremented z-index
const zIndex = formFieldManager.nextZIndex()
// Reset the z-index base
formFieldManager.resetZIndex()