Compare commits

...

11 Commits

Author SHA1 Message Date
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
eb3d396c68 v3.76.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 18:50:54 +00:00
13ba5670f0 feat(input): separate label info tooltips from description text across input components 2026-04-12 18:50:54 +00:00
961b811b7a v3.75.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 17:45:33 +00:00
cd491e1517 feat(dees-tile): add configurable overscroll handling to tile content and use it in modals 2026-04-12 17:45:33 +00:00
50 changed files with 982 additions and 622 deletions

View File

@@ -1 +0,0 @@
{"sessionId":"4b0f0a7f-f187-40a3-a38b-cb9a7e877011","pid":3110692,"acquiredAt":1775914414249}

View File

@@ -1,5 +1,40 @@
# Changelog
## 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
- adds a dedicated infoText property for dees-label tooltips while keeping description available for helper text rendered below inputs
- introduces a shared renderDescription() helper in the input base component and updates multiple input components to use the unified description styling
- updates demos and consuming components to migrate tooltip content from description to infoText where appropriate
## 2026-04-12 - 3.75.0 - feat(dees-tile)
add configurable overscroll handling to tile content and use it in modals
- introduces a reflected overscroll property on dees-tile with contain, auto, and none options
- moves tile content scrolling and scrollbar styling into dees-tile instead of modal-specific styling
- updates dees-modal to enable contained overscroll through the new dees-tile API
## 2026-04-12 - 3.74.2 - fix(modal,tile,input-text)
move scroll handling from tile content to modal and update input text demo to use changeSubject subscriptions

View File

@@ -1,6 +1,6 @@
{
"name": "@design.estate/dees-catalog",
"version": "3.74.2",
"version": "3.78.0",
"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.74.2',
version: '3.78.0',
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
}

View File

@@ -610,26 +610,26 @@ export class DeesTable<T> extends DeesElement {
<div class="searchGrid hidden">
<dees-input-text
.label=${'lucene syntax search'}
.description=${`
.infoText=${`
You can use the lucene syntax to search for data, e.g.:
\`\`\`
name: "john" AND age: 18
\`\`\`
`}
></dees-input-text>
<dees-input-multitoggle
.label=${'search mode'}
.options=${['table', 'data', 'server']}
.selectedOption=${'table'}
.description=${`
.infoText=${`
There are three basic modes:
* table: only searches data already in the table
* data: searches original data, ignoring table transforms
* server: searches data on the server
`}
></dees-input-multitoggle>
</div>
@@ -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

@@ -92,7 +92,7 @@ export const demoFunc = () => html`
.required=${true}
key="firstName"
label="First Name"
.description=${'Your given name'}
.infoText=${'Your given name'}
></dees-input-text>
<dees-input-text
@@ -105,7 +105,7 @@ export const demoFunc = () => html`
.required=${true}
key="email"
label="Email Address"
.description=${'We will use this to contact you'}
.infoText=${'We will use this to contact you'}
></dees-input-text>
<dees-input-dropdown
@@ -126,7 +126,7 @@ export const demoFunc = () => html`
key="password"
label="Password"
isPasswordBool
.description=${'Minimum 8 characters'}
.infoText=${'Minimum 8 characters'}
></dees-input-text>
<dees-input-checkbox
@@ -300,7 +300,7 @@ export const demoFunc = () => html`
<dees-input-fileupload
key="documents"
.label=${'Upload Documents'}
.description=${'PDF, DOC, or DOCX files up to 10MB'}
.infoText=${'PDF, DOC, or DOCX files up to 10MB'}
></dees-input-fileupload>
<dees-form-submit>Submit Application</dees-form-submit>

View File

@@ -1,6 +1,7 @@
import {
DeesElement,
property,
html,
css,
type CSSResult,
cssManager,
@@ -42,6 +43,9 @@ export abstract class DeesInputBase<T = any> extends DeesElement {
@property({ type: Boolean })
accessor disabled: boolean = false;
@property({ type: String })
accessor infoText!: string;
@property({ type: String })
accessor description!: string;
@@ -90,6 +94,14 @@ export abstract class DeesInputBase<T = any> extends DeesElement {
:host([label-position="none"]) dees-label {
display: none;
}
/* Description text below input */
.descriptionText {
margin-top: 4px;
font-size: 12px;
line-height: 1.4;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
}
`,
];
}
@@ -155,6 +167,14 @@ export abstract class DeesInputBase<T = any> extends DeesElement {
this.disabled = false;
}
/**
* Renders the description text below the input.
* Call ${this.renderDescription()} at the end of your render template.
*/
public renderDescription() {
return this.description ? html`<div class="descriptionText">${this.description}</div>` : '';
}
/**
* Abstract method that child classes must implement to get their value
*/

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

@@ -147,12 +147,6 @@ export class DeesInputCheckbox extends DeesInputBase<DeesInputCheckbox> {
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
}
/* Description */
.description-text {
font-size: 12px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
line-height: 1.5;
}
`,
];
@@ -185,7 +179,7 @@ export class DeesInputCheckbox extends DeesInputBase<DeesInputCheckbox> {
</div>
<div class="label-container">
${this.label ? html`<div class="checkbox-label">${this.label}</div>` : ''}
${this.description ? html`<div class="description-text">${this.description}</div>` : ''}
${this.renderDescription()}
</div>
</div>
</div>

View File

@@ -284,7 +284,7 @@ export class DeesInputCode extends DeesInputBase<string> {
}
</style>
<div class="input-wrapper">
<dees-label .label=${this.label} .description=${this.description} .required=${this.required}></dees-label>
<dees-label .label=${this.label} .infoText=${this.infoText} .required=${this.required}></dees-label>
<dees-tile>
<div slot="header" class="toolbar">
<div class="toolbar-left">
@@ -362,6 +362,7 @@ export class DeesInputCode extends DeesInputBase<string> {
</div>
</div>
</dees-tile>
${this.renderDescription()}
</div>
`;
}

View File

@@ -4,7 +4,7 @@ import type { DeesInputDatepicker } from './component.js';
export const renderDatepicker = (component: DeesInputDatepicker): TemplateResult => {
return html`
<div class="input-wrapper">
<dees-label .label=${component.label} .description=${component.description} .required=${component.required}></dees-label>
<dees-label .label=${component.label} .infoText=${component.infoText} .required=${component.required}></dees-label>
<div class="input-container">
<input
type="text"
@@ -27,6 +27,7 @@ export const renderDatepicker = (component: DeesInputDatepicker): TemplateResult
<dees-icon class="calendar-icon" icon="lucide:calendar" iconSize="16"></dees-icon>
</div>
</div>
${component.renderDescription()}
</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,9 +63,10 @@ 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'}
.options=${[
{ option: 'United States', key: 'us' },
{ option: 'Canada', key: 'ca' },
@@ -94,7 +89,7 @@ export const demoFunc = () => html`
{ option: 'Guest', key: 'guest' }
]}
></dees-input-dropdown>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
@@ -135,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>
@@ -184,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}
@@ -203,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

@@ -168,7 +168,7 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
public render(): TemplateResult {
return html`
<div class="input-wrapper">
<dees-label .label=${this.label} .description=${this.description} .required=${this.required}></dees-label>
<dees-label .label=${this.label} .infoText=${this.infoText} .required=${this.required}></dees-label>
<div class="maincontainer">
<div
class="selectedBox ${this.isOpened ? 'open' : ''} ${this.disabled ? 'disabled' : ''}"
@@ -179,6 +179,7 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
${this.selectedOption?.option || 'Select an option'}
</div>
</div>
${this.renderDescription()}
</div>
`;
}

View File

@@ -73,7 +73,7 @@ export class DeesInputFileupload extends DeesInputBase<DeesInputFileupload> {
<div class="input-wrapper">
<dees-label
.label=${this.label}
.description=${this.description}
.infoText=${this.infoText}
.required=${this.required}
></dees-label>
<dees-tile
@@ -114,6 +114,7 @@ export class DeesInputFileupload extends DeesInputBase<DeesInputFileupload> {
${this.validationMessage
? html`<div class="validation-message" aria-live="polite">${this.validationMessage}</div>`
: html``}
${this.renderDescription()}
</div>
`;
}

View File

@@ -55,40 +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'}
.description=${'Upload supporting documents for your request'}
.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'}
.description=${'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'}
.description=${'Share podcast drafts (MP3/WAV, max 25MB each)'}
.accept=${'audio/*'}
.maxSize=${25 * 1024 * 1024}
></dees-input-fileupload>
<dees-input-fileupload
.label=${'Disabled example'}
.description=${'Uploader is disabled while moderation is pending'}
.disabled=${true}
></dees-input-fileupload>
</div>
</div>
</dees-form>
</dees-panel>
<dees-panel
@@ -97,10 +100,9 @@ export const demoFunc = () => html`
>
<div class="demo-grid">
<dees-form>
<div class="demo-stack">
<dees-input-text
.label=${'Project name'}
.description=${'How should we refer to this project internally?'}
.infoText=${'How should we refer to this project internally?'}
.required=${true}
.key=${'projectName'}
></dees-input-text>
@@ -114,7 +116,7 @@ export const demoFunc = () => html`
<dees-input-fileupload
.label=${'Statement of work'}
.description=${'Upload a signed statement of work (PDF, max 15MB)'}
.infoText=${'Upload a signed statement of work (PDF, max 15MB)'}
.required=${true}
.accept=${'application/pdf'}
.maxSize=${15 * 1024 * 1024}
@@ -124,7 +126,7 @@ export const demoFunc = () => html`
<dees-input-fileupload
.label=${'Creative references'}
.description=${'Optional. Upload up to five visual references'}
.infoText=${'Optional. Upload up to five visual references'}
.accept=${'image/*'}
.maxFiles=${5}
.maxSize=${8 * 1024 * 1024}
@@ -133,13 +135,12 @@ export const demoFunc = () => html`
<dees-input-text
.label=${'Notes'}
.description=${'Add optional context for reviewers'}
.infoText=${'Add optional context for reviewers'}
.inputType=${'textarea'}
.key=${'notes'}
></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,58 +24,61 @@ 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'}
.description=${'Enter your International Bank Account Number'}
.infoText=${'Enter your International Bank Account Number'}
.description=${'Your IBAN can be found on your bank statement'}
></dees-input-iban>
<dees-input-iban
.label=${'Verified IBAN'}
.description=${'This IBAN has been verified'}
.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'}
.description=${'Required for processing payments'}
.infoText=${'Required for processing payments'}
.required=${true}
></dees-input-iban>
<dees-input-iban
.label=${'Locked IBAN'}
.description=${'This IBAN cannot be changed'}
.infoText=${'This IBAN cannot be changed'}
.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'}>
<dees-form>
<dees-input-text .label=${'Recipient Name'} .required=${true}></dees-input-text>
<dees-input-iban .label=${'Recipient IBAN'} .required=${true}></dees-input-iban>
<dees-input-text .label=${'Transfer Reference'} .description=${'Optional reference for the transfer'}></dees-input-text>
<dees-input-text .label=${'Transfer Reference'} .infoText=${'Optional reference for the transfer'}></dees-input-text>
<dees-input-text .label=${'Amount'} .inputType=${'number'} .required=${true}></dees-input-text>
</dees-form>
</dees-panel>

View File

@@ -44,7 +44,7 @@ export class DeesInputIban extends DeesInputBase<DeesInputIban> {
public render(): TemplateResult {
return html`
<div class="input-wrapper">
<dees-label .label=${this.label || 'IBAN'} .description=${this.description}></dees-label>
<dees-label .label=${this.label || 'IBAN'} .infoText=${this.infoText}></dees-label>
<dees-input-text
.value=${this.value}
.disabled=${this.disabled}
@@ -64,6 +64,7 @@ export class DeesInputIban extends DeesInputBase<DeesInputIban> {
this.validateIban(eventArg);
}}
></dees-input-text>
${this.renderDescription()}
</div>
`;
}

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

@@ -373,13 +373,6 @@ export class DeesInputList extends DeesInputBase<DeesInputList> {
line-height: 1.4;
}
.description {
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
font-size: 12px;
margin-top: 4px;
line-height: 1.4;
}
/* Scrollbar styling */
.list-items::-webkit-scrollbar {
width: 8px;
@@ -546,9 +539,7 @@ export class DeesInputList extends DeesInputBase<DeesInputList> {
<div class="validation-message">${this.validationText}</div>
` : ''}
${this.description ? html`
<div class="description">${this.description}</div>
` : ''}
${this.renderDescription()}
</div>
`;
}

View File

@@ -52,80 +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'}
.description=${'Choose how content is displayed'}
.options=${['List View', 'Grid View', 'Compact']}
.selectedOption=${'Grid View'}
></dees-input-multitoggle>
<br><br>
<dees-input-multitoggle
.label=${'T-Shirt Size'}
.description=${'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'}
.description=${'Enable or disable push notifications'}
.type=${'boolean'}
.selectedOption=${'true'}
></dees-input-multitoggle>
<br><br>
<dees-input-multitoggle
.label=${'Theme Mode'}
.description=${'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">
@@ -134,7 +137,7 @@ export const demoFunc = () => html`
<dees-input-multitoggle
.label=${'Account Type'}
.description=${'This setting is locked'}
.infoText=${'This setting is locked'}
.options=${['Free', 'Pro', 'Enterprise']}
.selectedOption=${'Enterprise'}
.disabled=${true}

View File

@@ -146,7 +146,7 @@ export class DeesInputMultitoggle extends DeesInputBase<DeesInputMultitoggle> {
public render(): TemplateResult {
return html`
<div class="input-wrapper">
<dees-label .label=${this.label} .description=${this.description}></dees-label>
<dees-label .label=${this.label} .infoText=${this.infoText}></dees-label>
<div class="mainbox">
<div class="selections">
<div class="indicator"></div>
@@ -158,6 +158,7 @@ export class DeesInputMultitoggle extends DeesInputBase<DeesInputMultitoggle> {
)}
</div>
</div>
${this.renderDescription()}
</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;
align-items: center;
@@ -30,43 +24,46 @@ 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'}
.description=${'Enter your phone number with country code'}
.infoText=${'Enter your phone number with country code'}
.description=${'Include country code for international numbers'}
.value=${'5551234567'}
></dees-input-phone>
<dees-input-phone
.label=${'Contact Phone'}
.description=${'Required for account verification'}
.infoText=${'Required for account verification'}
.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'}
.description=${'Automatically formats international numbers'}
.infoText=${'Automatically formats international numbers'}
.value=${'441234567890'}
></dees-input-phone>
@@ -75,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

@@ -47,7 +47,7 @@ export class DeesInputPhone extends DeesInputBase<DeesInputPhone> {
public render(): TemplateResult {
return html`
<div class="input-wrapper">
<dees-label .label=${this.label} .description=${this.description}></dees-label>
<dees-label .label=${this.label} .infoText=${this.infoText}></dees-label>
<dees-input-text
.value=${this.formattedPhone}
.disabled=${this.disabled}
@@ -55,6 +55,7 @@ export class DeesInputPhone extends DeesInputBase<DeesInputPhone> {
.placeholder=${this.placeholder}
@input=${(event: InputEvent) => this.handlePhoneInput(event)}
></dees-input-text>
${this.renderDescription()}
</div>
`;
}

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,19 +60,20 @@ 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'}
.description=${'Select the desired quantity'}
.infoText=${'Select the desired quantity'}
.description=${'Minimum order quantity is 1 item'}
.value=${1}
></dees-input-quantityselector>
<dees-input-quantityselector
.label=${'Items in Cart'}
.description=${'Adjust the quantity of items'}
.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) => {
@@ -177,21 +172,21 @@ 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'}
.description=${'Select how many licenses you need'}
.infoText=${'Select how many licenses you need'}
.required=${true}
.value=${1}
></dees-input-quantityselector>
<dees-input-quantityselector
.label=${'Fixed Quantity'}
.description=${'This quantity cannot be changed'}
.infoText=${'This quantity cannot be changed'}
.disabled=${true}
.value=${5}
></dees-input-quantityselector>
</div>
</dees-form>
</dees-panel>
<dees-panel .title=${'Order Form'} .subtitle=${'Complete order form with quantity selection'}>
@@ -204,7 +199,7 @@ export const demoFunc = () => html`
></dees-input-dropdown>
<dees-input-quantityselector
.label=${'Quantity'}
.description=${'Number of licenses'}
.infoText=${'Number of licenses'}
.value=${1}
></dees-input-quantityselector>
<dees-input-text

View File

@@ -129,7 +129,7 @@ export class DeesInputQuantitySelector extends DeesInputBase<DeesInputQuantitySe
public render(): TemplateResult {
return html`
<div class="input-wrapper">
${this.label ? html`<dees-label .label=${this.label} .description=${this.description} .required=${this.required}></dees-label>` : ''}
${this.label ? html`<dees-label .label=${this.label} .infoText=${this.infoText} .required=${this.required}></dees-label>` : ''}
<div
class="quantity-container ${this.disabled ? 'disabled' : ''}"
data-min="${this.value <= 0}"
@@ -162,6 +162,7 @@ export class DeesInputQuantitySelector extends DeesInputBase<DeesInputQuantitySe
aria-label="Increase quantity"
>+</div>
</div>
${this.renderDescription()}
</div>
`;
}

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

@@ -189,14 +189,6 @@ export class DeesInputRadiogroup extends DeesInputBase<string | object> {
line-height: 20px;
}
.description-text {
font-size: 13px;
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
margin-top: 10px;
line-height: 1.5;
letter-spacing: -0.003em;
}
/* Validation styles */
:host([validationState="invalid"]) .radio-circle {
border-color: ${cssManager.bdTheme('hsl(0 72.2% 50.6%)', 'hsl(0 62.8% 30.6%)')};
@@ -256,7 +248,7 @@ export class DeesInputRadiogroup extends DeesInputBase<string | object> {
`;
})}
</div>
${this.description ? html`<div class="description-text">${this.description}</div>` : ''}
${this.renderDescription()}
</div>
`;
}

View File

@@ -278,13 +278,6 @@ export const richtextStyles = [
border-color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
}
.description {
margin-top: 8px;
font-size: 12px;
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
line-height: 1.4;
}
:host([disabled]) dees-tile {
opacity: 0.6;
cursor: not-allowed;

View File

@@ -26,7 +26,7 @@ export const renderRichtext = (component: DeesInputRichtext): TemplateResult =>
`
: ''}
</dees-tile>
${component.description ? html`<div class="description">${component.description}</div>` : ''}
${component.renderDescription()}
</div>
`;

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

@@ -210,14 +210,6 @@ export class DeesInputTags extends DeesInputBase<DeesInputTags> {
line-height: 1.5;
}
/* Description styles */
.description {
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
font-size: 13px;
margin-top: 6px;
line-height: 1.5;
}
/* Scrollbar styling */
.suggestions-dropdown::-webkit-scrollbar {
width: 8px;
@@ -302,9 +294,7 @@ export class DeesInputTags extends DeesInputBase<DeesInputTags> {
<div class="validation-message">${this.validationText}</div>
` : ''}
${this.description ? html`
<div class="description">${this.description}</div>
` : ''}
${this.renderDescription()}
</div>
`;
}

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,17 +83,18 @@ 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'}
.key=${'username'}
.description=${'Your username will be visible to other users'}
></dees-input-text>
<dees-input-text
.label=${'Email Address'}
.value=${'john@example.com'}
.description=${'We will never share your email with anyone'}
.infoText=${'We will never share your email with anyone'}
.key=${'email'}
></dees-input-text>
@@ -109,7 +104,7 @@ export const demoFunc = () => html`
.value=${'secret123'}
.key=${'password'}
></dees-input-text>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>
@@ -139,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>
@@ -180,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'}
@@ -194,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}
@@ -236,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>
@@ -265,21 +262,21 @@ 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}
.value=${'mySecurePassword123'}
.description=${'Click the eye icon to show/hide password'}
.infoText=${'Click the eye icon to show/hide password'}
></dees-input-text>
<dees-input-text
.label=${'API Key'}
.isPasswordBool=${true}
.value=${'sk-1234567890abcdef'}
.description=${'Keep this key secure and never share it'}
.infoText=${'Keep this key secure and never share it'}
></dees-input-text>
</div>
</dees-form>
</dees-panel>
</dees-demowrapper>

View File

@@ -289,7 +289,7 @@ export class DeesInputText extends DeesInputBase {
`}
</style>
<div class="input-wrapper">
<dees-label .label=${this.label} .description=${this.description} .required=${this.required}></dees-label>
<dees-label .label=${this.label} .infoText=${this.infoText} .required=${this.required}></dees-label>
<div class="maincontainer">
<input
type="${this.isPasswordBool && !this.showPasswordBool ? 'password' : 'text'}"
@@ -315,6 +315,7 @@ export class DeesInputText extends DeesInputBase {
</div>
`
: html`<div class="validationContainer"></div>`}
${this.renderDescription()}
</div>
</div>
`;

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

@@ -170,12 +170,6 @@ export class DeesInputToggle extends DeesInputBase<DeesInputToggle> {
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
}
/* Description */
.description-text {
font-size: 12px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
line-height: 1.5;
}
`,
];
@@ -199,7 +193,7 @@ export class DeesInputToggle extends DeesInputBase<DeesInputToggle> {
</div>
<div class="label-container">
${this.label ? html`<div class="toggle-label">${this.label}</div>` : ''}
${this.description ? html`<div class="description-text">${this.description}</div>` : ''}
${this.renderDescription()}
</div>
</div>
</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,61 +39,62 @@ 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'}
.description=${'Add tags by typing and pressing Enter'}
.infoText=${'Add tags by typing and pressing Enter'}
.description=${'Tags help categorize and filter your content'}
.value=${['javascript', 'typescript', 'web-components']}
></dees-input-typelist>
<dees-input-typelist
.label=${'Team Members'}
.description=${'Add email addresses of team members'}
.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'}
.description=${'List your professional skills'}
.infoText=${'List your professional skills'}
.value=${['HTML', 'CSS', 'JavaScript', 'Node.js', 'React']}
></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'}
.description=${'List all required npm packages'}
.infoText=${'List all required npm packages'}
.required=${true}
.value=${['@design.estate/dees-element', '@design.estate/dees-domtools']}
></dees-input-typelist>
<dees-input-typelist
.label=${'System Tags'}
.description=${'These tags are managed by the system'}
.infoText=${'These tags are managed by the system'}
.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'}>
@@ -108,16 +103,16 @@ export const demoFunc = () => html`
<dees-input-text
.label=${'Summary'}
.inputType=${'textarea'}
.description=${'Brief description of the article'}
.infoText=${'Brief description of the article'}
></dees-input-text>
<dees-input-typelist
.label=${'Tags'}
.description=${'Add relevant tags for better discoverability'}
.infoText=${'Add relevant tags for better discoverability'}
.value=${['tutorial', 'web-development']}
></dees-input-typelist>
<dees-input-typelist
.label=${'Co-Authors'}
.description=${'Add email addresses of co-authors'}
.infoText=${'Add email addresses of co-authors'}
></dees-input-typelist>
</dees-form>

View File

@@ -153,7 +153,7 @@ export class DeesInputTypelist extends DeesInputBase<DeesInputTypelist> {
public render(): TemplateResult {
return html`
<div class="input-wrapper">
<dees-label .label=${this.label} .description=${this.description}></dees-label>
<dees-label .label=${this.label} .infoText=${this.infoText}></dees-label>
<div class="mainbox">
<div class="tags" @click=${() => {
this.shadowRoot!.querySelector('input')!.focus();
@@ -188,6 +188,7 @@ export class DeesInputTypelist extends DeesInputBase<DeesInputTypelist> {
.disabled=${this.disabled}
/>
</div>
${this.renderDescription()}
</div>
`;
}

View File

@@ -292,17 +292,18 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
return html`
<dees-label
.label="${this.label}"
.description="${this.description}"
.infoText="${this.infoText}"
.required="${this.required}"
></dees-label>
<div class="wysiwyg-container">
<div
<div
class="editor-content ${this.draggedBlockId ? 'dragging' : ''}"
id="editor-content"
>
<!-- Blocks will be rendered programmatically -->
</div>
</div>
${this.renderDescription()}
`;
}

View File

@@ -273,7 +273,7 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
render(): TemplateResult {
return html`
<div class="input-wrapper">
<dees-label .label=${this.label} .description=${this.description} .required=${this.required}></dees-label>
<dees-label .label=${this.label} .infoText=${this.infoText} .required=${this.required}></dees-label>
<div
class="profile-container"
@@ -329,6 +329,7 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
accept="${this.acceptedFormats.join(',')}"
@change=${this.handleFileSelect}
/>
${this.renderDescription()}
</div>
`;
}

View File

@@ -85,31 +85,31 @@ export const demoFunc = () => html`
</div>
<div class="demo-section">
<h3>Description (Info Icon)</h3>
<p>When <code>description</code> is set, an info icon appears next to the label. Hover over it to see the tooltip.</p>
<h3>Info Text (Info Icon)</h3>
<p>When <code>infoText</code> is set, an info icon appears next to the label. Hover over it to see the tooltip.</p>
<div class="label-grid">
<div class="label-row">
<span class="annotation">description="..."</span>
<dees-label .label=${'API Key'} .description=${'Your API key can be found in the developer settings dashboard.'}></dees-label>
<span class="annotation">infoText="..."</span>
<dees-label .label=${'API Key'} .infoText=${'Your API key can be found in the developer settings dashboard.'}></dees-label>
</div>
<div class="label-row">
<span class="annotation">short description</span>
<dees-label .label=${'Region'} .description=${'Select your nearest datacenter.'}></dees-label>
<span class="annotation">short infoText</span>
<dees-label .label=${'Region'} .infoText=${'Select your nearest datacenter.'}></dees-label>
</div>
</div>
</div>
<div class="demo-section">
<h3>Required + Description</h3>
<h3>Required + Info Text</h3>
<p>Both indicators can be combined. The asterisk appears first, then the info icon.</p>
<div class="label-grid">
<div class="label-row">
<span class="annotation">required + description</span>
<dees-label .label=${'Password'} .required=${true} .description=${'Must be at least 8 characters with one uppercase letter and one number.'}></dees-label>
<span class="annotation">required + infoText</span>
<dees-label .label=${'Password'} .required=${true} .infoText=${'Must be at least 8 characters with one uppercase letter and one number.'}></dees-label>
</div>
<div class="label-row">
<span class="annotation">required + description</span>
<dees-label .label=${'Email Address'} .required=${true} .description=${'We will send a verification link to this address.'}></dees-label>
<span class="annotation">required + infoText</span>
<dees-label .label=${'Email Address'} .required=${true} .infoText=${'We will send a verification link to this address.'}></dees-label>
</div>
</div>
</div>

View File

@@ -32,7 +32,7 @@ export class DeesLabel extends DeesElement {
type: String,
reflect: true,
})
accessor description!: string;
accessor infoText!: string;
@property({
type: Boolean,
@@ -98,12 +98,12 @@ export class DeesLabel extends DeesElement {
<div class="label">
${this.label}
${this.required ? html`<span class="required">*</span>` : ''}
${this.description
${this.infoText
? html`
<div class="description-icon">
<dees-icon .icon=${'lucide:info'}></dees-icon>
</div>
<dees-speechbubble .text=${this.description}></dees-speechbubble>
<dees-speechbubble .text=${this.infoText}></dees-speechbubble>
`
: html``}
</div>

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

@@ -45,6 +45,9 @@ export class DeesTile extends DeesElement {
@property({ type: String })
accessor heading: string = '';
@property({ type: String, reflect: true })
accessor overscroll: 'contain' | 'auto' | 'none' = 'auto';
@state()
accessor hasFooter: boolean = false;
@@ -100,7 +103,14 @@ export class DeesTile extends DeesElement {
border-radius: 8px;
border-top: 1px solid var(--dees-color-border-subtle);
border-bottom: 1px solid var(--dees-color-border-subtle);
overflow: hidden;
overflow-x: hidden;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: var(--dees-color-scrollbar-thumb) transparent;
}
:host([overscroll="contain"]) .tile-content {
overscroll-behavior: contain;
}
.tile-content.no-footer {

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

@@ -153,14 +153,6 @@ export class DeesModal extends DeesElement {
overscroll-behavior: contain;
}
dees-tile::part(content) {
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
scrollbar-width: thin;
scrollbar-color: var(--dees-color-scrollbar-thumb) transparent;
}
dees-tile::part(outer) {
box-shadow:
0 0 0 1px ${cssManager.bdTheme('hsl(0 0% 0% / 0.03)', 'hsl(0 0% 100% / 0.03)')},
@@ -351,7 +343,7 @@ export class DeesModal extends DeesElement {
${minWidthStyle ? `dees-tile { min-width: ${minWidthStyle}; }` : ''}
</style>
<div class="modalContainer" @click=${this.handleOutsideClick} style="z-index: ${this.modalZIndex}">
<dees-tile class="${widthClass} ${mobileFullscreenClass}">
<dees-tile class="${widthClass} ${mobileFullscreenClass}" .overscroll=${'contain'}>
<div slot="header" class="heading">
<div class="heading-text">${this.heading}</div>
<div class="header-buttons">