component Typography { props { size: string = "default" color: string = "primary" columns: number = 2 gap: string = "md" maxWidth: string = "xl" class: string = "" } view {
} style { .wrn-typography { color: var(--wrn-color-text); font-size: 1rem; } .wrn-typography[data-size="sm"] { font-size: 0.875rem; } .wrn-typography[data-size="lg"] { font-size: 1.125rem; } .wrn-typography[data-max-width="md"] { max-width: 48rem; } .wrn-typography[data-max-width="lg"] { max-width: 64rem; } .wrn-typography[data-max-width="xl"] { max-width: 80rem; } .wrn-typography[data-max-width="full"] { max-width: none; } /* * Multi-column prose only below a comfortable reading width; a narrow * screen split into columns is unreadable. */ .wrn-typography[data-gap="sm"] { column-gap: 1rem; } .wrn-typography[data-gap="md"] { column-gap: 2rem; } .wrn-typography[data-gap="lg"] { column-gap: 3rem; } @media (min-width: 768px) { .wrn-typography[data-columns="2"] { column-count: 2; } } @media (min-width: 1024px) { .wrn-typography[data-columns="3"] { column-count: 3; } } .wrn-typography :where(h1, h2, h3, h4) { color: var(--wrn-color-text); font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; break-after: avoid; } /* Prose styles apply to raw markup only. Every nested UI component renders inside a `.wrn-component` wrapper, so excluding that subtree stops these element rules from doubling up on a component's own styling — a nested Blockquote otherwise drew two left borders, its own plus this one. The exclusion lives inside :where() so specificity stays at zero and an application can still override any of these with a plain class. */ .wrn-typography :where(h1):not(:where(.wrn-typography .wrn-component *)) { font-size: clamp(2rem, 4vw, 3.5rem); margin: 0 0 1.5rem; } .wrn-typography :where(h2):not(:where(.wrn-typography .wrn-component *)) { font-size: clamp(1.5rem, 3vw, 2.25rem); margin: 2.5rem 0 1rem; } .wrn-typography :where(h3):not(:where(.wrn-typography .wrn-component *)) { font-size: 1.35rem; margin: 2rem 0 0.75rem; } .wrn-typography :where(p, ul, ol, blockquote, pre, table):not(:where(.wrn-typography .wrn-component *)) { margin: 1rem 0; } .wrn-typography :where(p, li):not(:where(.wrn-typography .wrn-component *)) { color: var(--wrn-color-text-muted); line-height: 1.8; } .wrn-typography :where(a):not(:where(.wrn-typography .wrn-component *)) { color: var(--wrn-color-primary); font-weight: 600; text-underline-offset: 0.2em; } .wrn-typography :where(a:hover):not(:where(.wrn-typography .wrn-component *)) { color: var(--wrn-color-primary-hover); text-decoration: underline; } .wrn-typography :where(ul, ol):not(:where(.wrn-typography .wrn-component *)) { padding-left: 1.4rem; } .wrn-typography :where(ul):not(:where(.wrn-typography .wrn-component *)) { list-style: disc; } .wrn-typography :where(ol):not(:where(.wrn-typography .wrn-component *)) { list-style: decimal; } .wrn-typography :where(blockquote):not(:where(.wrn-typography .wrn-component *)) { border-left: 4px solid var(--wrn-color-primary); background: var(--wrn-color-primary-soft); border-radius: 0 0.75rem 0.75rem 0; padding: 1rem 1.25rem; color: var(--wrn-color-text); } .wrn-typography :where(code):not(:where(.wrn-typography .wrn-component *)) { border-radius: 0.35rem; background: var(--wrn-color-surface-soft); padding: 0.15rem 0.35rem; font-size: 0.9em; } .wrn-typography :where(pre) { overflow-x: auto; border: 1px solid var(--wrn-color-border); border-radius: 1rem; background: var(--wrn-color-surface-raised); padding: 1rem; } .wrn-typography :where(img) { border-radius: 1rem; } .wrn-typography :where(hr) { border-color: var(--wrn-color-border); margin: 2rem 0; } } }