import { css, html } from "lit"; import { property } from "lit/decorators.js"; import { BaseElement } from "../../core/base-element.ts"; /** * CTChip - Reusable pill/chip component * * @element ct-chip * * @attr {string} label - Chip label text to display * @attr {string} variant - Visual variant: "default" | "primary" | "accent" (default: "default") * @attr {boolean} removable - Whether to show remove button (default: false) * @attr {boolean} interactive - Whether chip is clickable (default: false) * * @fires ct-remove - Fired when remove button is clicked * @fires ct-click - Fired when chip is clicked (if interactive) * * @slot icon - Optional icon before the label * @slot - Main content (overrides label) * * @example * * */ export class CTChip extends BaseElement { static override styles = [ BaseElement.baseStyles, css` :host { display: inline-block; } .chip { display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.25rem 0.625rem; background: var( --ct-theme-color-surface, var(--ct-color-gray-100, #f5f5f5) ); color: var( --ct-theme-color-text, var(--ct-color-gray-900, #212121) ); border: 1px solid var(--ct-theme-color-border, var(--ct-color-gray-300, #e0e0e0)); border-radius: var( --ct-theme-border-radius, var(--ct-border-radius-full, 9999px) ); font-size: 0.8125rem; line-height: 1; user-select: none; transition: background-color var(--ct-theme-animation-duration, 200ms) ease, border-color var(--ct-theme-animation-duration, 200ms) ease; } .chip.interactive { cursor: pointer; } .chip.interactive:hover { background: var( --ct-theme-color-surface-hover, var(--ct-color-gray-200, #eeeeee) ); } /* Variant: primary (blue - for mentions) */ .chip.primary { background: var( --ct-theme-color-primary-surface, var(--ct-color-blue-50, #eff6ff) ); border-color: var( --ct-theme-color-primary, var(--ct-color-blue-200, #bfdbfe) ); color: var( --ct-theme-color-primary, var(--ct-color-blue-700, #1d4ed8) ); } /* Variant: accent (purple - for clipboard) */ .chip.accent { background: var( --ct-theme-color-accent-surface, var(--ct-color-purple-50, #faf5ff) ); border-color: var( --ct-theme-color-accent, var(--ct-color-purple-200, #e9d5ff) ); color: var( --ct-theme-color-accent, var(--ct-color-purple-700, #7c3aed) ); } .chip-icon { display: flex; align-items: center; font-size: 0.8125rem; line-height: 1; } .chip-label { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .chip-remove { display: flex; align-items: center; justify-content: center; width: 0.75rem; height: 0.75rem; border-radius: 50%; cursor: pointer; transition: background-color 0.1s; color: currentColor; opacity: 0.6; } .chip-remove:hover { background: rgba(0, 0, 0, 0.1); opacity: 1; } `, ]; @property({ type: String }) label = ""; @property({ type: String }) variant: "default" | "primary" | "accent" = "default"; @property({ type: Boolean }) removable = false; @property({ type: Boolean }) interactive = false; private _handleRemove(e: Event): void { e.stopPropagation(); this.emit("ct-remove"); } private _handleClick(): void { if (this.interactive) { this.emit("ct-click"); } } override render() { const classes = [ "chip", this.variant, this.interactive && "interactive", ].filter(Boolean).join(" "); return html`
${this.label} ${this.removable ? html` × ` : ""}
`; } } customElements.define("ct-chip", CTChip);