diff --git a/projects/scion/dimension/src/lib/dimension.module.ts b/projects/scion/dimension/src/lib/dimension.module.ts
index 123e62e0b..1308bea4a 100644
--- a/projects/scion/dimension/src/lib/dimension.module.ts
+++ b/projects/scion/dimension/src/lib/dimension.module.ts
@@ -19,6 +19,9 @@ import { SciDimensionDirective } from './dimension.directive';
  * Web Performance Working Group is working on a W3C recommendation for natively observing changes to Element’s size.
  * The Web API draft is still work in progress and support limited to Google Chrome and Opera.
  *
+ * You can control if to use the native {ResizeObserver} by default with {USE_NATIVE_RESIZE_OBSERVER} DI injection token.
+ * If not provided, the native resize observable is used, unless explicitly set via options object when creating the resize observable.
+ *
  * @see https://wicg.github.io/ResizeObserver/
  * @see https://caniuse.com/#feat=resizeobserver
  */
diff --git a/projects/scion/dimension/src/lib/dimension.service.ts b/projects/scion/dimension/src/lib/dimension.service.ts
index 333382b7e..cacb1f5be 100644
--- a/projects/scion/dimension/src/lib/dimension.service.ts
+++ b/projects/scion/dimension/src/lib/dimension.service.ts
@@ -10,10 +10,21 @@
 
 import { concat, fromEvent, Observable, Observer, of, ReplaySubject, Subject, TeardownLogic } from 'rxjs';
 import { map, multicast, refCount, switchMap, takeUntil, tap } from 'rxjs/operators';
-import { Injectable } from '@angular/core';
+import { Injectable, InjectionToken, Injector } from '@angular/core';
 
+/**
+ * CSS class added to the HTML <object> element emitting resize events if not using the native {ResizeObserver}.
+ */
 const SYNTH_RESIZE_OBSERVABLE_OBJECT_MARKER = 'synth-resize-observable';
 
+/**
+ * DI injection token to control if to use the native {ResizeObserver} by default.
+ * If not provided, the native resize observable is used, unless explicitly set via options object when creating the resize observable.
+ *
+ * This flag is only evaluated if the user agent supports {ResizeObserver}.
+ */
+export const USE_NATIVE_RESIZE_OBSERVER = new InjectionToken<boolean>('USE_NATIVE_RESIZE_OBSERVER');
+
 /**
  * Allows observing the dimension of an element.
  *
@@ -37,6 +48,9 @@ export class SciDimensionService {
    */
   public _objectObservableRegistry = new Map<HTMLElement, Observable<SciDimension>>();
 
+  constructor(private _injector: Injector) {
+  }
+
   /**
    * Upon subscription, it emits the element's dimension, and then continuously emits when the dimension of the element changes. It never completes.
    *
@@ -48,9 +62,12 @@ export class SciDimensionService {
    *          By default, this flag is enabled.
    */
   public dimension$(target: HTMLElement, options?: { useNativeResizeObserver: boolean }): Observable<SciDimension> {
-    const useNativeResizeObserver = !options || options.useNativeResizeObserver === undefined || options.useNativeResizeObserver === true;
+    options = {
+      useNativeResizeObserver: this._injector.get(USE_NATIVE_RESIZE_OBSERVER, true),
+      ...options,
+    };
 
-    if (useNativeResizeObserver && supportsNativeResizeObserver()) {
+    if (options.useNativeResizeObserver && supportsNativeResizeObserver()) {
       return createNativeResizeObservable$(target);
     }
 
diff --git a/projects/scion/dimension/src/public_api.ts b/projects/scion/dimension/src/public_api.ts
index 9a68ef84c..cbf97a239 100644
--- a/projects/scion/dimension/src/public_api.ts
+++ b/projects/scion/dimension/src/public_api.ts
@@ -14,4 +14,4 @@
 export { SciDimensionModule } from './lib/dimension.module';
 export { SciDimensionDirective } from './lib/dimension.directive';
 export { SciMutationService } from './lib/mutation.service';
-export { SciDimensionService, SciDimension } from './lib/dimension.service';
+export { SciDimensionService, SciDimension, USE_NATIVE_RESIZE_OBSERVER } from './lib/dimension.service';
diff --git a/projects/scion/workbench-application.core/src/lib/intent.service.ts b/projects/scion/workbench-application.core/src/lib/intent.service.ts
index 6955371f8..3a5477209 100644
--- a/projects/scion/workbench-application.core/src/lib/intent.service.ts
+++ b/projects/scion/workbench-application.core/src/lib/intent.service.ts
@@ -19,6 +19,7 @@ import { map } from 'rxjs/operators';
  * Allows issuing an intent to interact with the platform.
  */
 export class IntentService implements Service {
+
   /**
    * Issues an intent to the application platform and receives a series of replies.
    *
diff --git a/projects/scion/workbench-application.core/src/lib/message-bus.service.ts b/projects/scion/workbench-application.core/src/lib/message-bus.service.ts
index ce5b8e2f3..012102c79 100644
--- a/projects/scion/workbench-application.core/src/lib/message-bus.service.ts
+++ b/projects/scion/workbench-application.core/src/lib/message-bus.service.ts
@@ -8,7 +8,7 @@
  *  SPDX-License-Identifier: EPL-2.0
  */
 
-import { fromEvent, Observable, Subject } from 'rxjs';
+import { fromEvent, merge, Observable, Observer, Subject, TeardownLogic } from 'rxjs';
 import { filter, first, takeUntil } from 'rxjs/operators';
 import { UUID } from './uuid.util';
 import { Service } from './metadata';
@@ -102,14 +102,22 @@ export class DefaultMessageBus implements MessageBus {
     envelope.replyToUid = replyToUid;
     envelope.protocol = PROTOCOL;
 
-    const reply$ = this._stream$
-      .pipe(
-        filter(env => env.channel === 'reply'),
-        filter(env => env.replyToUid === replyToUid),
-        takeUntil(this._destroy$),
-      );
-    this.postMessage(envelope);
-    return reply$;
+    return new Observable((observer: Observer<MessageEnvelope>): TeardownLogic => {
+      const destroy$ = new Subject<void>();
+      this._stream$
+        .pipe(
+          filter(env => env.channel === 'reply'),
+          filter(env => env.replyToUid === replyToUid),
+          takeUntil(merge(destroy$, this._destroy$)),
+        )
+        .subscribe(observer);
+
+      this.postMessage(envelope);
+
+      return (): void => {
+        destroy$.next();
+      };
+    });
   }
 
   public requestReply(envelope: MessageEnvelope): Promise<MessageEnvelope> {
diff --git a/projects/scion/workbench/src/lib/spec/workbench-testing.module.ts b/projects/scion/workbench/src/lib/spec/workbench-testing.module.ts
index 71e466586..c3a74d371 100644
--- a/projects/scion/workbench/src/lib/spec/workbench-testing.module.ts
+++ b/projects/scion/workbench/src/lib/spec/workbench-testing.module.ts
@@ -2,6 +2,7 @@ import { Injectable, ModuleWithProviders, NgModule } from '@angular/core';
 import { ViewActivationInstantProvider } from '../view-activation-instant-provider.service';
 import { WorkbenchModule } from '../workbench.module';
 import { WorkbenchConfig } from '../workbench.config';
+import { USE_NATIVE_RESIZE_OBSERVER } from '@scion/dimension';
 
 @Injectable()
 export class ViewActivationTestingInstantProvider implements ViewActivationInstantProvider {
@@ -27,6 +28,14 @@ export class WorkbenchTestingModule {
       providers: [
         WorkbenchModule.forRoot(config).providers,
         {provide: ViewActivationInstantProvider, useClass: ViewActivationTestingInstantProvider},
+        /**
+         * Disable native `ResizeObserver` in tests because it sometimes throws 'loop limit exceeded' error which can safely be ignored.
+         *
+         * Comment from the specification authors:
+         * This error means that `ResizeObserver` was not able to deliver all observations within a single animation frame. It is benign and the site will not break.
+         * See https://stackoverflow.com/a/50387233
+         */
+        {provide: USE_NATIVE_RESIZE_OBSERVER, useValue: false},
       ],
     };
   }
diff --git a/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.html b/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.html
index d3d2db276..d4fb4b73c 100644
--- a/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.html
+++ b/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.html
@@ -1,8 +1,7 @@
-<sci-viewport [style.width.px]="viewTabsWidthPx"
-              scrollbarStyle="hidden"
+<sci-viewport scrollbarStyle="hidden"
               sciDimension (sciDimensionChange)="onViewportChange()"
               (scroll)="onScroll()">
-  <div #viewport_client class="viewport-client" sciDimension (sciDimensionChange)="onViewportClientChange()">
+  <div class="viewport-client" sciDimension (sciDimensionChange)="onViewportClientChange($event)">
     <wb-view-tab *ngFor="let viewRef of viewPartService.viewRefs" [viewRef]="viewRef" [renderingHint]="'tab-item'"></wb-view-tab>
   </div>
 </sci-viewport>
diff --git a/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.ts b/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.ts
index 5981e1326..da72023cb 100644
--- a/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.ts
+++ b/projects/scion/workbench/src/lib/view-part/view-part-bar/view-part-bar.component.ts
@@ -16,6 +16,8 @@ import { VIEW_DRAG_TYPE } from '../../workbench.constants';
 import { WorkbenchLayoutService } from '../../workbench-layout.service';
 import { takeUntil } from 'rxjs/operators';
 import { Subject } from 'rxjs';
+import { SciViewportComponent } from '@scion/viewport';
+import { SciDimension } from '@scion/dimension';
 
 @Component({
   selector: 'wb-view-part-bar',
@@ -29,10 +31,8 @@ export class ViewPartBarComponent implements OnDestroy {
   @ViewChildren(ViewTabComponent)
   private _viewTabs: QueryList<ViewTabComponent>;
 
-  @ViewChild('viewport_client', {static: true})
-  private _viewportClient: ElementRef<HTMLElement>;
-
-  public viewTabsWidthPx: number;
+  @ViewChild(SciViewportComponent, {static: true, read: ElementRef})
+  private _viewport: ElementRef<HTMLElement>;
 
   constructor(private _workbench: InternalWorkbenchService,
               private _workbenchLayout: WorkbenchLayoutService,
@@ -68,20 +68,23 @@ export class ViewPartBarComponent implements OnDestroy {
   }
 
   public onViewportChange(): void {
-    this.layout();
+    this.computeHiddenViewTabs();
   }
 
-  public onViewportClientChange(): void {
-    this.layout();
+  public onViewportClientChange(dimension: SciDimension): void {
+    // The viewport is set to 'flex: initial' with its width set equal to the viewport client width. It shrinks if there is not enough space available.
+    // The viewport is not set to 'flex: auto' to render left-aligned actions right after the view tabs.
+
+    // The width is set directly to the viewport DOM element not to waste a change detection cycle when computing the hidden view tabs.
+    this._viewport.nativeElement.style.width = `${dimension.clientWidth}px`;
+    this.computeHiddenViewTabs();
   }
 
   public onScroll(): void {
-    this.layout();
+    this.computeHiddenViewTabs();
   }
 
-  private layout(): void {
-    this.viewTabsWidthPx = this._viewportClient.nativeElement.clientWidth;
-
+  private computeHiddenViewTabs(): void {
     // Compute tabs which are not visible in the viewtabs viewport.
     this._viewTabs && this.viewPartService.setHiddenViewTabs(this._viewTabs
       .filter(viewTab => !viewTab.isVisibleInViewport())