feat: Enhance selection options with icons and dividers for improved UI

This commit is contained in:
Juergen Kunz
2025-06-17 10:00:50 +00:00
parent a8f0e5659e
commit c1e8f8c2a6
5 changed files with 84 additions and 45 deletions

View File

@ -72,12 +72,13 @@ export const demoFunc = () => {
]; ];
// Selector options (second sidebar) // Selector options (second sidebar)
const selectorOptions: ISelectionOption[] = [ const selectorOptions: (ISelectionOption | { divider: true })[] = [
{ key: 'Overview', action: () => console.log('Overview selected') }, { key: 'Overview', iconName: 'home', action: () => console.log('Overview selected') },
{ key: 'Components', action: () => console.log('Components selected') }, { key: 'Components', iconName: 'package', action: () => console.log('Components selected') },
{ key: 'Services', action: () => console.log('Services selected') }, { key: 'Services', iconName: 'server', action: () => console.log('Services selected') },
{ key: 'Database', action: () => console.log('Database selected') }, { divider: true },
{ key: 'Settings', action: () => console.log('Settings selected') }, { key: 'Database', iconName: 'database', action: () => console.log('Database selected') },
{ key: 'Settings', iconName: 'settings', action: () => console.log('Settings selected') },
]; ];
// Main content tabs // Main content tabs

View File

@ -65,7 +65,7 @@ export class DeesAppuiBase extends DeesElement {
// Properties for mainselector // Properties for mainselector
@property({ type: Array }) @property({ type: Array })
public mainselectorOptions: interfaces.ISelectionOption[] = []; public mainselectorOptions: (interfaces.ISelectionOption | { divider: true })[] = [];
@property({ type: Object }) @property({ type: Object })
public mainselectorSelectedOption?: interfaces.ISelectionOption; public mainselectorSelectedOption?: interfaces.ISelectionOption;

View File

@ -2,6 +2,7 @@ import * as plugins from './00plugins.js';
import * as interfaces from './interfaces/index.js'; import * as interfaces from './interfaces/index.js';
import { DeesContextmenu } from './dees-contextmenu.js'; import { DeesContextmenu } from './dees-contextmenu.js';
import './dees-icon.js';
import { import {
DeesElement, DeesElement,
@ -22,18 +23,18 @@ export class DeesAppuiMainselector extends DeesElement {
public static demo = () => html` public static demo = () => html`
<dees-appui-mainselector <dees-appui-mainselector
.selectionOptions=${[ .selectionOptions=${[
{ key: 'Overview', action: () => console.log('Overview') }, { key: 'Overview', iconName: 'home', action: () => console.log('Overview') },
{ key: 'Components', action: () => console.log('Components') }, { key: 'Components', iconName: 'package', action: () => console.log('Components') },
{ key: 'Services', action: () => console.log('Services') }, { key: 'Services', iconName: 'server', action: () => console.log('Services') },
{ key: 'Database', action: () => console.log('Database') }, { key: 'Database', iconName: 'database', action: () => console.log('Database') },
{ key: 'Settings', action: () => console.log('Settings') }, { key: 'Settings', iconName: 'settings', action: () => console.log('Settings') },
]} ]}
></dees-appui-mainselector> ></dees-appui-mainselector>
`; `;
// INSTANCE // INSTANCE
@property({ type: Array }) @property({ type: Array })
public selectionOptions: interfaces.ISelectionOption[] = [ public selectionOptions: (interfaces.ISelectionOption | { divider: true })[] = [
{ key: '⚠️ Please set selection options', action: () => console.warn('No selection options configured for mainselector') }, { key: '⚠️ Please set selection options', action: () => console.warn('No selection options configured for mainselector') },
]; ];
@ -51,7 +52,7 @@ export class DeesAppuiMainselector extends DeesElement {
max-width: 300px; max-width: 300px;
height: 100%; height: 100%;
background: ${cssManager.bdTheme('#fafafa', '#000000')}; background: ${cssManager.bdTheme('#fafafa', '#000000')};
border-right: 1px solid ${cssManager.bdTheme('#e0e0e0', '#222222')}; border-right: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
} }
.maincontainer { .maincontainer {
position: absolute; position: absolute;
@ -63,55 +64,79 @@ export class DeesAppuiMainselector extends DeesElement {
.topbar { .topbar {
position: absolute; position: absolute;
height: 32px; height: 40px;
width: 100%; width: 100%;
display: flex;
align-items: center;
border-bottom: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
} }
.topbar .heading { .topbar .heading {
padding-left: 16px; padding-left: 12px;
padding-top: 8px;
line-height: 24px;
font-family: 'Geist Sans', sans-serif; font-family: 'Geist Sans', sans-serif;
font-weight: 600; font-weight: 600;
font-size: 14px; font-size: 12px;
color: ${cssManager.bdTheme('#666', '#ccc')}; color: ${cssManager.bdTheme('#666', '#999')};
text-transform: uppercase;
letter-spacing: 0.5px;
} }
.selectionOptions { .selectionOptions {
position: absolute; position: absolute;
top: 32px; top: 40px;
padding-top: 8px;
left: 0px; left: 0px;
width: 100%; right: 0px;
bottom: 0px;
overflow-y: auto;
font-family: 'Geist Sans', sans-serif; font-family: 'Geist Sans', sans-serif;
font-size: 14px; font-size: 12px;
padding: 4px 0;
} }
.selectionOptions .selectionOption { .selectionOptions .selectionOption {
cursor: default; cursor: default;
margin-left: 16px; padding: 8px 12px;
margin-right: 16px; margin: 0;
padding-top: 8px; transition: background 0.1s;
padding-bottom: 8px; display: flex;
border-top: 1px dotted ${cssManager.bdTheme('#e0e0e0', '#303030')}; align-items: center;
border-left: 0px solid rgba(0, 0, 0, 0); gap: 8px;
transition: all 0.1s; color: ${cssManager.bdTheme('#333', '#ccc')};
user-select: none;
} }
.selectionOptions .selectionOption:hover { .selectionOptions .selectionOption:hover {
border-left: 2px solid #26a69a50; background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.08)')};
padding-left: 8px;
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.02)', 'rgba(255, 255, 255, 0.02)')};
} }
.selectionOptions .selectionOption:first-child { .selectionOptions .selectionOption:active {
border-top: 1px solid rgba(0, 0, 0, 0); background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.12)')};
} }
.selectionOptions .selectionOption.selectedOption { .selectionOptions .selectionOption.selectedOption {
border-left: 4px solid #26a69a; background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.12)')};
padding-left: 10px; color: ${cssManager.bdTheme('#000', '#fff')};
background: ${cssManager.bdTheme('rgba(38, 166, 154, 0.05)', 'rgba(38, 166, 154, 0.1)')}; font-weight: 500;
}
.selectionOptions .selectionOption.selectedOption::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 3px;
background: ${cssManager.bdTheme('#26a69a', '#26a69a')};
}
.selectionOption {
position: relative;
}
.selection-divider {
height: 1px;
background: ${cssManager.bdTheme('#e0e0e0', '#202020')};
margin: 4px 0;
} }
`, `,
]; ];
@ -121,17 +146,22 @@ export class DeesAppuiMainselector extends DeesElement {
<style></style> <style></style>
<div class="maincontainer"> <div class="maincontainer">
<div class="topbar"> <div class="topbar">
<div class="heading">Properties</div> <div class="heading">Selector</div>
</div> </div>
<div class="selectionOptions"> <div class="selectionOptions">
${this.selectionOptions.map((selectionOptionArg) => { ${this.selectionOptions.map((selectionOptionArg) => {
if ('divider' in selectionOptionArg && selectionOptionArg.divider) {
return html`<div class="selection-divider"></div>`;
}
const option = selectionOptionArg as interfaces.ISelectionOption;
return html` return html`
<div <div
class="selectionOption ${this.selectedOption === selectionOptionArg class="selectionOption ${this.selectedOption === option
? 'selectedOption' ? 'selectedOption'
: null}" : null}"
@click="${() => { @click="${() => {
this.selectOption(selectionOptionArg); this.selectOption(option);
}}" }}"
@contextmenu="${(eventArg: MouseEvent) => { @contextmenu="${(eventArg: MouseEvent) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [ DeesContextmenu.openContextMenuWithOptions(eventArg, [
@ -143,7 +173,10 @@ export class DeesAppuiMainselector extends DeesElement {
]); ]);
}}" }}"
> >
${selectionOptionArg.key} ${option.iconName ? html`
<dees-icon .icon="${`lucide:${option.iconName}`}" style="font-size: 14px; opacity: 0.7;"></dees-icon>
` : ''}
<span style="flex: 1;">${option.key}</span>
</div> </div>
`; `;
})} })}
@ -168,7 +201,11 @@ export class DeesAppuiMainselector extends DeesElement {
await super.firstUpdated(_changedProperties); await super.firstUpdated(_changedProperties);
if (this.selectionOptions && this.selectionOptions.length > 0) { if (this.selectionOptions && this.selectionOptions.length > 0) {
await this.updateComplete; await this.updateComplete;
this.selectOption(this.selectionOptions[0]); // Find first non-divider option
const firstOption = this.selectionOptions.find(option => !('divider' in option)) as interfaces.ISelectionOption;
if (firstOption) {
this.selectOption(firstOption);
}
} }
} }
} }

View File

@ -51,7 +51,7 @@ export class DeesAppuiTabs extends DeesElement {
.tabs-wrapper { .tabs-wrapper {
position: relative; position: relative;
background: ${cssManager.bdTheme('#f5f5f5', '#000000')}; background: ${cssManager.bdTheme('#f5f5f5', '#000000')};
height: 56px; height: 52px;
} }
.tabsContainer { .tabsContainer {

View File

@ -1,4 +1,5 @@
export interface ISelectionOption { export interface ISelectionOption {
key: string; key: string;
iconName?: string;
action: () => void; action: () => void;
} }