From 7b883470cbf7f1920b49ade4991a041812dd256a Mon Sep 17 00:00:00 2001 From: shleewhite Date: Mon, 29 Sep 2025 15:46:43 -0400 Subject: [PATCH 1/2] chore: add some more examples for app side nav --- .../mock/app/sidebar/app-side-nav.gts | 216 +++++++++--------- showcase/app/router.ts | 1 + .../frameless/demo-remove-from-dom.gts | 27 +++ .../page-components/app-side-nav/index.hbs | 18 ++ .../components/hds/app-side-nav/index-test.js | 40 +++- 5 files changed, 197 insertions(+), 105 deletions(-) create mode 100644 showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts diff --git a/showcase/app/components/mock/app/sidebar/app-side-nav.gts b/showcase/app/components/mock/app/sidebar/app-side-nav.gts index e1c3d577968..1b4b38b579e 100644 --- a/showcase/app/components/mock/app/sidebar/app-side-nav.gts +++ b/showcase/app/components/mock/app/sidebar/app-side-nav.gts @@ -24,6 +24,7 @@ export interface MockAppSidebarAppSideNavSignature { isResponsive?: HdsAppSideNavSignature['Args']['isResponsive']; isCollapsible?: HdsAppSideNavSignature['Args']['isCollapsible']; showDevToggle?: boolean; + shouldRemoveFromDomOnCollapse?: boolean; }; Element: HdsAppSideNavSignature['Element']; } @@ -32,6 +33,7 @@ export default class MockAppSidebarAppSideNav extends Component { + if (isOpen && this.args.shouldRemoveFromDomOnCollapse) + this.isRendered = false; + }; + } diff --git a/showcase/app/router.ts b/showcase/app/router.ts index 3defc276327..cbc23642057 100644 --- a/showcase/app/router.ts +++ b/showcase/app/router.ts @@ -37,6 +37,7 @@ Router.map(function () { this.route('app-side-nav', function () { this.route('frameless', function () { this.route('demo-responsiveness'); + this.route('demo-remove-from-dom'); }); }); this.route('application-state'); diff --git a/showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts b/showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts new file mode 100644 index 00000000000..06c645b7b58 --- /dev/null +++ b/showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts @@ -0,0 +1,27 @@ +import type { TemplateOnlyComponent } from '@ember/component/template-only'; +import { pageTitle } from 'ember-page-title'; + +import MockApp from 'showcase/components/mock/app'; + +const PageComponentsAppSideNavFramelessDemoRemoveFromDom: TemplateOnlyComponent = + ; + +export default PageComponentsAppSideNavFramelessDemoRemoveFromDom; diff --git a/showcase/app/templates/page-components/app-side-nav/index.hbs b/showcase/app/templates/page-components/app-side-nav/index.hbs index 81d120f561f..e70b796af9e 100644 --- a/showcase/app/templates/page-components/app-side-nav/index.hbs +++ b/showcase/app/templates/page-components/app-side-nav/index.hbs @@ -699,4 +699,22 @@ @label="Full AppFrame with AppHeader & AppSideNav (small viewport)" /> + + + + + This demo verifies that when the `AppSideNav` component is removed from the DOM while page overflow styles are + overridden, the page's scroll functionality is properly restored. + + + + To check this, expand and then collapse the AppSideNav. Then try to scroll the page. + + \ No newline at end of file diff --git a/showcase/tests/integration/components/hds/app-side-nav/index-test.js b/showcase/tests/integration/components/hds/app-side-nav/index-test.js index 77c2ee1959a..23ca9d9f657 100644 --- a/showcase/tests/integration/components/hds/app-side-nav/index-test.js +++ b/showcase/tests/integration/components/hds/app-side-nav/index-test.js @@ -314,13 +314,49 @@ module('Integration | Component | hds/app-side-nav/index', function (hooks) { assert.dom('body', document).doesNotHaveStyle('overflow'); }); + test('when expanded in mobile and the component is removed from the DOM, scrolling is enabled', async function (assert) { + this.mockMedia(); + + let calls = []; + this.setProperties({ + onDesktopViewportChange: (...args) => calls.push(args), + }); + + this.set('isAppSideNavRendered', true); + + await render(hbs`{{#if this.isAppSideNavRendered}} + +{{/if}}`); + + await this.changeBrowserSize(false); + + assert.deepEqual( + calls[1], + [false], + 'resizing to mobile triggers a false event', + ); + + await click('.hds-app-side-nav__toggle-button'); + + assert.dom('body', document).hasStyle({ + overflow: 'hidden', + }); + + this.set('isAppSideNavRendered', false); + + assert.dom('body', document).doesNotHaveStyle('overflow'); + }); + test('when collapsed, the content in the AppSideNav is not focusable', async function (assert) { await render(hbs` - -`); + +`); await click('.hds-app-side-nav__toggle-button'); assert.dom('#test-app-side-nav').hasClass('hds-app-side-nav--is-minimized'); From 62efba0bb903855721b977f72830668b692cae87 Mon Sep 17 00:00:00 2001 From: shleewhite Date: Tue, 7 Oct 2025 13:18:29 -0400 Subject: [PATCH 2/2] fix: move where logic is --- .../mock/app/sidebar/app-side-nav.gts | 218 +++++++++--------- .../frameless/demo-remove-from-dom.gts | 31 ++- 2 files changed, 127 insertions(+), 122 deletions(-) diff --git a/showcase/app/components/mock/app/sidebar/app-side-nav.gts b/showcase/app/components/mock/app/sidebar/app-side-nav.gts index 1b4b38b579e..6f55aa824ba 100644 --- a/showcase/app/components/mock/app/sidebar/app-side-nav.gts +++ b/showcase/app/components/mock/app/sidebar/app-side-nav.gts @@ -24,7 +24,7 @@ export interface MockAppSidebarAppSideNavSignature { isResponsive?: HdsAppSideNavSignature['Args']['isResponsive']; isCollapsible?: HdsAppSideNavSignature['Args']['isCollapsible']; showDevToggle?: boolean; - shouldRemoveFromDomOnCollapse?: boolean; + onToggleMinimizedStatus?: HdsAppSideNavSignature['Args']['onToggleMinimizedStatus']; }; Element: HdsAppSideNavSignature['Element']; } @@ -33,7 +33,6 @@ export default class MockAppSidebarAppSideNav extends Component { - if (isOpen && this.args.shouldRemoveFromDomOnCollapse) - this.isRendered = false; - }; - } diff --git a/showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts b/showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts index 06c645b7b58..664d9ec4b21 100644 --- a/showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts +++ b/showcase/app/templates/page-components/app-side-nav/frameless/demo-remove-from-dom.gts @@ -1,18 +1,32 @@ -import type { TemplateOnlyComponent } from '@ember/component/template-only'; +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; import { pageTitle } from 'ember-page-title'; +import { tracked } from '@glimmer/tracking'; import MockApp from 'showcase/components/mock/app'; -const PageComponentsAppSideNavFramelessDemoRemoveFromDom: TemplateOnlyComponent = +export default class PageComponentsAppSideNavFramelessDemoRemoveFromDom extends Component { + @tracked isRendered = true; + + removeSideNavFromDOM = (isOpen: boolean) => { + if (isOpen) this.isRendered = false; + }; + ; - -export default PageComponentsAppSideNavFramelessDemoRemoveFromDom; + +}