feat(dees-button,dees-statsgrid): add unified icon property and icon-position support to dees-button; add partition and disk tile types to dees-statsgrid
This commit is contained in:
@@ -142,54 +142,95 @@ export const demoFunc = () => html`
|
||||
<dees-panel .title=${'3. Buttons with Icons'} .subtitle=${'Combining icons with text for enhanced visual communication'}>
|
||||
<div class="icon-row">
|
||||
<dees-button>
|
||||
<dees-icon iconFA="faPlus"></dees-icon>
|
||||
<dees-icon icon="fa:plus"></dees-icon>
|
||||
Add Item
|
||||
</dees-button>
|
||||
<dees-button type="destructive">
|
||||
<dees-icon iconFA="faTrash"></dees-icon>
|
||||
<dees-icon icon="fa:trash"></dees-icon>
|
||||
Delete
|
||||
</dees-button>
|
||||
<dees-button type="outline">
|
||||
<dees-icon iconFA="faDownload"></dees-icon>
|
||||
<dees-icon icon="lucide:Download"></dees-icon>
|
||||
Download
|
||||
</dees-button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="icon-row">
|
||||
<dees-button type="secondary" size="sm">
|
||||
<dees-icon iconFA="faCog"></dees-icon>
|
||||
<dees-icon icon="fa:gear"></dees-icon>
|
||||
Settings
|
||||
</dees-button>
|
||||
<dees-button type="ghost">
|
||||
<dees-icon iconFA="faChevronLeft"></dees-icon>
|
||||
<dees-icon icon="fa:caretLeft"></dees-icon>
|
||||
Back
|
||||
</dees-button>
|
||||
<dees-button type="ghost">
|
||||
Next
|
||||
<dees-icon iconFA="faChevronRight"></dees-icon>
|
||||
<dees-icon icon="fa:caretRight"></dees-icon>
|
||||
</dees-button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="icon-row">
|
||||
<dees-button size="icon" type="default">
|
||||
<dees-icon iconFA="faPlus"></dees-icon>
|
||||
<dees-icon icon="fa:plus"></dees-icon>
|
||||
</dees-button>
|
||||
<dees-button size="icon" type="secondary">
|
||||
<dees-icon iconFA="faCog"></dees-icon>
|
||||
<dees-icon icon="fa:gear"></dees-icon>
|
||||
</dees-button>
|
||||
<dees-button size="icon" type="outline">
|
||||
<dees-icon iconFA="faSearch"></dees-icon>
|
||||
<dees-icon icon="lucide:Search"></dees-icon>
|
||||
</dees-button>
|
||||
<dees-button size="icon" type="ghost">
|
||||
<dees-icon iconFA="faEllipsisV"></dees-icon>
|
||||
<dees-icon icon="lucide:MoreVertical"></dees-icon>
|
||||
</dees-button>
|
||||
<dees-button size="icon" type="destructive">
|
||||
<dees-icon iconFA="faTrash"></dees-icon>
|
||||
<dees-icon icon="fa:trash"></dees-icon>
|
||||
</dees-button>
|
||||
</div>
|
||||
</dees-panel>
|
||||
</dees-demowrapper>
|
||||
|
||||
|
||||
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
||||
// Track icon property button clicks
|
||||
const buttons = elementArg.querySelectorAll('dees-button');
|
||||
buttons.forEach((button) => {
|
||||
button.addEventListener('clicked', () => {
|
||||
const icon = button.getAttribute('icon') || 'none';
|
||||
const position = button.getAttribute('iconPosition') || 'left';
|
||||
console.log(`Icon property button: icon=${icon}, position=${position}`);
|
||||
});
|
||||
});
|
||||
}}>
|
||||
<dees-panel .title=${'4. Icons via Property'} .subtitle=${'Simplified icon syntax using the icon property'}>
|
||||
<div class="icon-row">
|
||||
<dees-button icon="fa:plus">Add Item</dees-button>
|
||||
<dees-button type="destructive" icon="fa:trash">Delete</dees-button>
|
||||
<dees-button type="outline" icon="lucide:Download">Download</dees-button>
|
||||
</div>
|
||||
|
||||
<div class="icon-row">
|
||||
<dees-button type="secondary" size="sm" icon="fa:gear">Settings</dees-button>
|
||||
<dees-button type="ghost" icon="fa:caretLeft">Back</dees-button>
|
||||
<dees-button type="ghost" icon="fa:caretRight" iconPosition="right">Next</dees-button>
|
||||
</div>
|
||||
|
||||
<div class="icon-row">
|
||||
<dees-button size="icon" type="default" icon="fa:plus"></dees-button>
|
||||
<dees-button size="icon" type="secondary" icon="lucide:Settings"></dees-button>
|
||||
<dees-button size="icon" type="outline" icon="lucide:Search"></dees-button>
|
||||
<dees-button size="icon" type="ghost" icon="lucide:MoreVertical"></dees-button>
|
||||
<dees-button size="icon" type="destructive" icon="fa:trash"></dees-button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 16px;">
|
||||
<div class="code-snippet">
|
||||
<dees-button icon="fa:plus">Add Item</dees-button><br>
|
||||
<dees-button icon="fa:caretRight" iconPosition="right">Next</dees-button>
|
||||
</div>
|
||||
</div>
|
||||
</dees-panel>
|
||||
</dees-demowrapper>
|
||||
|
||||
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
||||
// Demonstrate status changes
|
||||
const pendingButton = elementArg.querySelector('dees-button[status="pending"]');
|
||||
@@ -215,7 +256,7 @@ export const demoFunc = () => html`
|
||||
});
|
||||
}
|
||||
}}>
|
||||
<dees-panel .title=${'4. Button States'} .subtitle=${'Different states to indicate button status and loading conditions'}>
|
||||
<dees-panel .title=${'5. Button States'} .subtitle=${'Different states to indicate button status and loading conditions'}>
|
||||
<div class="button-group">
|
||||
<dees-button status="normal">Normal</dees-button>
|
||||
<dees-button status="pending">Processing...</dees-button>
|
||||
@@ -260,7 +301,7 @@ export const demoFunc = () => html`
|
||||
});
|
||||
}
|
||||
}}>
|
||||
<dees-panel .title=${'5. Event Handling'} .subtitle=${'Interactive examples with click event handling'}>
|
||||
<dees-panel .title=${'6. Event Handling'} .subtitle=${'Interactive examples with click event handling'}>
|
||||
<div class="button-group">
|
||||
<dees-button>Click Me</dees-button>
|
||||
<dees-button type="secondary" .eventDetailData=${'custom-data-123'}>
|
||||
@@ -303,7 +344,7 @@ export const demoFunc = () => html`
|
||||
});
|
||||
}
|
||||
}}>
|
||||
<dees-panel .title=${'6. Form Integration'} .subtitle=${'Buttons working within forms with automatic spacing'}>
|
||||
<dees-panel .title=${'7. Form Integration'} .subtitle=${'Buttons working within forms with automatic spacing'}>
|
||||
<dees-form>
|
||||
<dees-input-text label="Name" key="name" required></dees-input-text>
|
||||
<dees-input-text label="Email" key="email" type="email" required></dees-input-text>
|
||||
@@ -330,7 +371,7 @@ export const demoFunc = () => html`
|
||||
}
|
||||
});
|
||||
}}>
|
||||
<dees-panel .title=${'7. Backward Compatibility'} .subtitle=${'Old button types are automatically mapped to new variants'}>
|
||||
<dees-panel .title=${'8. Backward Compatibility'} .subtitle=${'Old button types are automatically mapped to new variants'}>
|
||||
<div class="button-group">
|
||||
<dees-button type="normal">Normal → Default</dees-button>
|
||||
<dees-button type="highlighted">Highlighted → Destructive</dees-button>
|
||||
@@ -371,36 +412,36 @@ export const demoFunc = () => html`
|
||||
});
|
||||
}
|
||||
}}>
|
||||
<dees-panel .title=${'8. Advanced Examples'} .subtitle=${'Complex button configurations and real-world use cases'}>
|
||||
<dees-panel .title=${'9. Advanced Examples'} .subtitle=${'Complex button configurations and real-world use cases'}>
|
||||
<div class="horizontal-group">
|
||||
<div class="vertical-group">
|
||||
<h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 500;">Action Group</h4>
|
||||
<dees-button type="default" size="sm">
|
||||
<dees-icon iconFA="faSave"></dees-icon>
|
||||
<dees-icon icon="lucide:Save"></dees-icon>
|
||||
Save Changes
|
||||
</dees-button>
|
||||
<dees-button type="secondary" size="sm">
|
||||
<dees-icon iconFA="faUndo"></dees-icon>
|
||||
<dees-icon icon="lucide:Undo2"></dees-icon>
|
||||
Discard
|
||||
</dees-button>
|
||||
<dees-button type="ghost" size="sm">
|
||||
<dees-icon iconFA="faQuestionCircle"></dees-icon>
|
||||
<dees-icon icon="lucide:HelpCircle"></dees-icon>
|
||||
Help
|
||||
</dees-button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="vertical-group">
|
||||
<h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 500;">Danger Zone</h4>
|
||||
<dees-button type="destructive" size="sm">
|
||||
<dees-icon iconFA="faTrash"></dees-icon>
|
||||
<dees-icon icon="fa:trash"></dees-icon>
|
||||
Delete Account
|
||||
</dees-button>
|
||||
<dees-button type="outline" size="sm">
|
||||
<dees-icon iconFA="faArchive"></dees-icon>
|
||||
<dees-icon icon="lucide:Archive"></dees-icon>
|
||||
Archive Data
|
||||
</dees-button>
|
||||
<dees-button type="ghost" size="sm" disabled>
|
||||
<dees-icon iconFA="faBan"></dees-icon>
|
||||
<dees-icon icon="lucide:Ban"></dees-icon>
|
||||
Not Available
|
||||
</dees-button>
|
||||
</div>
|
||||
@@ -409,8 +450,7 @@ export const demoFunc = () => html`
|
||||
<div style="margin-top: 24px;">
|
||||
<h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 500;">Code Example:</h4>
|
||||
<div class="code-snippet">
|
||||
<dees-button type="default" size="sm" @clicked="\${handleClick}"><br>
|
||||
<dees-icon iconFA="faSave"></dees-icon><br>
|
||||
<dees-button type="default" size="sm" icon="lucide:Save" @clicked="\${handleClick}"><br>
|
||||
Save Changes<br>
|
||||
</dees-button>
|
||||
</div>
|
||||
|
||||
@@ -68,6 +68,12 @@ export class DeesButton extends DeesElement {
|
||||
})
|
||||
accessor insideForm: boolean = false;
|
||||
|
||||
@property({ type: String, reflect: true })
|
||||
accessor icon: string;
|
||||
|
||||
@property({ type: String, reflect: true })
|
||||
accessor iconPosition: 'left' | 'right' = 'left';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
@@ -340,9 +346,62 @@ export class DeesButton extends DeesElement {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
/* Text alignment */
|
||||
.textbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
`,
|
||||
];
|
||||
|
||||
/**
|
||||
* Extracts icon and text from light DOM and sets properties
|
||||
*/
|
||||
private extractLightDom(): void {
|
||||
const iconElement = this.querySelector('dees-icon') as any;
|
||||
|
||||
// Get all text content from light DOM
|
||||
const textContent = Array.from(this.childNodes)
|
||||
.filter(node => node.nodeType === Node.TEXT_NODE)
|
||||
.map(node => node.textContent?.trim())
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
|
||||
if (textContent && !this.text) {
|
||||
this.text = textContent;
|
||||
}
|
||||
|
||||
if (iconElement) {
|
||||
// Get icon value
|
||||
const iconValue = iconElement.icon || iconElement.getAttribute('icon') ||
|
||||
(iconElement.iconFA ? `fa:${iconElement.iconFA}` : null);
|
||||
|
||||
if (iconValue) {
|
||||
// Determine position based on DOM order
|
||||
const children = Array.from(this.childNodes);
|
||||
const iconIndex = children.indexOf(iconElement);
|
||||
const textNodes = children.filter(node =>
|
||||
node.nodeType === Node.TEXT_NODE && node.textContent?.trim()
|
||||
);
|
||||
|
||||
if (textNodes.length > 0) {
|
||||
const firstTextIndex = children.indexOf(textNodes[0]);
|
||||
this.iconPosition = iconIndex < firstTextIndex ? 'left' : 'right';
|
||||
}
|
||||
|
||||
// Set the icon property
|
||||
this.icon = iconValue;
|
||||
}
|
||||
|
||||
// Remove the light DOM icon element
|
||||
iconElement.remove();
|
||||
}
|
||||
|
||||
// Clear all remaining light DOM
|
||||
this.innerHTML = '';
|
||||
}
|
||||
|
||||
public render(): TemplateResult {
|
||||
// Map old types to new types for backward compatibility
|
||||
const typeMap: {[key: string]: string} = {
|
||||
@@ -351,10 +410,20 @@ export class DeesButton extends DeesElement {
|
||||
'discreet': 'outline',
|
||||
'big': 'default' // Will use size instead
|
||||
};
|
||||
|
||||
|
||||
const actualType = typeMap[this.type] || this.type;
|
||||
const actualSize = this.type === 'big' ? 'lg' : this.size;
|
||||
|
||||
|
||||
const leftIcon = this.iconPosition === 'left' && this.icon
|
||||
? html`<dees-icon .icon=${this.icon}></dees-icon>`
|
||||
: '';
|
||||
const rightIcon = this.iconPosition === 'right' && this.icon
|
||||
? html`<dees-icon .icon=${this.icon}></dees-icon>`
|
||||
: '';
|
||||
|
||||
// For icon-only buttons, hide the textbox
|
||||
const isIconOnly = actualSize === 'icon' && this.icon;
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="button ${this.isHidden ? 'hidden' : ''} ${actualType} size-${actualSize} ${this.status} ${this.disabled
|
||||
@@ -363,13 +432,15 @@ export class DeesButton extends DeesElement {
|
||||
@click="${this.dispatchClick}"
|
||||
>
|
||||
${this.status === 'normal' ? html``: html`
|
||||
<dees-spinner
|
||||
.bnw=${true}
|
||||
<dees-spinner
|
||||
.bnw=${true}
|
||||
status="${this.status}"
|
||||
size="${actualSize === 'sm' ? 14 : actualSize === 'lg' ? 18 : 16}"
|
||||
></dees-spinner>
|
||||
`}
|
||||
<div class="textbox">${this.text || html`<slot>Button</slot>`}</div>
|
||||
${leftIcon}
|
||||
${isIconOnly ? '' : html`<div class="textbox">${this.text || 'Button'}</div>`}
|
||||
${rightIcon}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -390,6 +461,7 @@ export class DeesButton extends DeesElement {
|
||||
}
|
||||
|
||||
public async firstUpdated() {
|
||||
// Don't set default text here as it interferes with slotted content
|
||||
// Extract light DOM content (icon + text) and set as properties
|
||||
this.extractLightDom();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user