diff --git a/all.ts b/all.ts index 617e41970f..0a7e15a6a6 100644 --- a/all.ts +++ b/all.ts @@ -104,5 +104,9 @@ export * from './tabs/secondary-tab.js'; export * from './tabs/tabs.js'; export * from './textfield/filled-text-field.js'; export * from './textfield/outlined-text-field.js'; +export * from './topappbar/center-aligned-top-app-bar.js'; +export * from './topappbar/large-top-app-bar.js'; +export * from './topappbar/medium-top-app-bar.js'; +export * from './topappbar/small-top-app-bar.js'; // go/keep-sorted end // LINT.ThenChange(:imports) diff --git a/docs/components/images/topappbar/theming.png b/docs/components/images/topappbar/theming.png new file mode 100644 index 0000000000..990921f04d Binary files /dev/null and b/docs/components/images/topappbar/theming.png differ diff --git a/docs/components/top-app-bar.md b/docs/components/top-app-bar.md new file mode 100644 index 0000000000..e076e71db1 --- /dev/null +++ b/docs/components/top-app-bar.md @@ -0,0 +1,385 @@ + + + + + +# Top App Bar + + + + + + + + + + +**This documentation is fully rendered on the +[Material Web Additions catalog](https://material-web-additions.maicol07.it/components/top-app-bar/).** + + + + +[Top app bars](https://m3.material.io/components/top-app-bar) display navigation, actions, and text at the top of a screen. + + + + + + + +* [Design article](https://m3.material.io/components/top-app-bar) +* [API Documentation](#api) +* [Source code](https://github.com/maicol07/material-web-additions/tree/main/top-app-bar) + + + + + + + + +## Types + + + +![Top app bar types](https://firebasestorage.googleapis.com/v0/b/design-spec/o/projects%2Fgoogle-material-3%2Fimages%2Flz77955k-1.png?alt=media&token=7bc97a43-321a-4d2c-a232-9a5e5ae1463b "Center-aligned, small, medium and large top app bar types.") + + + + + + + + +1. [Center-aligned](#center-aligned) +2. [Small](#small) +3. [Medium](#medium) +4. [Large](#large) + +## Usage + +### Center-aligned +A center-aligned top app bar is a top app bar with the title centered. + +```html + + + menu + +
Title Large
+ + account_circle + +
+``` + +### Small +A small top app bar is a top app bar with a title and up to 3 trailing icons. + +```html + + + arrow_back + +
Title Large
+
+ + attach_file + + + event + + + more_vert + +
+
+``` + +### Medium +A medium top app bar is a top app bar with a title and up to 3 trailing icons. + +```html + + + arrow_back + +
Headline Small
+
+ + attach_file + + + event + + + more_vert + +
+
+``` + +### Large +A large top app bar is a top app bar with an headline and up to 3 trailing icons. + +```html + + + arrow_back + +
Headline Small
+
+ + attach_file + + + event + + + more_vert + +
+
+``` + +## Theming + +Top app bars supports [Material theming](https://material-web.dev/theming/material-theming/) and can be customized +in terms of color, typography, and shape. + +### Tokens +| Token | Default value | +|------------------------------------------|------------------------------| +| `--md-$type-top-app-bar-container-color` | `--md-sys-color-surface` | +| `--md-$type-top-app-bar-container-shape` | `--md-sys-shape-corner-none` | + +* [All tokens](https://github.com/maicol07/material-web-additions/blob/main/tokens/_md-comp-top-app-bar-small.scss) + + +### Example + + + +![Image of a small top app bar with a different theme applied](images/top-app-bar/theming.png "Small top app bar theming example.") + + + + + + + + +```html + + + + + arrow_back + +
Headline Small
+
+ + attach_file + + + event + + + more_vert + +
+
+``` + + + +## API + + +### MdCenterAlignedTopAppBar <md-center-aligned-top-app-bar> + +#### Properties + + + +Property | Attribute | Type | Default | Description +--- | --- | --- | --- | --- +`sticky` | `sticky` | `boolean` | `false` | Whether the top app bar is sticky. + + + +### MdLargeTopAppBar <md-large-top-app-bar> + +#### Properties + + + +Property | Attribute | Type | Default | Description +--- | --- | --- | --- | --- +`sticky` | `sticky` | `boolean` | `false` | Whether the top app bar is sticky. + + + +### MdMediumTopAppBar <md-medium-top-app-bar> + +#### Properties + + + +Property | Attribute | Type | Default | Description +--- | --- | --- | --- | --- +`sticky` | `sticky` | `boolean` | `false` | Whether the top app bar is sticky. + + + +### MdSmallTopAppBar <md-small-top-app-bar> + +#### Properties + + + +Property | Attribute | Type | Default | Description +--- | --- | --- | --- | --- +`sticky` | `sticky` | `boolean` | `false` | Whether the top app bar is sticky. + + + + diff --git a/tokens/_index.scss b/tokens/_index.scss index 27b16732d7..32d2b4c904 100644 --- a/tokens/_index.scss +++ b/tokens/_index.scss @@ -55,6 +55,10 @@ @forward './md-comp-switch' as md-comp-switch-*; @forward './md-comp-test-table' as md-comp-test-table-*; @forward './md-comp-text-button' as md-comp-text-button-*; +@forward './md-comp-top-app-bar-large' as md-comp-top-app-bar-large-*; +@forward './md-comp-top-app-bar-medium' as md-comp-top-app-bar-medium-*; +@forward './md-comp-top-app-bar-small' as md-comp-top-app-bar-small-*; +@forward './md-comp-top-app-bar-small-centered' as md-comp-top-app-bar-small-centered-*; @forward './md-ref-palette' as md-ref-palette-*; @forward './md-ref-typeface' as md-ref-typeface-*; @forward './md-sys-color' as md-sys-color-*; diff --git a/tokens/_md-comp-top-app-bar-large.scss b/tokens/_md-comp-top-app-bar-large.scss new file mode 100644 index 0000000000..d16e397346 --- /dev/null +++ b/tokens/_md-comp-top-app-bar-large.scss @@ -0,0 +1,23 @@ +// +// Copyright 2023 Google LLC +// SPDX-License-Identifier: Apache-2.0 +// + +// go/keep-sorted start +@use './md-sys-color'; +@use './md-sys-elevation'; +@use './md-sys-shape'; +@use './md-sys-typescale'; +@use './v0_192/md-comp-top-app-bar-large'; +// go/keep-sorted end + +$_default: ( + 'md-sys-color': md-sys-color.values-light(), + 'md-sys-elevation': md-sys-elevation.values(), + 'md-sys-shape': md-sys-shape.values(), + 'md-sys-typescale': md-sys-typescale.values(), +); + +@function values($deps: $_default, $exclude-hardcoded-values: false) { + @return md-comp-top-app-bar-large.values($deps, $exclude-hardcoded-values); +} diff --git a/tokens/_md-comp-top-app-bar-medium.scss b/tokens/_md-comp-top-app-bar-medium.scss new file mode 100644 index 0000000000..6b84722516 --- /dev/null +++ b/tokens/_md-comp-top-app-bar-medium.scss @@ -0,0 +1,24 @@ +// +// Copyright 2023 Google LLC +// SPDX-License-Identifier: Apache-2.0 +// + +// go/keep-sorted start +@use './md-sys-color'; +@use './md-sys-elevation'; +@use './md-sys-shape'; +@use './md-sys-typescale'; +@use './v0_192/md-comp-top-app-bar-medium'; +// go/keep-sorted end + + +$_default: ( + 'md-sys-color': md-sys-color.values-light(), + 'md-sys-elevation': md-sys-elevation.values(), + 'md-sys-shape': md-sys-shape.values(), + 'md-sys-typescale': md-sys-typescale.values(), +); + +@function values($deps: $_default, $exclude-hardcoded-values: false) { + @return md-comp-top-app-bar-medium.values($deps, $exclude-hardcoded-values); +} diff --git a/tokens/_md-comp-top-app-bar-small-centered.scss b/tokens/_md-comp-top-app-bar-small-centered.scss new file mode 100644 index 0000000000..059b9e4ec8 --- /dev/null +++ b/tokens/_md-comp-top-app-bar-small-centered.scss @@ -0,0 +1,23 @@ +// +// Copyright 2023 Google LLC +// SPDX-License-Identifier: Apache-2.0 +// + +// go/keep-sorted start +@use './md-sys-color'; +@use './md-sys-elevation'; +@use './md-sys-shape'; +@use './md-sys-typescale'; +@use './v0_192/md-comp-top-app-bar-small-centered'; +// go/keep-sorted end + +$_default: ( + 'md-sys-color': md-sys-color.values-light(), + 'md-sys-elevation': md-sys-elevation.values(), + 'md-sys-shape': md-sys-shape.values(), + 'md-sys-typescale': md-sys-typescale.values(), +); + +@function values($deps: $_default, $exclude-hardcoded-values: false) { + @return md-comp-top-app-bar-small-centered.values($deps, $exclude-hardcoded-values); +} diff --git a/tokens/_md-comp-top-app-bar-small.scss b/tokens/_md-comp-top-app-bar-small.scss new file mode 100644 index 0000000000..774dcf53e5 --- /dev/null +++ b/tokens/_md-comp-top-app-bar-small.scss @@ -0,0 +1,23 @@ +// +// Copyright 2023 Google LLC +// SPDX-License-Identifier: Apache-2.0 +// + +// go/keep-sorted start +@use './md-sys-color'; +@use './md-sys-elevation'; +@use './md-sys-shape'; +@use './md-sys-typescale'; +@use './v0_192/md-comp-top-app-bar-small'; +// go/keep-sorted end + +$_default: ( + 'md-sys-color': md-sys-color.values-light(), + 'md-sys-elevation': md-sys-elevation.values(), + 'md-sys-shape': md-sys-shape.values(), + 'md-sys-typescale': md-sys-typescale.values(), +); + +@function values($deps: $_default, $exclude-hardcoded-values: false) { + @return md-comp-top-app-bar-small.values($deps, $exclude-hardcoded-values); +} diff --git a/topappbar/center-aligned-top-app-bar.ts b/topappbar/center-aligned-top-app-bar.ts new file mode 100644 index 0000000000..bfbc4942bd --- /dev/null +++ b/topappbar/center-aligned-top-app-bar.ts @@ -0,0 +1,21 @@ +import {TopAppBar} from './internal/top-app-bar.js'; + +import {CSSResultOrNative} from 'lit'; +import {customElement} from 'lit/decorators.js'; + +import {styles as sharedStyles} from './internal/shared-styles.js'; +import {styles} from './internal/center-aligned-top-app-bar-styles.js'; + +declare global { + interface HTMLElementTagNameMap { + 'md-center-aligned-top-app-bar': MdCenterAlignedTopAppBar; + } +} + +/** + * @deprecated Due to new M3 expressive design update + */ +@customElement('md-center-aligned-top-app-bar') +export class MdCenterAlignedTopAppBar extends TopAppBar { + static override styles: CSSResultOrNative[] = [sharedStyles, styles]; +} diff --git a/topappbar/demo/demo.ts b/topappbar/demo/demo.ts new file mode 100644 index 0000000000..edc6dd81de --- /dev/null +++ b/topappbar/demo/demo.ts @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import '~catalog/stories/index.js'; +import '~catalog/stories/material-collection.js'; + +import {KnobTypesToKnobs, MaterialCollection, materialInitsToStoryInits, setUpDemo} from '~catalog/stories/material-collection.js'; +import {boolInput, Knob} from '~catalog/stories/index.js'; + +import {stories, StoryKnobs} from './stories.js'; + +const collection = + new MaterialCollection>('Top app bar', [ + new Knob('sticky', { + ui: boolInput(), + defaultValue: false + }) + ]); + +collection.addStories(...materialInitsToStoryInits(stories)); + +setUpDemo(collection, {fonts: 'roboto', icons: 'material-symbols'}); diff --git a/topappbar/demo/project.json b/topappbar/demo/project.json new file mode 100644 index 0000000000..92f3e79587 --- /dev/null +++ b/topappbar/demo/project.json @@ -0,0 +1,9 @@ +{ + "extends": "/assets/stories/base.json", + "files": { + "demo.ts": { + "hidden": true + }, + "stories.ts": {} + } +} diff --git a/topappbar/demo/stories.ts b/topappbar/demo/stories.ts new file mode 100644 index 0000000000..7ab88cbbca --- /dev/null +++ b/topappbar/demo/stories.ts @@ -0,0 +1,91 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import '@material/web/icon/icon.js'; +import '@material/web/top-app-bar/center-aligned-top-app-bar.js'; +import '@material/web/top-app-bar/small-top-app-bar.js'; +import '@material/web/top-app-bar/medium-top-app-bar.js'; +import '@material/web/top-app-bar/large-top-app-bar.js'; + +import {MaterialStoryInit} from '~catalog/stories/material-collection.js'; +import {html} from 'lit'; + +/** Knob types for button stories. */ +export interface StoryKnobs { + /** Whether the top app bar is open. */ + sticky: boolean; +} + + +const centerAlignedTopAppBar: MaterialStoryInit = { + name: 'Center Aligned Top App Bar', + render({sticky}) { + return html` + + + menu + + Title + + search + + + `; + } +}; +const smallTopAppBar: MaterialStoryInit = { + name: 'Small Top App Bar', + render({sticky}) { + return html` + + + menu + + Title + + search + + + `; + } +}; + +const mediumTopAppBar: MaterialStoryInit = { + name: 'Medium Top App Bar', + render({sticky}) { + return html` + + + menu + + Title + + search + + + `; + } +}; + +const largeTopAppBar: MaterialStoryInit = { + name: 'Large Top App Bar', + render({sticky}) { + return html` + + + menu + + Title + + search + + + `; + } +}; + +/** Button stories. */ +export const stories = [centerAlignedTopAppBar, smallTopAppBar, mediumTopAppBar, largeTopAppBar]; diff --git a/topappbar/internal/_center-aligned-top-app-bar.scss b/topappbar/internal/_center-aligned-top-app-bar.scss new file mode 100644 index 0000000000..d354cca1e2 --- /dev/null +++ b/topappbar/internal/_center-aligned-top-app-bar.scss @@ -0,0 +1,15 @@ +@use "../../tokens"; + +@mixin styles() { + :host { + $tokens: tokens.md-comp-top-app-bar-small-centered-values(); + @each $token, $value in $tokens { + --_#{$token}: var(--md-center-aligned-top-app-bar-#{$token}, #{$value}); + } + + slot:not([name])::slotted(*) { + display: flex; + justify-content: center; + } + } +} diff --git a/topappbar/internal/_large-top-app-bar.scss b/topappbar/internal/_large-top-app-bar.scss new file mode 100644 index 0000000000..2aa6522b23 --- /dev/null +++ b/topappbar/internal/_large-top-app-bar.scss @@ -0,0 +1,22 @@ +@use "../../tokens"; + +@mixin styles() { + :host { + $tokens: tokens.md-comp-top-app-bar-large-values(); + @each $token, $value in $tokens { + --_#{$token}: var(--md-large-top-app-bar-#{$token}, #{$value}); + } + + flex-wrap: wrap; + + slot[name="start"] { + flex-basis: 15%; + } + + slot[name="end"] { + flex-basis: 75%; + display: flex; + justify-content: flex-end; + } + } +} diff --git a/topappbar/internal/_medium-top-app-bar.scss b/topappbar/internal/_medium-top-app-bar.scss new file mode 100644 index 0000000000..67978f2a61 --- /dev/null +++ b/topappbar/internal/_medium-top-app-bar.scss @@ -0,0 +1,22 @@ +@use "../../tokens"; + +@mixin styles() { + :host { + $tokens: tokens.md-comp-top-app-bar-medium-values(); + @each $token, $value in $tokens { + --_#{$token}: var(--md-medium-top-app-bar-#{$token}, #{$value}); + } + + flex-wrap: wrap; + + slot[name="start"] { + flex-basis: 15%; + } + + slot[name="end"] { + flex-basis: 75%; + display: flex; + justify-content: flex-end; + } + } +} diff --git a/topappbar/internal/_shared.scss b/topappbar/internal/_shared.scss new file mode 100644 index 0000000000..a61c51b630 --- /dev/null +++ b/topappbar/internal/_shared.scss @@ -0,0 +1,74 @@ +@use 'sass:map'; +@use "../../elevation/elevation"; + +@mixin styles() { + :host { + background-color: var(--_container-color); + border-radius: var(--_container-shape); + height: var(--_container-height); + + width: 100%; + display: flex; + align-items: center; + position: relative; // For elevation + padding-inline: 16px; + gap: 24px; + + @include elevation.theme( + ( + level: var(--_container-elevation), + shadow-color: var(--_container-shadow-color) + ) + ); + + slot[name="start"] { + &::slotted(md-icon-button) { + --md-icon-button-icon-color: var(--_leading-icon-color); + --md-icon-button-icon-size: var(--_leading-icon-size); + } + &::slotted(md-icon) { + --md-icon-size: var(--_leading-icon-size); + color: var(--_leading-icon-color); + } + } + + slot[name="end"] { + &::slotted(md-icon-button) { + --md-icon-button-icon-color: var(--_trailing-icon-color); + --md-icon-button-icon-size: var(--_trailing-icon-size); + } + &::slotted(md-icon) { + --md-icon-size: var(--_trailing-icon-size); + color: var(--_trailing-icon-color); + } + } + + // Headline + slot:not([name]) { + color: var(--_headline-color); + font: var(--_headline-font); + line-height: var(--_headline-line-height); + font-size: var(--_headline-size); + font-weight: var(--_headline-weight); + + &::slotted(*) { + flex: 1; + } + } + } + + :host([sticky]) { + position: sticky; + transition-duration: 250ms; + transition-timing-function: ease-in-out; + } + + :host([sticky].is-scrolling) { + background-color: var(--_on-scroll-container-color); + @include elevation.theme( + ( + level: var(--_on-scroll-container-elevation) + ) + ) + } +} diff --git a/topappbar/internal/_small-top-app-bar.scss b/topappbar/internal/_small-top-app-bar.scss new file mode 100644 index 0000000000..6b631e3658 --- /dev/null +++ b/topappbar/internal/_small-top-app-bar.scss @@ -0,0 +1,10 @@ +@use "../../tokens"; + +@mixin styles() { + :host { + $tokens: tokens.md-comp-top-app-bar-small-values(); + @each $token, $value in $tokens { + --_#{$token}: var(--md-small-top-app-bar-#{$token}, #{$value}); + } + } +} diff --git a/topappbar/internal/center-aligned-top-app-bar-styles.scss b/topappbar/internal/center-aligned-top-app-bar-styles.scss new file mode 100644 index 0000000000..ec765623ba --- /dev/null +++ b/topappbar/internal/center-aligned-top-app-bar-styles.scss @@ -0,0 +1,3 @@ +@use './center-aligned-top-app-bar'; + +@include center-aligned-top-app-bar.styles(); diff --git a/topappbar/internal/expanded-top-app-bar.ts b/topappbar/internal/expanded-top-app-bar.ts new file mode 100644 index 0000000000..659b9b3347 --- /dev/null +++ b/topappbar/internal/expanded-top-app-bar.ts @@ -0,0 +1,49 @@ +import '../../elevation/elevation.js'; +import {html, LitElement} from 'lit'; +import {property} from 'lit/decorators/property.js'; + +/** + * ExpandedTopAppBar component. + */ +export abstract class ExpandedTopAppBar extends LitElement { + /** Whether the top app bar is sticky. */ + @property({type: Boolean, reflect: true}) sticky = false; + + protected override render() { + return html` + ${this.renderLeadingContent()} + ${this.renderTrailingContent()} + ${this.renderHeadline()} + + `; + } + + protected renderLeadingContent() { + return html``; + } + + protected renderHeadline() { + return html``; + } + + protected renderTrailingContent() { + return html``; + } + + override connectedCallback() { + super.connectedCallback(); + const observer = new IntersectionObserver( + ([e]) => this.onStuckChanged(e), + {threshold: [1]} + ); + + observer.observe(this) + } + + protected onStuckChanged(e: IntersectionObserverEntry) { + const isStuck = e.intersectionRatio < 1; + if (this.sticky) { + e.target.classList.toggle('is-scrolling', isStuck); + } + } +} diff --git a/topappbar/internal/large-top-app-bar-styles.scss b/topappbar/internal/large-top-app-bar-styles.scss new file mode 100644 index 0000000000..e203de5c38 --- /dev/null +++ b/topappbar/internal/large-top-app-bar-styles.scss @@ -0,0 +1,3 @@ +@use './large-top-app-bar'; + +@include large-top-app-bar.styles(); diff --git a/topappbar/internal/medium-top-app-bar-styles.scss b/topappbar/internal/medium-top-app-bar-styles.scss new file mode 100644 index 0000000000..a455663abc --- /dev/null +++ b/topappbar/internal/medium-top-app-bar-styles.scss @@ -0,0 +1,3 @@ +@use './medium-top-app-bar'; + +@include medium-top-app-bar.styles(); diff --git a/topappbar/internal/shared-styles.scss b/topappbar/internal/shared-styles.scss new file mode 100644 index 0000000000..db50a912bb --- /dev/null +++ b/topappbar/internal/shared-styles.scss @@ -0,0 +1,3 @@ +@use './shared'; + +@include shared.styles(); diff --git a/topappbar/internal/small-top-app-bar-styles.scss b/topappbar/internal/small-top-app-bar-styles.scss new file mode 100644 index 0000000000..a1e070ad30 --- /dev/null +++ b/topappbar/internal/small-top-app-bar-styles.scss @@ -0,0 +1,3 @@ +@use './small-top-app-bar'; + +@include small-top-app-bar.styles(); diff --git a/topappbar/internal/top-app-bar.ts b/topappbar/internal/top-app-bar.ts new file mode 100644 index 0000000000..ec9a4a13a5 --- /dev/null +++ b/topappbar/internal/top-app-bar.ts @@ -0,0 +1,49 @@ +import '../../elevation/elevation.js'; +import {html, LitElement} from 'lit'; +import {property} from 'lit/decorators/property.js'; + +/** + * TopAppBar component. + */ +export abstract class TopAppBar extends LitElement { + /** Whether the top app bar is sticky. */ + @property({type: Boolean, reflect: true}) sticky = false; + + protected override render() { + return html` + ${this.renderLeadingContent()} + ${this.renderHeadline()} + ${this.renderTrailingContent()} + + `; + } + + protected renderLeadingContent() { + return html``; + } + + protected renderHeadline() { + return html``; + } + + protected renderTrailingContent() { + return html``; + } + + override connectedCallback() { + super.connectedCallback(); + const observer = new IntersectionObserver( + ([e]) => this.onStuckChanged(e), + {threshold: [1]} + ); + + observer.observe(this) + } + + protected onStuckChanged(e: IntersectionObserverEntry) { + const isStuck = e.intersectionRatio < 1; + if (this.sticky) { + e.target.classList.toggle('is-scrolling', isStuck); + } + } +} diff --git a/topappbar/large-top-app-bar.ts b/topappbar/large-top-app-bar.ts new file mode 100644 index 0000000000..9750d1dcbd --- /dev/null +++ b/topappbar/large-top-app-bar.ts @@ -0,0 +1,18 @@ +import {ExpandedTopAppBar} from './internal/expanded-top-app-bar.js'; + +import {CSSResultOrNative} from 'lit'; +import {customElement} from 'lit/decorators.js'; + +import {styles as sharedStyles} from './internal/shared-styles.js'; +import {styles} from './internal/large-top-app-bar-styles.js'; + +declare global { + interface HTMLElementTagNameMap { + 'md-large-top-app-bar': MdLargeTopAppBar; + } +} + +@customElement('md-large-top-app-bar') +export class MdLargeTopAppBar extends ExpandedTopAppBar { + static override styles: CSSResultOrNative[] = [sharedStyles, styles]; +} diff --git a/topappbar/medium-top-app-bar.ts b/topappbar/medium-top-app-bar.ts new file mode 100644 index 0000000000..b58e5dd701 --- /dev/null +++ b/topappbar/medium-top-app-bar.ts @@ -0,0 +1,18 @@ +import {ExpandedTopAppBar} from './internal/expanded-top-app-bar.js'; + +import {CSSResultOrNative} from 'lit'; +import {customElement} from 'lit/decorators.js'; + +import {styles as sharedStyles} from './internal/shared-styles.js'; +import {styles} from './internal/medium-top-app-bar-styles.js'; + +declare global { + interface HTMLElementTagNameMap { + 'md-medium-top-app-bar': MdMediumTopAppBar; + } +} + +@customElement('md-medium-top-app-bar') +export class MdMediumTopAppBar extends ExpandedTopAppBar { + static override styles: CSSResultOrNative[] = [sharedStyles, styles]; +} diff --git a/topappbar/small-top-app-bar.ts b/topappbar/small-top-app-bar.ts new file mode 100644 index 0000000000..a75883072b --- /dev/null +++ b/topappbar/small-top-app-bar.ts @@ -0,0 +1,18 @@ +import {TopAppBar} from './internal/top-app-bar.js'; + +import {CSSResultOrNative} from 'lit'; +import {customElement} from 'lit/decorators.js'; + +import {styles as sharedStyles} from './internal/shared-styles.js'; +import {styles} from './internal/small-top-app-bar-styles.js'; + +declare global { + interface HTMLElementTagNameMap { + 'md-small-top-app-bar': MdSmallTopAppBar; + } +} + +@customElement('md-small-top-app-bar') +export class MdSmallTopAppBar extends TopAppBar { + static override styles: CSSResultOrNative[] = [sharedStyles, styles]; +}