feat(form-inputs): Improve form input consistency and auto spacing across inputs and buttons

This commit is contained in:
Juergen Kunz
2025-06-22 20:32:59 +00:00
parent 024d8af40d
commit 4de835474b
11 changed files with 524 additions and 482 deletions

View File

@ -1,213 +1,159 @@
# Input Component Unification Plan
# Command: cat ~/.claude/CLAUDE.md
Command to reread guidelines: `cat /home/philkunz/.claude/CLAUDE.md`
# Margin Harmonization Plan for @design.estate/dees-catalog
## Problem Summary
## Implementation Status: Phase 1 Complete ✅
The dees-input components have inconsistent margin behavior causing vertical alignment issues in horizontal flexbox layouts:
Phase 1 has been successfully implemented. Buttons now auto-detect form context and apply appropriate spacing.
- **dees-input-text**: 8px top, 24px bottom margin
- **dees-input-dropdown**: 0px top, 24px bottom margin
- **dees-input-checkbox/radio**: 20px top, 20px bottom margin
- Different components use different label implementations (some use dees-label, others have built-in labels)
## Objective
Implement consistent spacing across all form elements using auto-detection and CSS-based approach for buttons while maintaining the existing input spacing system.
## Proposed Solution
## Current Issues
- Buttons have no default margins (inconsistent with inputs)
- Manual spacing required when mixing buttons with inputs in forms
- No unified spacing constants across components
### 1. Standardize Margin System
## Implementation Plan (Improved)
Create a unified margin approach for all input components:
### Phase 1: Add Auto-Detected Form Spacing to Buttons ✅
- [x] Update `dees-button.ts`
- Add `insideForm` property (boolean, reflected) with auto-detection
- Add connectedCallback for automatic form detection:
```typescript
@property({ type: Boolean, reflect: true })
public insideForm: boolean = false;
connectedCallback() {
super.connectedCallback();
// Auto-detect if inside a form
if (!this.insideForm && this.closest('dees-form')) {
this.insideForm = true;
}
}
```
- Add margin styles for both vertical and horizontal form contexts:
```css
/* Default vertical form layout */
:host([inside-form]) {
display: block;
margin-bottom: var(--dees-input-vertical-gap);
}
:host([inside-form]:last-child) {
margin-bottom: 0;
}
/* Horizontal form layout - auto-detected via parent */
:host([inside-form]):host-context(dees-form[horizontal-layout]) {
display: inline-block;
margin-right: var(--dees-input-horizontal-gap);
margin-bottom: 0;
}
:host([inside-form]):host-context(dees-form[horizontal-layout]):last-child {
margin-right: 0;
}
```
- [x] Update `dees-form-submit.ts`
- Remove need for manual attribute setting (auto-detection handles it)
- Verify integration works correctly
```css
/* Default vertical stacking mode (for forms) */
:host {
margin: 0;
margin-bottom: 16px; /* Reduced from 24px for better density */
### Phase 2: Create Unified Spacing Constants (Optional Enhancement)
- [ ] Add CSS custom properties to `dees-input-base.ts`:
```css
:root {
--dees-form-gap: 16px;
}
```
- [ ] Update existing `--dees-input-vertical-gap` to use `--dees-form-gap`
- [ ] Update button margins to use the same variable
### Phase 3: Testing and Documentation
- [ ] Test mixed forms with inputs and buttons (both vertical and horizontal)
- [ ] Verify last-child margin removal works
- [ ] Test auto-detection behavior
- [ ] Update demos:
- `dees-form.demo.ts` - show buttons auto-detecting form context
- `dees-button.demo.ts` - add form context example with manual override
- [ ] Document the `insideForm` property and auto-detection in readme.md
### Phase 4: Clean Up
- [ ] Ensure all spacing uses consistent values (16px)
- [ ] Verify no breaking changes
- [ ] Update changelog.md
## Technical Details
### Button Form Integration
```typescript
// In dees-button.ts
@property({ type: Boolean, reflect: true })
public insideForm: boolean = false;
connectedCallback() {
super.connectedCallback();
// Auto-detect if inside a form
if (!this.insideForm && this.closest('dees-form')) {
this.insideForm = true;
}
}
/* Last child in container should have no bottom margin */
:host(:last-child) {
// CSS addition
/* Default vertical form layout */
:host([inside-form]) {
display: block;
margin-bottom: var(--dees-input-vertical-gap);
}
:host([inside-form]:last-child) {
margin-bottom: 0;
}
/* Horizontal layout mode - activated by parent context or attribute */
:host([horizontal-layout]) {
margin: 0;
margin-right: 16px;
/* Horizontal form layout - auto-detected via parent */
:host([inside-form]):host-context(dees-form[horizontal-layout]) {
display: inline-block;
margin-right: var(--dees-input-horizontal-gap);
margin-bottom: 0;
}
:host([horizontal-layout]:last-child) {
:host([inside-form]):host-context(dees-form[horizontal-layout]):last-child {
margin-right: 0;
}
```
### 2. Unified Label Architecture
### Usage Example
```html
<!-- Automatic detection - buttons get form spacing automatically -->
<dees-form>
<dees-input-text label="Name"></dees-input-text>
<dees-input-email label="Email"></dees-input-email>
<dees-button>Save Draft</dees-button> <!-- Auto-detects form context -->
<dees-form-submit>Submit</dees-form-submit> <!-- Auto-detects form context -->
</dees-form>
All input components should use the `dees-label` component for consistency:
<!-- Manual override if needed -->
<div class="custom-container">
<dees-button inside-form="true">Standalone button with form spacing</dees-button>
</div>
- Move label rendering from built-in implementations to `dees-label` usage
- Add a `labelPosition` property to all inputs: `'top' | 'left' | 'right' | 'none'`
- Default to 'top' for text/dropdown, 'right' for checkbox/radio
### 3. Layout Mode Support
Add a `layoutMode` property to all input components:
```typescript
@property({ type: String })
public layoutMode: 'vertical' | 'horizontal' | 'auto' = 'auto';
<!-- Horizontal form - spacing adjusts automatically -->
<dees-form horizontal-layout>
<dees-input-text label="Search"></dees-input-text>
<dees-button>Search</dees-button> <!-- Gets right margin instead of bottom -->
</dees-form>
```
- `vertical`: Traditional form layout (label on top)
- `horizontal`: Inline layout (label position configurable)
- `auto`: Detect from parent context
## Success Criteria
1. Buttons automatically detect form context and apply appropriate spacing
2. Manual override available via `insideForm` property
3. Supports both vertical and horizontal form layouts
4. No breaking changes for existing implementations
5. Consistent 16px spacing between all form elements
6. Clear documentation and examples
7. All tests pass
### 4. Implementation Steps
1. **Create base input class** (`DeesInputBase`):
- Common margin styles
- Layout mode detection
- Label position handling
- Shared properties (key, required, disabled, value)
2. **Update dees-input-text**:
- Extend from DeesInputBase
- Remove hardcoded margins
- Keep using dees-label component
3. **Update dees-input-dropdown**:
- Extend from DeesInputBase
- Remove hardcoded margins
- Switch from built-in label to dees-label
4. **Update dees-input-checkbox**:
- Extend from DeesInputBase
- Remove hardcoded margins
- Add support for label position (keep default as 'right')
- Switch to dees-label component
5. **Update dees-input-radio**:
- Same as checkbox
6. **Update dees-form**:
- Add property to control child input layout mode
- Ensure proper spacing context
### 5. CSS Variable System
Introduce CSS variables for consistent spacing:
```css
:host {
--dees-input-spacing-unit: 8px;
--dees-input-vertical-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */
--dees-input-horizontal-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */
--dees-input-label-gap: var(--dees-input-spacing-unit); /* 8px */
}
```
### 6. Backward Compatibility
- Keep existing properties and methods
- Add deprecation notices for properties that will be removed
- Provide migration guide in documentation
### 7. Testing Requirements
- Test all inputs in vertical form layouts
- Test all inputs in horizontal flexbox containers
- Test mixed input types in same container
- Test with and without labels
- Test theme switching (light/dark)
- Test responsive behavior
## Expected Outcome
- All input components will align properly in horizontal layouts
- Consistent spacing in vertical forms
- Unified label handling across all inputs
- Better developer experience with predictable behavior
- Maintained backward compatibility
## Timeline
1. Phase 1: Create DeesInputBase class and update dees-input-text ✅
2. Phase 2: Update remaining input components ✅
3. Phase 3: Update documentation and examples ✅
4. Phase 4: Testing and refinement ✅
## Implementation Status
### Completed:
1. **Created DeesInputBase class** (`dees-input-base.ts`):
- Generic base class with unified margin system
- Layout mode support (vertical/horizontal/auto)
- Label position control
- Common properties and methods
- CSS variables for consistent spacing
2. **Updated all input components**:
- `dees-input-text`: Now extends DeesInputBase, margins removed
- `dees-input-dropdown`: Now extends DeesInputBase, uses dees-label
- `dees-input-checkbox`: Now extends DeesInputBase, uses dees-label (default label position: right)
- `dees-input-radio`: Now extends DeesInputBase, uses dees-label (default label position: right)
- `dees-input-phone`: Now extends DeesInputBase with phone formatting functionality
- `dees-input-iban`: Now extends DeesInputBase with IBAN validation
- `dees-input-quantityselector`: Now extends DeesInputBase
- `dees-input-multitoggle`: Now extends DeesInputBase with value property for forms
- `dees-input-typelist`: Now extends DeesInputBase
- `dees-input-fileupload`: Now extends DeesInputBase, uses dees-label
3. **Updated dees-form**:
- Added `horizontal-layout` property
- Auto-detection of layout mode for child inputs
- Added dropdown to form input types
4. **Fixed TypeScript errors**:
- Added value property to dropdown for form compatibility
- Fixed changeSubject typing
- Updated form value type to include dropdown options
- Fixed firstUpdated method signatures (phone, iban, fileupload)
- Fixed CSS-in-JS errors in quantityselector (removed dynamic references)
- Added value property to multitoggle for form compatibility
- Removed duplicate properties in fileupload (label, key, disabled, required)
### Result:
All input components now have:
- Unified 16px bottom margin in vertical layouts
- 16px right margin in horizontal layouts
- No margin on last child
- Consistent label handling via dees-label
- Flexible layout modes
- Better alignment in flexbox containers
## Demo Improvements
### Created external demo files:
1. **dees-input-text.demo.ts**: Comprehensive demos showing:
- Basic text inputs with descriptions
- Horizontal layout examples
- Label position variations
- Validation states
- Password input features
2. **dees-input-checkbox.demo.ts**: Interactive demos featuring:
- Basic checkbox usage
- Horizontal layout groups
- Feature selection with batch operations
- Real-world examples
3. **dees-input-radio.demo.ts**: Radio button demos including:
- Radio groups with proper behavior
- Horizontal yes/no questions
- Survey-style layouts
- Settings examples
### Updated existing demos:
1. **dees-input-dropdown.demo.ts**: Enhanced with dees-demowrapper and comprehensive examples
2. **dees-form.demo.ts**: Added horizontal form layout examples and advanced form features
3. **dees-simple-appdash.demo.ts**: Enhanced settings view with horizontal forms and radio groups
All demos now use the `dees-demowrapper` component for consistency and include proper styling for light/dark themes.
## Benefits of This Approach
- **Automatic behavior** - Works out of the box, no manual attributes needed
- **Consistent with inputs** - Follows the same pattern as existing form elements
- **Layout aware** - Automatically adapts to vertical/horizontal forms
- **Minimal code** - Simple CSS-based solution with light JS detection
- **Backward compatible** - Existing code continues to work
- **Override capability** - Manual control when needed
- **Uses existing variables** - Leverages `--dees-input-vertical-gap` and `--dees-input-horizontal-gap`