Files
catalog/ts_web/elements/idp-mobile-showcase.ts
T

288 lines
9.4 KiB
TypeScript

import { DeesElement, html, customElement, css, type TemplateResult } from '@design.estate/dees-element';
import { idpElementStyles } from './tokens.js';
import './idp-button.js';
import './idp-icon.js';
import './idp-inbox-preview.js';
import './idp-mobile-frame.js';
declare global {
interface HTMLElementTagNameMap {
'idp-mobile-showcase': IdpMobileShowcase;
}
}
@customElement('idp-mobile-showcase')
export class IdpMobileShowcase extends DeesElement {
public static demo = () => html`<idp-mobile-showcase></idp-mobile-showcase>`;
public static demoGroups = ['idp.global v3 full pages'];
public static styles = [
...idpElementStyles,
css`
:host {
display: block;
}
.showcase {
min-height: 100vh;
padding: 56px;
background: radial-gradient(circle at 1px 1px, rgba(0,0,0,0.08) 1px, transparent 0) 0 0 / 24px 24px, #fafafa;
color: #09090b;
}
.head {
max-width: 1180px;
margin: 0 auto 44px;
}
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
margin-bottom: 16px;
padding: 4px 10px;
border: 1px solid #e4e4e7;
border-radius: 999px;
background: #fff;
color: #52525b;
font-size: 11px;
font-weight: 500;
}
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #16a34a;
}
h1 {
max-width: 900px;
margin: 0 0 14px;
font-family: var(--idp-display);
font-size: clamp(36px, 5vw, 56px);
font-weight: 750;
letter-spacing: -0.035em;
line-height: 1.05;
}
p {
max-width: 680px;
margin: 0;
color: #52525b;
font-size: 16px;
line-height: 1.55;
}
.tokens {
display: flex;
flex-wrap: wrap;
gap: 24px;
margin-top: 24px;
padding: 16px;
border: 1px solid #e4e4e7;
border-radius: 12px;
background: #fff;
}
.token-label {
margin-bottom: 4px;
color: #71717a;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.token-value {
display: flex;
align-items: center;
gap: 8px;
color: #18181b;
font-size: 13px;
font-weight: 550;
}
.swatch {
width: 18px;
height: 18px;
border-radius: 5px;
background: var(--swatch);
border: 1px solid #e4e4e7;
}
.section {
max-width: 1180px;
margin: 0 auto 56px;
}
.section-title {
margin-bottom: 18px;
color: #71717a;
font-family: var(--idp-mono);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
}
.phones {
display: grid;
grid-template-columns: repeat(2, minmax(300px, 402px));
gap: 28px;
align-items: start;
}
.multi {
display: grid;
grid-template-columns: 280px minmax(0, 1fr) 360px;
gap: 28px;
align-items: start;
}
.watch, .ipad, .mac {
border: 1px solid #e4e4e7;
background: #fff;
box-shadow: 0 20px 50px rgba(0,0,0,0.08);
}
.watch {
width: 236px;
height: 286px;
display: grid;
place-items: center;
border-radius: 60px;
background: #09090b;
color: #fafafa;
}
.watch-screen {
width: 178px;
display: grid;
gap: 12px;
text-align: center;
}
.watch-app {
color: #a1a1aa;
font-family: var(--idp-mono);
font-size: 10px;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.watch-title {
font-size: 18px;
font-weight: 700;
}
.watch-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.watch-actions button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 5px;
height: 34px;
border: 1px solid #27272a;
border-radius: 999px;
background: #18181b;
color: #fafafa;
}
.watch-actions .approve {
background: #3b82f6;
border-color: #3b82f6;
}
.ipad {
min-height: 520px;
overflow: hidden;
border-radius: 26px;
}
.ipad-shell {
display: grid;
grid-template-columns: 220px 1fr;
min-height: 520px;
}
.ipad-sidebar {
padding: 18px;
border-right: 1px solid #e4e4e7;
background: #f8f8f7;
}
.ipad-main {
padding: 22px;
}
.ipad-card {
display: flex;
align-items: flex-start;
gap: 10px;
margin-top: 16px;
padding: 16px;
border: 1px solid #e4e4e7;
border-radius: 12px;
}
.mac {
overflow: hidden;
border-radius: 14px;
}
.mac-bar {
display: flex;
gap: 6px;
padding: 11px 14px;
border-bottom: 1px solid #e4e4e7;
}
.tdot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.mac-body {
display: grid;
gap: 12px;
padding: 18px;
}
.mac-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 12px;
border: 1px solid #e4e4e7;
border-radius: 10px;
}
.row-label {
display: inline-flex;
align-items: center;
gap: 8px;
}
@media (max-width: 1120px) {
.multi {
grid-template-columns: 1fr;
}
}
@media (max-width: 900px) {
.showcase {
padding: 28px;
}
.phones {
grid-template-columns: 1fr;
}
}
`,
];
public render(): TemplateResult {
return html`
<div class="showcase">
<header class="head">
<div class="badge"><span class="dot"></span>Mobile redesign - v3 - shadcn tokens</div>
<h1>A personal identity provider, built across every device you carry.</h1>
<p>Same four-platform architecture: flat surfaces, 1px borders, neutral palette, and blue accent used only where action is expected.</p>
<div class="tokens">
${[
['Primary', '#18181b', 'zinc-900'],
['Accent', '#0050b9', 'idp blue'],
['Muted', '#f4f4f2', 'paper muted'],
['Border', '#e4e4e7', 'zinc-200'],
].map((tokenArg) => html`<div><div class="token-label">${tokenArg[0]}</div><div class="token-value"><span class="swatch" style="--swatch:${tokenArg[1]}"></span>${tokenArg[2]}</div></div>`)}
</div>
</header>
<section class="section">
<div class="section-title">iPhone</div>
<div class="phones"><idp-inbox-preview></idp-inbox-preview><idp-inbox-preview dark></idp-inbox-preview></div>
</section>
<section class="section">
<div class="section-title">Watch, iPad, Mac</div>
<div class="multi">
<div class="watch"><div class="watch-screen"><div class="watch-app">idp.global</div><idp-icon name="shield" size="28" style="margin:0 auto;color:#60a5fa"></idp-icon><div class="watch-title">GitHub wants access</div><div style="color:#a1a1aa;font-size:12px;">repo:read - Berlin</div><div class="watch-actions"><button><idp-icon name="x" size="13"></idp-icon>Deny</button><button class="approve"><idp-icon name="check" size="13"></idp-icon>Approve</button></div></div></div>
<div class="ipad"><div class="ipad-shell"><aside class="ipad-sidebar"><strong>Inbox</strong><p>3 pending approvals</p><div class="ipad-card"><idp-icon name="globe" size="16"></idp-icon><div><strong>GitHub OAuth</strong><br/><span style="color:#71717a">repo:read - now</span></div></div><div class="ipad-card"><idp-icon name="cloud" size="16"></idp-icon><div><strong>Hetzner Cloud</strong><br/><span style="color:#71717a">new network - 8m</span></div></div></aside><main class="ipad-main"><h2>Approval detail</h2><p>Full context before a sensitive action is approved.</p><div class="ipad-card"><idp-icon name="laptop" size="16"></idp-icon><div><strong>Device</strong><br/>MacBook Pro - Safari - Berlin, DE</div></div><div class="ipad-card"><idp-icon name="key" size="16"></idp-icon><div><strong>Requested scopes</strong><br/>openid, profile, email, repo:read</div></div></main></div></div>
<div class="mac"><div class="mac-bar"><span class="tdot" style="background:#ff5f57"></span><span class="tdot" style="background:#ffbd2e"></span><span class="tdot" style="background:#28c840"></span></div><div class="mac-body"><strong>Menu bar approvals</strong><div class="mac-row"><span class="row-label"><idp-icon name="globe" size="15"></idp-icon>GitHub OAuth</span><idp-button variant="accent" size="sm" icon="check">Approve</idp-button></div><div class="mac-row"><span class="row-label"><idp-icon name="nfc" size="15"></idp-icon>NFC tap - door 4F</span><idp-button variant="ghost" size="sm" icon="chevron-right">Review</idp-button></div><div class="mac-row"><span class="row-label"><idp-icon name="key" size="15"></idp-icon>Key rotation</span><idp-button variant="ghost" size="sm" icon="shield">Confirm</idp-button></div></div></div>
</div>
</section>
</div>
`;
}
}