import { customElement, DeesElement, html, css, cssManager, property, state, type TemplateResult, } from '@design.estate/dees-element'; import { demoFunc } from './dees-tile.demo.js'; import { cssGeistFontFamily } from '../../00fonts.js'; import { themeDefaultStyles } from '../../00theme.js'; declare global { interface HTMLElementTagNameMap { 'dees-tile': DeesTile; } } /** * dees-tile — the unified "rounded on rounded" tile frame. * * RESPONSIBILITIES (what this component owns): * 1. Outer card — border, border-radius, background, overflow clipping * 2. Flex column layout — stacking header / content / footer vertically * 3. Content inset — the rounded inner area with border-top and border-bottom * 4. Default heading — styled 32px heading text when no slot="header" is provided * 5. Footer visibility — auto-hides footer area when slot="footer" is empty * * NOT RESPONSIBILITIES (what consumer components own): * - Header/footer height, padding, font-size, colors when using custom slots * - Content layout (absolute, flex, grid — consumer decides) * - Any semantic meaning of header/footer content * * The header and footer slots are BARE containers (just flex-shrink: 0). * The slotted content fully controls its own appearance. * Only the default heading fallback (.tile-heading) carries tile-level styling. */ @customElement('dees-tile') export class DeesTile extends DeesElement { public static demo = demoFunc; public static demoGroups = ['Layout']; @property({ type: String }) accessor heading: string = ''; @state() accessor hasFooter: boolean = false; public static styles = [ themeDefaultStyles, cssManager.defaultStyles, css` :host { display: flex; flex-direction: column; font-family: ${cssGeistFontFamily}; color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')}; } /* --- The frame --- */ .tile-outer { position: relative; flex: 1; min-height: 0; background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')}; border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')}; border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; } /* --- Header: bare container, only the default heading gets styled --- */ .tile-header { flex-shrink: 0; } .tile-heading { height: 32px; line-height: 32px; padding: 0 16px; font-size: 14px; font-weight: 500; letter-spacing: -0.01em; color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')}; } /* --- Content: the rounded inset --- */ .tile-content { flex: 1; position: relative; border-radius: 8px; border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')}; border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')}; overflow: hidden; } .tile-content.no-footer { border-bottom: none; border-bottom-left-radius: 0; border-bottom-right-radius: 0; } /* --- Footer: bare container, consumer styles the slotted content --- */ .tile-footer { flex-shrink: 0; } .tile-footer.hidden { display: none; } `, ]; public render(): TemplateResult { return html`