Files
catalog_admin/ts_web/elements/upladmin-option-card/upladmin-option-card.ts

179 lines
5.2 KiB
TypeScript

import {
DeesElement,
property,
html,
customElement,
type TemplateResult,
css,
cssManager,
unsafeCSS,
} from '@design.estate/dees-element';
import * as sharedStyles from '../../styles/shared.styles.js';
import { demoFunc } from './upladmin-option-card.demo.js';
declare global {
interface HTMLElementTagNameMap {
'upladmin-option-card': UpladminOptionCard;
}
}
export type TOptionVariant =
// Severity variants
| 'critical' | 'major' | 'minor' | 'maintenance'
// Status variants
| 'investigating' | 'identified' | 'monitoring' | 'resolved' | 'postmortem'
// Generic variants
| 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
@customElement('upladmin-option-card')
export class UpladminOptionCard extends DeesElement {
public static demo = demoFunc;
@property({ type: String })
accessor icon: string = '';
@property({ type: String })
accessor label: string = '';
@property({ type: String })
accessor description: string = '';
@property({ type: String, reflect: true })
accessor variant: TOptionVariant = 'default';
@property({ type: Boolean, reflect: true })
accessor selected: boolean = false;
@property({ type: Boolean, reflect: true })
accessor disabled: boolean = false;
public static styles = [
cssManager.defaultStyles,
css`
:host {
display: block;
font-family: ${unsafeCSS(sharedStyles.fonts.base)};
}
.option-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 18px 14px;
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
border: 2px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
border-radius: 6px;
cursor: pointer;
transition: all 0.1s ease;
text-align: center;
user-select: none;
}
.option-card:hover:not(.disabled) {
border-color: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
}
:host([selected]) .option-card {
border-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
background: ${cssManager.bdTheme('rgba(59, 130, 246, 0.05)', 'rgba(96, 165, 250, 0.1)')};
}
:host([disabled]) .option-card {
opacity: 0.5;
cursor: not-allowed;
}
.option-label {
font-size: 13px;
font-weight: 600;
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
}
.option-desc {
font-size: 11px;
color: ${cssManager.bdTheme('#a1a1aa', '#71717a')};
line-height: 1.3;
}
/* Variant icon colors - all using bdTheme for proper light/dark support */
/* Severity variants */
:host([variant="critical"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#dc2626', '#f87171')};
}
:host([variant="major"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#ea580c', '#fb923c')};
}
:host([variant="minor"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#ca8a04', '#fbbf24')};
}
:host([variant="maintenance"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
}
/* Status variants */
:host([variant="investigating"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#ea580c', '#fb923c')};
}
:host([variant="identified"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#ca8a04', '#fbbf24')};
}
:host([variant="monitoring"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
}
:host([variant="resolved"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
}
:host([variant="postmortem"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#9333ea', '#a855f7')};
}
/* Generic variants */
:host([variant="default"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
}
:host([variant="primary"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
}
:host([variant="success"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
}
:host([variant="warning"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#ca8a04', '#fbbf24')};
}
:host([variant="danger"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#dc2626', '#f87171')};
}
:host([variant="info"]) dees-icon {
--icon-color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
}
dees-icon {
color: var(--icon-color);
}
`,
];
public render(): TemplateResult {
return html`
<div class="option-card ${this.disabled ? 'disabled' : ''}" @click="${this.handleClick}">
${this.icon ? html`<dees-icon .icon=${this.icon} .iconSize=${24}></dees-icon>` : ''}
${this.label ? html`<span class="option-label">${this.label}</span>` : ''}
${this.description ? html`<span class="option-desc">${this.description}</span>` : ''}
</div>
`;
}
private handleClick() {
if (this.disabled) return;
this.dispatchEvent(new CustomEvent('select', {
detail: { selected: !this.selected },
bubbles: true,
composed: true,
}));
}
}