import { css, html, nothing } from 'lit'; import { customElement } from 'lit/decorators.js'; import type { GetDreamSymbolResponse } from '../types/index.js'; import { RoxyDataElement } from '../utils/base-element.js'; import { baseStyles } from '../utils/base-styles.js'; /** * Dream symbol card. Renders /dreams/symbols/{id}: the symbol name as a heading, the full psychological interpretation as the body, and the dictionary letter as a chip for alphabetical context. * * @remarks * **`hide-readings` is a deliberate no-op here, and it is the only card in the library that is.** The response is `{id, name, letter, meaning}`: three of those four fields are the lookup key itself, and `meaning` is the entire card. Honouring the attribute would leave a dictionary heading with nothing under it, which is not a chart without a report, it is an empty card. Rendering nothing at all was the other option and is worse, because a site-wide `hide-readings` would then delete the component from the page rather than trim it. Documented in README.md and AGENTS.md so an integrator learns this without testing for it, and pinned by `components.test.ts`. */ @customElement('roxy-dream-card') export class RoxyDreamCard extends RoxyDataElement { static styles = [ baseStyles, css` .card { background: var(--roxy-surface, #fff); color: var(--roxy-fg, #0a0a0a); border: 1px solid var(--roxy-border, #e4e4e7); border-radius: var(--roxy-radius-md, 8px); padding: var(--roxy-space-lg, 1.5rem); box-shadow: var(--roxy-shadow-sm); display: grid; /* Never an implicit auto column: it floors at min-content, so one long * unbreakable string widens the track past the padded card. */ grid-template-columns: minmax(0, 1fr); gap: var(--roxy-space-md, 1rem); } .head { display: flex; align-items: center; gap: var(--roxy-space-md, 1rem); } .letter { display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; flex: none; border-radius: var(--roxy-radius-full, 9999px); background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 16%, transparent); color: var(--roxy-accent-ink, #b45309); font-size: var(--roxy-text-lg, 1.125rem); font-weight: var(--roxy-weight-bold, 600); text-transform: uppercase; font-variant-numeric: tabular-nums; } .label { margin: 0; font-size: var(--roxy-text-xs, 0.75rem); color: var(--roxy-muted, #71717a); text-transform: uppercase; letter-spacing: 0.06em; } .name { margin: 0; font-size: var(--roxy-text-lg, 1.125rem); font-weight: var(--roxy-weight-bold, 600); color: var(--roxy-fg, #0a0a0a); } .meaning { margin: 0; color: var(--roxy-fg, #0a0a0a); line-height: 1.6; } `, ]; protected renderData(d: GetDreamSymbolResponse) { return html`
${d.letter ? html`` : nothing}

${this.t('Dream symbol')}

${d.name ? html`

${d.name}

` : nothing}
${d.meaning ? html`

${d.meaning}

` : nothing}
`; } } declare global { interface HTMLElementTagNameMap { 'roxy-dream-card': RoxyDreamCard; } }