Files
dees-catalog/ts_web/elements/00group-layout/dees-heading/dees-heading.ts

158 lines
4.5 KiB
TypeScript

import {
customElement,
html,
css,
property,
cssManager,
type TemplateResult,
DeesElement,
type CSSResult,
} from '@design.estate/dees-element';
import { demoFunc } from './dees-heading.demo.js';
import { cssCalSansFontFamily } from '../../00fonts.js';
import { themeDefaultStyles } from '../../00theme.js';
declare global {
interface HTMLElementTagNameMap {
'dees-heading': DeesHeading;
}
}
@customElement('dees-heading')
export class DeesHeading extends DeesElement {
// demo
public static demo = demoFunc;
public static demoGroups = ['Layout'];
// properties
/**
* Heading level:
* '1'-'6' → <h1>..<h6>
* '7'|'hr' → horizontal-rule style heading
* '8'|'hr-small' → small horizontal-rule style heading
*/
@property({ type: String, reflect: true })
accessor level: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | 'hr' | 'hr-small' = '1';
// STATIC STYLES
public static styles: CSSResult[] = [
themeDefaultStyles,
cssManager.defaultStyles,
css`
:host {
display: block;
}
/* Heading styles.
* Color hierarchy: h1-h2 stay prominent with text-primary; h3-h6 step
* down to text-secondary so they read as subheadings instead of
* mini-h1s. Keeps the visual loudness out of smaller headings. */
h1, h2, h3, h4, h5, h6 {
font-weight: 600;
}
h1, h2 {
color: var(--dees-color-text-primary);
}
h3, h4, h5, h6 {
color: var(--dees-color-text-secondary);
}
/* Per-level typography + spacing.
* Margin scales with importance: h1 gets the most breathing room,
* h6 the least. Top margin > bottom margin so headings group with
* the content that follows them. */
h1 {
/* h1 uses weight 500, not 600: the Cal Sans display font is
* already stylized enough that bold + max contrast + 32px stacks
* too much emphasis. 500 keeps the typographic impact without
* shouting. */
font-weight: 500;
font-size: 32px;
font-family: ${cssCalSansFontFamily};
letter-spacing: 0.025em;
margin: var(--dees-spacing-2xl) 0 var(--dees-spacing-lg);
}
h2 {
font-size: 28px;
margin: var(--dees-spacing-xl) 0 var(--dees-spacing-md);
}
h3 {
font-size: 24px;
margin: var(--dees-spacing-xl) 0 var(--dees-spacing-md);
}
h4 {
font-size: 20px;
margin: var(--dees-spacing-lg) 0 var(--dees-spacing-sm);
}
h5 {
font-size: 16px;
margin: var(--dees-spacing-md) 0 var(--dees-spacing-sm);
}
h6 {
font-size: 14px;
margin: var(--dees-spacing-md) 0 var(--dees-spacing-xs);
}
/* Horizontal rule style heading */
.heading-hr {
display: flex;
align-items: center;
text-align: center;
margin: var(--dees-spacing-lg) 0;
color: var(--dees-color-text-muted);
}
/* Fade lines toward and away from text for hr style */
.heading-hr::before {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(to right, transparent, var(--dees-color-border-strong));
margin: 0 var(--dees-spacing-sm);
}
.heading-hr::after {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(to right, var(--dees-color-border-strong), transparent);
margin: 0 var(--dees-spacing-sm);
}
/* Small hr variant with reduced margins */
.heading-hr.heading-hr-small {
margin: var(--dees-spacing-sm) 0;
font-size: 12px;
}
.heading-hr.heading-hr-small::before,
.heading-hr.heading-hr-small::after {
margin: 0 var(--dees-spacing-sm);
}
`,
];
// INSTANCE
public render(): TemplateResult {
switch (this.level) {
case '1':
return html`<h1><slot></slot></h1>`;
case '2':
return html`<h2><slot></slot></h2>`;
case '3':
return html`<h3><slot></slot></h3>`;
case '4':
return html`<h4><slot></slot></h4>`;
case '5':
return html`<h5><slot></slot></h5>`;
case '6':
return html`<h6><slot></slot></h6>`;
case '7':
case 'hr':
return html`<div class="heading-hr"><slot></slot></div>`;
case '8':
case 'hr-small':
return html`<div class="heading-hr heading-hr-small"><slot></slot></div>`;
default:
return html`<h1><slot></slot></h1>`;
}
}
}