From bdb666cbe21ae3aa0b56cac6502232d9d81af373 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Tue, 17 Jun 2025 11:45:25 +0000 Subject: [PATCH] feat: Enhance demo components with improved layout, styling, and functionality for login and dashboard views --- ts_web/elements/dees-appui-base.demo.ts | 6 +- ts_web/elements/dees-simple-appdash.demo.ts | 197 ++++++++++++++-- ts_web/elements/dees-simple-appdash.ts | 244 +++++++++++++++----- ts_web/elements/dees-simple-login.demo.ts | 30 ++- ts_web/elements/dees-simple-login.ts | 69 ++++-- 5 files changed, 445 insertions(+), 101 deletions(-) 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`
@@ -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'; - - - } }