// components/ui-badge.ts import { LitElement, html, css } from "lit"; import { customElement, property, state } from "lit/decorators.js"; export type BadgeVariant = "accent" | "success" | "warning" | "error" | "muted"; @customElement("ui-badge") export class UiBadge extends LitElement { static styles = css` :host { display: inline-flex; } .badge { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.35rem 0.75rem; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; border-radius: 2rem; border: 1px solid transparent; white-space: nowrap; line-height: 1; } .icon { display: inline-flex; align-items: center; flex-shrink: 0; } .icon ::slotted(*) { display: inline-flex; width: 0.85rem; height: 0.85rem; } .icon ::slotted(svg), .icon ::slotted(* > svg) { width: 0.85rem; height: 0.85rem; } .label { display: inline-flex; align-items: center; padding-top: 0.05em; } .badge.white { color: #ffffff; background: color-mix(in srgb, #ffffff 10%, transparent); border-color: color-mix(in srgb, #ffffff 25%, transparent); } .badge.accent { color: var(--color-accent); background: color-mix(in srgb, var(--color-accent) 10%, transparent); border-color: color-mix(in srgb, var(--color-accent) 25%, transparent); } .badge.success { color: #30a46c; background: color-mix(in srgb, #30a46c 10%, transparent); border-color: color-mix(in srgb, #30a46c 25%, transparent); } .badge.warning { color: #e79d13; background: color-mix(in srgb, #e79d13 10%, transparent); border-color: color-mix(in srgb, #e79d13 25%, transparent); } .badge.error { color: #e5484d; background: color-mix(in srgb, #e5484d 10%, transparent); border-color: color-mix(in srgb, #e5484d 25%, transparent); } .badge.muted { color: color-mix(in srgb, var(--color-text) 45%, transparent); background: color-mix(in srgb, var(--color-text) 6%, transparent); border-color: var(--color-border); } `; @property() variant: BadgeVariant = "accent"; @state() private hasIcon = false; private handleSlotChange(e: Event) { const slot = e.target as HTMLSlotElement; this.hasIcon = slot.assignedNodes().length > 0; } render() { return html` ${this.hasIcon ? html` ` : html``} `; } }