feat(dees-form): add layout styles to dees-form and standardize demo input grouping

This commit is contained in:
2026-02-17 17:34:53 +00:00
parent ecd35683e6
commit 2abf7e356d
11 changed files with 350 additions and 270 deletions

View File

@@ -1,5 +1,13 @@
# Changelog # Changelog
## 2026-02-17 - 3.43.0 - feat(dees-form)
add layout styles to dees-form and standardize demo input grouping
- Add static CSS to dees-form: default column layout with gap and support for [horizontal-layout] (row wrapping, alignment and gap).
- Remove inline <style> from dees-form render to centralize styling.
- Simplify dees-input-base styles by removing host margins and making spacing container-driven.
- Update multiple demo files to wrap related inputs in a new .input-group container and include .input-group CSS for consistent vertical spacing.
## 2026-02-16 - 3.42.2 - fix(dees-chart-area) ## 2026-02-16 - 3.42.2 - fix(dees-chart-area)
add ApexAxisChartSeries type to dees-chart-area component to improve typing for ApexCharts series data add ApexAxisChartSeries type to dees-chart-area component to improve typing for ApexCharts series data

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@design.estate/dees-catalog', name: '@design.estate/dees-catalog',
version: '3.42.2', version: '3.43.0',
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.' description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
} }

View File

@@ -1,6 +1,7 @@
import { import {
customElement, customElement,
html, html,
css,
type TemplateResult, type TemplateResult,
DeesElement, DeesElement,
type CSSResult, type CSSResult,
@@ -81,13 +82,25 @@ export class DeesForm extends DeesElement {
@property({ type: Boolean, reflect: true, attribute: 'horizontal-layout' }) @property({ type: Boolean, reflect: true, attribute: 'horizontal-layout' })
accessor horizontalLayout: boolean = false; accessor horizontalLayout: boolean = false;
public static styles = [
css`
:host {
display: flex;
flex-direction: column;
gap: 16px;
}
:host([horizontal-layout]) {
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
gap: 16px;
}
`,
];
public render(): TemplateResult { public render(): TemplateResult {
return html` return html`
<style>
:host {
display: contents;
}
</style>
<slot></slot> <slot></slot>
`; `;
} }

View File

@@ -54,37 +54,20 @@ export abstract class DeesInputBase<T = any> extends DeesElement {
/* CSS Variables for consistent spacing */ /* CSS Variables for consistent spacing */
:host { :host {
--dees-input-spacing-unit: 8px; --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 */ --dees-input-label-gap: var(--dees-input-spacing-unit); /* 8px */
} }
/* Default vertical stacking mode (for forms) */ /* Default block display with no margins - spacing is container-driven */
:host { :host {
display: block; display: block;
margin: 0; margin: 0;
margin-bottom: var(--dees-input-vertical-gap);
}
/* Last child in container should have no bottom margin */
:host(:last-child) {
margin-bottom: 0;
} }
/* Horizontal layout mode - activated by attribute */ /* Horizontal layout mode - activated by attribute */
:host([layout-mode="horizontal"]) { :host([layout-mode="horizontal"]) {
display: inline-block; display: inline-block;
margin: 0;
margin-right: var(--dees-input-horizontal-gap);
margin-bottom: 0;
} }
:host([layout-mode="horizontal"]:last-child) {
margin-right: 0;
}
/* Auto mode - inherit from parent dees-form if present */
/* Label position variations */ /* Label position variations */
:host([label-position="left"]) .input-wrapper { :host([label-position="left"]) .input-wrapper {
display: grid; display: grid;

View File

@@ -31,6 +31,12 @@ export const demoFunc = () => html`
flex-wrap: wrap; flex-wrap: wrap;
} }
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.spacer { .spacer {
height: 200px; height: 200px;
display: flex; display: flex;
@@ -63,6 +69,7 @@ export const demoFunc = () => html`
} }
}}> }}>
<dees-panel .title=${'1. Basic Dropdowns'} .subtitle=${'Standard dropdown with search functionality and various options'}> <dees-panel .title=${'1. Basic Dropdowns'} .subtitle=${'Standard dropdown with search functionality and various options'}>
<div class="input-group">
<dees-input-dropdown <dees-input-dropdown
.label=${'Select Country'} .label=${'Select Country'}
.options=${[ .options=${[
@@ -87,6 +94,7 @@ export const demoFunc = () => html`
{ option: 'Guest', key: 'guest' } { option: 'Guest', key: 'guest' }
]} ]}
></dees-input-dropdown> ></dees-input-dropdown>
</div>
</dees-panel> </dees-panel>
</dees-demowrapper> </dees-demowrapper>
@@ -176,6 +184,7 @@ export const demoFunc = () => html`
} }
}}> }}>
<dees-panel .title=${'4. States'} .subtitle=${'Different states and configurations'}> <dees-panel .title=${'4. States'} .subtitle=${'Different states and configurations'}>
<div class="input-group">
<dees-input-dropdown <dees-input-dropdown
.label=${'Required Field'} .label=${'Required Field'}
.required=${true} .required=${true}
@@ -194,6 +203,7 @@ export const demoFunc = () => html`
]} ]}
.selectedOption=${{ option: 'Cannot Select', key: 'disabled' }} .selectedOption=${{ option: 'Cannot Select', key: 'disabled' }}
></dees-input-dropdown> ></dees-input-dropdown>
</div>
</dees-panel> </dees-panel>
</dees-demowrapper> </dees-demowrapper>

View File

@@ -13,6 +13,12 @@ export const demoFunc = () => html`
margin: 0 auto; margin: 0 auto;
} }
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.payment-group { .payment-group {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -24,6 +30,7 @@ export const demoFunc = () => html`
<div class="demo-container"> <div class="demo-container">
<dees-panel .title=${'Basic IBAN Input'} .subtitle=${'International Bank Account Number with automatic formatting'}> <dees-panel .title=${'Basic IBAN Input'} .subtitle=${'International Bank Account Number with automatic formatting'}>
<div class="input-group">
<dees-input-iban <dees-input-iban
.label=${'Bank Account IBAN'} .label=${'Bank Account IBAN'}
.description=${'Enter your International Bank Account Number'} .description=${'Enter your International Bank Account Number'}
@@ -34,6 +41,7 @@ export const demoFunc = () => html`
.description=${'This IBAN has been verified'} .description=${'This IBAN has been verified'}
.value=${'DE89370400440532013000'} .value=${'DE89370400440532013000'}
></dees-input-iban> ></dees-input-iban>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Payment Information'} .subtitle=${'IBAN input with horizontal layout for payment forms'}> <dees-panel .title=${'Payment Information'} .subtitle=${'IBAN input with horizontal layout for payment forms'}>
@@ -53,6 +61,7 @@ export const demoFunc = () => html`
</dees-panel> </dees-panel>
<dees-panel .title=${'Validation & States'} .subtitle=${'Required fields and disabled states'}> <dees-panel .title=${'Validation & States'} .subtitle=${'Required fields and disabled states'}>
<div class="input-group">
<dees-input-iban <dees-input-iban
.label=${'Payment Account'} .label=${'Payment Account'}
.description=${'Required for processing payments'} .description=${'Required for processing payments'}
@@ -65,6 +74,7 @@ export const demoFunc = () => html`
.value=${'FR1420041010050500013M02606'} .value=${'FR1420041010050500013M02606'}
.disabled=${true} .disabled=${true}
></dees-input-iban> ></dees-input-iban>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Bank Transfer Form'} .subtitle=${'Complete form example with IBAN validation'}> <dees-panel .title=${'Bank Transfer Form'} .subtitle=${'Complete form example with IBAN validation'}>

View File

@@ -13,6 +13,12 @@ export const demoFunc = () => html`
margin: 0 auto; margin: 0 auto;
} }
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.horizontal-group { .horizontal-group {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -24,6 +30,7 @@ export const demoFunc = () => html`
<div class="demo-container"> <div class="demo-container">
<dees-panel .title=${'Basic Phone Input'} .subtitle=${'Automatic formatting for phone numbers'}> <dees-panel .title=${'Basic Phone Input'} .subtitle=${'Automatic formatting for phone numbers'}>
<div class="input-group">
<dees-input-phone <dees-input-phone
.label=${'Phone Number'} .label=${'Phone Number'}
.description=${'Enter your phone number with country code'} .description=${'Enter your phone number with country code'}
@@ -36,6 +43,7 @@ export const demoFunc = () => html`
.required=${true} .required=${true}
.placeholder=${'+1 (555) 000-0000'} .placeholder=${'+1 (555) 000-0000'}
></dees-input-phone> ></dees-input-phone>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Horizontal Layout'} .subtitle=${'Phone inputs arranged horizontally'}> <dees-panel .title=${'Horizontal Layout'} .subtitle=${'Phone inputs arranged horizontally'}>
@@ -55,6 +63,7 @@ export const demoFunc = () => html`
</dees-panel> </dees-panel>
<dees-panel .title=${'International Numbers'} .subtitle=${'Supports formatting for numbers with country codes'}> <dees-panel .title=${'International Numbers'} .subtitle=${'Supports formatting for numbers with country codes'}>
<div class="input-group">
<dees-input-phone <dees-input-phone
.label=${'International Contact'} .label=${'International Contact'}
.description=${'Automatically formats international numbers'} .description=${'Automatically formats international numbers'}
@@ -66,6 +75,7 @@ export const demoFunc = () => html`
.value=${'911'} .value=${'911'}
.disabled=${true} .disabled=${true}
></dees-input-phone> ></dees-input-phone>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Form Integration'} .subtitle=${'Phone input as part of a contact form'}> <dees-panel .title=${'Form Integration'} .subtitle=${'Phone input as part of a contact form'}>

View File

@@ -14,6 +14,12 @@ export const demoFunc = () => html`
margin: 0 auto; margin: 0 auto;
} }
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.shopping-grid { .shopping-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
@@ -60,6 +66,7 @@ export const demoFunc = () => html`
<div class="demo-container"> <div class="demo-container">
<dees-panel .title=${'Basic Quantity Selector'} .subtitle=${'Simple quantity input with increment/decrement buttons'}> <dees-panel .title=${'Basic Quantity Selector'} .subtitle=${'Simple quantity input with increment/decrement buttons'}>
<div class="input-group">
<dees-input-quantityselector <dees-input-quantityselector
.label=${'Quantity'} .label=${'Quantity'}
.description=${'Select the desired quantity'} .description=${'Select the desired quantity'}
@@ -71,6 +78,7 @@ export const demoFunc = () => html`
.description=${'Adjust the quantity of items'} .description=${'Adjust the quantity of items'}
.value=${3} .value=${3}
></dees-input-quantityselector> ></dees-input-quantityselector>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Shopping Cart'} .subtitle=${'Modern e-commerce product cards with interactive quantity selectors'} .runAfterRender=${async (elementArg: HTMLElement) => { <dees-panel .title=${'Shopping Cart'} .subtitle=${'Modern e-commerce product cards with interactive quantity selectors'} .runAfterRender=${async (elementArg: HTMLElement) => {
@@ -169,6 +177,7 @@ export const demoFunc = () => html`
</dees-panel> </dees-panel>
<dees-panel .title=${'Required & Disabled States'} .subtitle=${'Different states for validation and restrictions'}> <dees-panel .title=${'Required & Disabled States'} .subtitle=${'Different states for validation and restrictions'}>
<div class="input-group">
<dees-input-quantityselector <dees-input-quantityselector
.label=${'Number of Licenses'} .label=${'Number of Licenses'}
.description=${'Select how many licenses you need'} .description=${'Select how many licenses you need'}
@@ -182,6 +191,7 @@ export const demoFunc = () => html`
.disabled=${true} .disabled=${true}
.value=${5} .value=${5}
></dees-input-quantityselector> ></dees-input-quantityselector>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Order Form'} .subtitle=${'Complete order form with quantity selection'}> <dees-panel .title=${'Order Form'} .subtitle=${'Complete order form with quantity selection'}>

View File

@@ -23,6 +23,12 @@ export const demoFunc = () => html`
margin-bottom: 0; margin-bottom: 0;
} }
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.demo-grid { .demo-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
@@ -60,6 +66,7 @@ export const demoFunc = () => html`
</dees-panel> </dees-panel>
<dees-panel .title=${'2. Horizontal Layout'} .subtitle=${'Radio groups with horizontal arrangement'}> <dees-panel .title=${'2. Horizontal Layout'} .subtitle=${'Radio groups with horizontal arrangement'}>
<div class="input-group">
<dees-input-radiogroup <dees-input-radiogroup
.label=${'Do you agree with the terms?'} .label=${'Do you agree with the terms?'}
.options=${['Yes', 'No', 'Maybe']} .options=${['Yes', 'No', 'Maybe']}
@@ -74,6 +81,7 @@ export const demoFunc = () => html`
.selectedOption=${'Intermediate'} .selectedOption=${'Intermediate'}
.description=${'Select your experience level with web development'} .description=${'Select your experience level with web development'}
></dees-input-radiogroup> ></dees-input-radiogroup>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'3. Advanced Options'} .subtitle=${'Using object format with keys and payloads'}> <dees-panel .title=${'3. Advanced Options'} .subtitle=${'Using object format with keys and payloads'}>
@@ -132,6 +140,7 @@ export const demoFunc = () => html`
</dees-panel> </dees-panel>
<dees-panel .title=${'6. Settings Example'} .subtitle=${'Common patterns in application settings'}> <dees-panel .title=${'6. Settings Example'} .subtitle=${'Common patterns in application settings'}>
<div class="input-group">
<dees-input-radiogroup <dees-input-radiogroup
.label=${'Theme Preference'} .label=${'Theme Preference'}
.options=${[ .options=${[
@@ -156,6 +165,7 @@ export const demoFunc = () => html`
.selectedOption=${'English'} .selectedOption=${'English'}
.direction=${'horizontal'} .direction=${'horizontal'}
></dees-input-radiogroup> ></dees-input-radiogroup>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'7. Form Integration'} .subtitle=${'Works seamlessly with dees-form'}> <dees-panel .title=${'7. Form Integration'} .subtitle=${'Works seamlessly with dees-form'}>

View File

@@ -30,6 +30,12 @@ export const demoFunc = () => html`
flex-wrap: wrap; flex-wrap: wrap;
} }
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.grid-layout { .grid-layout {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
@@ -83,6 +89,7 @@ export const demoFunc = () => html`
} }
}}> }}>
<dees-panel .title=${'Basic Text Inputs'} .subtitle=${'Standard text inputs with labels and descriptions'}> <dees-panel .title=${'Basic Text Inputs'} .subtitle=${'Standard text inputs with labels and descriptions'}>
<div class="input-group">
<dees-input-text <dees-input-text
.label=${'Username'} .label=${'Username'}
.value=${'johndoe'} .value=${'johndoe'}
@@ -102,6 +109,7 @@ export const demoFunc = () => html`
.value=${'secret123'} .value=${'secret123'}
.key=${'password'} .key=${'password'}
></dees-input-text> ></dees-input-text>
</div>
</dees-panel> </dees-panel>
</dees-demowrapper> </dees-demowrapper>
@@ -172,6 +180,7 @@ export const demoFunc = () => html`
} }
}}> }}>
<dees-panel .title=${'Label Positions'} .subtitle=${'Different label positioning options for various layouts'}> <dees-panel .title=${'Label Positions'} .subtitle=${'Different label positioning options for various layouts'}>
<div class="input-group">
<dees-input-text <dees-input-text
.label=${'Label on Top (Default)'} .label=${'Label on Top (Default)'}
.value=${'Standard layout'} .value=${'Standard layout'}
@@ -197,6 +206,7 @@ export const demoFunc = () => html`
.labelPosition=${'left'} .labelPosition=${'left'}
></dees-input-text> ></dees-input-text>
</div> </div>
</div>
</dees-panel> </dees-panel>
</dees-demowrapper> </dees-demowrapper>
@@ -234,6 +244,7 @@ export const demoFunc = () => html`
} }
}}> }}>
<dees-panel .title=${'Validation & States'} .subtitle=${'Different validation states and input configurations'}> <dees-panel .title=${'Validation & States'} .subtitle=${'Different validation states and input configurations'}>
<div class="input-group">
<dees-input-text <dees-input-text
.label=${'Required Field'} .label=${'Required Field'}
.required=${true} .required=${true}
@@ -252,6 +263,7 @@ export const demoFunc = () => html`
.validationText=${'Please enter a valid email address'} .validationText=${'Please enter a valid email address'}
.validationState=${'invalid'} .validationState=${'invalid'}
></dees-input-text> ></dees-input-text>
</div>
</dees-panel> </dees-panel>
</dees-demowrapper> </dees-demowrapper>
@@ -279,6 +291,7 @@ export const demoFunc = () => html`
}); });
}}> }}>
<dees-panel .title=${'Advanced Features'} .subtitle=${'Password visibility toggle and other advanced features'}> <dees-panel .title=${'Advanced Features'} .subtitle=${'Password visibility toggle and other advanced features'}>
<div class="input-group">
<dees-input-text <dees-input-text
.label=${'Password with Toggle'} .label=${'Password with Toggle'}
.isPasswordBool=${true} .isPasswordBool=${true}
@@ -292,6 +305,7 @@ export const demoFunc = () => html`
.value=${'sk-1234567890abcdef'} .value=${'sk-1234567890abcdef'}
.description=${'Keep this key secure and never share it'} .description=${'Keep this key secure and never share it'}
></dees-input-text> ></dees-input-text>
</div>
</dees-panel> </dees-panel>
</dees-demowrapper> </dees-demowrapper>

View File

@@ -13,6 +13,12 @@ export const demoFunc = () => html`
margin: 0 auto; margin: 0 auto;
} }
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.horizontal-group { .horizontal-group {
display: flex; display: flex;
gap: 24px; gap: 24px;
@@ -39,6 +45,7 @@ export const demoFunc = () => html`
<div class="demo-container"> <div class="demo-container">
<dees-panel .title=${'Basic Type List'} .subtitle=${'Add and remove items from a list'}> <dees-panel .title=${'Basic Type List'} .subtitle=${'Add and remove items from a list'}>
<div class="input-group">
<dees-input-typelist <dees-input-typelist
.label=${'Tags'} .label=${'Tags'}
.description=${'Add tags by typing and pressing Enter'} .description=${'Add tags by typing and pressing Enter'}
@@ -50,9 +57,11 @@ export const demoFunc = () => html`
.description=${'Add email addresses of team members'} .description=${'Add email addresses of team members'}
.value=${['alice@example.com', 'bob@example.com']} .value=${['alice@example.com', 'bob@example.com']}
></dees-input-typelist> ></dees-input-typelist>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Skills & Keywords'} .subtitle=${'Manage lists of skills and keywords'}> <dees-panel .title=${'Skills & Keywords'} .subtitle=${'Manage lists of skills and keywords'}>
<div class="input-group">
<dees-input-typelist <dees-input-typelist
.label=${'Your Skills'} .label=${'Your Skills'}
.description=${'List your professional skills'} .description=${'List your professional skills'}
@@ -72,9 +81,11 @@ export const demoFunc = () => html`
.value=${['innovation', 'startup', 'growth']} .value=${['innovation', 'startup', 'growth']}
></dees-input-typelist> ></dees-input-typelist>
</div> </div>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Required & Disabled States'} .subtitle=${'Different input states for validation'}> <dees-panel .title=${'Required & Disabled States'} .subtitle=${'Different input states for validation'}>
<div class="input-group">
<dees-input-typelist <dees-input-typelist
.label=${'Project Dependencies'} .label=${'Project Dependencies'}
.description=${'List all required npm packages'} .description=${'List all required npm packages'}
@@ -88,6 +99,7 @@ export const demoFunc = () => html`
.disabled=${true} .disabled=${true}
.value=${['system', 'protected', 'readonly']} .value=${['system', 'protected', 'readonly']}
></dees-input-typelist> ></dees-input-typelist>
</div>
</dees-panel> </dees-panel>
<dees-panel .title=${'Article Publishing Form'} .subtitle=${'Complete form with tag management'}> <dees-panel .title=${'Article Publishing Form'} .subtitle=${'Complete form with tag management'}>