import { DeesElement, html, property, customElement, css, type TemplateResult } from '@design.estate/dees-element'; import { idpElementStyles } from './tokens.js'; import './idp-badge.js'; import './idp-button.js'; import './idp-icon.js'; declare global { interface HTMLElementTagNameMap { 'idp-approval-card': IdpApprovalCard; } } @customElement('idp-approval-card') export class IdpApprovalCard extends DeesElement { public static demo = () => html` `; public static demoGroups = ['idp.global v3 approval surfaces']; @property({ type: String, attribute: 'app-name' }) public accessor appName = 'GitHub'; @property({ type: String, attribute: 'app-initials' }) public accessor appInitials = 'GH'; @property({ type: String, attribute: 'app-color' }) public accessor appColor = '#24292F'; @property({ type: String, attribute: 'request-text' }) public accessor requestText = 'Sign in to github.com'; @property({ type: String }) public accessor location = 'Berlin · DE'; @property({ type: String }) public accessor device = 'Safari · MacBook Pro'; @property({ type: String }) public accessor risk: 'trusted' | 'warning' | 'low' = 'trusted'; @property({ type: String, attribute: 'time-label' }) public accessor timeLabel = 'now'; @property({ type: Boolean, reflect: true }) public accessor primary = false; public static styles = [ ...idpElementStyles, css` :host { display: block; } .card { background: var(--idp-card); border: 1px solid var(--idp-border); border-radius: 12px; padding: 14px; color: var(--idp-fg); } :host([primary]) .card { border-color: var(--idp-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--idp-accent), transparent 92%); } .top { display: flex; gap: 12px; align-items: flex-start; } .avatar { width: 40px; height: 40px; border-radius: 8px; background: var(--app-color); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 750; letter-spacing: -0.03em; flex: 0 0 auto; } .body { flex: 1; min-width: 0; } .line { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .app { font-size: 14px; font-weight: 650; letter-spacing: -0.02em; } .time, .sub, .meta { color: var(--idp-muted-fg); } .time { font-size: 12px; } .sub { margin-top: 1px; font-size: 13px; } .meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 9px; font-size: 12px; } .meta-item { display: inline-flex; align-items: center; gap: 4px; } .actions { display: flex; gap: 8px; margin-top: 12px; } idp-button:first-child { flex: 1; } idp-button:last-child { flex: 2; } `, ]; private dispatchAction(actionArg: 'approve' | 'deny') { this.dispatchEvent(new CustomEvent(`idp-${actionArg}`, { detail: { appName: this.appName, requestText: this.requestText, }, bubbles: true, composed: true, })); } public render(): TemplateResult { const badgeVariant = this.risk === 'warning' ? 'warn' : 'ok'; const badgeText = this.risk === 'warning' ? 'new network' : 'trusted'; return html`
${this.appInitials}
${this.appName}
${this.timeLabel}
${this.requestText}
${this.location} ${this.device} ${badgeText}
this.dispatchAction('deny')}>Deny this.dispatchAction('approve')}>Approve
`; } }