summaryrefslogtreecommitdiffstats
path: root/FORM-COMPONENT-GUIDE.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-04-16 16:55:50 +0200
committerDanilo M. <danix@danix.xyz>2026-04-16 16:55:50 +0200
commit691bb79d29429ce9e445753092575ec564c68cd2 (patch)
treed48e71e925ab390867e4344a5ab0b700a9924d29 /FORM-COMPONENT-GUIDE.md
parenta4c5d4fa64f4e5491b1ef3195a00801ea4f21b44 (diff)
downloaddanixxyz-691bb79d29429ce9e445753092575ec564c68cd2.tar.gz
danixxyz-691bb79d29429ce9e445753092575ec564c68cd2.zip
feat: add Week 4 documentation (implementation guide, component examples, HANDOFF update)
Diffstat (limited to 'FORM-COMPONENT-GUIDE.md')
-rw-r--r--FORM-COMPONENT-GUIDE.md646
1 files changed, 646 insertions, 0 deletions
diff --git a/FORM-COMPONENT-GUIDE.md b/FORM-COMPONENT-GUIDE.md
new file mode 100644
index 0000000..a916152
--- /dev/null
+++ b/FORM-COMPONENT-GUIDE.md
@@ -0,0 +1,646 @@
+# Form Component Guide
+
+Quick reference for all form components with usage examples.
+
+---
+
+## Table of Contents
+
+1. [Input Fields](#input-fields)
+2. [Textareas](#textareas)
+3. [Select Dropdowns](#select-dropdowns)
+4. [Checkboxes](#checkboxes)
+5. [Radio Buttons](#radio-buttons)
+6. [Form Groups](#form-groups)
+7. [Form Layouts](#form-layouts)
+8. [Modals](#modals)
+9. [Notifications](#notifications)
+10. [Tooltips](#tooltips)
+
+---
+
+## Input Fields
+
+### Basic Input
+
+```html
+<input type="text" class="form-input" placeholder="Enter text...">
+```
+
+### Email Input with Validation
+
+```html
+<div class="form-group">
+ <label for="email">Email</label>
+ <input type="email" id="email" class="form-input" placeholder="user@example.com">
+</div>
+```
+
+### Password Input
+
+```html
+<div class="form-group">
+ <label for="password">Password</label>
+ <input type="password" id="password" class="form-input" placeholder="••••••">
+ <div class="form-group-help">Must be at least 8 characters</div>
+</div>
+```
+
+### Number Input
+
+```html
+<div class="form-group">
+ <label for="quantity">Quantity</label>
+ <input type="number" id="quantity" class="form-input" value="1" min="1">
+</div>
+```
+
+### Disabled Input
+
+```html
+<input type="text" class="form-input" value="Cannot edit" disabled>
+```
+
+### Input with Error
+
+```html
+<div class="form-group error">
+ <label for="username">Username</label>
+ <input type="text" id="username" class="form-input error" value="invalid">
+ <div class="form-error">Username must be 3-20 characters</div>
+</div>
+```
+
+---
+
+## Textareas
+
+### Basic Textarea
+
+```html
+<textarea class="form-textarea" placeholder="Enter message..."></textarea>
+```
+
+### Textarea with Label and Help Text
+
+```html
+<div class="form-group">
+ <label for="bio">Bio</label>
+ <textarea id="bio" class="form-textarea" placeholder="Tell us about yourself..."></textarea>
+ <div class="form-group-help">Maximum 500 characters</div>
+</div>
+```
+
+### Auto-Expanding Textarea
+
+```html
+<div class="form-group">
+ <label for="auto-textarea">Auto-expanding Textarea</label>
+ <textarea
+ id="auto-textarea"
+ class="form-textarea auto-expand"
+ placeholder="Grows as you type..."
+ @input="autoExpandTextarea($event)">
+ </textarea>
+</div>
+```
+
+---
+
+## Select Dropdowns
+
+### Basic Select
+
+```html
+<select class="form-select">
+ <option>Choose an option...</option>
+ <option>Option 1</option>
+ <option>Option 2</option>
+ <option>Option 3</option>
+</select>
+```
+
+### Select with Label
+
+```html
+<div class="form-group">
+ <label for="country">Country</label>
+ <select id="country" class="form-select">
+ <option>Select a country...</option>
+ <option value="us">United States</option>
+ <option value="uk">United Kingdom</option>
+ <option value="de">Germany</option>
+ </select>
+</div>
+```
+
+### Multi-Select
+
+```html
+<select class="form-select" multiple>
+ <option>Python</option>
+ <option>JavaScript</option>
+ <option>Go</option>
+ <option>Rust</option>
+</select>
+```
+
+---
+
+## Checkboxes
+
+### Single Checkbox
+
+```html
+<label class="flex items-center gap-3 cursor-pointer">
+ <input type="checkbox" class="form-checkbox">
+ <span>I agree to the terms and conditions</span>
+</label>
+```
+
+### Checkbox Group
+
+```html
+<fieldset>
+ <legend class="font-semibold">Select your interests</legend>
+ <div class="space-y-2 mt-3">
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="checkbox" class="form-checkbox" name="interests" value="tech">
+ <span>Technology</span>
+ </label>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="checkbox" class="form-checkbox" name="interests" value="design">
+ <span>Design</span>
+ </label>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="checkbox" class="form-checkbox" name="interests" value="business">
+ <span>Business</span>
+ </label>
+ </div>
+</fieldset>
+```
+
+### Disabled Checkbox
+
+```html
+<label class="flex items-center gap-3 cursor-pointer opacity-50">
+ <input type="checkbox" class="form-checkbox" disabled>
+ <span>This option is not available</span>
+</label>
+```
+
+---
+
+## Radio Buttons
+
+### Radio Button Group
+
+```html
+<fieldset>
+ <legend class="font-semibold">Choose an option</legend>
+ <div class="space-y-2 mt-3">
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="radio" name="option" class="form-radio" value="a">
+ <span>Option A</span>
+ </label>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="radio" name="option" class="form-radio" value="b">
+ <span>Option B</span>
+ </label>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="radio" name="option" class="form-radio" value="c">
+ <span>Option C</span>
+ </label>
+ </div>
+</fieldset>
+```
+
+### Inline Radio Buttons
+
+```html
+<div class="flex gap-6">
+ <label class="flex items-center gap-2 cursor-pointer">
+ <input type="radio" name="size" class="form-radio" value="sm">
+ <span>Small</span>
+ </label>
+ <label class="flex items-center gap-2 cursor-pointer">
+ <input type="radio" name="size" class="form-radio" value="md">
+ <span>Medium</span>
+ </label>
+ <label class="flex items-center gap-2 cursor-pointer">
+ <input type="radio" name="size" class="form-radio" value="lg">
+ <span>Large</span>
+ </label>
+</div>
+```
+
+---
+
+## Form Groups
+
+### Basic Form Group
+
+```html
+<div class="form-group">
+ <label for="name">Name</label>
+ <input type="text" id="name" class="form-input">
+</div>
+```
+
+### Required Form Group
+
+```html
+<div class="form-group required">
+ <label for="email">Email</label>
+ <input type="email" id="email" class="form-input" required>
+</div>
+```
+
+### Form Group with Help Text
+
+```html
+<div class="form-group">
+ <label for="username">Username</label>
+ <input type="text" id="username" class="form-input">
+ <div class="form-group-help">3-20 characters, alphanumeric only</div>
+</div>
+```
+
+### Form Group with Error
+
+```html
+<div class="form-group error">
+ <label for="password">Password</label>
+ <input type="password" id="password" class="form-input error">
+ <div class="form-error">Password must be at least 8 characters</div>
+</div>
+```
+
+---
+
+## Form Layouts
+
+### Single Column Form
+
+```html
+<form class="space-y-4">
+ <div class="form-group">
+ <label for="name">Name</label>
+ <input type="text" id="name" class="form-input">
+ </div>
+
+ <div class="form-group">
+ <label for="email">Email</label>
+ <input type="email" id="email" class="form-input">
+ </div>
+
+ <div class="form-group">
+ <label for="message">Message</label>
+ <textarea id="message" class="form-textarea"></textarea>
+ </div>
+
+ <button type="submit" class="btn btn-primary">Submit</button>
+</form>
+```
+
+### Two-Column Form (Responsive)
+
+```html
+<form class="space-y-4">
+ <div class="form-row">
+ <div class="form-group">
+ <label for="first">First Name</label>
+ <input type="text" id="first" class="form-input">
+ </div>
+ <div class="form-group">
+ <label for="last">Last Name</label>
+ <input type="text" id="last" class="form-input">
+ </div>
+ </div>
+
+ <div class="form-row">
+ <div class="form-group">
+ <label for="phone">Phone</label>
+ <input type="tel" id="phone" class="form-input">
+ </div>
+ <div class="form-group">
+ <label for="country">Country</label>
+ <select id="country" class="form-select">
+ <option>Select...</option>
+ </select>
+ </div>
+ </div>
+
+ <button type="submit" class="btn btn-primary">Submit</button>
+</form>
+```
+
+### Inline Form (Search)
+
+```html
+<div class="form-inline">
+ <div class="form-group">
+ <label for="search">Search</label>
+ <input type="search" id="search" class="form-input" placeholder="Type...">
+ </div>
+ <button class="btn btn-primary">Search</button>
+</div>
+```
+
+---
+
+## Modals
+
+### Alert Modal
+
+```html
+<div class="modal" :class="{ active: showAlert }" x-show="showAlert" x-data="{ showAlert: false }">
+ <div class="modal-backdrop" @click="showAlert = false"></div>
+ <div class="modal-content modal-sm">
+ <div class="modal-header">
+ <h3 class="modal-title">Alert</h3>
+ <div class="modal-close" @click="showAlert = false"></div>
+ </div>
+ <div class="modal-body">
+ <p>This is an important message.</p>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" @click="showAlert = false">OK</button>
+ </div>
+ </div>
+</div>
+
+<button @click="showAlert = true" class="btn btn-primary">Open Alert</button>
+```
+
+### Confirm Modal
+
+```html
+<div class="modal" :class="{ active: showConfirm }" x-show="showConfirm" x-data="{ showConfirm: false }">
+ <div class="modal-backdrop" @click="showConfirm = false"></div>
+ <div class="modal-content modal-sm">
+ <div class="modal-header">
+ <h3 class="modal-title">Confirm Action</h3>
+ <div class="modal-close" @click="showConfirm = false"></div>
+ </div>
+ <div class="modal-body">
+ <p>Are you sure you want to delete this item? This action cannot be undone.</p>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-outline" @click="showConfirm = false">Cancel</button>
+ <button class="btn btn-primary" @click="handleDelete()">Delete</button>
+ </div>
+ </div>
+</div>
+```
+
+### Modal with Form
+
+```html
+<div class="modal" :class="{ active: showModal }" x-show="showModal" x-data="{ showModal: false, form: {} }">
+ <div class="modal-backdrop" @click="showModal = false"></div>
+ <div class="modal-content modal-md">
+ <div class="modal-header">
+ <h3 class="modal-title">Edit Profile</h3>
+ <div class="modal-close" @click="showModal = false"></div>
+ </div>
+ <form @submit.prevent="saveProfile()">
+ <div class="modal-body space-y-4">
+ <div class="form-group">
+ <label for="name">Name</label>
+ <input type="text" id="name" class="form-input" x-model="form.name">
+ </div>
+ <div class="form-group">
+ <label for="bio">Bio</label>
+ <textarea id="bio" class="form-textarea" x-model="form.bio"></textarea>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-outline" @click="showModal = false">Cancel</button>
+ <button type="submit" class="btn btn-primary">Save</button>
+ </div>
+ </form>
+ </div>
+</div>
+```
+
+---
+
+## Notifications
+
+### Toast Notification
+
+```html
+<!-- Container in layout -->
+<div class="toast-container" x-data="formComponentsData()">
+ <template x-for="toast in toasts" :key="toast.id">
+ <div class="toast" :class="`toast-${toast.type}`">
+ <span x-text="toast.message"></span>
+ <div class="toast-close" @click="removeToast(toast.id)"></div>
+ </div>
+ </template>
+</div>
+
+<!-- Trigger toast -->
+<button @click="showToast('success', 'Item saved!')">Save</button>
+<button @click="showToast('error', 'Failed to delete.')">Delete</button>
+<button @click="showToast('info', 'Welcome back!')">Info</button>
+<button @click="showToast('warning', 'Unsaved changes.')">Warning</button>
+```
+
+### Toast Usage in Forms
+
+```html
+<form @submit.prevent="submitForm()">
+ <!-- Form fields -->
+ <button type="submit" class="btn btn-primary" :disabled="isSubmitting">
+ {{ isSubmitting ? 'Submitting...' : 'Submit' }}
+ </button>
+</form>
+
+<script>
+function formData() {
+ return {
+ isSubmitting: false,
+ async submitForm() {
+ this.isSubmitting = true;
+ try {
+ await fetch('/api/submit', { method: 'POST' });
+ this.showToast('success', 'Form submitted successfully!');
+ } catch (error) {
+ this.showToast('error', 'Failed to submit form.');
+ } finally {
+ this.isSubmitting = false;
+ }
+ }
+ };
+}
+</script>
+```
+
+---
+
+## Tooltips
+
+### Top Tooltip (Default)
+
+```html
+<div class="tooltip">
+ <span>Hover me</span>
+ <span class="tooltip-text">I'm a tooltip on top!</span>
+</div>
+```
+
+### Bottom Tooltip
+
+```html
+<div class="tooltip tooltip-bottom">
+ <span>Hover me</span>
+ <span class="tooltip-text">I'm below!</span>
+</div>
+```
+
+### Left Tooltip
+
+```html
+<div class="tooltip tooltip-left">
+ <span>Hover me</span>
+ <span class="tooltip-text">I'm on the left!</span>
+</div>
+```
+
+### Right Tooltip
+
+```html
+<div class="tooltip tooltip-right">
+ <span>Hover me</span>
+ <span class="tooltip-text">I'm on the right!</span>
+</div>
+```
+
+### Tooltip with Icon
+
+```html
+<div class="tooltip" title="Click to copy email">
+ <button class="btn btn-icon">
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+ <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
+ </svg>
+ </button>
+ <span class="tooltip-text">Copy to clipboard</span>
+</div>
+```
+
+---
+
+## Loading States
+
+### Button with Spinner
+
+```html
+<button class="btn btn-primary" :disabled="isLoading">
+ <span x-show="isLoading" class="spinner mr-2"></span>
+ {{ isLoading ? 'Submitting...' : 'Submit' }}
+</button>
+```
+
+### Spinner Sizes
+
+```html
+<div class="spinner spinner-sm"></div>
+<div class="spinner"></div>
+<div class="spinner spinner-lg"></div>
+```
+
+---
+
+## Complete Contact Form Example
+
+```html
+<form x-data="formComponentsData()" @submit.prevent="submitForm()" class="space-y-4 max-w-md">
+ <div class="form-group required">
+ <label for="name">Name</label>
+ <input
+ type="text"
+ id="name"
+ class="form-input"
+ x-model="form.name"
+ @blur="validateName()"
+ :class="{ error: errors.name }"
+ required>
+ <div x-show="errors.name" class="form-error" x-text="errors.name"></div>
+ </div>
+
+ <div class="form-group required">
+ <label for="email">Email</label>
+ <input
+ type="email"
+ id="email"
+ class="form-input"
+ x-model="form.email"
+ @blur="validateEmail()"
+ :class="{ error: errors.email }"
+ required>
+ <div x-show="errors.email" class="form-error" x-text="errors.email"></div>
+ </div>
+
+ <div class="form-group required">
+ <label for="message">Message</label>
+ <textarea
+ id="message"
+ class="form-textarea auto-expand"
+ x-model="form.message"
+ @input="autoExpandTextarea($event)"
+ required
+ placeholder="Your message..."></textarea>
+ </div>
+
+ <div class="form-group">
+ <label class="flex items-center gap-3">
+ <input type="checkbox" class="form-checkbox" x-model="form.subscribe">
+ <span>Subscribe to our newsletter</span>
+ </label>
+ </div>
+
+ <button
+ type="submit"
+ class="btn btn-primary w-full"
+ :disabled="isSubmitting">
+ <span x-show="isSubmitting" class="spinner mr-2"></span>
+ {{ isSubmitting ? 'Submitting...' : 'Send Message' }}
+ </button>
+</form>
+```
+
+---
+
+## Keyboard Shortcuts
+
+| Key | Action |
+|-----|--------|
+| Tab | Focus next form field |
+| Shift+Tab | Focus previous form field |
+| Space | Toggle checkbox/radio |
+| Enter | Submit form / Confirm dialog |
+| Escape | Close modal / Cancel dialog |
+| Arrow Up/Down | Navigate select options |
+
+---
+
+## Best Practices
+
+1. **Always use labels** — Associate with `for` attribute
+2. **Group related fields** — Use `.form-group` wrapper
+3. **Provide help text** — Use `.form-group-help` for guidance
+4. **Show errors clearly** — Use `.form-error` with specific messages
+5. **Test keyboard navigation** — Use Tab, Shift+Tab, Enter, Space, Escape
+6. **Verify contrast** — Check both dark and light modes
+7. **Respect motion preferences** — Use `prefers-reduced-motion` media query
+8. **Validate early** — Real-time feedback, but allow recovery
+9. **Disable during submission** — Prevent duplicate submissions
+10. **Use semantic HTML** — `<fieldset>`, `<legend>`, `<label>` elements
+
+---
+
+**Last Updated:** 2026-04-16
+**Version:** 1.0