@use 'sass:list'; @use 'sass:map'; @use 'sass:string'; @use 'typography-utils'; @use '../theming/inspection'; // Definition and versioning functions live in their own files to avoid circular dependencies, but // we re-export them here so that historical imports from this file continue to work without needing // to be updated. @forward './versioning'; @mixin typography-hierarchy($theme, $selector: '.mat-typography', $back-compat: false) { @if inspection.get-theme-version($theme) == 1 { @include _m3-typography-hierarchy($theme, $selector, $back-compat); } @else { @include _m2-typography-hierarchy($theme, $selector); } } @function _get-selector($selectors, $prefix) { $result: (); @each $selector in $selectors { // Don't add "naked" tag selectors, and don't nest prefix selector. @if string.index($selector, '.') == 1 { $result: list.append($result, $selector, $separator: comma); } // Don't nest the prefix selector in itself. @if $selector != $prefix { $result: list.append($result, '#{$prefix} #{$selector}', $separator: comma); } } @return $result; } @mixin _m3-typography-level($theme, $selector-prefix, $level, $selectors, $margin: null) { #{_get-selector($selectors, $selector-prefix)} { // TODO(mmalerba): When we expose system tokens as CSS vars, we should change this to emit token // slots. font: inspection.get-theme-typography($theme, $level, font); letter-spacing: inspection.get-theme-typography($theme, $level, letter-spacing); @if $margin != null { margin: 0 0 $margin; } } } @mixin _m3-typography-hierarchy($theme, $selector-prefix, $add-m2-selectors) { $levels: ( display-large: ( selectors: ('.mat-display-large', 'h1'), m2-selectors: ('.mat-h1', '.mat-headline-1'), margin: 0.5em ), display-medium: ( selectors: ('.mat-display-medium', 'h2'), m2-selectors: ('.mat-h2', '.mat-headline-2'), margin: 0.5em ), display-small: ( selectors: ('.mat-display-small', 'h3'), m2-selectors: ('.mat-h3', '.mat-headline-3'), margin: 0.5em ), headline-large: ( selectors: ('.mat-headline-large', 'h4'), m2-selectors: ('.mat-h4', '.mat-headline-4'), margin: 0.5em ), headline-medium: ( selectors: ('.mat-headline-medium', 'h5'), m2-selectors: ('.mat-h5', '.mat-headline-5'), margin: 0.5em ), headline-small: ( selectors: ('.mat-headline-small', 'h6'), m2-selectors: ('.mat-h6', '.mat-headline-6'), margin: 0.5em ), title-large: ( selectors: ('.mat-title-large'), m2-selectors: ('.mat-subtitle-1'), ), title-medium: ( selectors: ('.mat-title-medium'), m2-selectors: ('.mat-subtitle-2'), ), title-small: ( selectors: ('.mat-title-small') ), body-large: ( selectors: ('.mat-body-large', $selector-prefix), m2-selectors: ('.mat-body', '.mat-body-strong', '.mat-body-2'), ), body-medium: ( selectors: ('.mat-body-medium') ), body-small: ( selectors: ('.mat-body-small') ), label-large: ( selectors: ('.mat-label-large') ), label-medium: ( selectors: ('.mat-label-medium') ), label-small: ( selectors: ('.mat-label-small'), m2-selectors: ('.mat-small', '.mat-caption') ), ); @each $level, $options in $levels { @if $add-m2-selectors { $options: map.set($options, selectors, list.join(map.get($options, selectors), map.get($options, m2-selectors) or ())); } $options: map.remove($options, m2-selectors); // Apply styles for the level. @include _m3-typography-level($theme, $selector-prefix, $level, $options...); // Also style
inside body-large. @if $level == body-large { #{_get-selector(map.get($options, selectors), $selector-prefix)} { p { margin: 0 0 0.75em; } } } } } /// Emits baseline typographic styles based on a given config. /// @param {Map} $config-or-theme A typography config for an entire theme. /// @param {String} $selector Ancestor selector under which native elements, such as h1, will /// be styled. @mixin _m2-typography-hierarchy($theme, $selector) { // Note that it seems redundant to prefix the class rules with the `$selector`, however it's // necessary if we want to allow people to overwrite the tag selectors. This is due to // selectors like `#{$selector} h1` being more specific than ones like `.mat-title`. .mat-h1, .mat-headline-5, #{$selector} .mat-h1, #{$selector} .mat-headline-5, #{$selector} h1 { font: inspection.get-theme-typography($theme, headline-5, font); letter-spacing: inspection.get-theme-typography($theme, headline-5, letter-spacing); margin: 0 0 16px; } .mat-h2, .mat-headline-6, #{$selector} .mat-h2, #{$selector} .mat-headline-6, #{$selector} h2 { font: inspection.get-theme-typography($theme, headline-6, font); letter-spacing: inspection.get-theme-typography($theme, headline-6, letter-spacing); margin: 0 0 16px; } .mat-h3, .mat-subtitle-1, #{$selector} .mat-h3, #{$selector} .mat-subtitle-1, #{$selector} h3 { font: inspection.get-theme-typography($theme, subtitle-1, font); letter-spacing: inspection.get-theme-typography($theme, subtitle-1, letter-spacing); margin: 0 0 16px; } .mat-h4, .mat-body-1, #{$selector} .mat-h4, #{$selector} .mat-body-1, #{$selector} h4 { font: inspection.get-theme-typography($theme, body-1, font); letter-spacing: inspection.get-theme-typography($theme, body-1, letter-spacing); margin: 0 0 16px; } // Note: the spec doesn't have anything that would correspond to h5 and h6, but we add these for // consistency. The font sizes come from the Chrome user agent styles which have h5 at 0.83em // and h6 at 0.67em. .mat-h5, #{$selector} .mat-h5, #{$selector} h5 { @include typography-utils.font-shorthand( // calc is used here to support css variables calc(#{inspection.get-theme-typography($theme, body-2, font-size)} * 0.83), inspection.get-theme-typography($theme, body-2, font-weight), inspection.get-theme-typography($theme, body-2, line-height), inspection.get-theme-typography($theme, body-2, font-family) ); margin: 0 0 12px; } .mat-h6, #{$selector} .mat-h6, #{$selector} h6 { @include typography-utils.font-shorthand( // calc is used here to support css variables calc(#{inspection.get-theme-typography($theme, body-2, font-size)} * 0.67), inspection.get-theme-typography($theme, body-2, font-weight), inspection.get-theme-typography($theme, body-2, line-height), inspection.get-theme-typography($theme, body-2, font-family) ); margin: 0 0 12px; } .mat-body-strong, .mat-subtitle-2, #{$selector} .mat-body-strong, #{$selector} .mat-subtitle-2 { font: inspection.get-theme-typography($theme, subtitle-2, font); letter-spacing: inspection.get-theme-typography($theme, subtitle-2, letter-spacing); } .mat-body, .mat-body-2, #{$selector} .mat-body, #{$selector} .mat-body-2, #{$selector} { font: inspection.get-theme-typography($theme, body-2, font); letter-spacing: inspection.get-theme-typography($theme, body-2, letter-spacing); p { margin: 0 0 12px; } } .mat-small, .mat-caption, #{$selector} .mat-small, #{$selector} .mat-caption { font: inspection.get-theme-typography($theme, caption, font); letter-spacing: inspection.get-theme-typography($theme, caption, letter-spacing); } .mat-headline-1, #{$selector} .mat-headline-1 { font: inspection.get-theme-typography($theme, headline-1, font); letter-spacing: inspection.get-theme-typography($theme, headline-1, letter-spacing); margin: 0 0 56px; } .mat-headline-2, #{$selector} .mat-headline-2 { font: inspection.get-theme-typography($theme, headline-2, font); letter-spacing: inspection.get-theme-typography($theme, headline-2, letter-spacing); margin: 0 0 64px; } .mat-headline-3, #{$selector} .mat-headline-3 { font: inspection.get-theme-typography($theme, headline-3, font); letter-spacing: inspection.get-theme-typography($theme, headline-3, letter-spacing); margin: 0 0 64px; } .mat-headline-4, #{$selector} .mat-headline-4 { font: inspection.get-theme-typography($theme, headline-4, font); letter-spacing: inspection.get-theme-typography($theme, headline-4, letter-spacing); margin: 0 0 64px; } }