feat(appui): add dees-appui-bottombar component with config, programmatic API, demo and docs
This commit is contained in:
@@ -663,6 +663,44 @@ export const demoFunc = () => {
|
||||
|
||||
defaultView: 'dashboard',
|
||||
|
||||
bottomBar: {
|
||||
visible: true,
|
||||
widgets: [
|
||||
{
|
||||
id: 'status',
|
||||
iconName: 'lucide:activity',
|
||||
label: 'System Online',
|
||||
status: 'success',
|
||||
tooltip: 'All systems operational',
|
||||
onClick: () => console.log('Status clicked'),
|
||||
},
|
||||
{
|
||||
id: 'notifications',
|
||||
iconName: 'lucide:bell',
|
||||
label: '3 notifications',
|
||||
status: 'warning',
|
||||
tooltip: 'You have unread notifications',
|
||||
onClick: () => console.log('Notifications clicked'),
|
||||
},
|
||||
{
|
||||
id: 'version',
|
||||
iconName: 'lucide:gitBranch',
|
||||
label: 'v1.2.3',
|
||||
position: 'right',
|
||||
tooltip: 'Current version',
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
id: 'terminal',
|
||||
iconName: 'lucide:terminal',
|
||||
tooltip: 'Open Terminal',
|
||||
position: 'right',
|
||||
onClick: () => console.log('Terminal clicked'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
onViewChange: (viewId, view) => {
|
||||
console.log(`View changed to: ${viewId} (${view.name})`);
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ import type { DeesAppuiMainmenu } from '../dees-appui-mainmenu/dees-appui-mainme
|
||||
import type { DeesAppuiSecondarymenu } from '../dees-appui-secondarymenu/dees-appui-secondarymenu.js';
|
||||
import type { DeesAppuiMaincontent } from '../dees-appui-maincontent/dees-appui-maincontent.js';
|
||||
import type { DeesAppuiActivitylog } from '../dees-appui-activitylog/dees-appui-activitylog.js';
|
||||
import type { DeesAppuiBottombar } from '../dees-appui-bottombar/dees-appui-bottombar.js';
|
||||
import { demoFunc } from './dees-appui.demo.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
|
||||
@@ -23,6 +24,7 @@ import { ViewRegistry } from './view.registry.js';
|
||||
|
||||
// Import child components
|
||||
import '../dees-appui-appbar/index.js';
|
||||
import '../dees-appui-bottombar/dees-appui-bottombar.js';
|
||||
import '../dees-appui-mainmenu/dees-appui-mainmenu.js';
|
||||
import '../dees-appui-secondarymenu/dees-appui-secondarymenu.js';
|
||||
import '../dees-appui-maincontent/dees-appui-maincontent.js';
|
||||
@@ -156,6 +158,12 @@ export class DeesAppui extends DeesElement {
|
||||
@state()
|
||||
accessor activitylogElement: DeesAppuiActivitylog | undefined = undefined;
|
||||
|
||||
@state()
|
||||
accessor bottombarElement: DeesAppuiBottombar | undefined = undefined;
|
||||
|
||||
@state()
|
||||
accessor bottombarVisible: boolean = true;
|
||||
|
||||
// Current view state
|
||||
@state()
|
||||
accessor currentView: interfaces.IViewDefinition | undefined = undefined;
|
||||
@@ -179,15 +187,27 @@ export class DeesAppui extends DeesElement {
|
||||
.maingrid {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
height: calc(100% - 40px);
|
||||
height: calc(100% - 40px - 24px);
|
||||
width: 100%;
|
||||
display: grid;
|
||||
/* grid-template-columns set dynamically in template */
|
||||
grid-template-rows: 1fr;
|
||||
transition: grid-template-columns 0.3s ease;
|
||||
transition: grid-template-columns 0.3s ease, height 0.3s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:host([bottombar-hidden]) .maingrid {
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
dees-appui-bottombar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
/* Z-index layering for proper stacking */
|
||||
.maingrid > dees-appui-mainmenu {
|
||||
position: relative;
|
||||
@@ -295,6 +315,9 @@ export class DeesAppui extends DeesElement {
|
||||
class="${this.activityLogVisible ? 'visible' : 'hidden'}"
|
||||
></dees-appui-activitylog>
|
||||
</div>
|
||||
${this.bottombarVisible ? html`
|
||||
<dees-appui-bottombar></dees-appui-bottombar>
|
||||
` : ''}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -305,6 +328,7 @@ export class DeesAppui extends DeesElement {
|
||||
this.secondarymenu = this.shadowRoot!.querySelector('dees-appui-secondarymenu') as DeesAppuiSecondarymenu;
|
||||
this.maincontent = this.shadowRoot!.querySelector('dees-appui-maincontent') as DeesAppuiMaincontent;
|
||||
this.activitylogElement = this.shadowRoot!.querySelector('dees-appui-activitylog') as DeesAppuiActivitylog;
|
||||
this.bottombarElement = this.shadowRoot!.querySelector('dees-appui-bottombar') as DeesAppuiBottombar;
|
||||
|
||||
// Subscribe to activity log entry changes for badge count
|
||||
if (this.activitylogElement) {
|
||||
@@ -730,6 +754,72 @@ export class DeesAppui extends DeesElement {
|
||||
return this.activityLogVisible;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// PROGRAMMATIC API: BOTTOM BAR
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Get the bottom bar API for widget/action management
|
||||
*/
|
||||
public get bottomBar(): interfaces.IBottomBarAPI {
|
||||
if (!this.bottombarElement) {
|
||||
// Return a deferred API that will work after firstUpdated
|
||||
return {
|
||||
addWidget: (widget) => {
|
||||
this.updateComplete.then(() => this.bottombarElement?.addWidget(widget));
|
||||
},
|
||||
updateWidget: (id, update) => {
|
||||
this.updateComplete.then(() => this.bottombarElement?.updateWidget(id, update));
|
||||
},
|
||||
removeWidget: (id) => {
|
||||
this.updateComplete.then(() => this.bottombarElement?.removeWidget(id));
|
||||
},
|
||||
getWidget: (id) => this.bottombarElement?.getWidget(id),
|
||||
clearWidgets: () => {
|
||||
this.updateComplete.then(() => this.bottombarElement?.clearWidgets());
|
||||
},
|
||||
addAction: (action) => {
|
||||
this.updateComplete.then(() => this.bottombarElement?.addAction(action));
|
||||
},
|
||||
removeAction: (id) => {
|
||||
this.updateComplete.then(() => this.bottombarElement?.removeAction(id));
|
||||
},
|
||||
clearActions: () => {
|
||||
this.updateComplete.then(() => this.bottombarElement?.clearActions());
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
addWidget: (widget) => this.bottombarElement!.addWidget(widget),
|
||||
updateWidget: (id, update) => this.bottombarElement!.updateWidget(id, update),
|
||||
removeWidget: (id) => this.bottombarElement!.removeWidget(id),
|
||||
getWidget: (id) => this.bottombarElement!.getWidget(id),
|
||||
clearWidgets: () => this.bottombarElement!.clearWidgets(),
|
||||
addAction: (action) => this.bottombarElement!.addAction(action),
|
||||
removeAction: (id) => this.bottombarElement!.removeAction(id),
|
||||
clearActions: () => this.bottombarElement!.clearActions(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bottom bar visibility
|
||||
*/
|
||||
public setBottomBarVisible(visible: boolean): void {
|
||||
this.bottombarVisible = visible;
|
||||
if (!visible) {
|
||||
this.setAttribute('bottombar-hidden', '');
|
||||
} else {
|
||||
this.removeAttribute('bottombar-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bottom bar visibility state
|
||||
*/
|
||||
public getBottomBarVisible(): boolean {
|
||||
return this.bottombarVisible;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// PROGRAMMATIC API: NAVIGATION
|
||||
// ==========================================
|
||||
@@ -842,6 +932,23 @@ export class DeesAppui extends DeesElement {
|
||||
}
|
||||
}
|
||||
|
||||
// Apply bottom bar config
|
||||
if (config.bottomBar) {
|
||||
this.setBottomBarVisible(config.bottomBar.visible ?? true);
|
||||
|
||||
if (config.bottomBar.widgets) {
|
||||
config.bottomBar.widgets.forEach(widget => {
|
||||
this.bottomBar.addWidget(widget);
|
||||
});
|
||||
}
|
||||
|
||||
if (config.bottomBar.actions) {
|
||||
config.bottomBar.actions.forEach(action => {
|
||||
this.bottomBar.addAction(action);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Setup domtools.router integration
|
||||
this.setupRouterIntegration(config);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user