Form Components
Form elements that enable user input and data collection.
📝 Components
Select Dropdown
Dropdown component for selecting one option from a list.
States:
- Default: Initial, unselected state with placeholder
- Hover: Mouse over state
- Focus: Keyboard focus or clicked state
- Selected: Option chosen, displays selected value
- Error: Invalid selection or validation error
- Disabled: Non-interactive state
- Success: Valid selection confirmed
Visual Indicators:
- Dropdown icon (chevron) on the right
- Checkmark icon for selected options in dropdown list
- Red border/highlight for error state
- Green highlight for success state
- Reduced opacity for disabled state
Usage:
tsx
<Select
label="Name me"
placeholder="Select an option"
options={['Option 1', 'Option 2', 'Option 3']}
state="default" // default | hover | focus | selected | error | disabled | success
/>Toggle Switch / Switch
Binary on/off switch for settings and preferences.
Component: LgSwitch
Features:
- Animated sliding thumb on toggle
- Label and description support
- Disabled state
- Keyboard accessible (Space to toggle)
- LawnGuru green for active state
Props:
modelValue(Boolean): Current switch state (default: false)label(String): Label text displayed next to switchdescription(String): Helper text below switchdisabled(Boolean): Disable interaction
Events:
update:modelValue: Emitted when switch is toggled
Visual Design:
- Width: 44px, Height: 24px
- Rounded pill shape with sliding thumb
- Green color (
#008934) for on state - Grey color for off state
- Reduced opacity (0.5) for disabled states
- Smooth 200ms transition animation
Usage:
vue
<LgSwitch
v-model="notificationsEnabled"
label="Enable notifications"
description="Receive email notifications for updates"
/>
<!-- Disabled switch -->
<LgSwitch
:model-value="true"
disabled
label="Auto-save (Premium feature)"
/>Interactive Demo: See the Component Showcase for live examples.
Checkbox
Multi-select option component for forms and lists.
States:
- Unchecked: Empty checkbox
- Checked: Filled with checkmark
- Indeterminate: Partial selection (for parent/child relationships)
- Disabled Unchecked: Non-interactive empty
- Disabled Checked: Non-interactive checked
- Error: Invalid state with red styling
- Success: Valid state with green styling
Visual Design:
- Square shape with rounded corners (
radius-sm: 8px) - Green fill (
#008934) when checked - Red border for error state
- Green border for success state
- White checkmark icon on colored background
Usage:
tsx
<Checkbox
label="Name me"
checked={false}
indeterminate={false}
disabled={false}
error={false}
onChange={(checked) => console.log(checked)}
/>Radio Button / Radio Group
Single-select option component for mutually exclusive choices.
Component: LgRadioGroup
Features:
- Group multiple radio options together
- Support for labels and descriptions per option
- Individual option disable state
- Accessible with proper ARIA attributes
- Hidden native radio inputs for accessibility
- Custom styled indicators
Props:
modelValue(String|Number): Currently selected valuelabel(String): Group labeloptions(Array): Array of option objects- Each option:
{ value, label, description?, disabled? }
- Each option:
disabled(Boolean): Disable entire group
Events:
update:modelValue: Emitted when selection changes
Visual Design:
- Circular indicators (20px)
- Green border (
#008934) when selected - Inner dot (10px) scales in on selection
- Supports rich descriptions per option
- 2px border width
- Smooth scale transition (150ms)
Usage:
vue
<LgRadioGroup
v-model="selectedPlan"
label="Select a plan"
:options="[
{
value: 'free',
label: 'Free',
description: 'Perfect for getting started'
},
{
value: 'pro',
label: 'Pro',
description: 'Best for professionals'
},
{
value: 'enterprise',
label: 'Enterprise',
description: 'For large organizations',
disabled: true
}
]"
/>Interactive Demo: See the Component Showcase for live examples.
Text Input
Standard single-line text input field.
States:
- Default: Initial unfocused state
- Focus: Active input state
- Filled: Contains user input
- Error: Validation error with red border
- Success: Valid input with green border
- Disabled: Non-interactive state
- Read-only: Display-only mode
Variants:
- With label (top-aligned)
- With placeholder text
- With helper text (below input)
- With icon (left or right)
- With character counter
- With clear button
Visual Design:
- Border radius:
radius-sm(8px) - Padding:
spacing-12vertical,spacing-16horizontal - Border:
border-width-regular(1px) - Font size:
font-size-16 - Line height:
font-height-24
Usage:
tsx
<Input
label="Email Address"
placeholder="your@email.com"
type="email"
helperText="We'll never share your email"
error={false}
errorMessage="Please enter a valid email"
disabled={false}
/>Search Input
Specialized input field for search functionality.
Features:
- Search icon (magnifying glass) on left
- Clear button (X) on right when filled
- Auto-complete/suggestions dropdown
- Search history
States:
- Default (with search icon)
- Focus (active searching)
- Filled (with clear button)
- Loading (with spinner)
Visual Design:
- Same styling as text input
- Search icon: Left-aligned, grey color
- Clear button: Right-aligned, appears on input
- Border radius:
radius-md(10px) for softer look
Usage:
tsx
<SearchInput
placeholder="Search..."
onSearch={(query) => console.log(query)}
showSuggestions={true}
clearable={true}
/>Textarea
Multi-line text input for longer content.
Component: LgTextarea
Features:
- Resizable (vertical only)
- Character counter with max length enforcement
- Label and helper text support
- Error and success states with messages
- Disabled and read-only states
- Configurable row height
Props:
modelValue(String): Current textarea valuelabel(String): Label text above textareaplaceholder(String): Placeholder texthelperText(String): Helper text below textareaerror(Boolean): Error stateerrorMessage(String): Error message textsuccess(Boolean): Success statesuccessMessage(String): Success message textdisabled(Boolean): Disable textarearows(Number): Number of visible rows (default: 4)maxLength(Number): Maximum character count
Events:
update:modelValue: Emitted on input changefocus: Emitted when textarea receives focusblur: Emitted when textarea loses focus
Visual Design:
- Min height: 80px (resizable)
- Border: 1px solid, changes on states
- Border radius: 8px
- Padding: 12px vertical, 16px horizontal
- Green border on focus
- Character counter appears bottom-right when maxLength set
Usage:
vue
<LgTextarea
v-model="message"
label="Your message"
placeholder="Type your message here..."
helperText="Your message will be sent to the team"
:rows="6"
:max-length="500"
/>
<!-- With error state -->
<LgTextarea
v-model="feedback"
label="Feedback"
error
errorMessage="Feedback must be at least 20 characters"
/>Interactive Demo: See the Component Showcase for live examples.
Date Picker
Calendar-based date selection component (see screenshot #5).
Variants:
- Single date picker
- Date range picker
- With time selection
- Calendar view
- List view
- Menu view with presets (Today, Yesterday, This week, etc.)
Features:
- Month/year navigation
- Selected date highlighting (green)
- Today indicator
- Disabled dates
- Min/max date ranges
- Keyboard navigation
File Upload
Component for file selection and upload.
Variants:
- Drag and drop area
- Click to browse button
- Multiple file support
- File preview thumbnails
- Progress indicator
States:
- Default (empty)
- Dragging over
- Uploading (with progress)
- Completed
- Error (file too large, wrong type)
Slider / Range Input
Input for selecting a value from within a given range.
Component: LgSlider
Features:
- Horizontal range slider
- Custom min/max/step values
- Optional value display
- Label support
- Disabled state
- Visual thumb and track
Props:
modelValue(Number): Current slider value (default: 50)label(String): Label text above slidermin(Number): Minimum value (default: 0)max(Number): Maximum value (default: 100)step(Number): Step increment (default: 1)disabled(Boolean): Disable slidershowValue(Boolean): Display current value below slider
Events:
update:modelValue: Emitted when value changes
Visual Design:
- Track height: 6px
- Thumb size: 20px circle
- Green fill (
#008934) for selected range - White thumb with green border
- Smooth transitions (150ms)
- Focus ring on keyboard focus
Usage:
vue
<LgSlider
v-model="volume"
label="Volume"
:min="0"
:max="100"
:step="1"
:show-value="true"
/>
<!-- Custom range -->
<LgSlider
v-model="price"
label="Price Range"
:min="0"
:max="1000"
:step="10"
/>Interactive Demo: See the Component Showcase for live examples.
Tabs
Tabbed interface for organizing content into separate views.
Component: LgTabs
Features:
- Multiple tab support
- Named slots for tab content
- Active tab highlighting
- Keyboard navigation
- Responsive design
Props:
modelValue(String): Currently active tab value (required)tabs(Array): Array of tab objects (required)- Each tab:
{ value, label }
- Each tab:
Events:
update:modelValue: Emitted when tab changes
Slots:
- Dynamic named slots based on tab values
- Slot name matches tab value
Visual Design:
- Pills-style tabs with rounded background
- Active tab: white background with shadow
- Inactive tabs: transparent with hover effect
- 4px padding around tab list
- Smooth transitions
Usage:
vue
<LgTabs
v-model="activeTab"
:tabs="[
{ value: 'account', label: 'Account' },
{ value: 'password', label: 'Password' },
{ value: 'notifications', label: 'Notifications' }
]"
>
<template #account>
<div>Account settings content...</div>
</template>
<template #password>
<div>Password change form...</div>
</template>
<template #notifications>
<div>Notification preferences...</div>
</template>
</LgTabs>Interactive Demo: See the Component Showcase for live examples.
Toggle Group
Group of toggle buttons for multi-select or single-select options.
Component: LgToggleGroup
Features:
- Single or multiple selection modes
- Icon support for items
- Active state styling
- Keyboard accessible
Props:
modelValue(String|Array): Selected value(s)items(Array): Array of item objects (required)- Each item:
{ value, label, icon? }
- Each item:
type(String): 'single' or 'multiple' (default: 'single')
Events:
update:modelValue: Emitted when selection changes
Usage:
vue
<!-- Single select (like text formatting) -->
<LgToggleGroup
v-model="textFormat"
:items="[
{ value: 'bold', label: 'B' },
{ value: 'italic', label: 'I' },
{ value: 'underline', label: 'U' }
]"
/>
<!-- Multiple select -->
<LgToggleGroup
v-model="selectedFilters"
type="multiple"
:items="[
{ value: 'all', label: 'All' },
{ value: 'active', label: 'Active' },
{ value: 'archived', label: 'Archived' }
]"
/>Interactive Demo: See the Component Showcase for live examples.
📋 Usage Guidelines
Form Layout
- Stack form fields vertically with consistent spacing
- Group related fields together
- Use clear, descriptive labels
- Provide helpful placeholder text
- Show validation inline
Labels
- Always provide visible labels
- Position labels above inputs (recommended)
- Use sentence case
- Keep labels concise
Helper Text
- Provide context before users interact
- Use for format requirements
- Keep brief and actionable
Error Messages
- Show inline validation
- Be specific about the error
- Suggest how to fix it
- Use red semantic color
Required Fields
- Mark with asterisk (*) or "Required" label
- Indicate at form level what's required
- Don't make everything required
♿ Accessibility
- Associate labels with inputs using
for/id - Provide error messages linked with
aria-describedby - Ensure sufficient color contrast
- Support keyboard navigation
- Use appropriate input types
🔄 Auto-generated Section
Note: To add detailed specifications:
- Export form components from Figma
- Run
npm run docs:update-forms- Full documentation will be generated
Related: