Compare commits

...

4 Commits

Author SHA1 Message Date
888430d55a v3.1.0
Some checks failed
Default (tags) / security (push) Failing after 16s
Default (tags) / test (push) Failing after 17s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-12-08 15:40:12 +00:00
85424d07cd feat(dees-appui): Add collapsible/compact mode to AppUI sidebars (mainmenu & secondarymenu) with toggles, tooltips and improved z-index stacking 2025-12-08 15:40:12 +00:00
24d3afe85d v3.0.1
Some checks failed
Default (tags) / security (push) Failing after 15s
Default (tags) / test (push) Failing after 17s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-12-08 14:50:53 +00:00
9735af05c8 fix(dees-appui): Normalize header heights and box-sizing for App UI components 2025-12-08 14:50:53 +00:00
8 changed files with 399 additions and 20 deletions

View File

@@ -1,5 +1,24 @@
# Changelog # Changelog
## 2025-12-08 - 3.1.0 - feat(dees-appui)
Add collapsible/compact mode to AppUI sidebars (mainmenu & secondarymenu) with toggles, tooltips and improved z-index stacking
- Add collapsed property to dees-appui-mainmenu and dees-appui-secondarymenu (reflect: true) to enable compact horizontal mode.
- Add floating collapse toggle buttons and public toggleCollapse() methods on mainmenu and secondarymenu; these dispatch 'collapse-change' events (bubbles & composed).
- Expose and track collapse state in dees-appui-base via mainmenuCollapsed and secondarymenuCollapsed properties; bind states to child components and re-emit collapse-change events as mainmenu-collapse-change and secondarymenu-collapse-change.
- Implement collapsed styles and animations: reduced sidebar widths, hide/compact labels and headers, center icons, hide badges, and add smooth width/opacity transitions.
- Add tooltips that appear for tabs/items when sidebars are collapsed to preserve discoverability.
- Adjust layout grid in DeesAppuiBase (use auto columns) and add explicit z-index layering to ensure proper stacking order of mainmenu, secondarymenu, maincontent and activitylog.
## 2025-12-08 - 3.0.1 - fix(dees-appui)
Normalize header heights and box-sizing for App UI components
- Set topbar/header heights to 48px (was 40px) and adjusted dependent offsets (activity container top, topShadow position) in dees-appui-activitylog.
- Make logo and secondary menu headers fixed 48px tall and replace vertical padding with horizontal padding for consistent vertical alignment (dees-appui-mainmenu, dees-appui-secondarymenu).
- Ensure tabs wrapper uses explicit 48px height and tabsContainer fills height (height:100%) to keep tab items vertically centered (dees-appui-tabs).
- Add box-sizing: border-box to affected header/logo containers to prevent overflow and ensure correct sizing.
- Minor CSS alignment and overflow fixes to improve consistent layout and scrolling behavior across the app UI components.
## 2025-12-08 - 3.0.0 - BREAKING CHANGE(dees-appui-secondarymenu) ## 2025-12-08 - 3.0.0 - BREAKING CHANGE(dees-appui-secondarymenu)
Add SecondaryMenu component and replace Mainselector with new SecondaryMenu in AppUI Add SecondaryMenu component and replace Mainselector with new SecondaryMenu in AppUI

View File

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

View File

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

View File

@@ -63,13 +63,14 @@ export class DeesAppuiActivitylog extends DeesElement {
.topbar { .topbar {
position: absolute; position: absolute;
top: 0px; top: 0px;
height: 40px; height: 48px;
width: 100%; width: 100%;
padding: 0px 16px; padding: 0px 16px;
background: ${cssManager.bdTheme('#ffffff', '#09090b')}; background: ${cssManager.bdTheme('#ffffff', '#09090b')};
border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')}; border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
display: flex; display: flex;
align-items: center; align-items: center;
box-sizing: border-box;
} }
.topbar .heading { .topbar .heading {
@@ -81,7 +82,7 @@ export class DeesAppuiActivitylog extends DeesElement {
.activityContainer { .activityContainer {
position: absolute; position: absolute;
top: 40px; top: 48px;
bottom: 48px; bottom: 48px;
width: 100%; width: 100%;
padding: 12px 0px; padding: 12px 0px;
@@ -315,7 +316,7 @@ export class DeesAppuiActivitylog extends DeesElement {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 24px; height: 24px;
top: 40px; top: 48px;
background: ${cssManager.bdTheme( background: ${cssManager.bdTheme(
'linear-gradient(0deg, transparent 0%, #fafafa 100%)', 'linear-gradient(0deg, transparent 0%, #fafafa 100%)',
'linear-gradient(0deg, transparent 0%, #0a0a0a 100%)' 'linear-gradient(0deg, transparent 0%, #0a0a0a 100%)'

View File

@@ -89,6 +89,13 @@ export class DeesAppuiBase extends DeesElement {
@property({ type: Array }) @property({ type: Array })
accessor secondarymenuOptions: (interfaces.ISelectionOption | { divider: true })[] = []; accessor secondarymenuOptions: (interfaces.ISelectionOption | { divider: true })[] = [];
// Collapse states
@property({ type: Boolean })
accessor mainmenuCollapsed: boolean = false;
@property({ type: Boolean })
accessor secondarymenuCollapsed: boolean = false;
// Properties for maincontent // Properties for maincontent
@property({ type: Array }) @property({ type: Array })
accessor maincontentTabs: interfaces.ITab[] = []; accessor maincontentTabs: interfaces.ITab[] = [];
@@ -124,9 +131,30 @@ export class DeesAppuiBase extends DeesElement {
height: calc(100% - 40px); height: calc(100% - 40px);
width: 100%; width: 100%;
display: grid; display: grid;
grid-template-columns: 200px 240px 1fr 240px; grid-template-columns: auto auto 1fr 240px;
grid-template-rows: 1fr; grid-template-rows: 1fr;
} }
/* Z-index layering for proper stacking (position: relative required for z-index to work) */
.maingrid > dees-appui-mainmenu {
position: relative;
z-index: 3;
}
.maingrid > dees-appui-secondarymenu {
position: relative;
z-index: 2;
}
.maingrid > dees-appui-maincontent {
position: relative;
z-index: 1;
}
.maingrid > dees-appui-activitylog {
position: relative;
z-index: 1;
}
`, `,
]; ];
@@ -156,14 +184,18 @@ export class DeesAppuiBase extends DeesElement {
.bottomTabs=${this.mainmenuBottomTabs} .bottomTabs=${this.mainmenuBottomTabs}
.tabs=${this.mainmenuTabs} .tabs=${this.mainmenuTabs}
.selectedTab=${this.mainmenuSelectedTab} .selectedTab=${this.mainmenuSelectedTab}
.collapsed=${this.mainmenuCollapsed}
@tab-select=${(e: CustomEvent) => this.handleMainmenuTabSelect(e)} @tab-select=${(e: CustomEvent) => this.handleMainmenuTabSelect(e)}
@collapse-change=${(e: CustomEvent) => this.handleMainmenuCollapseChange(e)}
></dees-appui-mainmenu> ></dees-appui-mainmenu>
<dees-appui-secondarymenu <dees-appui-secondarymenu
.heading=${this.secondarymenuHeading} .heading=${this.secondarymenuHeading}
.groups=${this.secondarymenuGroups} .groups=${this.secondarymenuGroups}
.selectionOptions=${this.secondarymenuOptions} .selectionOptions=${this.secondarymenuOptions}
.selectedItem=${this.secondarymenuSelectedItem} .selectedItem=${this.secondarymenuSelectedItem}
.collapsed=${this.secondarymenuCollapsed}
@item-select=${(e: CustomEvent) => this.handleSecondarymenuItemSelect(e)} @item-select=${(e: CustomEvent) => this.handleSecondarymenuItemSelect(e)}
@collapse-change=${(e: CustomEvent) => this.handleSecondarymenuCollapseChange(e)}
></dees-appui-secondarymenu> ></dees-appui-secondarymenu>
<dees-appui-maincontent <dees-appui-maincontent
.tabs=${this.maincontentTabs} .tabs=${this.maincontentTabs}
@@ -244,4 +276,23 @@ export class DeesAppuiBase extends DeesElement {
composed: true composed: true
})); }));
} }
// Event handlers for collapse state changes
private handleMainmenuCollapseChange(e: CustomEvent) {
this.mainmenuCollapsed = e.detail.collapsed;
this.dispatchEvent(new CustomEvent('mainmenu-collapse-change', {
detail: e.detail,
bubbles: true,
composed: true
}));
}
private handleSecondarymenuCollapseChange(e: CustomEvent) {
this.secondarymenuCollapsed = e.detail.collapsed;
this.dispatchEvent(new CustomEvent('secondarymenu-collapse-change', {
detail: e.detail,
bubbles: true,
composed: true
}));
}
} }

View File

@@ -87,27 +87,74 @@ export class DeesAppuiMainmenu extends DeesElement {
@property() @property()
accessor selectedTab: interfaces.ITab; accessor selectedTab: interfaces.ITab;
@property({ type: Boolean, reflect: true })
accessor collapsed: boolean = false;
public static styles = [ public static styles = [
cssManager.defaultStyles, cssManager.defaultStyles,
css` css`
:host { :host {
--menu-width-expanded: 200px;
--menu-width-collapsed: 56px;
--tooltip-bg: ${cssManager.bdTheme('#18181b', '#fafafa')};
--tooltip-fg: ${cssManager.bdTheme('#fafafa', '#18181b')};
display: block; display: block;
height: 100%; height: 100%;
} }
.mainContainer { .mainContainer {
--menuWidth: 200px;
color: ${cssManager.bdTheme('#666', '#ccc')}; color: ${cssManager.bdTheme('#666', '#ccc')};
z-index: ${zIndexLayers.fixed.appBar}; z-index: ${zIndexLayers.fixed.appBar};
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative; position: relative;
width: var(--menuWidth); width: var(--menu-width-expanded);
height: 100%; height: 100%;
background: ${cssManager.bdTheme('#fafafa', '#0a0a0a')}; background: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
user-select: none; user-select: none;
border-right: 1px solid ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')}; border-right: 1px solid ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')};
font-family: 'Geist Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; font-family: 'Geist Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
transition: width 0.25s ease;
}
:host([collapsed]) .mainContainer {
width: var(--menu-width-collapsed);
}
/* Floating collapse toggle button */
.collapse-toggle {
position: absolute;
right: -12px;
top: 24px;
transform: translateY(-50%);
width: 24px;
height: 24px;
border-radius: 50%;
background: ${cssManager.bdTheme('#ffffff', '#27272a')};
border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#3f3f46')};
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
color: ${cssManager.bdTheme('#737373', '#a1a1aa')};
opacity: 0;
transition: opacity 0.2s ease, background 0.15s ease;
padding: 0;
}
.collapse-toggle:hover {
background: ${cssManager.bdTheme('#f4f4f5', '#3f3f46')};
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
}
:host(:hover) .collapse-toggle {
opacity: 1;
}
.collapse-toggle dees-icon {
font-size: 14px;
} }
/* Logo Section */ /* Logo Section */
@@ -115,23 +162,39 @@ export class DeesAppuiMainmenu extends DeesElement {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
padding: 16px 14px; height: 48px;
padding: 0 14px;
border-bottom: 1px solid ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')}; border-bottom: 1px solid ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')};
flex-shrink: 0; flex-shrink: 0;
box-sizing: border-box;
}
.logoSection .logoIcon {
font-size: 22px;
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
flex-shrink: 0;
} }
.logoSection dees-icon {
font-size: 22px;
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
}
.logoSection .logoText { .logoSection .logoText {
flex: 1;
font-size: 15px; font-size: 15px;
font-weight: 600; font-weight: 600;
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')}; color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
transition: opacity 0.2s ease, width 0.25s ease;
}
:host([collapsed]) .logoSection {
justify-content: center;
padding: 0 8px;
}
:host([collapsed]) .logoSection .logoText {
opacity: 0;
width: 0;
overflow: hidden;
} }
/* Middle Section (scrollable) */ /* Middle Section (scrollable) */
@@ -176,6 +239,17 @@ export class DeesAppuiMainmenu extends DeesElement {
color: ${cssManager.bdTheme('#737373', '#737373')}; color: ${cssManager.bdTheme('#737373', '#737373')};
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.5px; letter-spacing: 0.5px;
white-space: nowrap;
overflow: hidden;
transition: opacity 0.2s ease, max-height 0.25s ease;
max-height: 30px;
}
:host([collapsed]) .groupHeader {
opacity: 0;
max-height: 0;
padding: 0;
margin: 0;
} }
.groupTabs { .groupTabs {
@@ -184,6 +258,10 @@ export class DeesAppuiMainmenu extends DeesElement {
gap: 2px; gap: 2px;
} }
:host([collapsed]) .menuGroup {
padding: 0 4px;
}
/* Tab Item */ /* Tab Item */
.tab { .tab {
position: relative; position: relative;
@@ -240,6 +318,60 @@ export class DeesAppuiMainmenu extends DeesElement {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
transition: opacity 0.2s ease, width 0.25s ease;
}
/* Collapsed tab styles */
:host([collapsed]) .tab {
justify-content: center;
padding: 10px;
gap: 0;
}
:host([collapsed]) .tab .tabLabel {
opacity: 0;
width: 0;
position: absolute;
}
:host([collapsed]) .tab.selectedTab::before {
left: -4px;
}
/* Tooltip for collapsed state */
.tab-tooltip {
position: absolute;
left: 100%;
top: 50%;
transform: translateY(-50%);
margin-left: 12px;
padding: 6px 12px;
background: var(--tooltip-bg);
color: var(--tooltip-fg);
border-radius: 6px;
font-size: 13px;
font-weight: 500;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s ease;
z-index: 1000;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.tab-tooltip::before {
content: '';
position: absolute;
left: -4px;
top: 50%;
transform: translateY(-50%);
border: 4px solid transparent;
border-right-color: var(--tooltip-bg);
}
:host([collapsed]) .tab:hover .tab-tooltip {
opacity: 1;
transition-delay: 1s;
} }
/* Bottom Section */ /* Bottom Section */
@@ -251,6 +383,10 @@ export class DeesAppuiMainmenu extends DeesElement {
flex-direction: column; flex-direction: column;
gap: 2px; gap: 2px;
} }
:host([collapsed]) .bottomSection {
padding: 8px 4px;
}
`, `,
]; ];
@@ -259,6 +395,9 @@ export class DeesAppuiMainmenu extends DeesElement {
const allTabs = this.getAllTabs(); const allTabs = this.getAllTabs();
return html` return html`
<button class="collapse-toggle" @click="${() => this.toggleCollapse()}">
<dees-icon .icon="${this.collapsed ? 'lucide:chevronRight' : 'lucide:chevronLeft'}"></dees-icon>
</button>
<div class="mainContainer" @contextmenu=${(eventArg: MouseEvent) => { <div class="mainContainer" @contextmenu=${(eventArg: MouseEvent) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [{ DeesContextmenu.openContextMenuWithOptions(eventArg, [{
name: 'app settings', name: 'app settings',
@@ -268,7 +407,7 @@ export class DeesAppuiMainmenu extends DeesElement {
}}> }}>
${this.logoIcon || this.logoText ? html` ${this.logoIcon || this.logoText ? html`
<div class="logoSection"> <div class="logoSection">
${this.logoIcon ? html`<dees-icon .icon="${this.logoIcon}"></dees-icon>` : ''} ${this.logoIcon ? html`<dees-icon class="logoIcon" .icon="${this.logoIcon}"></dees-icon>` : ''}
${this.logoText ? html`<span class="logoText">${this.logoText}</span>` : ''} ${this.logoText ? html`<span class="logoText">${this.logoText}</span>` : ''}
</div> </div>
` : ''} ` : ''}
@@ -319,6 +458,7 @@ export class DeesAppuiMainmenu extends DeesElement {
> >
<dees-icon .icon="${tabArg.iconName || ''}"></dees-icon> <dees-icon .icon="${tabArg.iconName || ''}"></dees-icon>
<span class="tabLabel">${tabArg.key}</span> <span class="tabLabel">${tabArg.key}</span>
<span class="tab-tooltip">${tabArg.key}</span>
</div> </div>
`; `;
} }
@@ -349,4 +489,13 @@ export class DeesAppuiMainmenu extends DeesElement {
this.updateTab(allTabs[0]); this.updateTab(allTabs[0]);
} }
} }
public toggleCollapse(): void {
this.collapsed = !this.collapsed;
this.dispatchEvent(new CustomEvent('collapse-change', {
detail: { collapsed: this.collapsed },
bubbles: true,
composed: true
}));
}
} }

View File

@@ -89,11 +89,16 @@ export class DeesAppuiSecondarymenu extends DeesElement {
@state() @state()
accessor collapsedGroups: Set<string> = new Set(); accessor collapsedGroups: Set<string> = new Set();
/** Horizontal collapse state */
@property({ type: Boolean, reflect: true })
accessor collapsed: boolean = false;
public static styles = [ public static styles = [
cssManager.defaultStyles, cssManager.defaultStyles,
css` css`
:host { :host {
--sidebar-width: 240px; --sidebar-width-expanded: 240px;
--sidebar-width-collapsed: 56px;
--sidebar-bg: ${cssManager.bdTheme('#fafafa', '#0a0a0a')}; --sidebar-bg: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
--sidebar-fg: ${cssManager.bdTheme('#525252', '#a3a3a3')}; --sidebar-fg: ${cssManager.bdTheme('#525252', '#a3a3a3')};
--sidebar-fg-muted: ${cssManager.bdTheme('#737373', '#737373')}; --sidebar-fg-muted: ${cssManager.bdTheme('#737373', '#737373')};
@@ -102,6 +107,8 @@ export class DeesAppuiSecondarymenu extends DeesElement {
--sidebar-hover: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.06)')}; --sidebar-hover: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.06)')};
--sidebar-active: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.08)')}; --sidebar-active: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.08)')};
--sidebar-accent: ${cssManager.bdTheme('#0a0a0a', '#fafafa')}; --sidebar-accent: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
--tooltip-bg: ${cssManager.bdTheme('#18181b', '#fafafa')};
--tooltip-fg: ${cssManager.bdTheme('#fafafa', '#18181b')};
/* Badge colors */ /* Badge colors */
--badge-default-bg: ${cssManager.bdTheme('#f4f4f5', '#27272a')}; --badge-default-bg: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
@@ -115,11 +122,16 @@ export class DeesAppuiSecondarymenu extends DeesElement {
display: block; display: block;
height: 100%; height: 100%;
width: var(--sidebar-width); width: var(--sidebar-width-expanded);
background: var(--sidebar-bg); background: var(--sidebar-bg);
border-right: 1px solid var(--sidebar-border); border-right: 1px solid var(--sidebar-border);
font-family: 'Geist Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; font-family: 'Geist Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
user-select: none; user-select: none;
transition: width 0.25s ease;
}
:host([collapsed]) {
width: var(--sidebar-width-collapsed);
} }
.maincontainer { .maincontainer {
@@ -127,6 +139,43 @@ export class DeesAppuiSecondarymenu extends DeesElement {
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
position: relative;
}
/* Floating collapse toggle button */
.collapse-toggle {
position: absolute;
right: -12px;
top: 24px;
transform: translateY(-50%);
width: 24px;
height: 24px;
border-radius: 50%;
background: ${cssManager.bdTheme('#ffffff', '#27272a')};
border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#3f3f46')};
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
color: ${cssManager.bdTheme('#737373', '#a1a1aa')};
opacity: 0;
transition: opacity 0.2s ease, background 0.15s ease;
padding: 0;
}
.collapse-toggle:hover {
background: ${cssManager.bdTheme('#f4f4f5', '#3f3f46')};
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
}
:host(:hover) .collapse-toggle {
opacity: 1;
}
.collapse-toggle dees-icon {
font-size: 14px;
} }
/* Header Section */ /* Header Section */
@@ -134,18 +183,33 @@ export class DeesAppuiSecondarymenu extends DeesElement {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 16px 16px; height: 48px;
padding: 0 16px;
border-bottom: 1px solid var(--sidebar-border); border-bottom: 1px solid var(--sidebar-border);
flex-shrink: 0; flex-shrink: 0;
box-sizing: border-box;
} }
.header .heading { .header .heading {
flex: 1;
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
color: var(--sidebar-fg-active); color: var(--sidebar-fg-active);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
transition: opacity 0.2s ease, width 0.25s ease;
}
:host([collapsed]) .header {
justify-content: center;
padding: 0 8px;
}
:host([collapsed]) .header .heading {
opacity: 0;
width: 0;
overflow: hidden;
} }
/* Scrollable Menu Section */ /* Scrollable Menu Section */
@@ -179,6 +243,10 @@ export class DeesAppuiSecondarymenu extends DeesElement {
margin-bottom: 4px; margin-bottom: 4px;
} }
:host([collapsed]) .menuGroup {
padding: 0 4px;
}
.groupHeader { .groupHeader {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -186,7 +254,8 @@ export class DeesAppuiSecondarymenu extends DeesElement {
padding: 8px 8px; padding: 8px 8px;
cursor: pointer; cursor: pointer;
border-radius: 6px; border-radius: 6px;
transition: background 0.15s ease; transition: background 0.15s ease, opacity 0.2s ease, max-height 0.25s ease;
max-height: 40px;
} }
.groupHeader:hover { .groupHeader:hover {
@@ -202,6 +271,8 @@ export class DeesAppuiSecondarymenu extends DeesElement {
color: var(--sidebar-fg-muted); color: var(--sidebar-fg-muted);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.5px; letter-spacing: 0.5px;
white-space: nowrap;
overflow: hidden;
} }
.groupHeader .groupTitle dees-icon { .groupHeader .groupTitle dees-icon {
@@ -219,6 +290,15 @@ export class DeesAppuiSecondarymenu extends DeesElement {
transform: rotate(-90deg); transform: rotate(-90deg);
} }
/* Hide group headers when horizontally collapsed */
:host([collapsed]) .groupHeader {
opacity: 0;
max-height: 0;
padding: 0;
margin: 0;
pointer-events: none;
}
/* Group Items Container */ /* Group Items Container */
.groupItems { .groupItems {
overflow: hidden; overflow: hidden;
@@ -232,6 +312,12 @@ export class DeesAppuiSecondarymenu extends DeesElement {
opacity: 0; opacity: 0;
} }
/* Always show items when horizontally collapsed (regardless of group collapse state) */
:host([collapsed]) .groupItems {
max-height: none;
opacity: 1;
}
/* Menu Item */ /* Menu Item */
.menuItem { .menuItem {
position: relative; position: relative;
@@ -290,6 +376,60 @@ export class DeesAppuiSecondarymenu extends DeesElement {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
transition: opacity 0.2s ease, width 0.25s ease;
}
/* Collapsed menu item styles */
:host([collapsed]) .menuItem {
justify-content: center;
padding: 8px;
gap: 0;
}
:host([collapsed]) .menuItem .itemLabel {
opacity: 0;
width: 0;
position: absolute;
}
:host([collapsed]) .menuItem.selected::before {
left: -4px;
}
/* Tooltip for collapsed state */
.item-tooltip {
position: absolute;
left: 100%;
top: 50%;
transform: translateY(-50%);
margin-left: 12px;
padding: 6px 12px;
background: var(--tooltip-bg);
color: var(--tooltip-fg);
border-radius: 6px;
font-size: 13px;
font-weight: 500;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s ease;
z-index: 1000;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.item-tooltip::before {
content: '';
position: absolute;
left: -4px;
top: 50%;
transform: translateY(-50%);
border: 4px solid transparent;
border-right-color: var(--tooltip-bg);
}
:host([collapsed]) .menuItem:hover .item-tooltip {
opacity: 1;
transition-delay: 1s;
} }
/* Badge Styles */ /* Badge Styles */
@@ -326,6 +466,10 @@ export class DeesAppuiSecondarymenu extends DeesElement {
color: var(--badge-error-fg); color: var(--badge-error-fg);
} }
:host([collapsed]) .badge {
display: none;
}
/* Divider */ /* Divider */
.divider { .divider {
height: 1px; height: 1px;
@@ -342,6 +486,9 @@ export class DeesAppuiSecondarymenu extends DeesElement {
public render(): TemplateResult { public render(): TemplateResult {
return html` return html`
<button class="collapse-toggle" @click="${() => this.toggleCollapse()}">
<dees-icon .icon="${this.collapsed ? 'lucide:chevronRight' : 'lucide:chevronLeft'}"></dees-icon>
</button>
<div class="maincontainer"> <div class="maincontainer">
<div class="header"> <div class="header">
<span class="heading">${this.heading}</span> <span class="heading">${this.heading}</span>
@@ -390,6 +537,7 @@ export class DeesAppuiSecondarymenu extends DeesElement {
${item.badge !== undefined ? html` ${item.badge !== undefined ? html`
<span class="badge ${item.badgeVariant || 'default'}">${item.badge}</span> <span class="badge ${item.badgeVariant || 'default'}">${item.badge}</span>
` : ''} ` : ''}
<span class="item-tooltip">${item.key}</span>
</div> </div>
`; `;
} }
@@ -422,6 +570,15 @@ export class DeesAppuiSecondarymenu extends DeesElement {
this.collapsedGroups = newCollapsed; this.collapsedGroups = newCollapsed;
} }
public toggleCollapse(): void {
this.collapsed = !this.collapsed;
this.dispatchEvent(new CustomEvent('collapse-change', {
detail: { collapsed: this.collapsed },
bubbles: true,
composed: true
}));
}
private selectItem(item: interfaces.ISecondaryMenuItem, group?: interfaces.ISecondaryMenuGroup): void { private selectItem(item: interfaces.ISecondaryMenuItem, group?: interfaces.ISecondaryMenuGroup): void {
this.selectedItem = item; this.selectedItem = item;
item.action(); item.action();

View File

@@ -132,7 +132,9 @@ export class DeesAppuiTabs extends DeesElement {
} }
.tabs-wrapper.horizontal-wrapper { .tabs-wrapper.horizontal-wrapper {
height: 48px;
border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')}; border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
box-sizing: border-box;
} }
.tabsContainer { .tabsContainer {
@@ -146,7 +148,7 @@ export class DeesAppuiTabs extends DeesElement {
font-size: 14px; font-size: 14px;
overflow-x: auto; overflow-x: auto;
scrollbar-width: none; scrollbar-width: none;
height: 48px; height: 100%;
padding: 0 16px; padding: 0 16px;
gap: 4px; gap: 4px;
} }