Compare commits

...

9 Commits

Author SHA1 Message Date
bfbc0f108e v3.78.1
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-12 23:33:52 +00:00
bab7528f0b fix(dees-simple-login): use dees-tile for the login credentials container 2026-04-12 23:33:52 +00:00
6047705e7d v3.78.0
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-12 20:33:19 +00:00
ab19b561c4 feat(dees-settings): add dees-settings layout component for displaying read-only settings with footer actions 2026-04-12 20:33:19 +00:00
7ef3613e91 v3.77.0
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-12 20:18:05 +00:00
940eebe29f feat(dees-table): add configurable cell flash comparison and border highlight mode 2026-04-12 20:18:05 +00:00
8ecaffe165 refactor(demos): remove redundant input group styles from demo components 2026-04-12 19:58:01 +00:00
e5cb31ffb1 v3.76.1
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-12 19:04:43 +00:00
7c2635fc13 fix(demo-inputs): wrap input component demos in dees-form containers for consistent form integration 2026-04-12 19:04:43 +00:00
25 changed files with 864 additions and 504 deletions

View File

@@ -1,5 +1,33 @@
# Changelog
## 2026-04-12 - 3.78.1 - fix(dees-simple-login)
use dees-tile for the login credentials container
- replace the custom login card wrapper with a dees-tile component
- update styles to target dees-tile and its content part while preserving form layout
- add a credentials heading to the login tile
## 2026-04-12 - 3.78.0 - feat(dees-settings)
add dees-settings layout component for displaying read-only settings with footer actions
- introduces a new dees-settings element with heading, description, settings field grid, and footer action support
- exports dees-settings from the 00group-layout module index
- adds demo examples covering populated, empty, and multi-action states
## 2026-04-12 - 3.77.0 - feat(dees-table)
add configurable cell flash comparison and border highlight mode
- adds column-level flashCompare support so update highlighting can detect meaningful changes for custom cell values
- adds flashBorder styling for cells with badges, icons, or custom rendered content where text-color flashing is not visible
- avoids false-positive flash animations for non-primitive cell values unless a custom comparator is provided
## 2026-04-12 - 3.76.1 - fix(demo-inputs)
wrap input component demos in dees-form containers for consistent form integration
- Adds dees-form wrappers across multiple input demo pages including checkbox, dropdown, file upload, iban, list, multitoggle, phone, quantity selector, radio group, tags, text, toggle, and typelist demos
- Keeps horizontal and grid example layouts intact while nesting them inside form containers
- Cleans up file upload and text demo markup to better match expected dees-form structure
## 2026-04-12 - 3.76.0 - feat(input)
separate label info tooltips from description text across input components

View File

@@ -1,6 +1,6 @@
{
"name": "@design.estate/dees-catalog",
"version": "3.76.0",
"version": "3.78.1",
"private": false,
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
"main": "dist_ts_web/index.js",

View File

@@ -59,8 +59,8 @@ For developers working on this library, please refer to the [UI Components Playb
| **Forms** | [`DeesForm`](#deesform), [`DeesInputText`](#deesinputtext), [`DeesInputCheckbox`](#deesinputcheckbox), [`DeesInputDropdown`](#deesinputdropdown), [`DeesInputRadiogroup`](#deesinputradiogroup), [`DeesInputFileupload`](#deesinputfileupload), [`DeesInputIban`](#deesinputiban), [`DeesInputPhone`](#deesinputphone), [`DeesInputQuantitySelector`](#deesinputquantityselector), [`DeesInputMultitoggle`](#deesinputmultitoggle), [`DeesInputToggle`](#deesinputtoggle), [`DeesInputTags`](#deesinputtags), [`DeesInputTypelist`](#deesinputtypelist), [`DeesInputList`](#deesinputlist), [`DeesInputProfilepicture`](#deesinputprofilepicture), [`DeesInputRichtext`](#deesinputrichtext), [`DeesInputWysiwyg`](#deesinputwysiwyg), [`DeesInputDatepicker`](#deesinputdatepicker), [`DeesInputSearchselect`](#deesinputsearchselect), [`DeesInputCode`](#deesinputcode), [`DeesFormSubmit`](#deesformsubmit) |
| **App Shell (Layout)** | [`DeesAppui`](#deesappui-), [`DeesAppuiMainmenu`](#deesappuimainmenu), [`DeesAppuiSecondarymenu`](#deesappuisecondarymenu), [`DeesAppuiMaincontent`](#deesappuimaincontent), [`DeesAppuiAppbar`](#deesappuiappbar), [`DeesAppuiActivitylog`](#deesappuiactivitylog), [`DeesAppuiBottombar`](#deesappuibottombar), [`DeesAppuiProfiledropdown`](#deesappuiprofiledropdown), [`DeesAppuiTabs`](#deesappuitabs), [`DeesMobileNavigation`](#deesmobilenavigation), [`DeesDashboardGrid`](#deesdashboardgrid) |
| **Data Display** | [`DeesTable`](#deestable), [`DeesDataviewCodebox`](#deesdataviewcodebox), [`DeesDataviewStatusobject`](#deesdataviewstatusobject), [`DeesPdf`](#deespdf), [`DeesStatsGrid`](#deesstatsgrid), [`DeesPagination`](#deespagination), [`DeesStorageBrowser`](#deesstorgebrowser) |
| **Media & Tiles** | [`DeesTilePdf`](#deestilepdf), [`DeesTileImage`](#deestileimage), [`DeesTileAudio`](#deestileaudio), [`DeesTileVideo`](#deestilevideo), [`DeesTileNote`](#deestilenote), [`DeesTileFolder`](#deestilefolder), [`DeesPreview`](#deespreview), [`DeesPdfViewer`](#deespdfviewer), [`DeesPdfPreview`](#deespdfpreview), [`DeesImageViewer`](#deesimageviewer), [`DeesAudioViewer`](#deesaudioviewer), [`DeesVideoViewer`](#deesvideoviewer) |
| **Visualization** | [`DeesChartArea`](#deeschartarea), [`DeesChartLog`](#deeschartlog) |
| **Media & Thumbnails** | [`DeesThumbnailPdf`](#deesthumbnailpdf), [`DeesThumbnailImage`](#deesthumbnailimage), [`DeesThumbnailAudio`](#deesthumbnailaudio), [`DeesThumbnailVideo`](#deesthumbnalvideo), [`DeesThumbnailNote`](#deesthumbnailnote), [`DeesThumbnailFolder`](#deesthumbnailfolder), [`DeesPreview`](#deespreview), [`DeesPdfViewer`](#deespdfviewer), [`DeesImageViewer`](#deesimageviewer), [`DeesAudioViewer`](#deesaudioviewer), [`DeesVideoViewer`](#deesvideoviewer) |
| **Visualization** | [`DeesChartArea`](#deeschartarea), [`DeesChartBar`](#deeschartbar), [`DeesChartDonut`](#deeschartdonut), [`DeesChartGauge`](#deeschartgauge), [`DeesChartRadar`](#deeschartradar), [`DeesChartLog`](#deeschartlog) |
| **Dialogs & Overlays** | [`DeesModal`](#deesmodal), [`DeesContextmenu`](#deescontextmenu), [`DeesSpeechbubble`](#deesspeechbubble), [`DeesWindowlayer`](#deeswindowlayer) |
| **Navigation** | [`DeesStepper`](#deesstepper), [`DeesProgressbar`](#deesprogressbar) |
| **Workspace / IDE** | [`DeesWorkspace`](#deesworkspace), [`DeesWorkspaceMonaco`](#deesworkspacemonaco), [`DeesWorkspaceDiffEditor`](#deesworkspacediffeditor), [`DeesWorkspaceFiletree`](#deesworkspacefiletree), [`DeesWorkspaceTerminal`](#deesworkspaceterminal), [`DeesWorkspaceTerminalPreview`](#deesworkspaceterminalpreview), [`DeesWorkspaceMarkdown`](#deesworkspacemarkdown), [`DeesWorkspaceMarkdownoutlet`](#deesworkspacemarkdownoutlet), [`DeesWorkspaceBottombar`](#deesworkspacebottombar) |
@@ -143,14 +143,13 @@ Display icons from FontAwesome and Lucide icon libraries with library prefixes.
```
#### `DeesLabel`
Text label component with optional icon and status indicators.
Text label component with optional required indicator and info tooltip. Used internally by all input components.
```typescript
<dees-label
text="Status" // Label text
icon="info-circle" // Optional: icon name
type="info" // Options: default, info, success, warning, error
size="medium" // Options: small, medium, large
.label=${'Email Address'} // Label text
.required=${true} // Optional: shows red asterisk
.infoText=${'We will never share your email'} // Optional: shows hover info icon with tooltip
></dees-label>
```
@@ -321,7 +320,7 @@ Container component for form elements with built-in validation and data handling
```
#### `DeesInputText`
Text input field with validation and formatting options.
Text input field with validation, info tooltips, description text, and context menu (Cut/Copy/Paste/Select All).
```typescript
<dees-input-text
@@ -330,10 +329,20 @@ Text input field with validation and formatting options.
value="initial@value.com" // Initial value
required // Makes the field required
disabled // Disables the input
placeholder="Enter your email"
.infoText=${'Hover icon tooltip text'} // Shows ⓘ icon on label with hover tooltip
.description=${'Permanent help text below the input'} // Small text below the input
.validationFunction=${(value) => { // Auto-validates on every keystroke
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (emailRegex.test(value)) {
return { valid: true, message: 'Email is valid' };
}
return { valid: false, message: 'Please enter a valid email' };
}}
></dees-input-text>
```
> 💡 **All input components** share these common properties from `DeesInputBase`: `key`, `label`, `required`, `disabled`, `infoText`, `description`, `layoutMode`, `labelPosition`.
#### `DeesInputCheckbox`
Checkbox input component for boolean values.
@@ -1780,7 +1789,7 @@ interface ITileFolderItem {
## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./license) file.
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
@@ -1798,5 +1807,3 @@ Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

View File

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

View File

@@ -695,6 +695,7 @@ export class DeesTable<T> extends DeesElement {
this.__editingCell?.rowId === rowId &&
this.__editingCell?.colKey === editKey;
const isFlashing = !!flashSet?.has(editKey);
const useFlashBorder = isFlashing && !!col.flashBorder;
const cellClasses = [
isEditable ? 'editable' : '',
isFocused && !isEditing ? 'focused' : '',
@@ -702,8 +703,13 @@ export class DeesTable<T> extends DeesElement {
]
.filter(Boolean)
.join(' ');
const flashClass = isFlashing
? useFlashBorder
? 'innerCellContainer flashing-border'
: 'innerCellContainer flashing'
: 'innerCellContainer';
const innerHtml = html`<div
class=${isFlashing ? 'innerCellContainer flashing' : 'innerCellContainer'}
class=${flashClass}
>
${isEditing ? this.renderCellEditor(itemArg, col) : content}
</div>`;
@@ -1362,6 +1368,7 @@ export class DeesTable<T> extends DeesElement {
const effectiveColumns = this.__getEffectiveColumns();
const visibleCols = effectiveColumns.filter((c) => !c.hidden);
const colByKey = new Map<string, Column<T>>(visibleCols.map((c) => [String(c.key), c]));
const nextSnapshot = new Map<string, Map<string, unknown>>();
const newlyFlashing = new Map<string, Set<string>>();
@@ -1376,7 +1383,26 @@ export class DeesTable<T> extends DeesElement {
const prevCells = this.__prevSnapshot?.get(rowId);
if (!prevCells) continue; // new row — not an "update"
for (const [colKey, nextVal] of cellMap) {
if (prevCells.get(colKey) !== nextVal) {
const prevVal = prevCells.get(colKey);
// Look up the column definition for flash options.
const colDef = colByKey.get(colKey);
// Determine whether the cell changed.
let changed: boolean;
if (colDef?.flashCompare) {
// Explicit custom comparator — caller decides.
changed = colDef.flashCompare(prevVal, nextVal);
} else if (nextVal !== null && nextVal !== undefined && typeof nextVal === 'object') {
// Non-primitive (TemplateResult, object, array, etc.) — skip by
// default. Custom renderings don't benefit from the text-color
// flash and reference inequality causes false positives.
changed = false;
} else {
changed = prevVal !== nextVal;
}
if (changed) {
// Don't flash the cell the user is actively editing.
if (
this.__editingCell &&

View File

@@ -404,11 +404,44 @@ export const tableStyles: CSSResult[] = [
100% { color: var(--dees-color-text-primary); }
}
/* Border/background flash variant for cells with styled content
(badges, icons, custom components) where a text-color animation
would be invisible. Activated via flashBorder on Column. */
.innerCellContainer.flashing-border {
animation: dees-table-cell-flash-border
var(--dees-table-flash-duration, 900ms)
var(--dees-table-flash-easing);
border-radius: 3px;
}
@keyframes dees-table-cell-flash-border {
0%,
35% {
box-shadow: inset 0 0 0 1.5px var(--dees-table-flash-color);
background: ${cssManager.bdTheme(
'hsl(45 93% 62% / 0.10)',
'hsl(45 93% 62% / 0.08)'
)};
}
100% {
box-shadow: inset 0 0 0 1.5px transparent;
background: transparent;
}
}
@media (prefers-reduced-motion: reduce) {
.innerCellContainer.flashing {
animation: none;
color: var(--dees-table-flash-color);
}
.innerCellContainer.flashing-border {
animation: none;
box-shadow: inset 0 0 0 1.5px var(--dees-table-flash-color);
background: ${cssManager.bdTheme(
'hsl(45 93% 62% / 0.10)',
'hsl(45 93% 62% / 0.08)'
)};
}
}
/* Dev-time warning banner shown when highlight-updates="flash" but

View File

@@ -65,6 +65,25 @@ export interface Column<T = any> {
parse?: (editorValue: any, row: T) => any;
/** Validate the parsed value before commit. Return string for error, true/void for ok. */
validate?: (value: any, row: T) => true | string | void;
// ─── Flash highlight options ───
/**
* Custom comparison for flash-on-update diffing.
* Return `true` if the cell should flash (i.e. the values differ).
* When absent, non-primitive cell values are skipped entirely
* (only strings, numbers, booleans, null, and undefined are diffed).
*/
flashCompare?: (prevVal: any, nextVal: any) => boolean;
/**
* When `true`, flash this cell with a border/background pulse instead of
* the default text-color animation. Useful for cells containing styled
* badges, icons, or custom web-component renderings where a text-color
* change would be invisible.
* @default false
*/
flashBorder?: boolean;
}
/**

View File

@@ -111,90 +111,92 @@ export const demoFunc = () => html`
<div class="demo-container">
<dees-panel .title=${'Basic Checkboxes'} .subtitle=${'Simple checkbox examples with various labels'}>
<div class="checkbox-group">
<dees-input-checkbox
.label=${'I agree to the Terms and Conditions'}
<dees-form>
<dees-input-checkbox
.label=${'I agree to the Terms and Conditions'}
.value=${true}
.key=${'terms'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Subscribe to newsletter'}
<dees-input-checkbox
.label=${'Subscribe to newsletter'}
.value=${false}
.key=${'newsletter'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Enable notifications'}
<dees-input-checkbox
.label=${'Enable notifications'}
.value=${false}
.description=${'Receive email updates about your account'}
.key=${'notifications'}
></dees-input-checkbox>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'Checkbox States'} .subtitle=${'Different checkbox states and configurations'}>
<div class="checkbox-group">
<dees-input-checkbox
.label=${'Default state'}
<dees-form>
<dees-input-checkbox
.label=${'Default state'}
.value=${false}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Checked state'}
<dees-input-checkbox
.label=${'Checked state'}
.value=${true}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Disabled unchecked'}
<dees-input-checkbox
.label=${'Disabled unchecked'}
.value=${false}
.disabled=${true}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Disabled checked'}
<dees-input-checkbox
.label=${'Disabled checked'}
.value=${true}
.disabled=${true}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Required checkbox'}
<dees-input-checkbox
.label=${'Required checkbox'}
.required=${true}
.key=${'required'}
></dees-input-checkbox>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'Horizontal Layout'} .subtitle=${'Checkboxes arranged horizontally for compact forms'}>
<div class="horizontal-checkboxes">
<dees-input-checkbox
.label=${'Option A'}
.value=${false}
.layoutMode=${'horizontal'}
.key=${'optionA'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Option B'}
.value=${true}
.layoutMode=${'horizontal'}
.key=${'optionB'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Option C'}
.value=${false}
.layoutMode=${'horizontal'}
.key=${'optionC'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Option D'}
.value=${true}
.layoutMode=${'horizontal'}
.key=${'optionD'}
></dees-input-checkbox>
</div>
<dees-form>
<div class="horizontal-checkboxes">
<dees-input-checkbox
.label=${'Option A'}
.value=${false}
.layoutMode=${'horizontal'}
.key=${'optionA'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Option B'}
.value=${true}
.layoutMode=${'horizontal'}
.key=${'optionB'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Option C'}
.value=${false}
.layoutMode=${'horizontal'}
.key=${'optionC'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Option D'}
.value=${true}
.layoutMode=${'horizontal'}
.key=${'optionD'}
></dees-input-checkbox>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'Feature Selection Example'} .subtitle=${'Common use case for feature toggles with batch operations'}>
@@ -204,76 +206,76 @@ export const demoFunc = () => html`
</div>
<div class="feature-list">
<div class="checkbox-group">
<dees-input-checkbox
.label=${'Dark Mode Support'}
<dees-form>
<dees-input-checkbox
.label=${'Dark Mode Support'}
.value=${true}
.key=${'feature1'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Email Notifications'}
<dees-input-checkbox
.label=${'Email Notifications'}
.value=${true}
.key=${'feature2'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Two-Factor Authentication'}
<dees-input-checkbox
.label=${'Two-Factor Authentication'}
.value=${false}
.key=${'feature3'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'API Access'}
<dees-input-checkbox
.label=${'API Access'}
.value=${true}
.key=${'feature4'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Advanced Analytics'}
<dees-input-checkbox
.label=${'Advanced Analytics'}
.value=${false}
.key=${'feature5'}
></dees-input-checkbox>
</div>
</dees-form>
</div>
</dees-panel>
<dees-panel .title=${'Privacy Settings Example'} .subtitle=${'Checkboxes in a typical form context'}>
<div class="form-section">
<h4 class="section-title">Privacy Preferences</h4>
<div class="checkbox-group">
<dees-input-checkbox
.label=${'Share analytics data'}
<dees-form>
<dees-input-checkbox
.label=${'Share analytics data'}
.value=${true}
.description=${'Help us improve by sharing anonymous usage data'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Personalized recommendations'}
<dees-input-checkbox
.label=${'Personalized recommendations'}
.value=${true}
.description=${'Get suggestions based on your activity'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Marketing communications'}
<dees-input-checkbox
.label=${'Marketing communications'}
.value=${false}
.description=${'Receive promotional emails and special offers'}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Third-party integrations'}
<dees-input-checkbox
.label=${'Third-party integrations'}
.value=${false}
.description=${'Allow approved partners to access your data'}
></dees-input-checkbox>
</div>
</dees-form>
</div>
</dees-panel>
<dees-panel .title=${'Interactive Example'} .subtitle=${'Click checkboxes to see value changes'}>
<div class="checkbox-group">
<dees-input-checkbox
.label=${'Feature toggle'}
<dees-form>
<dees-input-checkbox
.label=${'Feature toggle'}
.value=${false}
@changeSubject=${(event: CustomEvent) => {
const output = document.querySelector('#checkbox-output');
@@ -283,9 +285,9 @@ export const demoFunc = () => html`
}
}}
></dees-input-checkbox>
<dees-input-checkbox
.label=${'Debug mode'}
<dees-input-checkbox
.label=${'Debug mode'}
.value=${false}
@changeSubject=${(event: CustomEvent) => {
const output = document.querySelector('#debug-output');
@@ -295,8 +297,8 @@ export const demoFunc = () => html`
}
}}
></dees-input-checkbox>
</div>
</dees-form>
<div class="interactive-section">
<div id="checkbox-output" class="output-text">Feature is disabled</div>
<div id="debug-output" class="output-text" style="margin-top: 8px;">Debug mode: OFF</div>

View File

@@ -31,12 +31,6 @@ export const demoFunc = () => html`
flex-wrap: wrap;
}
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.spacer {
height: 200px;
display: flex;
@@ -69,7 +63,7 @@ export const demoFunc = () => html`
}
}}>
<dees-panel .title=${'1. Basic Dropdowns'} .subtitle=${'Standard dropdown with search functionality and various options'}>
<div class="input-group">
<dees-form>
<dees-input-dropdown
.label=${'Select Country'}
.description=${'Choose the country where your business is registered'}
@@ -95,7 +89,7 @@ export const demoFunc = () => html`
{ option: 'Guest', key: 'guest' }
]}
></dees-input-dropdown>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
@@ -136,40 +130,42 @@ export const demoFunc = () => html`
});
}}>
<dees-panel .title=${'3. Horizontal Layout'} .subtitle=${'Multiple dropdowns in a horizontal layout for compact forms'}>
<div class="horizontal-group">
<dees-input-dropdown
.label=${'Department'}
.layoutMode=${'horizontal'}
.options=${[
{ option: 'Engineering', key: 'eng' },
{ option: 'Design', key: 'design' },
{ option: 'Marketing', key: 'marketing' },
{ option: 'Sales', key: 'sales' }
]}
></dees-input-dropdown>
<dees-input-dropdown
.label=${'Team Size'}
.layoutMode=${'horizontal'}
.enableSearch=${false}
.options=${[
{ option: '1-5', key: 'small' },
{ option: '6-20', key: 'medium' },
{ option: '21-50', key: 'large' },
{ option: '50+', key: 'xlarge' }
]}
></dees-input-dropdown>
<dees-input-dropdown
.label=${'Location'}
.layoutMode=${'horizontal'}
.options=${[
{ option: 'Remote', key: 'remote' },
{ option: 'On-site', key: 'onsite' },
{ option: 'Hybrid', key: 'hybrid' }
]}
></dees-input-dropdown>
</div>
<dees-form>
<div class="horizontal-group">
<dees-input-dropdown
.label=${'Department'}
.layoutMode=${'horizontal'}
.options=${[
{ option: 'Engineering', key: 'eng' },
{ option: 'Design', key: 'design' },
{ option: 'Marketing', key: 'marketing' },
{ option: 'Sales', key: 'sales' }
]}
></dees-input-dropdown>
<dees-input-dropdown
.label=${'Team Size'}
.layoutMode=${'horizontal'}
.enableSearch=${false}
.options=${[
{ option: '1-5', key: 'small' },
{ option: '6-20', key: 'medium' },
{ option: '21-50', key: 'large' },
{ option: '50+', key: 'xlarge' }
]}
></dees-input-dropdown>
<dees-input-dropdown
.label=${'Location'}
.layoutMode=${'horizontal'}
.options=${[
{ option: 'Remote', key: 'remote' },
{ option: 'On-site', key: 'onsite' },
{ option: 'Hybrid', key: 'hybrid' }
]}
></dees-input-dropdown>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
@@ -185,7 +181,7 @@ export const demoFunc = () => html`
}
}}>
<dees-panel .title=${'4. States'} .subtitle=${'Different states and configurations'}>
<div class="input-group">
<dees-form>
<dees-input-dropdown
.label=${'Required Field'}
.required=${true}
@@ -204,7 +200,7 @@ export const demoFunc = () => html`
]}
.selectedOption=${{ option: 'Cannot Select', key: 'disabled' }}
></dees-input-dropdown>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>

View File

@@ -55,41 +55,43 @@ export const demoFunc = () => html`
.title=${'Modern file uploader'}
.subtitle=${'Shadcn-inspired layout with drag & drop, previews and validation'}
>
<div class="demo-grid demo-grid--two">
<div class="demo-stack">
<dees-input-fileupload
.label=${'Attachments'}
.infoText=${'Upload supporting documents for your request'}
.description=${'Accepted formats: images, PDF, and ZIP archives up to 10MB'}
.accept=${'image/*,.pdf,.zip'}
.maxSize=${10 * 1024 * 1024}
></dees-input-fileupload>
<dees-form>
<div class="demo-grid demo-grid--two">
<div class="demo-stack">
<dees-input-fileupload
.label=${'Attachments'}
.infoText=${'Upload supporting documents for your request'}
.description=${'Accepted formats: images, PDF, and ZIP archives up to 10MB'}
.accept=${'image/*,.pdf,.zip'}
.maxSize=${10 * 1024 * 1024}
></dees-input-fileupload>
<dees-input-fileupload
.label=${'Brand assets'}
.infoText=${'Upload high-resolution imagery (JPG/PNG)'}
.accept=${'image/jpeg,image/png'}
.multiple=${false}
.maxSize=${5 * 1024 * 1024}
.buttonText=${'Select cover image'}
></dees-input-fileupload>
<dees-input-fileupload
.label=${'Brand assets'}
.infoText=${'Upload high-resolution imagery (JPG/PNG)'}
.accept=${'image/jpeg,image/png'}
.multiple=${false}
.maxSize=${5 * 1024 * 1024}
.buttonText=${'Select cover image'}
></dees-input-fileupload>
</div>
<div class="demo-stack">
<dees-input-fileupload
.label=${'Audio uploads'}
.infoText=${'Share podcast drafts (MP3/WAV, max 25MB each)'}
.accept=${'audio/*'}
.maxSize=${25 * 1024 * 1024}
></dees-input-fileupload>
<dees-input-fileupload
.label=${'Disabled example'}
.infoText=${'Uploader is disabled while moderation is pending'}
.disabled=${true}
></dees-input-fileupload>
</div>
</div>
<div class="demo-stack">
<dees-input-fileupload
.label=${'Audio uploads'}
.infoText=${'Share podcast drafts (MP3/WAV, max 25MB each)'}
.accept=${'audio/*'}
.maxSize=${25 * 1024 * 1024}
></dees-input-fileupload>
<dees-input-fileupload
.label=${'Disabled example'}
.infoText=${'Uploader is disabled while moderation is pending'}
.disabled=${true}
></dees-input-fileupload>
</div>
</div>
</dees-form>
</dees-panel>
<dees-panel
@@ -98,7 +100,6 @@ export const demoFunc = () => html`
>
<div class="demo-grid">
<dees-form>
<div class="demo-stack">
<dees-input-text
.label=${'Project name'}
.infoText=${'How should we refer to this project internally?'}
@@ -140,7 +141,6 @@ export const demoFunc = () => html`
></dees-input-text>
<dees-form-submit .text=${'Submit briefing'}></dees-form-submit>
</div>
</dees-form>
<div class="demo-note">

View File

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

View File

@@ -109,25 +109,27 @@ export const demoFunc = () => html`
</dees-panel>
<dees-panel .title=${'3. Validation & Constraints'} .subtitle=${'Lists with minimum/maximum items and duplicate prevention'}>
<div class="grid-layout">
<dees-input-list
.label=${'Team Members (Min 2, Max 5)'}
.placeholder=${'Add team member...'}
.minItems=${2}
.maxItems=${5}
.value=${['Alice', 'Bob']}
.required=${true}
.description=${'Add 2-5 team members'}
></dees-input-list>
<dees-input-list
.label=${'Unique Tags (No Duplicates)'}
.placeholder=${'Add unique tag...'}
.allowDuplicates=${false}
.value=${['frontend', 'backend', 'database']}
.description=${'Duplicate items are not allowed'}
></dees-input-list>
</div>
<dees-form>
<div class="grid-layout">
<dees-input-list
.label=${'Team Members (Min 2, Max 5)'}
.placeholder=${'Add team member...'}
.minItems=${2}
.maxItems=${5}
.value=${['Alice', 'Bob']}
.required=${true}
.description=${'Add 2-5 team members'}
></dees-input-list>
<dees-input-list
.label=${'Unique Tags (No Duplicates)'}
.placeholder=${'Add unique tag...'}
.allowDuplicates=${false}
.value=${['frontend', 'backend', 'database']}
.description=${'Duplicate items are not allowed'}
></dees-input-list>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'4. Delete Confirmation'} .subtitle=${'Require confirmation before deleting items'}>

View File

@@ -52,81 +52,83 @@ export const demoFunc = () => html`
<div class="section">
<div class="section-title">Multi-Option Toggle</div>
<div class="section-description">Select from multiple options with a smooth sliding indicator animation.</div>
<dees-input-multitoggle
.label=${'Display Mode'}
.infoText=${'Choose how content is displayed'}
.description=${'This setting affects how items appear on your dashboard'}
.options=${['List View', 'Grid View', 'Compact']}
.selectedOption=${'Grid View'}
></dees-input-multitoggle>
<br><br>
<dees-input-multitoggle
.label=${'T-Shirt Size'}
.infoText=${'Select your preferred size'}
.options=${['XS', 'S', 'M', 'L', 'XL', 'XXL']}
.selectedOption=${'M'}
></dees-input-multitoggle>
<dees-form>
<dees-input-multitoggle
.label=${'Display Mode'}
.infoText=${'Choose how content is displayed'}
.description=${'This setting affects how items appear on your dashboard'}
.options=${['List View', 'Grid View', 'Compact']}
.selectedOption=${'Grid View'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'T-Shirt Size'}
.infoText=${'Select your preferred size'}
.options=${['XS', 'S', 'M', 'L', 'XL', 'XXL']}
.selectedOption=${'M'}
></dees-input-multitoggle>
</dees-form>
</div>
<div class="section">
<div class="section-title">Boolean Toggle</div>
<div class="section-description">Simple on/off switches with customizable labels for clearer context.</div>
<dees-input-multitoggle
.label=${'Notifications'}
.infoText=${'Enable or disable push notifications'}
.type=${'boolean'}
.selectedOption=${'true'}
></dees-input-multitoggle>
<br><br>
<dees-input-multitoggle
.label=${'Theme Mode'}
.infoText=${'Switch between light and dark theme'}
.type=${'boolean'}
.booleanTrueName=${'Dark'}
.booleanFalseName=${'Light'}
.selectedOption=${'Dark'}
></dees-input-multitoggle>
<dees-form>
<dees-input-multitoggle
.label=${'Notifications'}
.infoText=${'Enable or disable push notifications'}
.type=${'boolean'}
.selectedOption=${'true'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'Theme Mode'}
.infoText=${'Switch between light and dark theme'}
.type=${'boolean'}
.booleanTrueName=${'Dark'}
.booleanFalseName=${'Light'}
.selectedOption=${'Dark'}
></dees-input-multitoggle>
</dees-form>
</div>
<div class="section">
<div class="section-title">Settings Grid</div>
<div class="section-description">Configuration options arranged in a responsive grid layout.</div>
<div class="settings-grid">
<dees-input-multitoggle
.label=${'Auto-Save'}
.type=${'boolean'}
.booleanTrueName=${'Enabled'}
.booleanFalseName=${'Disabled'}
.selectedOption=${'Enabled'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'Language'}
.options=${['English', 'German', 'French', 'Spanish']}
.selectedOption=${'English'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'Quality'}
.options=${['Low', 'Medium', 'High', 'Ultra']}
.selectedOption=${'High'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'Privacy'}
.type=${'boolean'}
.booleanTrueName=${'Private'}
.booleanFalseName=${'Public'}
.selectedOption=${'Private'}
></dees-input-multitoggle>
</div>
<dees-form>
<div class="settings-grid">
<dees-input-multitoggle
.label=${'Auto-Save'}
.type=${'boolean'}
.booleanTrueName=${'Enabled'}
.booleanFalseName=${'Disabled'}
.selectedOption=${'Enabled'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'Language'}
.options=${['English', 'German', 'French', 'Spanish']}
.selectedOption=${'English'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'Quality'}
.options=${['Low', 'Medium', 'High', 'Ultra']}
.selectedOption=${'High'}
></dees-input-multitoggle>
<dees-input-multitoggle
.label=${'Privacy'}
.type=${'boolean'}
.booleanTrueName=${'Private'}
.booleanFalseName=${'Public'}
.selectedOption=${'Private'}
></dees-input-multitoggle>
</div>
</dees-form>
</div>
<div class="section">

View File

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

View File

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

View File

@@ -23,12 +23,6 @@ export const demoFunc = () => html`
margin-bottom: 0;
}
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.demo-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
@@ -48,25 +42,27 @@ export const demoFunc = () => html`
<div class="demo-container">
<dees-panel .title=${'1. Basic Radio Groups'} .subtitle=${'Simple string options for common use cases'}>
<div class="demo-grid">
<dees-input-radiogroup
.label=${'Subscription Plan'}
.options=${['Basic - $9/month', 'Pro - $29/month', 'Enterprise - $99/month']}
.selectedOption=${'Pro - $29/month'}
.description=${'Choose your subscription tier'}
></dees-input-radiogroup>
<dees-input-radiogroup
.label=${'Priority Level'}
.options=${['High', 'Medium', 'Low']}
.selectedOption=${'Medium'}
.required=${true}
></dees-input-radiogroup>
</div>
<dees-form>
<div class="demo-grid">
<dees-input-radiogroup
.label=${'Subscription Plan'}
.options=${['Basic - $9/month', 'Pro - $29/month', 'Enterprise - $99/month']}
.selectedOption=${'Pro - $29/month'}
.description=${'Choose your subscription tier'}
></dees-input-radiogroup>
<dees-input-radiogroup
.label=${'Priority Level'}
.options=${['High', 'Medium', 'Low']}
.selectedOption=${'Medium'}
.required=${true}
></dees-input-radiogroup>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'2. Horizontal Layout'} .subtitle=${'Radio groups with horizontal arrangement'}>
<div class="input-group">
<dees-form>
<dees-input-radiogroup
.label=${'Do you agree with the terms?'}
.options=${['Yes', 'No', 'Maybe']}
@@ -81,7 +77,7 @@ export const demoFunc = () => html`
.selectedOption=${'Intermediate'}
.description=${'Select your experience level with web development'}
></dees-input-radiogroup>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'3. Advanced Options'} .subtitle=${'Using object format with keys and payloads'}>
@@ -106,41 +102,45 @@ export const demoFunc = () => html`
</dees-panel>
<dees-panel .title=${'4. Survey Example'} .subtitle=${'Multiple radio groups for surveys and forms'}>
<div class="demo-grid">
<dees-input-radiogroup
.label=${'How satisfied are you?'}
.options=${['Very Satisfied', 'Satisfied', 'Neutral', 'Dissatisfied', 'Very Dissatisfied']}
.selectedOption=${'Satisfied'}
></dees-input-radiogroup>
<dees-input-radiogroup
.label=${'Would you recommend us?'}
.options=${['Definitely', 'Probably', 'Not Sure', 'Probably Not', 'Definitely Not']}
.selectedOption=${'Probably'}
></dees-input-radiogroup>
</div>
<dees-form>
<div class="demo-grid">
<dees-input-radiogroup
.label=${'How satisfied are you?'}
.options=${['Very Satisfied', 'Satisfied', 'Neutral', 'Dissatisfied', 'Very Dissatisfied']}
.selectedOption=${'Satisfied'}
></dees-input-radiogroup>
<dees-input-radiogroup
.label=${'Would you recommend us?'}
.options=${['Definitely', 'Probably', 'Not Sure', 'Probably Not', 'Definitely Not']}
.selectedOption=${'Probably'}
></dees-input-radiogroup>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'5. States & Validation'} .subtitle=${'Different states and validation examples'}>
<div class="demo-grid">
<dees-input-radiogroup
.label=${'Required Selection'}
.options=${['Option A', 'Option B', 'Option C']}
.required=${true}
.description=${'This field is required'}
></dees-input-radiogroup>
<dees-input-radiogroup
.label=${'Disabled State'}
.options=${['Disabled Option 1', 'Disabled Option 2', 'Disabled Option 3']}
.selectedOption=${'Disabled Option 2'}
.disabled=${true}
></dees-input-radiogroup>
</div>
<dees-form>
<div class="demo-grid">
<dees-input-radiogroup
.label=${'Required Selection'}
.options=${['Option A', 'Option B', 'Option C']}
.required=${true}
.description=${'This field is required'}
></dees-input-radiogroup>
<dees-input-radiogroup
.label=${'Disabled State'}
.options=${['Disabled Option 1', 'Disabled Option 2', 'Disabled Option 3']}
.selectedOption=${'Disabled Option 2'}
.disabled=${true}
></dees-input-radiogroup>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'6. Settings Example'} .subtitle=${'Common patterns in application settings'}>
<div class="input-group">
<dees-form>
<dees-input-radiogroup
.label=${'Theme Preference'}
.options=${[
@@ -165,7 +165,7 @@ export const demoFunc = () => html`
.selectedOption=${'English'}
.direction=${'horizontal'}
></dees-input-radiogroup>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'7. Form Integration'} .subtitle=${'Works seamlessly with dees-form'}>

View File

@@ -115,24 +115,26 @@ export const demoFunc = () => html`
</dees-panel>
<dees-panel .title=${'3. Limited Tags'} .subtitle=${'Restrict the number of tags users can add'}>
<div class="grid-layout">
<dees-input-tags
.label=${'Top 3 Skills'}
.placeholder=${'Add up to 3 skills...'}
.maxTags=${3}
.value=${['Design', 'Development']}
.description=${'Maximum 3 tags allowed'}
></dees-input-tags>
<dees-input-tags
.label=${'Categories (Max 5)'}
.placeholder=${'Select categories...'}
.maxTags=${5}
.suggestions=${['Blog', 'Tutorial', 'News', 'Review', 'Guide', 'Case Study', 'Interview']}
.value=${['Tutorial', 'Guide']}
.description=${'Choose up to 5 categories'}
></dees-input-tags>
</div>
<dees-form>
<div class="grid-layout">
<dees-input-tags
.label=${'Top 3 Skills'}
.placeholder=${'Add up to 3 skills...'}
.maxTags=${3}
.value=${['Design', 'Development']}
.description=${'Maximum 3 tags allowed'}
></dees-input-tags>
<dees-input-tags
.label=${'Categories (Max 5)'}
.placeholder=${'Select categories...'}
.maxTags=${5}
.suggestions=${['Blog', 'Tutorial', 'News', 'Review', 'Guide', 'Case Study', 'Interview']}
.value=${['Tutorial', 'Guide']}
.description=${'Choose up to 5 categories'}
></dees-input-tags>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'4. Required & Validation'} .subtitle=${'Tags input with validation requirements'}>

View File

@@ -30,12 +30,6 @@ export const demoFunc = () => html`
flex-wrap: wrap;
}
.input-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.grid-layout {
display: grid;
grid-template-columns: 1fr 1fr;
@@ -89,7 +83,7 @@ export const demoFunc = () => html`
}
}}>
<dees-panel .title=${'Basic Text Inputs'} .subtitle=${'Standard text inputs with labels and descriptions'}>
<div class="input-group">
<dees-form>
<dees-input-text
.label=${'Username'}
.value=${'johndoe'}
@@ -110,7 +104,7 @@ export const demoFunc = () => html`
.value=${'secret123'}
.key=${'password'}
></dees-input-text>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
@@ -140,28 +134,30 @@ export const demoFunc = () => html`
}
}}>
<dees-panel .title=${'Horizontal Layout'} .subtitle=${'Multiple inputs arranged horizontally for compact forms'}>
<div class="horizontal-group">
<dees-input-text
.label=${'First Name'}
.value=${'John'}
.layoutMode=${'horizontal'}
.key=${'firstName'}
></dees-input-text>
<dees-input-text
.label=${'Last Name'}
.value=${'Doe'}
.layoutMode=${'horizontal'}
.key=${'lastName'}
></dees-input-text>
<dees-input-text
.label=${'Age'}
.value=${'28'}
.layoutMode=${'horizontal'}
.key=${'age'}
></dees-input-text>
</div>
<dees-form>
<div class="horizontal-group">
<dees-input-text
.label=${'First Name'}
.value=${'John'}
.layoutMode=${'horizontal'}
.key=${'firstName'}
></dees-input-text>
<dees-input-text
.label=${'Last Name'}
.value=${'Doe'}
.layoutMode=${'horizontal'}
.key=${'lastName'}
></dees-input-text>
<dees-input-text
.label=${'Age'}
.value=${'28'}
.layoutMode=${'horizontal'}
.key=${'age'}
></dees-input-text>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
@@ -181,7 +177,7 @@ export const demoFunc = () => html`
}
}}>
<dees-panel .title=${'Label Positions'} .subtitle=${'Different label positioning options for various layouts'}>
<div class="input-group">
<dees-form>
<dees-input-text
.label=${'Label on Top (Default)'}
.value=${'Standard layout'}
@@ -195,25 +191,25 @@ export const demoFunc = () => html`
></dees-input-text>
<div class="grid-layout">
<dees-input-text
.label=${'City'}
.value=${'New York'}
<dees-input-text
.label=${'City'}
.value=${'New York'}
.labelPosition=${'left'}
></dees-input-text>
<dees-input-text
.label=${'ZIP Code'}
.value=${'10001'}
.labelPosition=${'left'}
></dees-input-text>
</div>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
<dees-demowrapper>
<dees-panel .title=${'Validation & States'} .subtitle=${'Different validation states and input configurations'}>
<div class="input-group">
<dees-form>
<dees-input-text
.label=${'Required Field'}
.required=${true}
@@ -237,7 +233,7 @@ export const demoFunc = () => html`
return { valid: false, message: 'Please enter a valid email address' };
}}
></dees-input-text>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
@@ -266,7 +262,7 @@ export const demoFunc = () => html`
});
}}>
<dees-panel .title=${'Advanced Features'} .subtitle=${'Password visibility toggle and other advanced features'}>
<div class="input-group">
<dees-form>
<dees-input-text
.label=${'Password with Toggle'}
.isPasswordBool=${true}
@@ -280,7 +276,7 @@ export const demoFunc = () => html`
.value=${'sk-1234567890abcdef'}
.infoText=${'Keep this key secure and never share it'}
></dees-input-text>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>

View File

@@ -116,7 +116,7 @@ export const demoFunc = () => html`
<div class="demo-container">
<dees-panel .title=${'Basic Toggle'} .subtitle=${'Simple on/off toggle switch with drag support'}>
<div class="toggle-group">
<dees-form>
<dees-input-toggle
.label=${'Enable feature'}
.value=${false}
@@ -135,12 +135,12 @@ export const demoFunc = () => html`
.description=${'This toggle has additional helper text explaining its purpose'}
.key=${'withDesc'}
></dees-input-toggle>
</div>
</dees-form>
<p class="drag-hint">Tip: You can drag the toggle knob to switch states</p>
</dees-panel>
<dees-panel .title=${'Toggle States'} .subtitle=${'Different toggle states and configurations'}>
<div class="toggle-group">
<dees-form>
<dees-input-toggle
.label=${'Default (off)'}
.value=${false}
@@ -169,42 +169,44 @@ export const demoFunc = () => html`
.required=${true}
.description=${'This toggle cannot be turned off'}
></dees-input-toggle>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'Horizontal Layout'} .subtitle=${'Toggles arranged horizontally for compact interfaces'}>
<div class="horizontal-toggles">
<dees-input-toggle
.label=${'WiFi'}
.value=${true}
.layoutMode=${'horizontal'}
></dees-input-toggle>
<dees-form>
<div class="horizontal-toggles">
<dees-input-toggle
.label=${'WiFi'}
.value=${true}
.layoutMode=${'horizontal'}
></dees-input-toggle>
<dees-input-toggle
.label=${'Bluetooth'}
.value=${false}
.layoutMode=${'horizontal'}
></dees-input-toggle>
<dees-input-toggle
.label=${'Bluetooth'}
.value=${false}
.layoutMode=${'horizontal'}
></dees-input-toggle>
<dees-input-toggle
.label=${'GPS'}
.value=${true}
.layoutMode=${'horizontal'}
></dees-input-toggle>
<dees-input-toggle
.label=${'GPS'}
.value=${true}
.layoutMode=${'horizontal'}
></dees-input-toggle>
<dees-input-toggle
.label=${'NFC'}
.value=${false}
.layoutMode=${'horizontal'}
></dees-input-toggle>
</div>
<dees-input-toggle
.label=${'NFC'}
.value=${false}
.layoutMode=${'horizontal'}
></dees-input-toggle>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'Settings Example'} .subtitle=${'Toggles in a typical settings context'}>
<div class="settings-section">
<h4 class="section-title">Notification Settings</h4>
<div class="toggle-group">
<dees-form>
<dees-input-toggle
.label=${'Push notifications'}
.value=${true}
@@ -232,7 +234,7 @@ export const demoFunc = () => html`
.description=${'Vibrate for notifications'}
.key=${'vibration'}
></dees-input-toggle>
</div>
</dees-form>
</div>
</dees-panel>
@@ -243,7 +245,7 @@ export const demoFunc = () => html`
</div>
<div class="feature-toggles">
<div class="toggle-group">
<dees-form>
<dees-input-toggle
.label=${'Dark Mode'}
.value=${true}
@@ -273,12 +275,12 @@ export const demoFunc = () => html`
.value=${false}
.key=${'beta'}
></dees-input-toggle>
</div>
</dees-form>
</div>
</dees-panel>
<dees-panel .title=${'Interactive Example'} .subtitle=${'Toggle to see value changes in real-time'}>
<div class="toggle-group">
<dees-form>
<dees-input-toggle
.label=${'Airplane mode'}
.value=${false}
@@ -300,7 +302,7 @@ export const demoFunc = () => html`
}
}}
></dees-input-toggle>
</div>
</dees-form>
<div class="interactive-section">
<div id="airplane-output" class="output-text">Airplane mode: OFF</div>

View File

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

View File

@@ -0,0 +1,65 @@
import { html, css, cssManager } from '@design.estate/dees-element';
import './dees-settings.js';
import type { ISettingsField, ISettingsAction } from './dees-settings.js';
export const demoFunc = () => {
const acmeFields: ISettingsField[] = [
{ key: 'email', label: 'Account email', value: 'admin@example.com' },
{ key: 'status', label: 'Status', value: 'enabled' },
{ key: 'mode', label: 'Mode', value: 'production' },
{ key: 'autoRenew', label: 'Auto-renew', value: 'on' },
{ key: 'threshold', label: 'Renewal threshold', value: '30 days' },
];
const acmeActions: ISettingsAction[] = [
{ name: 'Edit', action: () => console.log('Edit clicked') },
];
const emptyActions: ISettingsAction[] = [
{ name: 'Configure', action: () => console.log('Configure clicked') },
];
const multiActions: ISettingsAction[] = [
{ name: 'Reset', action: () => console.log('Reset clicked') },
{ name: 'Edit', action: () => console.log('Edit clicked') },
];
return html`
<dees-demowrapper>
<style>
${css`
.demoBox {
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 9%)')};
padding: 40px;
display: flex;
flex-direction: column;
gap: 24px;
max-width: 600px;
}
`}
</style>
<div class="demoBox">
<dees-settings
.heading=${'ACME Settings'}
.settingsFields=${acmeFields}
.actions=${acmeActions}
></dees-settings>
<dees-settings
.heading=${'ACME Settings'}
.description=${'No ACME configuration yet. Click Configure to set up automated TLS certificate issuance.'}
.actions=${emptyActions}
></dees-settings>
<dees-settings
.heading=${'Server Config'}
.settingsFields=${[
{ key: 'host', label: 'Hostname', value: 'proxy.example.com' },
{ key: 'port', label: 'Port', value: '443' },
]}
.actions=${multiActions}
></dees-settings>
</div>
</dees-demowrapper>
`;
};

View File

@@ -0,0 +1,196 @@
import {
customElement,
DeesElement,
html,
css,
cssManager,
property,
type TemplateResult,
} from '@design.estate/dees-element';
import { demoFunc } from './dees-settings.demo.js';
import { cssGeistFontFamily } from '../../00fonts.js';
import { themeDefaultStyles } from '../../00theme.js';
import '../../00group-layout/dees-tile/dees-tile.js';
declare global {
interface HTMLElementTagNameMap {
'dees-settings': DeesSettings;
}
}
export interface ISettingsField {
key: string;
label: string;
value: string | TemplateResult;
}
export interface ISettingsAction {
name: string;
action: () => void | Promise<void>;
}
/**
* dees-settings — a read-only settings display tile with modal-style footer actions.
*
* Renders a dees-tile with a heading, a grid of label/value fields,
* and a footer action bar. When an action is clicked the component
* dispatches a `settings-action` CustomEvent with the action name.
*/
@customElement('dees-settings')
export class DeesSettings extends DeesElement {
public static demo = demoFunc;
public static demoGroups = ['Layout'];
@property({ type: String })
accessor heading: string = '';
@property({ type: String })
accessor description: string = '';
@property({ attribute: false })
accessor settingsFields: ISettingsField[] = [];
@property({ attribute: false })
accessor actions: ISettingsAction[] = [];
public static styles = [
themeDefaultStyles,
cssManager.defaultStyles,
css`
:host {
display: block;
font-family: ${cssGeistFontFamily};
}
.settingsGrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px 24px;
padding: 16px;
}
.settingsField {
display: flex;
flex-direction: column;
gap: 2px;
}
.fieldLabel {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.03em;
color: var(--dees-color-text-muted);
}
.fieldValue {
font-size: 13px;
color: var(--dees-color-text-primary);
}
.settingsDescription {
padding: 16px;
font-size: 13px;
line-height: 1.5;
color: var(--dees-color-text-muted);
}
.bottomButtons {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
gap: 0;
height: 36px;
width: 100%;
box-sizing: border-box;
}
.bottomButtons .bottomButton {
padding: 0 16px;
height: 100%;
text-align: center;
font-size: 12px;
font-weight: 500;
cursor: pointer;
user-select: none;
transition: all 0.15s ease;
background: transparent;
border: none;
border-left: 1px solid var(--dees-color-border-subtle);
color: var(--dees-color-text-muted);
white-space: nowrap;
display: flex;
align-items: center;
}
.bottomButtons .bottomButton:first-child {
border-left: none;
}
.bottomButtons .bottomButton:hover {
background: var(--dees-color-hover);
color: var(--dees-color-text-primary);
}
.bottomButtons .bottomButton:active {
background: ${cssManager.bdTheme('hsl(0 0% 92%)', 'hsl(0 0% 13%)')};
}
.bottomButtons .bottomButton.primary {
color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
font-weight: 600;
}
.bottomButtons .bottomButton.primary:hover {
background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
}
.bottomButtons .bottomButton.primary:active {
background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.15)', 'hsl(213.1 93.9% 67.8% / 0.15)')};
}
`,
];
public render(): TemplateResult {
const hasFields = this.settingsFields.length > 0;
const hasActions = this.actions.length > 0;
return html`
<dees-tile .heading=${this.heading}>
${hasFields
? html`
<div class="settingsGrid">
${this.settingsFields.map(
(field) => html`
<div class="settingsField">
<span class="fieldLabel">${field.label}</span>
<span class="fieldValue">${field.value}</span>
</div>
`,
)}
</div>
`
: html`
<div class="settingsDescription">${this.description}</div>
`}
${hasActions
? html`
<div slot="footer" class="bottomButtons">
${this.actions.map(
(actionArg, index) => html`
<div
class="bottomButton ${index === this.actions.length - 1 ? 'primary' : ''}"
@click=${() => actionArg.action()}
>
${actionArg.name}
</div>
`,
)}
</div>
`
: ''}
</dees-tile>
`;
}
}

View File

@@ -0,0 +1 @@
export * from './dees-settings.js';

View File

@@ -5,5 +5,6 @@ export * from './dees-heading/index.js';
export * from './dees-label/index.js';
export * from './dees-pagination/index.js';
export * from './dees-panel/index.js';
export * from './dees-settings/index.js';
export * from './dees-stepper/index.js';
export * from './dees-tile/index.js';

View File

@@ -10,6 +10,7 @@ import {
css,
} from '@design.estate/dees-element';
import { themeDefaultStyles } from '../../00theme.js';
import '../../00group-layout/dees-tile/dees-tile.js';
declare global {
interface HTMLElementTagNameMap {
@@ -90,24 +91,25 @@ export class DeesSimpleLogin extends DeesElement {
color: var(--dees-color-text-muted);
}
.login-card {
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 8px;
dees-tile {
width: 100%;
}
dees-tile::part(content) {
padding: 24px;
}
.login-card dees-form {
dees-tile dees-form {
display: flex;
flex-direction: column;
gap: 16px;
}
.login-card dees-input-text {
dees-tile dees-input-text {
width: 100%;
}
.login-card dees-form-submit {
dees-tile dees-form-submit {
margin-top: 8px;
width: 100%;
}
@@ -122,13 +124,13 @@ export class DeesSimpleLogin extends DeesElement {
<div class="header">Sign in</div>
<div class="subheader">Enter your credentials to access ${this.name}</div>
</div>
<div class="login-card">
<dees-tile .heading=${'Credentials'}>
<dees-form>
<dees-input-text key="username" label="Username" required></dees-input-text>
<dees-input-text key="password" label="Password" isPasswordBool required></dees-input-text>
<dees-form-submit>Sign in</dees-form-submit>
</dees-form>
</div>
</dees-tile>
</div>
</div>
<div class="slotContainer">