Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AppSideNav - Component branch (HDS-3800) #2384

Merged
merged 71 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
42b5265
HDS-3800 Add AppSideNav component initial files
KristinLBradley Sep 3, 2024
729903d
HDS-3800 Fix failing tests
KristinLBradley Sep 3, 2024
33843fc
HDS-3800 Include app-side-nav Showcase styles, update Showcase to mat…
KristinLBradley Sep 4, 2024
03bbb8d
HDS-3800 Regenerate design tokens in output
KristinLBradley Sep 4, 2024
d3b73a7
HDS-3800 Update JS & CSS for Showcase display
KristinLBradley Sep 4, 2024
c9df162
HDS-3800 Make preliminary css updates to AppSideNav to replace dark t…
KristinLBradley Sep 4, 2024
3d6d232
HDS-3800 Add new framed example with AppSideNav
KristinLBradley Sep 4, 2024
167c6c0
HDS-3800 Update styles for current active List::Link
KristinLBradley Sep 5, 2024
c2e053f
HDS-3800 Update Badges in AppSideNav to outlined variant
KristinLBradley Sep 5, 2024
30e4b92
HDS-3800 Add border-radius to active indicator
KristinLBradley Sep 5, 2024
e903d7b
HDS-3800 Update JSON values
KristinLBradley Sep 5, 2024
9096539
HDS-3800 Regenerate design tokens in output
KristinLBradley Sep 5, 2024
b5797f0
HDS-3800 Fix states for active List::Link, remove temporary token def…
KristinLBradley Sep 5, 2024
06982fd
HDS-3800 Fix background color of :active state for List::Link
KristinLBradley Sep 5, 2024
756d2db
HDS-3800 Expose color prop of icons in List::Link, add example with c…
KristinLBradley Sep 6, 2024
e1e399b
HDS-3800 Remove interaction styles for current/active link since it d…
KristinLBradley Sep 6, 2024
72e9c9e
HDS-3800 Add fix for toggle border overlaying AppSideNav border
KristinLBradley Sep 6, 2024
93ae299
HDS-3800 Add clip-path to prevent white background of toggle corners …
KristinLBradley Sep 6, 2024
ae43580
HDS-3800 Add test for iconColor arg
KristinLBradley Sep 10, 2024
c00a2d8
HDS-3800 Remove NavigatorNarrator (a11y-refocus) from AppSideNav
KristinLBradley Sep 10, 2024
f60c125
HDS-3800 Remove old argument, fix failing test
KristinLBradley Sep 10, 2024
2457d1d
HDS-3800 Fix failing tests, comment out web tests until web docs are …
KristinLBradley Sep 11, 2024
9e5e609
HDS-3800 Remove skip link example from Showcase as it's no longer app…
KristinLBradley Sep 11, 2024
7914b6c
HDS-3800 Undo temp styles for testing skip link
KristinLBradley Sep 11, 2024
476bed1
HDS-3800 Remove header component and HomeLink child component
KristinLBradley Sep 12, 2024
21b3d1c
HDS-3800 Clean up Showcase examples
KristinLBradley Sep 12, 2024
f05c92e
HDS-3800 Update to remove ember-testing reference matching SideNav co…
KristinLBradley Sep 12, 2024
349d036
HDS-3800 Clean up type definitions
KristinLBradley Sep 18, 2024
6e82e49
HDS-3800 Rename ariaLabel for toggle button for clarity
KristinLBradley Sep 18, 2024
519b731
HDS-3800 Add aria-current=page for active ListLink
KristinLBradley Sep 18, 2024
ed375b7
HDS-3800 Delete TODO comment
KristinLBradley Sep 18, 2024
729c888
HDS-3800 Remove examples of nested BUttons & Dropdowns from Showcase …
KristinLBradley Sep 18, 2024
17c6958
HDS-3800 Set negative tabindex for active Link
KristinLBradley Sep 18, 2024
69ff58e
HDS-3800 Remove background-color from hds-app-side-nav__list-item-link
KristinLBradley Sep 18, 2024
bc144f1
HDS-3800 Refactor .active state styles to fix issue with link :active…
KristinLBradley Sep 19, 2024
c133e15
HDS-3800 Improve toggle tab rounded corner rendering
KristinLBradley Sep 19, 2024
f875869
HDS-3800 Remove colored icons from framed example, remove typesafe di…
KristinLBradley Sep 19, 2024
114d2e9
HDS-3800 Update color used for border in design tokens, update relate…
KristinLBradley Sep 20, 2024
06a80d0
HDS-3800 Regenerate design tokens in output
KristinLBradley Sep 20, 2024
c2e4aa9
HDS-3800 Remove negative tabIndex
KristinLBradley Sep 20, 2024
eaa6637
HDS-3800 Add example of BackLink used in context to Showcase
KristinLBradley Sep 20, 2024
67dc8d1
HDS-3800 Remove uneeded id
KristinLBradley Sep 20, 2024
07c9d2f
HDS-3800 Port fix for inert synchronization from SideNav
KristinLBradley Sep 20, 2024
26e87df
HDS-3800 Update design token value used by titles
KristinLBradley Sep 20, 2024
52277ba
HDS-3800 Regenerate design tokens in output
KristinLBradley Sep 20, 2024
833a484
HDS-3800 UPdate list item color
KristinLBradley Sep 20, 2024
d535776
HDS-3800 Add changelog
KristinLBradley Sep 23, 2024
4fd5086
Update silver-planes-occur.md
KristinLBradley Sep 23, 2024
26be75c
Update silver-planes-occur.md
KristinLBradley Sep 24, 2024
1c9a9b3
HDS-3800 Remove glint-expect-error
KristinLBradley Sep 25, 2024
05719a0
HDS-3800 Update to swap empty component classes to templateOnly and m…
KristinLBradley Sep 25, 2024
1da5653
HDS-3800 Remove Component from names to match SideNav updates
KristinLBradley Sep 25, 2024
0bd56e3
HDS-3800 Fix incorrect class names
KristinLBradley Sep 25, 2024
d63232c
HDS-3800 Update comment
KristinLBradley Sep 25, 2024
22ac894
HDS-3800 Remove iconColor option
KristinLBradley Sep 27, 2024
b8adf31
`AppSideNav` - overlay scrolling bug fix (HDS-3914) (#2472)
KristinLBradley Oct 2, 2024
fead0ea
`AppSideNav` - Follow-on improvements for headers & aria (HDS-3897) (…
KristinLBradley Oct 3, 2024
7bd67c1
`AppSideNav` - Web docs (HDS-3807) (#2410)
KristinLBradley Oct 4, 2024
52f9446
`AppSideNav` - Remove named blocks (HDS-3924) (#2477)
KristinLBradley Oct 8, 2024
9858cf9
`AppSideNav` - Replace tracked variables from args (#2486)
KristinLBradley Oct 8, 2024
ce68b9a
`AppSideNav` - Fix bug with scrolling caused by hidden panels (HDS-38…
KristinLBradley Oct 15, 2024
986b2ec
`SideNav` - Deprecate component (HDS-3848) (#2425)
KristinLBradley Oct 15, 2024
a9eefa1
Update website/docs/components/app-side-nav/index.md
KristinLBradley Oct 16, 2024
7841ab5
HDS-3800 Update references to versioning
KristinLBradley Oct 16, 2024
52e972a
HDS-3800 Add back missing line
KristinLBradley Oct 16, 2024
35bbd4f
HDS-3800 export signature
KristinLBradley Oct 17, 2024
b4973a6
`AppSideNav` - deprioritize adoption (#2518)
KristinLBradley Oct 29, 2024
12a3149
HDS-3800 Remove changeset, comment out link to styles, skip tests
KristinLBradley Oct 30, 2024
87dde33
HDS-3800 skip tests
KristinLBradley Oct 30, 2024
b0e31b2
HDS-3800 Remove release badge and version history
KristinLBradley Oct 30, 2024
3480d21
Update website/docs/components/app-side-nav/index.md
KristinLBradley Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@
"./components/hds/app-frame/parts/main.js": "./dist/_app_/components/hds/app-frame/parts/main.js",
"./components/hds/app-frame/parts/modals.js": "./dist/_app_/components/hds/app-frame/parts/modals.js",
"./components/hds/app-frame/parts/sidebar.js": "./dist/_app_/components/hds/app-frame/parts/sidebar.js",
"./components/hds/app-header/home-link.js": "./dist/_app_/components/hds/app-header/home-link.js",
"./components/hds/app-header/index.js": "./dist/_app_/components/hds/app-header/index.js",
"./components/hds/app-header/menu-button.js": "./dist/_app_/components/hds/app-header/menu-button.js",
"./components/hds/application-state/body.js": "./dist/_app_/components/hds/application-state/body.js",
"./components/hds/application-state/footer.js": "./dist/_app_/components/hds/application-state/footer.js",
"./components/hds/application-state/header.js": "./dist/_app_/components/hds/application-state/header.js",
Expand Down
10 changes: 8 additions & 2 deletions packages/components/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,14 @@ const plugins = [
'components/**/!(*types).js',
'helpers/**/*.js',
'modifiers/**/*.js',
'instance-initializers/**/*.js',
]),
'instance-initializers/**/*.js'],
{
exclude: [
'components/**/app-header/**/*.js',
'components/**/app-side-nav/**/*.js',
],
}
),

// Follow the V2 Addon rules about dependencies. Your code can import from
// `dependencies` and `peerDependencies` as well as standard Ember-provided
Expand Down
34 changes: 34 additions & 0 deletions packages/components/src/components/hds/app-side-nav/index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}
{{! IMPORTANT: we need to add "squishies" here (~) because otherwise the whitespace added by Ember causes the empty element to still have visible padding - See https://handlebarsjs.com/guide/expressions.html#whitespace-control }}
<div
class={{this.classNames}}
...attributes
{{on "transitionstart" (fn this.setTransition "start")}}
{{on "transitionend" (fn this.setTransition "end")}}
{{! @glint-expect-error - https://github.com/josemarluedke/ember-focus-trap/issues/86 }}
{{focus-trap isActive=this.shouldTrapFocus}}
{{did-insert this.didInsert}}
>
<h2 class="sr-only" id="hds-app-side-nav-header">Application local navigation</h2>

<div class="hds-app-side-nav__wrapper">
{{#if this.showToggleButton}}
{{! template-lint-disable no-invalid-interactive}}
<div class="hds-app-side-nav__overlay" {{on "click" this.toggleMinimizedStatus}} />
{{! template-lint-enable no-invalid-interactive}}
<Hds::AppSideNav::ToggleButton
aria-labelledby="hds-app-side-nav-header"
aria-expanded={{if this.isMinimized "false" "true"}}
@icon={{if this.isMinimized "chevrons-right" "chevrons-left"}}
{{on "click" this.toggleMinimizedStatus}}
/>
{{/if}}

<div class="hds-app-side-nav__wrapper-body">
{{~yield~}}
</div>
</div>
</div>
210 changes: 210 additions & 0 deletions packages/components/src/components/hds/app-side-nav/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/**
KristinLBradley marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { registerDestructor } from '@ember/destroyable';

export interface HdsAppSideNavSignature {
Args: {
isResponsive?: boolean;
isCollapsible?: boolean;
isMinimized?: boolean;
onToggleMinimizedStatus?: (arg: boolean) => void;
onDesktopViewportChange?: (arg: boolean) => void;
};
Blocks: {
default?: [];
};
Element: HTMLDivElement;
}

export default class HdsAppSideNav extends Component<HdsAppSideNavSignature> {
@tracked isMinimized;
@tracked isAnimating = false;
@tracked isDesktop = true;

body!: HTMLElement;
bodyInitialOverflowValue = '';
desktopMQ: MediaQueryList;
containersToHide!: NodeListOf<Element>;

desktopMQVal = getComputedStyle(document.documentElement).getPropertyValue(
'--hds-app-desktop-breakpoint'
);

constructor(owner: unknown, args: HdsAppSideNavSignature['Args']) {
super(owner, args);
this.isMinimized = this.args.isMinimized ?? false; // sets the default state on 'desktop' viewports
this.desktopMQ = window.matchMedia(`(min-width:${this.desktopMQVal})`);
this.addEventListeners();
registerDestructor(this, (): void => {
this.removeEventListeners();
});
}

addEventListeners(): void {
document.addEventListener('keydown', this.escapePress, true);
this.desktopMQ.addEventListener('change', this.updateDesktopVariable, true);
shleewhite marked this conversation as resolved.
Show resolved Hide resolved
// if not instantiated as minimized via arguments
if (!this.args.isMinimized) {
// set initial state based on viewport using a "synthetic" event
const syntheticEvent = new MediaQueryListEvent('change', {
matches: this.desktopMQ.matches,
media: this.desktopMQ.media,
});
this.updateDesktopVariable(syntheticEvent);
}
}

removeEventListeners(): void {
document.removeEventListener('keydown', this.escapePress, true);
this.desktopMQ.removeEventListener(
'change',
this.updateDesktopVariable,
true
);
}

// controls if the component reacts to viewport changes
get isResponsive(): boolean {
return this.args.isResponsive ?? true;
}

// controls if users can collapse the appsidenav on 'desktop' viewports
get isCollapsible(): boolean {
return this.args.isCollapsible ?? false;
}

get shouldTrapFocus(): boolean {
return this.isResponsive && !this.isDesktop && !this.isMinimized;
}

get showToggleButton(): boolean {
return (this.isResponsive && !this.isDesktop) || this.isCollapsible;
}

get classNames(): string {
const classes = [`hds-app-side-nav`];

// add specific class names for the different possible states
if (this.isResponsive) {
classes.push('hds-app-side-nav--is-responsive');
}
if (!this.isDesktop && this.isResponsive) {
classes.push('hds-app-side-nav--is-mobile');
} else {
classes.push('hds-app-side-nav--is-desktop');
}
if (this.isMinimized && this.isResponsive) {
classes.push('hds-app-side-nav--is-minimized');
} else {
classes.push('hds-app-side-nav--is-not-minimized');
}
if (this.isAnimating) {
classes.push('hds-app-side-nav--is-animating');
}

return classes.join(' ');
}

synchronizeInert(): void {
this.containersToHide?.forEach((element): void => {
if (this.isMinimized) {
element.setAttribute('inert', '');
} else {
element.removeAttribute('inert');
}
});
}

lockBodyScroll(): void {
if (this.body) {
// Prevent page from scrolling when the dialog is open
this.body.style.setProperty('overflow', 'hidden');
}
}

unlockBodyScroll(): void {
// Reset page `overflow` property
if (this.body) {
this.body.style.removeProperty('overflow');
if (this.bodyInitialOverflowValue === '') {
if (this.body.style.length === 0) {
this.body.removeAttribute('style');
}
} else {
this.body.style.setProperty('overflow', this.bodyInitialOverflowValue);
}
}
}

@action
escapePress(event: KeyboardEvent): void {
if (event.key === 'Escape' && !this.isMinimized && !this.isDesktop) {
this.isMinimized = true;
this.synchronizeInert();
}
}

@action
toggleMinimizedStatus(): void {
this.isMinimized = !this.isMinimized;
this.synchronizeInert();

const { onToggleMinimizedStatus } = this.args;

if (typeof onToggleMinimizedStatus === 'function') {
onToggleMinimizedStatus(this.isMinimized);
}

if (this.isMinimized) {
this.unlockBodyScroll();
} else {
this.lockBodyScroll();
}
}

@action
didInsert(element: HTMLElement): void {
this.containersToHide = element.querySelectorAll(
'.hds-app-side-nav-hide-when-minimized'
);
this.body = document.body;
// Store the initial `overflow` value of `<body>` so we can reset to it
this.bodyInitialOverflowValue =
this.body.style.getPropertyValue('overflow');
}

@action
setTransition(phase: string, event: TransitionEvent): void {
// we only want to respond to `width` animation/transitions
if (event.propertyName !== 'width') {
return;
}
if (phase === 'start') {
this.isAnimating = true;
} else {
this.isAnimating = false;
}
}

@action
updateDesktopVariable(event: MediaQueryListEvent): void {
this.isDesktop = event.matches;

// automatically minimize on narrow viewports (when not in desktop mode)
this.isMinimized = !this.isDesktop;

this.synchronizeInert();

const { onDesktopViewportChange } = this.args;

if (typeof onDesktopViewportChange === 'function') {
onDesktopViewportChange(this.isDesktop);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}

<Hds::AppSideNav::List::Item>
<Hds::Interactive
class="hds-app-side-nav__list-item-link hds-app-side-nav__list-item-link--back-link"
@current-when={{@current-when}}
@models={{hds-link-to-models @model @models}}
@query={{hds-link-to-query @query}}
@replace={{@replace}}
@route={{@route}}
@isRouteExternal={{@isRouteExternal}}
@href={{@href}}
@isHrefExternal={{@isHrefExternal}}
...attributes
>
<Hds::Icon class="hds-app-side-nav__list-item-icon-leading" @name="chevron-left" />
<span class="hds-app-side-nav__list-item-text hds-typography-body-200 hds-font-weight-medium">
{{@text}}
</span>
</Hds::Interactive>
</Hds::AppSideNav::List::Item>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import TemplateOnlyComponent from '@ember/component/template-only';

import type { HdsInteractiveSignature } from '../../interactive';

export interface HdsAppSideNavListBackLinkSignature {
Args: HdsInteractiveSignature['Args'] & {
text: string;
};
Element: HdsInteractiveSignature['Element'];
}

const HdsAppSideNavListBackLink =
TemplateOnlyComponent<HdsAppSideNavListBackLinkSignature>();

export default HdsAppSideNavListBackLink;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}

<nav class="hds-app-side-nav__list-wrapper" aria-labelledby="hds-app-side-nav-header" ...attributes>
{{yield (hash ExtraBefore=(component "hds/yield"))}}
<ul class="hds-app-side-nav__list" role="list" aria-labelledby={{this.titleIds}}>
{{yield
(hash
Item=(component "hds/app-side-nav/list/item")
BackLink=(component "hds/app-side-nav/list/back-link")
Title=(component "hds/app-side-nav/list/title" didInsertTitle=this.didInsertTitle)
Link=(component "hds/app-side-nav/list/link")
)
}}
</ul>
{{yield (hash ExtraAfter=(component "hds/yield"))}}
</nav>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import type { ComponentLike } from '@glint/template';
import type { HdsYieldSignature } from '../../yield';
import type { HdsAppSideNavListItemSignature } from './item';
import type { HdsAppSideNavListBackLinkSignature } from './back-link';
import type { HdsAppSideNavListTitleSignature } from './title';
import type { HdsAppSideNavListLinkSignature } from './link';

export interface HdsAppSideNavListSignature {
Blocks: {
default: [
{
ExtraBefore?: ComponentLike<HdsYieldSignature>;
Item?: ComponentLike<HdsAppSideNavListItemSignature>;
BackLink?: ComponentLike<HdsAppSideNavListBackLinkSignature>;
Title?: ComponentLike<HdsAppSideNavListTitleSignature>;
Link?: ComponentLike<HdsAppSideNavListLinkSignature>;
ExtraAfter?: ComponentLike<HdsYieldSignature>;
},
];
};
Element: HTMLElement;
}

export default class HdsAppSideNavList extends Component<HdsAppSideNavListSignature> {
@tracked _titleIds: string[] = [];

get titleIds(): string {
return this._titleIds.join(' ');
}

@action
didInsertTitle(titleId: string): void {
this._titleIds = [...this._titleIds, titleId];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}

<li class="hds-app-side-nav__list-item" ...attributes>
{{yield}}
</li>
Loading