Forms
Forms
UltraViolet Pro includes comprehensive form components with validation, styling, and interactive elements built with Bootstrap 5 and enhanced with custom features.
Basic Form Elements
Text Inputs
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
<div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1">
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">Check me out</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
Form Sizes
<!-- Large form -->
<div class="mb-3">
<input type="text" class="form-control form-control-lg" placeholder="Large input">
</div>
<!-- Default form -->
<div class="mb-3">
<input type="text" class="form-control" placeholder="Default input">
</div>
<!-- Small form -->
<div class="mb-3">
<input type="text" class="form-control form-control-sm" placeholder="Small input">
</div>
Form Controls
Select Dropdowns
<div class="mb-3">
<label for="formSelect" class="form-label">Default select</label>
<select class="form-select" id="formSelect" aria-label="Default select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
Textareas
<div class="mb-3">
<label for="exampleFormControlTextarea1" class="form-label">Example textarea</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>
File Inputs
<div class="mb-3">
<label for="formFile" class="form-label">Default file input example</label>
<input class="form-control" type="file" id="formFile">
</div>
<div class="mb-3">
<label for="formFileMultiple" class="form-label">Multiple files input example</label>
<input class="form-control" type="file" id="formFileMultiple" multiple>
</div>
Form Validation
Client-side Validation
<form class="row g-3 needs-validation" novalidate>
<div class="col-md-4">
<label for="validationCustom01" class="form-label">First name</label>
<input type="text" class="form-control" id="validationCustom01" value="Mark" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
<div class="col-md-4">
<label for="validationCustom02" class="form-label">Last name</label>
<input type="text" class="form-control" id="validationCustom02" value="Otto" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
<div class="col-md-4">
<label for="validationCustomUsername" class="form-label">Username</label>
<div class="input-group has-validation">
<span class="input-group-text" id="inputGroupPrepend">@</span>
<input type="text" class="form-control" id="validationCustomUsername" aria-describedby="inputGroupPrepend" required>
<div class="invalid-feedback">
Please choose a username.
</div>
</div>
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit form</button>
</div>
</form>
Server-side Validation (Laravel)
// Controller
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed',
]);
// Process validated data
}
<!-- Blade template with validation errors -->
<form method="POST" action="{{ route('users.store') }}">
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control @error('name') is-invalid @enderror"
id="name" name="name" value="{{ old('name') }}" required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control @error('email') is-invalid @enderror"
id="email" name="email" value="{{ old('email') }}" required>
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Form Layouts
Horizontal Form
<form>
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="inputEmail3">
</div>
</div>
<div class="row mb-3">
<label for="inputPassword3" class="col-sm-2 col-form-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3">
</div>
</div>
<fieldset class="row mb-3">
<legend class="col-form-label col-sm-2 pt-0">Radios</legend>
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios1" value="option1" checked>
<label class="form-check-label" for="gridRadios1">
First radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios2" value="option2">
<label class="form-check-label" for="gridRadios2">
Second radio
</label>
</div>
</div>
</fieldset>
<div class="row mb-3">
<div class="col-sm-10 offset-sm-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck1">
<label class="form-check-label" for="gridCheck1">
Example checkbox
</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Sign in</button>
</form>
Inline Form
<form class="row g-3 align-items-center">
<div class="col-auto">
<label for="inlineFormInput" class="visually-hidden">Name</label>
<input type="text" class="form-control" id="inlineFormInput" placeholder="Jane Doe">
</div>
<div class="col-auto">
<label for="inlineFormSelectPref" class="visually-hidden">Preference</label>
<select class="form-select" id="inlineFormSelectPref">
<option selected>Choose...</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
<div class="col-auto">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="autoSizingCheck">
<label class="form-check-label" for="autoSizingCheck">
Remember me
</label>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
Advanced Form Components
Floating Labels
UltraViolet Pro includes @tkrotoff/bootstrap-floating-label for enhanced form styling.
<div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingInput" placeholder="name@example.com">
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">Password</label>
</div>
Input Groups
<div class="input-group mb-3">
<span class="input-group-text">@</span>
<input type="text" class="form-control" placeholder="Username" aria-label="Username">
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username">
<span class="input-group-text">@example.com</span>
</div>
<div class="input-group mb-3">
<span class="input-group-text">$</span>
<input type="text" class="form-control" aria-label="Amount (to the nearest dollar)">
<span class="input-group-text">.00</span>
</div>
Form Switches
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="flexSwitchCheckDefault">
<label class="form-check-label" for="flexSwitchCheckDefault">
Default switch checkbox input
</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="flexSwitchCheckChecked" checked>
<label class="form-check-label" for="flexSwitchCheckChecked">
Checked switch checkbox input
</label>
</div>
Form Components
Checkboxes and Radios
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="flexCheckDefault">
<label class="form-check-label" for="flexCheckDefault">
Default checkbox
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="flexCheckChecked" checked>
<label class="form-check-label" for="flexCheckChecked">
Checked checkbox
</label>
</div>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
<label class="form-check-label" for="flexRadioDefault1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault2" checked>
<label class="form-check-label" for="flexRadioDefault2">
Default checked radio
</label>
</div>
</div>
Range Inputs
<div class="mb-3">
<label for="customRange1" class="form-label">Example range</label>
<input type="range" class="form-range" id="customRange1">
</div>
Form Integration with Livewire
Livewire Form Component
// Livewire component
class ContactForm extends Component
{
public $name = '';
public $email = '';
public $message = '';
protected $rules = [
'name' => 'required|min:3',
'email' => 'required|email',
'message' => 'required|min:10',
];
public function submit()
{
$this->validate();
// Process form submission
Contact::create([
'name' => $this->name,
'email' => $this->email,
'message' => $this->message,
]);
session()->flash('message', 'Contact form submitted successfully!');
$this->reset();
}
public function render()
{
return view('livewire.contact-form');
}
}
<!-- Livewire view -->
<div>
@if (session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
@endif
<form wire:submit.prevent="submit">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control @error('name') is-invalid @enderror"
wire:model="name" id="name">
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control @error('email') is-invalid @enderror"
wire:model="email" id="email">
@error('email') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control @error('message') is-invalid @enderror"
wire:model="message" id="message" rows="5"></textarea>
@error('message') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<button type="submit" class="btn btn-primary" wire:loading.attr="disabled">
<span wire:loading.remove>Submit</span>
<span wire:loading>Sending...</span>
</button>
</form>
</div>
Customization
Custom Form Styling
.custom-form {
.form-control {
border-radius: 0.5rem;
border: 2px solid #e9ecef;
transition: all 0.3s ease;
&:focus {
border-color: var(--bs-primary);
box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb), 0.25);
}
}
.form-label {
font-weight: 600;
color: var(--bs-dark);
margin-bottom: 0.5rem;
}
.btn-submit {
background: linear-gradient(45deg, var(--bs-primary), var(--bs-secondary));
border: none;
border-radius: 0.5rem;
padding: 0.75rem 2rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
}
Best Practices
- Accessibility: Always include proper labels and ARIA attributes
- Validation: Implement both client-side and server-side validation
- User Experience: Provide clear feedback and error messages
- Security: Use CSRF protection and validate all inputs
- Performance: Optimize form loading and submission
- Responsive: Ensure forms work well on all device sizes
- Progressive Enhancement: Start with basic HTML and enhance with JavaScript