diff --git a/packages/components/src/components.d.ts b/packages/components/src/components.d.ts index b77d86a667..c4964391d7 100644 --- a/packages/components/src/components.d.ts +++ b/packages/components/src/components.d.ts @@ -31,6 +31,7 @@ import { ButtonOrLinkOrTextWithChildrenProps } from "./types/button-link-text"; import { KoliBriCardEventCallbacks } from "./components/card/types"; import { EventCallbacks } from "./components/details/types"; import { KoliBriFormCallbacks } from "./components/form/types"; +import { HeadingVariantPropType } from "./types/props/heading-variant"; import { Loading } from "./utils/validators/loading"; import { SuggestionsPropType } from "./types/props/suggestions"; import { InputCheckboxIconsProp, InputCheckboxVariant } from "./components/input-checkbox/types"; @@ -87,6 +88,7 @@ export { ButtonOrLinkOrTextWithChildrenProps } from "./types/button-link-text"; export { KoliBriCardEventCallbacks } from "./components/card/types"; export { EventCallbacks } from "./components/details/types"; export { KoliBriFormCallbacks } from "./components/form/types"; +export { HeadingVariantPropType } from "./types/props/heading-variant"; export { Loading } from "./utils/validators/loading"; export { SuggestionsPropType } from "./types/props/suggestions"; export { InputCheckboxIconsProp, InputCheckboxVariant } from "./components/input-checkbox/types"; @@ -561,6 +563,10 @@ export namespace Components { * Defines the text of the secondary headline. */ "_secondaryHeadline"?: string; + /** + * Defines which variant should be used for presentation. + */ + "_variant"?: HeadingVariantPropType; } interface KolHeadingWc { /** @@ -575,6 +581,10 @@ export namespace Components { * Setzt den Text einer weiteren Überschrift, einen Level kleiner, unter der Ersten. */ "_secondaryHeadline"?: string; + /** + * Defines which variant should be used for presentation. + */ + "_variant"?: HeadingVariantPropType; } interface KolIcon { /** @@ -3363,6 +3373,10 @@ declare namespace LocalJSX { * Defines the text of the secondary headline. */ "_secondaryHeadline"?: string; + /** + * Defines which variant should be used for presentation. + */ + "_variant"?: HeadingVariantPropType; } interface KolHeadingWc { /** @@ -3377,6 +3391,10 @@ declare namespace LocalJSX { * Setzt den Text einer weiteren Überschrift, einen Level kleiner, unter der Ersten. */ "_secondaryHeadline"?: string; + /** + * Defines which variant should be used for presentation. + */ + "_variant"?: HeadingVariantPropType; } interface KolIcon { /** diff --git a/packages/components/src/components/heading/component.tsx b/packages/components/src/components/heading/component.tsx index e07d23a941..89eaacc2cb 100644 --- a/packages/components/src/components/heading/component.tsx +++ b/packages/components/src/components/heading/component.tsx @@ -5,6 +5,7 @@ import { LabelWithExpertSlotPropType, validateLabelWithExpertSlot } from '../../ import { watchString } from '../../utils/prop.validators'; import { API, States } from './types'; import { watchHeadingLevel } from './validation'; +import { HeadingVariantPropType, validateHeadingVariant } from '../../types/props/heading-variant'; /** * @slot - Inhalt der Überschrift. @@ -29,6 +30,11 @@ export class KolHeadingWc implements API { */ @Prop() public _secondaryHeadline?: string; + /** + * Defines which variant should be used for presentation. + */ + @Prop() public _variant?: HeadingVariantPropType; + @State() public state: States = { _label: '', // ⚠ required _level: 1, @@ -49,64 +55,34 @@ export class KolHeadingWc implements API { watchString(this, '_secondaryHeadline', value); } + @Watch('_variant') + public validateVariant(value?: HeadingVariantPropType): void { + validateHeadingVariant(this, value); + } + public componentWillLoad(): void { this.validateLabel(this._label); this.validateLevel(this._level); this.validateSecondaryHeadline(this._secondaryHeadline); + this.validateVariant(this._variant); } private readonly renderHeadline = (headline: LabelWithExpertSlotPropType, level?: number): JSX.Element => { - switch (level) { - case 1: - return ( -

- {headline} - -

- ); - case 2: - return ( -

- {headline} - -

- ); - case 3: - return ( -

- {headline} - -

- ); - case 4: - return ( -

- {headline} - -

- ); - case 5: - return ( -
- {headline} - -
- ); - case 6: - return ( -
- {headline} - -
- ); - default: - return ( - - {headline} - - - ); - } + const validHeadline = typeof level === 'number' && level > 0 && level <= 6; + const HeadlineTag = validHeadline ? `h${level}` : 'strong'; + const variant = this._variant || HeadlineTag; + + return ( + + {headline} + + + ); }; private readonly renderSecondaryHeadline = (headline: string, level?: number): JSX.Element => { diff --git a/packages/components/src/components/heading/shadow.tsx b/packages/components/src/components/heading/shadow.tsx index cebaa56c2c..c49f6ebb33 100644 --- a/packages/components/src/components/heading/shadow.tsx +++ b/packages/components/src/components/heading/shadow.tsx @@ -3,9 +3,10 @@ import { Component, h, JSX, Prop } from '@stencil/core'; import { HeadingLevel } from '../../types/heading-level'; import { LabelWithExpertSlotPropType } from '../../types/props/label'; import { Props } from './types'; +import { HeadingVariantPropType } from '../../types/props/heading-variant'; /** - * @slot - Inhalt der Überschrift. + * @slot headline - Content of the headline. */ @Component({ tag: 'kol-heading', @@ -17,7 +18,7 @@ import { Props } from './types'; export class KolHeading implements Props { public render(): JSX.Element { return ( - + ); @@ -37,4 +38,9 @@ export class KolHeading implements Props { * Defines the text of the secondary headline. */ @Prop() public _secondaryHeadline?: string; + + /** + * Defines which variant should be used for presentation. + */ + @Prop() public _variant?: HeadingVariantPropType; } diff --git a/packages/components/src/components/heading/style.css b/packages/components/src/components/heading/style.css index 788d42f8df..06e7262a62 100644 --- a/packages/components/src/components/heading/style.css +++ b/packages/components/src/components/heading/style.css @@ -1,14 +1 @@ @import url(../style.css); -@layer kol-component { - :host > kol-heading-wc { - display: grid; - } - - :host > kol-heading-wc > .overline { - order: 1; - } - - :host > kol-heading-wc > .headline { - order: 2; - } -} diff --git a/packages/components/src/components/heading/test/html.mock.ts b/packages/components/src/components/heading/test/html.mock.ts index ca2e75a78e..d9c805b0ea 100644 --- a/packages/components/src/components/heading/test/html.mock.ts +++ b/packages/components/src/components/heading/test/html.mock.ts @@ -20,7 +20,7 @@ export const getHeadingWcHtml = ( return ` - <${tag} class="headline"> + <${tag} class="headline headline-${props._variant || tag}"> ${state._label} ${slots.expert !== undefined ? slots.expert : ''} diff --git a/packages/components/src/components/heading/test/snapshot.spec.tsx b/packages/components/src/components/heading/test/snapshot.spec.tsx index 6f793faa51..e13d4c9bab 100644 --- a/packages/components/src/components/heading/test/snapshot.spec.tsx +++ b/packages/components/src/components/heading/test/snapshot.spec.tsx @@ -19,6 +19,7 @@ executeTests( { _label: ['Headline'], _level: [1, 2, 3, 4, 5, 6], + _variant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong'], // _secondaryHeadline: ['Secondary Headline'], }, getHeadingHtml, diff --git a/packages/components/src/components/heading/types.ts b/packages/components/src/components/heading/types.ts index 7ff5a9314f..d2f76a4ffd 100644 --- a/packages/components/src/components/heading/types.ts +++ b/packages/components/src/components/heading/types.ts @@ -2,9 +2,10 @@ import { Generic } from '@a11y-ui/core'; import { HeadingLevel } from '../../types/heading-level'; import { PropLabelWithExpertSlot } from '../../types/props/label'; +import { PropHeadingVariant } from '../../types/props/heading-variant'; type RequiredProps = PropLabelWithExpertSlot; -type OptionalProps = { +type OptionalProps = PropHeadingVariant & { secondaryHeadline: string; level: HeadingLevel; }; @@ -13,7 +14,7 @@ export type Props = Generic.Element.Members; type RequiredStates = RequiredProps & { level: HeadingLevel; }; -type OptionalStates = { +type OptionalStates = PropHeadingVariant & { secondaryHeadline: string; }; export type States = Generic.Element.Members; diff --git a/packages/components/src/types/props/heading-variant.ts b/packages/components/src/types/props/heading-variant.ts new file mode 100644 index 0000000000..827c23757d --- /dev/null +++ b/packages/components/src/types/props/heading-variant.ts @@ -0,0 +1,24 @@ +/* types */ +import { Generic } from '@a11y-ui/core'; +import { watchValidator } from '../../utils/prop.validators'; + +const headingVariantPropTypeOptions = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong'] as const; +export type HeadingVariantPropType = (typeof headingVariantPropTypeOptions)[number]; + +/** + * Defines which variant should be used for presentation. + */ +export type PropHeadingVariant = { + variant: HeadingVariantPropType; +}; + +/* validator */ +export const validateHeadingVariant = (component: Generic.Element.Component, value?: HeadingVariantPropType): void => { + watchValidator( + component, + `_variant`, + (value) => typeof value === 'string' && headingVariantPropTypeOptions.includes(value), + new Set([`KoliBriHeadingVariant {${headingVariantPropTypeOptions.join(', ')}`]), + value + ); +}; diff --git a/packages/themes/bmf/src/index.ts b/packages/themes/bmf/src/index.ts index e73552878e..81a0e50f2d 100644 --- a/packages/themes/bmf/src/index.ts +++ b/packages/themes/bmf/src/index.ts @@ -1084,31 +1084,31 @@ export const BMF = KoliBri.createTheme('bmf', { } `, 'KOL-HEADING': css` - h1, - h2, - h3, - h4, - h5, - h6 { + .headline-h1, + .headline-h2, + .headline-h3, + .headline-h4, + .headline-h5, + .headline-h6 { color: inherit; font-style: normal; margin: 0; padding: 0; } - h1, - h2, - h3 { + .headline-h1, + .headline-h2, + .headline-h3 { font-weight: 700; } - h1 { + .headline-h1 { font-size: 1.5rem; line-height: 1.75rem; } - h2 { + .headline-h2 { font-size: 1.25rem; line-height: 1.75rem; } - h3 { + .headline-h3 { font-size: 1.125rem; line-height: 1.5rem; } diff --git a/packages/themes/default/src/index.ts b/packages/themes/default/src/index.ts index 43111faef5..d1e10974f9 100644 --- a/packages/themes/default/src/index.ts +++ b/packages/themes/default/src/index.ts @@ -992,29 +992,29 @@ export const DEFAULT = KoliBri.createTheme('default', { } `, 'KOL-HEADING': css` - h1, - h2, - h3, - h4, - h5, - h6 { + .headline-h1, + .headline-h2, + .headline-h3, + .headline-h4, + .headline-h5, + .headline-h6 { color: inherit; font-style: normal; } - h1, - h2, - h3 { + .headline-h1, + .headline-h2, + .headline-h3 { font-weight: 700; } - h1 { + .headline-h1 { font-size: 1.5rem; line-height: 1.75rem; } - h2 { + .headline-h2 { font-size: 1.25rem; line-height: 1.75rem; } - h3 { + .headline-h3 { font-size: 1.125rem; line-height: 1.5rem; } diff --git a/packages/themes/ecl/src/ecl-ec.ts b/packages/themes/ecl/src/ecl-ec.ts index 8341f35cd3..3ca306e555 100644 --- a/packages/themes/ecl/src/ecl-ec.ts +++ b/packages/themes/ecl/src/ecl-ec.ts @@ -101,27 +101,27 @@ export const ECL_EC = KoliBri.createTheme('ecl-ec', { } `, 'KOL-HEADING': css` - h1 { + .headline-h1 { font-size: 2rem; line-height: 2.5rem; } - h2 { + .headline-h2 { font-size: 1.75rem; line-height: 2rem; } - h3 { + .headline-h3 { font-size: 1.5rem; line-height: 1.75rem; } - h4 { + .headline-h4 { font-size: 1.25rem; line-height: 1.75rem; } - h5 { + .headline-h5 { font-size: 1rem; line-height: 1.5rem; } - h6 { + .headline-h6 { color: rgb(234, 0, 255); } `, diff --git a/packages/themes/ecl/src/ecl-eu.ts b/packages/themes/ecl/src/ecl-eu.ts index 7c6aafa9f3..2c1f0131f2 100644 --- a/packages/themes/ecl/src/ecl-eu.ts +++ b/packages/themes/ecl/src/ecl-eu.ts @@ -179,35 +179,35 @@ export const ECL_EU = KoliBri.createTheme('ecl-eu', { } `, 'KOL-HEADING': css` - h1, - h2, - h3, - h4, - h5, - h6 { + .headline-h1, + .headline-h2, + .headline-h3, + .headline-h4, + .headline-h5, + .headline-h6 { font-weight: var(--font-weight-bold); } - h1 { + .headline-h1 { font-size: 2.625rem; line-height: 3.25rem; } - h2 { + .headline-h2 { font-size: 2.25rem; line-height: 2.75rem; } - h3 { + .headline-h3 { font-size: 2rem; line-height: 2.5rem; } - h4 { + .headline-h4 { font-size: 1.75rem; line-height: 2rem; } - h5 { + .headline-h5 { font-size: 1.5rem; line-height: 1.75rem; } - h6 { + .headline-h6 { font-size: 1.25rem; line-height: 1.75rem; } diff --git a/packages/themes/itzbund/src/index.ts b/packages/themes/itzbund/src/index.ts index 3427a0e15b..119c4cf147 100644 --- a/packages/themes/itzbund/src/index.ts +++ b/packages/themes/itzbund/src/index.ts @@ -796,42 +796,42 @@ export const ITZBund = KoliBri.createTheme('itzbund', { } `, 'KOL-HEADING': css` - h1, - h2, - h3, - h4, - h5, - h6 { + .headline-h1, + .headline-h2, + .headline-h3, + .headline-h4, + .headline-h5, + .headline-h6 { line-height: 1em; margin: 0; padding: 0; } - h1 { + .headline-h1 { font-family: var(--font-family-serif); font-size: 54px; font-weight: bold; } - h2 { + .headline-h2 { font-family: var(--font-family-serif); font-size: 32px; font-weight: bold; } - h3 { + .headline-h3 { font-family: var(--font-family-serif); font-size: 26px; font-weight: bold; } - h4 { + .headline-h4 { font-family: var(--font-family-serif); font-size: 20px; font-weight: normal; } - h5 { + .headline-h5 { font-family: var(--font-family-serif); font-size: 17px; font-weight: bold; } - h6 { + .headline-h6 { font-family: var(--font-family-sans); font-size: 17px; font-weight: normal; diff --git a/packages/themes/zoll/src/mapz.ts b/packages/themes/zoll/src/mapz.ts index c1300d40cb..9f6c02c44d 100644 --- a/packages/themes/zoll/src/mapz.ts +++ b/packages/themes/zoll/src/mapz.ts @@ -852,32 +852,32 @@ export const MAPZ = KoliBri.createTheme('mapz', { } `, 'KOL-HEADING': css` - h1, - h2, - h3, - h4, - h5, - h6 { + .headline-h1, + .headline-h2, + .headline-h3, + .headline-h4, + .headline-h5, + .headline-h6 { line-height: 1.25em; margin: 0; padding: 0; } - h1 { + .headline-h1 { font-size: 1.5rem !important; } - h2 { + .headline-h2 { font-size: 1.4rem !important; } - h3 { + .headline-h3 { font-size: 1.3rem !important; } - h4 { + .headline-h4 { font-size: 1.2rem !important; } - h5 { + .headline-h5 { font-size: 1.1rem !important; } - h6 { + .headline-h6 { font-size: 1rem !important; } `, diff --git a/packages/themes/zoll/src/v3/index.ts b/packages/themes/zoll/src/v3/index.ts index ca9203832c..571ed8e8be 100644 --- a/packages/themes/zoll/src/v3/index.ts +++ b/packages/themes/zoll/src/v3/index.ts @@ -134,39 +134,39 @@ export const ZOLLv3 = KoliBri.createTheme('zoll-v3', { } `, 'KOL-HEADING': css` - h1, - h2, - h3, - h4, - h5, - h6 { + .headline-h1, + .headline-h2, + .headline-h3, + .headline-h4, + .headline-h5, + .headline-h6 { font-weight: var(--font-weight-bold); margin: 0; padding: 1rem 0; text-align: left; } - h1 { + .headline-h1 { font-size: 2.5rem; line-height: 1.2; padding: 0 0 1rem 0; } - h2 { + .headline-h2 { font-size: 2rem; line-height: 1.25; } - h3 { + .headline-h3 { font-size: 1.75rem; line-height: 1.29; } - h4 { + .headline-h4 { font-size: 1.5rem; line-height: 1.33; } - h5 { + .headline-h5 { font-size: 1.25rem; line-height: 1.4; } - h6 { + .headline-h6 { font-size: 1rem; line-height: 1.5; } diff --git a/packages/themes/zoll/src/zoll-v2.ts b/packages/themes/zoll/src/zoll-v2.ts index 5fcbcf8db6..21dc1ce183 100644 --- a/packages/themes/zoll/src/zoll-v2.ts +++ b/packages/themes/zoll/src/zoll-v2.ts @@ -123,39 +123,39 @@ export const ZOLLv2 = KoliBri.createTheme('zoll-v2', { } `, 'KOL-HEADING': css` - h1, - h2, - h3, - h4, - h5, - h6 { + .headline-h1, + .headline-h2, + .headline-h3, + .headline-h4, + .headline-h5, + .headline-h6 { font-weight: var(--font-weight-bold); margin: 0; padding: 1rem 0; text-align: left; } - h1 { + .headline-h1 { font-size: 2.5rem; line-height: 1.2; padding: 0 0 1rem 0; } - h2 { + .headline-h2 { font-size: 2rem; line-height: 1.25; } - h3 { + .headline-h3 { font-size: 1.75rem; line-height: 1.29; } - h4 { + .headline-h4 { font-size: 1.5rem; line-height: 1.33; } - h5 { + .headline-h5 { font-size: 1.25rem; line-height: 1.4; } - h6 { + .headline-h6 { font-size: 1rem; line-height: 1.5; }