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
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+```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];
+}