diff --git a/.playwright-mcp/welcome-page.png b/.playwright-mcp/welcome-page.png new file mode 100644 index 0000000..e4ac07d Binary files /dev/null and b/.playwright-mcp/welcome-page.png differ diff --git a/npmextra.json b/npmextra.json index e7a7daf..1f536e0 100644 --- a/npmextra.json +++ b/npmextra.json @@ -31,7 +31,11 @@ "user data", "user sessions" ] - } + }, + "services": [ + "mongodb", + "minio" + ] }, "npmci": { "npmGlobalTools": [], diff --git a/ts_web/elements/idp-centercontainer.ts b/ts_web/elements/idp-centercontainer.ts index 2f62b83..6b9deb7 100644 --- a/ts_web/elements/idp-centercontainer.ts +++ b/ts_web/elements/idp-centercontainer.ts @@ -32,89 +32,279 @@ export class IdpCenterContainer extends DeesElement { cssManager.defaultStyles, css` :host { - font-family: 'Geist Sans'; + --background: hsl(240 10% 3.9%); + --foreground: hsl(0 0% 98%); + --muted: hsl(240 3.7% 15.9%); + --muted-foreground: hsl(240 5% 64.9%); + --border: hsl(240 3.7% 15.9%); + --card: hsl(240 6% 6%); + + font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif; position: absolute; width: 100%; height: 100%; + background: var(--background); } - .mainContainer { + .split-container { position: absolute; - top: 0px; + top: 0; + left: 0; width: 100%; height: 100%; + display: grid; + grid-template-columns: 45% 55%; + } + + /* Left Panel - Branding */ + .brand-panel { + background: linear-gradient(135deg, hsl(240 10% 8%) 0%, hsl(240 10% 4%) 50%, hsl(240 12% 6%) 100%); display: flex; + flex-direction: column; justify-content: center; - align-items: center; - opacity: 0; - transition: all 0.2s; - transition-delay: 0.05s; - transform: translate3d(0px, 8px, 0px); - pointer-events: none; - } - - .mainContainer.show { - opacity: 1; - pointer-events: all; - transform: translate3d(0px, 0px, 0px); - } - - .loginblock { - max-width: 500px; - flex-grow: 1; - transform: translate3d(0px, 0px, 0px); - transition: all 0.2s; - box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); - background: ${cssManager.bdTheme('#ffffff', '#111111')}; - border-top: 1px solid ${cssManager.bdTheme('#ffffff', '#222222')}; - border-radius: 16px; + padding: 48px; + position: relative; overflow: hidden; } - h1 { - font-size: 24px; - font-family: 'Cal Sans'; - text-align: center; - letter-spacing:0.0125em; + .brand-panel::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: radial-gradient(ellipse at 30% 20%, hsla(240 20% 20% / 0.3) 0%, transparent 50%), + radial-gradient(ellipse at 70% 80%, hsla(240 20% 15% / 0.2) 0%, transparent 50%); + pointer-events: none; } - .contentSpacer { - padding: 0px 0px 16px 0px; + .brand-content { + position: relative; + z-index: 1; + max-width: 400px; } - .legalinfo { + .logo { + font-family: 'Cal Sans', 'Geist Sans', sans-serif; + font-size: 42px; + font-weight: 600; + color: var(--foreground); + margin: 0 0 12px 0; + letter-spacing: -0.02em; + } + + .tagline { + font-size: 18px; + color: var(--muted-foreground); + margin: 0 0 48px 0; + line-height: 1.5; + } + + .features { + display: flex; + flex-direction: column; + gap: 28px; + } + + .feature { + display: flex; + align-items: flex-start; + gap: 16px; + } + + .feature-icon { + width: 40px; + height: 40px; + border-radius: 10px; + background: hsla(240 10% 20% / 0.5); + border: 1px solid hsla(240 10% 30% / 0.3); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + + .feature-icon dees-icon { + color: var(--muted-foreground); + font-size: 18px; + } + + .feature-text h3 { + font-size: 15px; + font-weight: 600; + color: var(--foreground); + margin: 0 0 4px 0; + } + + .feature-text p { + font-size: 14px; + color: var(--muted-foreground); + margin: 0; + line-height: 1.4; + } + + .learn-more { + margin-top: 48px; + } + + /* Right Panel - Form */ + .form-panel { + background: var(--card); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 48px; + position: relative; + border-left: 1px solid var(--border); + } + + .form-content { + width: 100%; + max-width: 400px; + transform: translateY(8px); + opacity: 0; + transition: all 0.3s ease; + } + + .form-content.show { + transform: translateY(0); + opacity: 1; + } + + .form-footer { + position: absolute; + bottom: 24px; + left: 0; + right: 0; text-align: center; - margin: auto; - color: ${cssManager.bdTheme('#666', '#ccc')}; font-size: 12px; - line-height: 100%; - padding: 8px; - background: ${cssManager.bdTheme('#f5f5f5', '#111')}; - border-top: 1px solid ${cssManager.bdTheme('#ccc', '#222222')}; - color: ${cssManager.bdTheme('#666', '#888')}; + color: var(--muted-foreground); } - .legalinfo a { - color: ${cssManager.bdTheme('#666', '#ccc')}; + .form-footer a { + color: var(--muted-foreground); text-decoration: none; + transition: color 0.15s ease; + } + + .form-footer a:hover { + color: var(--foreground); + } + + .form-footer .separator { + margin: 0 8px; + opacity: 0.5; + } + + .version { + margin-top: 8px; + font-size: 11px; + opacity: 0.6; + } + + /* Mobile Responsive */ + @media (max-width: 900px) { + .split-container { + grid-template-columns: 1fr; + grid-template-rows: auto 1fr; + } + + .brand-panel { + padding: 32px 24px; + min-height: auto; + } + + .brand-content { + max-width: 100%; + } + + .logo { + font-size: 32px; + } + + .tagline { + font-size: 16px; + margin-bottom: 24px; + } + + .features { + display: none; + } + + .form-panel { + border-left: none; + border-top: 1px solid var(--border); + padding: 32px 24px; + } } `, ]; render() { return html` -
-
-

idp.global

-
+
+ +
+
+

idp.global

+

Your permanent identity on the web

+ +
+
+
+ +
+
+

Open Source

+

Fully transparent, community-driven, no vendor lock-in

+
+
+ +
+
+ +
+
+

Always Free

+

Free for individuals and organizations. Paid support available for SLAs

+
+
+ +
+
+ +
+
+

Permanent Identity

+

One identity across all your applications

+
+
+
+ +
+ window.open('https://about.idp.global', '_blank')} + >Learn more +
+
+
+ + +
+
-
- Legal Info - | Company Website - | Support - | idp.global v${commitinfo.version} -
+
`; @@ -125,8 +315,8 @@ export class IdpCenterContainer extends DeesElement { const domtoolsInstance = await this.domtoolsPromise; const done = plugins.smartpromise.defer(); requestAnimationFrame(async () => { - this.shadowRoot.querySelector('.mainContainer').classList.add('show'); - await domtoolsInstance.convenience.smartdelay.delayFor(250); + this.shadowRoot.querySelector('.form-content').classList.add('show'); + await domtoolsInstance.convenience.smartdelay.delayFor(350); done.resolve(); }); return done.promise; @@ -137,8 +327,8 @@ export class IdpCenterContainer extends DeesElement { const domtoolsInstance = await this.domtoolsPromise; const done = plugins.smartpromise.defer(); requestAnimationFrame(async () => { - this.shadowRoot.querySelector('.mainContainer').classList.remove('show'); - await domtoolsInstance.convenience.smartdelay.delayFor(250); + this.shadowRoot.querySelector('.form-content').classList.remove('show'); + await domtoolsInstance.convenience.smartdelay.delayFor(350); done.resolve(); }); return done.promise; diff --git a/ts_web/elements/idp-loginprompt.ts b/ts_web/elements/idp-loginprompt.ts index 1813409..88ae30a 100644 --- a/ts_web/elements/idp-loginprompt.ts +++ b/ts_web/elements/idp-loginprompt.ts @@ -52,17 +52,56 @@ export class IdpLoginPrompt extends DeesElement { cssManager.defaultStyles, css` :host { - font-family: 'Geist Sans'; + --foreground: hsl(0 0% 98%); + --muted-foreground: hsl(240 5% 64.9%); + + font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif; display: block; - color: ${cssManager.bdTheme('#333333', '#ffffff')}; + color: var(--foreground); } - .boxcontent { - margin: 0px 20px; + .form-header { + margin-bottom: 32px; + text-align: center; } - .registerButton { - margin-top: 16px; + .form-header h2 { + font-size: 24px; + font-weight: 600; + color: var(--foreground); + margin: 0 0 8px 0; + letter-spacing: -0.02em; + } + + .form-header p { + font-size: 14px; + color: var(--muted-foreground); + margin: 0; + } + + dees-form { + display: flex; + flex-direction: column; + gap: 16px; + } + + .form-footer { + margin-top: 24px; + text-align: center; + font-size: 14px; + color: var(--muted-foreground); + } + + .form-footer a { + color: var(--foreground); + text-decoration: none; + font-weight: 500; + cursor: pointer; + transition: opacity 0.15s ease; + } + + .form-footer a:hover { + opacity: 0.8; } `, ]; @@ -70,34 +109,38 @@ export class IdpLoginPrompt extends DeesElement { public render(): TemplateResult { return html` -
- - - - - - { +
+

Sign in to your account

+

Enter your credentials to continue

+
+ + + + + + `; diff --git a/ts_web/elements/idp-registerprompt.ts b/ts_web/elements/idp-registerprompt.ts index 6b5d3c3..0ce4c07 100644 --- a/ts_web/elements/idp-registerprompt.ts +++ b/ts_web/elements/idp-registerprompt.ts @@ -52,29 +52,56 @@ export class IdpRegistrationPrompt extends DeesElement { cssManager.defaultStyles, css` :host { - font-family: 'Geist Sans'; + --foreground: hsl(0 0% 98%); + --muted-foreground: hsl(240 5% 64.9%); + + font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif; display: block; - color: ${cssManager.bdTheme('#333333', '#ffffff')}; + color: var(--foreground); } - .boxcontent { - margin: 0px 20px; + .form-header { + margin-bottom: 32px; + text-align: center; } - .registerButton { - display: block; - transition: all 0.2s ease; - will-change: transform; + .form-header h2 { + font-size: 24px; + font-weight: 600; + color: var(--foreground); + margin: 0 0 8px 0; + letter-spacing: -0.02em; + } + + .form-header p { + font-size: 14px; + color: var(--muted-foreground); + margin: 0; + } + + dees-form { + display: flex; + flex-direction: column; + gap: 16px; + } + + .form-footer { + margin-top: 24px; + text-align: center; + font-size: 14px; + color: var(--muted-foreground); + } + + .form-footer a { + color: var(--foreground); + text-decoration: none; + font-weight: 500; cursor: pointer; + transition: opacity 0.15s ease; } - .registerButton:hover { - color: #fff; - transform: scale(1.02); - } - - .loginButton { - margin-top: 16px; + .form-footer a:hover { + opacity: 0.8; } `, ]; @@ -82,29 +109,34 @@ export class IdpRegistrationPrompt extends DeesElement { public render(): TemplateResult { return html` -
- - - - Send Verification Email - - { +
+

Create your account

+

Get started with your permanent identity

+
+ + + + Send Verification Email + + `; diff --git a/ts_web/elements/idp-registration-stepper.ts b/ts_web/elements/idp-registration-stepper.ts index 79e43e2..2b90129 100644 --- a/ts_web/elements/idp-registration-stepper.ts +++ b/ts_web/elements/idp-registration-stepper.ts @@ -34,9 +34,13 @@ export class IdpRegistrationStepper extends DeesElement { cssManager.defaultStyles, css` :host { + --foreground: hsl(0 0% 98%); + --muted-foreground: hsl(240 5% 64.9%); + --background: hsl(240 10% 3.9%); + display: block; - height: 100px; - color: ${cssManager.bdTheme('#333', '#fff')}; + color: var(--foreground); + font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif; } .main { @@ -48,17 +52,37 @@ export class IdpRegistrationStepper extends DeesElement { display: flex; justify-content: center; align-items: center; + background: var(--background); + } + + .stepper-container { + width: 100%; + max-width: 480px; + padding: 48px 24px; + } + + .error-message { + text-align: center; + color: var(--muted-foreground); + font-size: 14px; + line-height: 1.6; + padding: 24px; + } + + dees-stepper { + --dees-stepper-background: transparent; } `, ]; public render(): TemplateResult { return html` -
- ${this.usedSubTemplate - ? this.usedSubTemplate - : html``} +
+ ${this.usedSubTemplate + ? this.usedSubTemplate + : html``} +
`; } @@ -71,8 +95,10 @@ export class IdpRegistrationStepper extends DeesElement { console.log(`validationToken is ${this.storedData.validationTokenUrlParam}`); if (!this.storedData.validationTokenUrlParam) { this.usedSubTemplate = html` - You need a validation token, but we couldn't find one. Please contact workspace.global - support. +
+ You need a validation token, but we couldn't find one.
+ Please contact support for assistance. +
`; await this.domtools.convenience.smartdelay.delayFor(5000); window.location.href = '/'; @@ -97,8 +123,10 @@ export class IdpRegistrationStepper extends DeesElement { if (!resAfterRegEmailClicked || !resAfterRegEmailClicked.email) { this.usedSubTemplate = html` - the supplied validation token does not match any registration sessions.
- ${tokenErrorMessage ? html`Reason: ${tokenErrorMessage}` : null} +
+ The supplied validation token does not match any registration sessions.
+ ${tokenErrorMessage ? html`
Reason: ${tokenErrorMessage}` : null} +
`; await this.domtools.convenience.smartdelay.delayFor(5000); idpState.domtools.router.pushUrl('/'); diff --git a/ts_web/elements/idp-welcome.ts b/ts_web/elements/idp-welcome.ts index 98024c8..5dfc539 100644 --- a/ts_web/elements/idp-welcome.ts +++ b/ts_web/elements/idp-welcome.ts @@ -28,86 +28,125 @@ export class IdpWelcome extends DeesElement { cssManager.defaultStyles, css` :host { + --foreground: hsl(0 0% 98%); + --muted-foreground: hsl(240 5% 64.9%); + display: block; - color: #fff; - font-family: 'Geist Sans'; + color: var(--foreground); + font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif; } + :host([hidden]) { display: none; } - .maincontainer { - padding: 0px 16px; + .form-header { + margin-bottom: 32px; + text-align: center; + } + + .form-header h2 { + font-size: 24px; + font-weight: 600; + color: var(--foreground); + margin: 0 0 8px 0; + letter-spacing: -0.02em; + } + + .form-header p { + font-size: 14px; + color: var(--muted-foreground); + margin: 0; + } + + .button-group { + display: flex; + flex-direction: column; + gap: 12px; + } + + .secondary-actions { + margin-top: 24px; + padding-top: 24px; + border-top: 1px solid hsla(240 3.7% 15.9% / 0.5); + display: flex; + flex-direction: column; + gap: 8px; } .greeting { + font-size: 14px; + color: var(--muted-foreground); text-align: center; - font-size: 16px; - font-weight: 600; - margin: 24px auto; + margin-bottom: 8px; } - dees-button { - margin-top: 16px; - margin-bottom: 16px; + .greeting strong { + color: var(--foreground); + font-weight: 600; } `, ]; public render(): TemplateResult { return html` - -
${directives.resolveExec(async () => { const idpState = await IdpState.getSingletonInstance(); await idpState.idpClient.determineLoginStatus(); const data = await idpState.idpClient.whoIs().catch(); if (data?.user) { return html` -
Hello ${data.user.data.name}!
- { - const idpState = await IdpState.getSingletonInstance(); - idpState.domtools.router.pushUrl('/account'); - }} - >Manage your account - { - const idpState = await IdpState.getSingletonInstance(); - idpState.domtools.router.pushUrl('/logout'); - }} - >Logout +
+

Welcome back

+

Signed in as ${data.user.data.name}

+
+
+ { + const idpState = await IdpState.getSingletonInstance(); + idpState.domtools.router.pushUrl('/account'); + }} + >Manage your account + { + const idpState = await IdpState.getSingletonInstance(); + idpState.domtools.router.pushUrl('/logout'); + }} + >Sign out +
`; } return html` - Do you want to sign in or register? - { - const idpState = await IdpState.getSingletonInstance(); - idpState.domtools.router.pushUrl('/login'); - }} - >Sign In - { - const idpState = await IdpState.getSingletonInstance(); - idpState.domtools.router.pushUrl('/register'); - }} - >Register +
+

Welcome

+

Sign in to your account or create a new one

+
+
+ { + const idpState = await IdpState.getSingletonInstance(); + idpState.domtools.router.pushUrl('/login'); + }} + >Sign In + { + const idpState = await IdpState.getSingletonInstance(); + idpState.domtools.router.pushUrl('/register'); + }} + >Create Account +
`; })} - {}}>Learn more about idp.global - {}}>Open Developer Dashboard - { - window.open('https://code.foss.global/idp.global/idp.global', '_blank'); - }} - >Get the Source Code +
+ { + window.open('https://code.foss.global/idp.global/idp.global', '_blank'); + }} + >View Source Code
`;