diff --git a/ts_web/elements/dees-appui-base.demo.ts b/ts_web/elements/dees-appui-base.demo.ts
index e5b17f1..f8b995e 100644
--- a/ts_web/elements/dees-appui-base.demo.ts
+++ b/ts_web/elements/dees-appui-base.demo.ts
@@ -104,8 +104,10 @@ export const demoFunc = () => {
+
+ {
+ console.log('Logout event triggered');
+ alert('Logout clicked!');
+ }}
+ @view-select=${(e: CustomEvent) => {
+ console.log('View selected:', e.detail.view.name);
+ }}
+ >
+
`;
diff --git a/ts_web/elements/dees-simple-appdash.ts b/ts_web/elements/dees-simple-appdash.ts
index 77f63a3..4c1fff7 100644
--- a/ts_web/elements/dees-simple-appdash.ts
+++ b/ts_web/elements/dees-simple-appdash.ts
@@ -1,5 +1,4 @@
import { demoFunc } from './dees-simple-appdash.demo.js';
-import * as colors from './00colors.js';
import {
customElement,
@@ -14,7 +13,8 @@ import {
state,
domtools,
} from '@design.estate/dees-element';
-import { DeesTerminal } from './dees-terminal.js';
+import './dees-icon.js';
+import type { DeesTerminal } from './dees-terminal.js';
declare global {
interface HTMLElementTagNameMap {
@@ -24,6 +24,7 @@ declare global {
export interface IView {
name: string;
+ iconName?: string;
element: DeesElement['constructor']['prototype'];
}
@@ -34,13 +35,17 @@ export class DeesSimpleAppDash extends DeesElement {
// INSTANCE
@property()
- public name = 'Dees Simple Login';
+ public name: string = 'Application Dashboard';
- @property()
+ @property({ type: Array })
public viewTabs: IView[] = [];
+
+ @property({ type: String })
+ public terminalSetupCommand: string = `echo "Terminal ready"`;
+
+ @state()
+ private selectedView: IView;
- @property()
- public terminalSetupCommand: string = `pnpm install @serve.zone/cli && clear && servezone info`;
public static styles = [
cssManager.defaultStyles,
@@ -69,54 +74,110 @@ export class DeesSimpleAppDash extends DeesElement {
top: 0px;
left: 0px;
height: calc(100% - 24px);
- width: 200px;
- background: ${cssManager.bdTheme('#eeeeeb', '#000')};
- border-right: 1px solid ${cssManager.bdTheme('#ccc', '#ffffff20')};
- font-size: 14px;
- line-height: 32px;
+ width: 240px;
+ background: ${cssManager.bdTheme('#fafafa', '#000')};
+ border-right: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
+ font-size: 12px;
font-family: 'Geist Sans', sans-serif;
- padding: 0px 16px;
z-index: 2;
- box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.8);
display: grid;
- grid-template-rows: min-content auto min-content;
+ grid-template-rows: auto min-content;
+ overflow: hidden;
}
- .appbar .viewTabs {
- margin-left: -8px;
- margin-right: -8px;
+ .sidebar-header {
+ padding: 16px 12px;
+ border-bottom: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .appName {
+ font-size: 14px;
+ font-weight: 600;
+ color: ${cssManager.bdTheme('#000', '#fff')};
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .viewTabs-container {
+ flex: 1;
+ overflow-y: auto;
+ padding: 4px 0;
+ }
+
+ .viewTabs {
display: flex;
flex-direction: column;
- align-items: top;
}
.viewTab {
- padding: 0px 8px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px 12px;
+ cursor: default;
+ transition: background 0.1s;
+ color: ${cssManager.bdTheme('#333', '#ccc')};
+ user-select: none;
+ position: relative;
}
.viewTab:hover {
- background: ${cssManager.bdTheme('#ccc', '#ffffff10')};
- color: ${cssManager.bdTheme('#000', '#fff')};
+ background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.08)')};
}
.viewTab:active {
- background: ${cssManager.bdTheme('#aaa', '#ffffff20')};
+ background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.12)')};
+ }
+
+ .viewTab.selected {
+ background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.12)')};
color: ${cssManager.bdTheme('#000', '#fff')};
+ font-weight: 500;
+ }
+
+ .viewTab.selected::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ width: 3px;
+ background: ${cssManager.bdTheme('#26a69a', '#26a69a')};
+ }
+
+ .viewTab dees-icon {
+ font-size: 14px;
+ opacity: 0.7;
}
- .appName {
- white-space: nowrap;
- color: ${cssManager.bdTheme('#666', '#999')};
- }
.appActions {
- display: flex;
+ padding: 12px;
+ border-top: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
}
- .appActions .action {
+ .action {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px;
+ border-radius: 4px;
+ cursor: default;
+ transition: background 0.1s;
+ color: ${cssManager.bdTheme('#333', '#ccc')};
}
- .appActions .action:hover {
- color: ${cssManager.bdTheme('#000', '#fff')};
+
+ .action:hover {
+ background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.08)')};
+ }
+
+ .action dees-icon {
+ font-size: 14px;
+ opacity: 0.7;
}
.appcontent {
@@ -124,37 +185,50 @@ export class DeesSimpleAppDash extends DeesElement {
position: absolute;
top: 0px;
right: 0px;
- height: calc(100vh - 24px);
+ height: calc(100% - 24px);
bottom: 24px;
- width: calc(100vw - 200px);
+ width: calc(100% - 240px);
overflow: auto;
- background: ${cssManager.bdTheme('#eeeeeb', '#000')};
+ background: ${cssManager.bdTheme('#f5f5f5', '#000')};
overscroll-behavior: contain;
}
-
+
.controlbar {
color: #fff;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
- border-top: 1px solid #44444480;
+ border-top: 1px solid ${cssManager.bdTheme('#00000020', '#ffffff20')};
height: 24px;
- background: ${cssManager.bdTheme(colors.bright.blueMuted, colors.dark.blueMuted)};
+ background: ${cssManager.bdTheme('#2196f3', '#1565c0')};
z-index: 2;
display: flex;
justify-content: flex-end;
align-items: center;
flex-direction: row;
- box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.8);
+ font-size: 12px;
}
.control {
- width: min-content;
+ display: flex;
+ align-items: center;
+ gap: 4px;
margin-right: 16px;
- font-size: 12px;
white-space: nowrap;
+ cursor: default;
+ opacity: 0.8;
+ transition: opacity 0.2s;
}
+
+ .control:hover {
+ opacity: 1;
+ }
+
+ .control dees-icon {
+ font-size: 14px;
+ }
+
`,
];
@@ -162,31 +236,49 @@ export class DeesSimpleAppDash extends DeesElement {
return html`
-
${this.name}
-
- ${this.viewTabs.map(
- (view) => html`
-
{
- this.loadView(view);
- }}>${view.name}
- `
- )}
+
+
+
+
+ ${this.viewTabs.map(
+ (view) => html`
+
this.loadView(view)}
+ >
+ ${view.iconName ? html`
+
+ ` : ''}
+ ${view.name}
+
+ `
+ )}
+
+
{
- this.dispatchEvent(new CustomEvent('logout'));
- }}>Logout
+ this.dispatchEvent(new CustomEvent('logout', { bubbles: true, composed: true }));
+ }}>
+
+
Logout
+
-
+
-
+
+ Connected
-
+
+ Terminal
@@ -196,30 +288,58 @@ export class DeesSimpleAppDash extends DeesElement {
public async firstUpdated(_changedProperties): Promise {
const domtools = await this.domtoolsPromise;
super.firstUpdated(_changedProperties);
- await this.loadView(this.viewTabs[0]);
+ if (this.viewTabs && this.viewTabs.length > 0) {
+ await this.loadView(this.viewTabs[0]);
+ }
}
-
+
public currentTerminal: DeesTerminal;
public async launchTerminal() {
+ const domtools = await this.domtoolsPromise;
+ if (this.currentTerminal) {
+ // If terminal already exists, remove it
+ await this.closeTerminal();
+ return;
+ }
+
const maincontainer = this.shadowRoot.querySelector('.maincontainer');
+ const { DeesTerminal } = await import('./dees-terminal.js');
const terminal = new DeesTerminal();
terminal.setupCommand = this.terminalSetupCommand;
this.currentTerminal = terminal;
maincontainer.appendChild(terminal);
terminal.style.position = 'absolute';
- terminal.style.zIndex = '1';
+ terminal.style.zIndex = '10';
terminal.style.top = '0px';
- terminal.style.left = '200px';
+ terminal.style.left = '240px';
terminal.style.right = '0px';
terminal.style.bottom = '24px';
terminal.style.opacity = '0';
terminal.style.transform = 'translateY(20px)';
terminal.style.transition = 'all 0.2s';
- await domtools.plugins.smartdelay.delayFor(0);
+ terminal.style.background = '#000';
+ terminal.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.3)';
+
+ // Add close button to terminal
+ terminal.addEventListener('close', () => this.closeTerminal());
+
+ await domtools.convenience.smartdelay.delayFor(0);
terminal.style.opacity = '1';
terminal.style.transform = 'translateY(0px)';
return terminal;
}
+
+ private async closeTerminal() {
+ const domtools = await this.domtoolsPromise;
+ if (this.currentTerminal) {
+ this.currentTerminal.style.opacity = '0';
+ this.currentTerminal.style.transform = 'translateY(20px)';
+ await domtools.convenience.smartdelay.delayFor(200);
+ this.currentTerminal.remove();
+ this.currentTerminal = null;
+ }
+ }
+
private currentView: DeesElement;
public async loadView(viewArg: IView) {
@@ -230,5 +350,13 @@ export class DeesSimpleAppDash extends DeesElement {
}
appcontent.appendChild(view);
this.currentView = view;
+ this.selectedView = viewArg;
+
+ // Emit view-select event
+ this.dispatchEvent(new CustomEvent('view-select', {
+ detail: { view: viewArg },
+ bubbles: true,
+ composed: true
+ }));
}
}
diff --git a/ts_web/elements/dees-simple-login.demo.ts b/ts_web/elements/dees-simple-login.demo.ts
index 27e7aac..7e708cb 100644
--- a/ts_web/elements/dees-simple-login.demo.ts
+++ b/ts_web/elements/dees-simple-login.demo.ts
@@ -1,3 +1,31 @@
import { html } from '@design.estate/dees-element';
-export const demoFunc = () => html` Hello there `;
+export const demoFunc = () => html`
+
+
+
{
+ console.log('Login event received:', e.detail);
+ alert(`Login attempted with:\nUsername: ${e.detail.formData.username}\nPassword: ${e.detail.formData.password}`);
+ }}
+ >
+
+
Welcome!
+
This is the slotted content that appears after login.
+
+
+
+`;
diff --git a/ts_web/elements/dees-simple-login.ts b/ts_web/elements/dees-simple-login.ts
index 5311b77..37b6943 100644
--- a/ts_web/elements/dees-simple-login.ts
+++ b/ts_web/elements/dees-simple-login.ts
@@ -26,51 +26,77 @@ export class DeesSimpleLogin extends DeesElement {
// INSTANCE
@property()
- public name = 'Dees Simple Login';
+ public name: string = 'Application';
public static styles = [
cssManager.defaultStyles,
css`
:host {
- color: ${cssManager.bdTheme('#333', '#fff')};
+ color: ${cssManager.bdTheme('#333', '#ccc')};
user-select: none;
+ display: block;
+ width: 100%;
+ height: 100%;
+ font-family: 'Geist Sans', sans-serif;
}
+
.loginContainer {
position: absolute;
display: flex;
- justify-content: center; /* aligns horizontally */
- align-items: center; /* aligns vertically */
+ justify-content: center;
+ align-items: center;
width: 100%;
height: 100%;
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
+ background: ${cssManager.bdTheme('#f5f5f5', '#000')};
}
.slotContainer {
position: absolute;
width: 100%;
height: 100%;
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
+ opacity: 0;
+ transition: opacity 0.3s, transform 0.3s;
+ pointer-events: none;
}
.login {
min-width: 320px;
- min-height: 100px;
- background: ${cssManager.bdTheme('#eeeeeb', '#111')};
- box-shadow: ${cssManager.bdTheme('0px 1px 4px rgba(0,0,0,0.3)', 'none')};
+ background: ${cssManager.bdTheme('#ffffff', '#111')};
+ box-shadow: ${cssManager.bdTheme(
+ '0 4px 12px rgba(0, 0, 0, 0.15)',
+ '0 4px 12px rgba(0, 0, 0, 0.3)'
+ )};
border-radius: 8px;
+ border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
padding: 24px;
transition: opacity 0.3s, transform 0.3s;
}
.header {
text-align: center;
+ font-size: 16px;
+ font-weight: 600;
+ margin-bottom: 20px;
+ color: ${cssManager.bdTheme('#000', '#fff')};
}
- .slotContainer {
- opacity:0;
- transition: opacity 0.3s, transform 0.3s;
- pointer-events: none;
+
+ .login dees-form {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ }
+
+ .login dees-input-text {
+ width: 100%;
+ }
+
+ .login dees-form-submit {
+ margin-top: 4px;
+ width: 100%;
}
`,
];
@@ -79,11 +105,11 @@ export class DeesSimpleLogin extends DeesElement {
return html`
+
-
-
-
- login
+
+
+ Login
@@ -102,7 +128,7 @@ export class DeesSimpleLogin extends DeesElement {
const password = this.shadowRoot.querySelector('dees-input-text[label="password"]');
const submit = this.shadowRoot.querySelector('dees-form-submit');
form.addEventListener('formData', (event: CustomEvent) => {
- this.dispatchEvent(new CustomEvent('login', { detail: event.detail }));
+ this.dispatchEvent(new CustomEvent('login', { detail: event.detail, bubbles: true, composed: true }));
});
}
@@ -123,8 +149,5 @@ export class DeesSimpleLogin extends DeesElement {
slotContainerDiv.style.transform = 'translateY(0px)';
await domtools.convenience.smartdelay.delayFor(300);
slotContainerDiv.style.pointerEvents = 'all';
-
-
-
}
}