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

Hds::SideNav - add @isCollapsible and @isMinimized arguments #1630

Merged
merged 35 commits into from Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d8e7c44
Expose `isMinimized` argument
alex-ju Aug 21, 2023
95ddf58
Separate minimized from deskop/mobile styles
alex-ju Aug 21, 2023
f254c6a
Add `isCollapsible` argument
alex-ju Sep 11, 2023
fa7e148
Update collapse/expand button design
alex-ju Sep 11, 2023
dc2a72e
Change width when minimized
alex-ju Sep 11, 2023
8fc9a5a
Update `SideNav` showcase
alex-ju Sep 11, 2023
4689f3a
Simplify menu toggle button example labels
alex-ju Sep 18, 2023
92dc8ec
Update SideNav tokens
alex-ju Sep 18, 2023
dd810d5
Update design to preserve home link
alex-ju Sep 18, 2023
f90394a
Use CSS variables for border values
alex-ju Sep 18, 2023
28072af
Update transition duration for the toggle button
alex-ju Sep 18, 2023
3599039
Update additional class names logic
alex-ju Sep 18, 2023
281ad0b
Refactor CSS to allow easy change of border-width
alex-ju Sep 19, 2023
943f083
Add new arguments to docs
alex-ju Sep 19, 2023
04da954
Add changelog entry
alex-ju Sep 19, 2023
46aaa5a
Animate the logo on collapse/expand
alex-ju Sep 20, 2023
d6c386c
Remove unused style definitions
alex-ju Sep 20, 2023
f63468f
Align animation durations to 200ms
alex-ju Sep 21, 2023
aeabd16
Clarify arguments in backing class
alex-ju Sep 22, 2023
d116f18
Highlight the reason for the box model change
alex-ju Sep 22, 2023
6e15901
Rename `--hds-app-sidenav-border-radius`
alex-ju Sep 22, 2023
e375fce
Move some variable to tokens
alex-ju Sep 22, 2023
dc88ee0
Rename `hds-side-nav__menu-toggle-button` class
alex-ju Sep 22, 2023
326c887
Refactor `SideNav::ToggleButton`
alex-ju Sep 22, 2023
a718e9f
Explicitly set transition properties
alex-ju Sep 28, 2023
f4536f3
Adjust label in showcase
alex-ju Sep 28, 2023
c17d047
Remove unused property
alex-ju Sep 28, 2023
09be8c7
Update changelog entry
alex-ju Sep 28, 2023
f3dc299
Update SideNav guidelines, anatomy, docs (#1665)
jorytindall Sep 29, 2023
10b7ad0
Remove Y-axis transform
alex-ju Sep 29, 2023
44068f0
Refactor toggle button box model
alex-ju Sep 29, 2023
e37b22b
Remove unused tokens
alex-ju Sep 29, 2023
c401404
Fix SideNav showcase for toggle button
alex-ju Sep 29, 2023
b1d0076
Add tests for 'mobile'
alex-ju Oct 2, 2023
2cb4681
Apply suggestions from code review
alex-ju Oct 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/two-pumas-deny.md
@@ -0,0 +1,6 @@
---
"@hashicorp/design-system-components": minor
"@hashicorp/design-system-tokens": minor
---

`SideNav` - add `@isCollapsible` (to control if users can collapse the sidenav on 'desktop' viewports) and `@isMinimized` (to control the default state on 'desktop' viewports) arguments
13 changes: 5 additions & 8 deletions packages/components/addon/components/hds/side-nav/index.hbs
Expand Up @@ -19,18 +19,15 @@
@navigationText={{@a11yRefocusNavigationText}}
/>
{{/if}}
{{#if this.isResponsive}}
{{#if this.showToggleButton}}
{{! template-lint-disable no-invalid-interactive}}
<div class="hds-side-nav__overlay" {{on "click" this.toggleMinimizedStatus}} />
{{! template-lint-enable no-invalid-interactive}}
<button
class="hds-side-nav__menu-toggle-button"
type="button"
{{on "click" this.toggleMinimizedStatus}}
<Hds::SideNav::ToggleButton
aria-label={{this.ariaLabel}}
>
<FlightIcon @name={{if this.isMinimized "menu" "x"}} @size="24" @stretched={{true}} />
</button>
@icon={{if this.isMinimized "chevrons-right" "chevrons-left"}}
{{on "click" this.toggleMinimizedStatus}}
/>
{{/if}}
</:root>
<:header as |Header|>
Expand Down
33 changes: 22 additions & 11 deletions packages/components/addon/components/hds/side-nav/index.js
Expand Up @@ -10,8 +10,9 @@ import { assert } from '@ember/debug';
import { registerDestructor } from '@ember/destroyable';

export default class HdsSideNavComponent extends Component {
@tracked isResponsive = this.args.isResponsive ?? true;
@tracked isMinimized = this.isResponsive; // we set it minimized by default so that if we switch viewport from desktop to mobile its already minimized
@tracked isResponsive = this.args.isResponsive ?? true; // controls if the component reacts to viewport changes
@tracked isMinimized = this.args.isMinimized ?? false; // sets the default state on 'desktop' viewports
@tracked isCollapsible = this.args.isCollapsible ?? false; // controls if users can collapse the sidenav on 'desktop' viewports
@tracked isAnimating = false;
@tracked isDesktop = true;
hasA11yRefocus = this.args.hasA11yRefocus ?? true;
Expand Down Expand Up @@ -39,8 +40,11 @@ export default class HdsSideNavComponent extends Component {
addEventListeners() {
document.addEventListener('keydown', this.escapePress, true);
this.desktopMQ.addEventListener('change', this.updateDesktopVariable, true);
// set initial state based on viewport
this.updateDesktopVariable({ matches: this.desktopMQ.matches });
// if not instantiated as minimized via arguments
if (!this.args.isMinimized) {
didoo marked this conversation as resolved.
Show resolved Hide resolved
// set initial state based on viewport
this.updateDesktopVariable({ matches: this.desktopMQ.matches });
}
}

removeEventListeners() {
Expand All @@ -56,6 +60,10 @@ export default class HdsSideNavComponent extends Component {
return this.isResponsive && !this.isDesktop && !this.isMinimized;
}

get showToggleButton() {
return (this.isResponsive && !this.isDesktop) || this.isCollapsible;
didoo marked this conversation as resolved.
Show resolved Hide resolved
didoo marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @param ariaLabel
* @type {string}
Expand All @@ -72,15 +80,15 @@ export default class HdsSideNavComponent extends Component {
let classes = []; // `hds-side-nav` is already set by the "Hds::SideNav::Base" component

// add specific class names for the different possible states
if (this.isDesktop) {
classes.push('hds-side-nav--is-desktop');
} else {
classes.push('hds-side-nav--is-mobile');
}
if (this.isResponsive) {
classes.push('hds-side-nav--is-responsive');
}
if (this.isMinimized) {
if (!this.isDesktop && this.isResponsive) {
didoo marked this conversation as resolved.
Show resolved Hide resolved
classes.push('hds-side-nav--is-mobile');
} else {
classes.push('hds-side-nav--is-desktop');
}
if (this.isMinimized && this.isResponsive) {
classes.push('hds-side-nav--is-minimized');
} else {
classes.push('hds-side-nav--is-not-minimized');
Expand All @@ -94,7 +102,7 @@ export default class HdsSideNavComponent extends Component {

@action
escapePress(event) {
if (event.key === 'Escape' && !this.isMinimized) {
if (event.key === 'Escape' && !this.isMinimized && !this.isDesktop) {
this.isMinimized = true;
}
}
Expand Down Expand Up @@ -127,6 +135,9 @@ export default class HdsSideNavComponent extends Component {
updateDesktopVariable(event) {
this.isDesktop = event.matches;

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

let { onDesktopViewportChange } = this.args;

if (typeof onDesktopViewportChange === 'function') {
Expand Down
@@ -0,0 +1,7 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}
<button class="hds-side-nav__toggle-button" type="button" ...attributes>
<FlightIcon @name={{@icon}} />
didoo marked this conversation as resolved.
Show resolved Hide resolved
</button>
@@ -0,0 +1,6 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

export { default } from '@hashicorp/design-system-components/components/hds/side-nav/toggle-button';
10 changes: 10 additions & 0 deletions packages/components/app/styles/components/side-nav/header.scss
Expand Up @@ -60,6 +60,16 @@
justify-content: center;
width: var(--token-side-nav-header-home-link-logo-size);
height: var(--token-side-nav-header-home-link-logo-size);
transition:
width var(--hds-app-sidenav-animation-duration)
var(--hds-app-sidenav-animation-easing),
height var(--hds-app-sidenav-animation-duration)
var(--hds-app-sidenav-animation-easing);

.hds-side-nav--is-minimized & {
didoo marked this conversation as resolved.
Show resolved Hide resolved
width: var(--token-side-nav-header-home-link-logo-size-minimized);
height: var(--token-side-nav-header-home-link-logo-size-minimized);
}
}

// "home-link"
Expand Down
Expand Up @@ -7,4 +7,5 @@
@use "./main.scss";
@use "./header.scss";
@use "./content.scss";
@use "./toggle-button.scss";
@use "./a11y-refocus.scss";
93 changes: 21 additions & 72 deletions packages/components/app/styles/components/side-nav/main.scss
Expand Up @@ -31,7 +31,13 @@

// desktop
&.hds-side-nav--is-desktop {
width: var(--hds-app-sidenav-width-expanded);
&.hds-side-nav--is-not-minimized {
width: var(--hds-app-sidenav-width-expanded);
}

&.hds-side-nav--is-minimized {
width: var(--hds-app-sidenav-width-minimized);
}
}
}

Expand Down Expand Up @@ -61,65 +67,6 @@
}
}


// MENU/TOGGLE BUTTON

.hds-side-nav__menu-toggle-button {
position: absolute;
z-index: 1;
color: var(--token-color-foreground-high-contrast);
background: none;
border: 1px solid transparent;
cursor: pointer;
transition-timing-function: var(--hds-app-sidenav-animation-easing);
transition-duration: var(--hds-app-sidenav-animation-duration);
transition-property: width, height, padding, border-radius, transform;

&:hover {
background-color: var(--token-color-palette-neutral-600);
border-color: transparent;
}

&:active {
background-color: var(--token-color-palette-neutral-500);
border-color: transparent;
}

&:focus {
background-color: var(--token-color-palette-neutral-500);
border-color: var(--token-color-focus-action-internal);
outline: 3px solid var(--token-color-focus-action-external);
}

// by default it's styled as "close" button
.hds-side-nav--is-mobile & {
width: 24px;
height: 24px;
padding: 1px;
background-color: var(--token-color-foreground-primary);
border-radius: 3px;
transform:
translateX(calc(var(--hds-app-sidenav-width-expanded) + 8px))
translateY(24px);
// z-index: 15; // not needed anymore?
}

// when the sidenav is minimized it's styled as "menu" button
.hds-side-nav--is-mobile.hds-side-nav--is-minimized & {
width: 36px;
height: 36px;
padding: 5px;
border-radius: 5px;
transform: translateX(22px) translateY(var(--hds-app-sidenav-menu-button-y-shift));
}

// when it's desktop we _never_ want to show the menu/toggle button
.hds-side-nav--is-desktop & {
display: none;
}
}


// RESPONSIVE WRAPPER
// this container element is used to control the width of the sidebar at different viewports (desktop/mobile) and states (minimized/expanded)

Expand All @@ -129,6 +76,7 @@
height: 100%;
color: var(--token-side-nav-color-foreground-primary); // we set a default color (in case generic content is added to the header/body/footer of the sidenav)
background: var(--token-side-nav-color-surface-primary);
border-right: var(--token-side-nav-wrapper-border-width) solid var(--token-side-nav-wrapper-border-color);

// RESPONSIVENESS - This controls the width of the "sidenav" container, and is independent (bur related) from the parent "sidebar" grid area

Expand All @@ -138,17 +86,11 @@
var(--hds-app-sidenav-animation-easing);
}

// mobile
.hds-side-nav--is-mobile.hds-side-nav--is-minimized & {
.hds-side-nav--is-minimized & {
width: var(--hds-app-sidenav-width-minimized);
}

.hds-side-nav--is-mobile.hds-side-nav--is-not-minimized & {
width: var(--hds-app-sidenav-width-expanded);
}

// desktop
.hds-side-nav--is-desktop & {
.hds-side-nav--is-not-minimized & {
width: var(--hds-app-sidenav-width-expanded);
}
}
Expand All @@ -160,6 +102,15 @@
padding-right: var(--token-side-nav-wrapper-padding-horizontal);
padding-bottom: 8px; // by design
padding-left: var(--token-side-nav-wrapper-padding-horizontal);
transition:
padding var(--hds-app-sidenav-animation-duration)
var(--hds-app-sidenav-animation-easing);

.hds-side-nav--is-minimized & {
padding-top: var(--token-side-nav-wrapper-padding-vertical-minimized);
didoo marked this conversation as resolved.
Show resolved Hide resolved
padding-right: var(--token-side-nav-wrapper-padding-horizontal-minimized);
padding-left: var(--token-side-nav-wrapper-padding-horizontal-minimized);
}
}

.hds-side-nav__wrapper-body {
Expand Down Expand Up @@ -187,10 +138,9 @@
// - shown (transitioning their opacity) when the sidenav is "expanded"

.hds-side-nav-hide-when-minimized {
.hds-side-nav--is-mobile.hds-side-nav--is-minimized & {
.hds-side-nav--is-minimized & {
visibility: hidden !important; // we need `!important` here to override the inline style applied to the single panels
opacity: 0;
transition: none;
// this is needed because, despite the element having `visibility: hidden`,
// the child elements ("panels") have their visibility dynamically managed via JS
// and when they have "visibility: visible" applied, they are not visually visible
Expand All @@ -206,8 +156,7 @@
pointer-events: none;
}

.hds-side-nav--is-mobile.hds-side-nav--is-not-minimized &,
.hds-side-nav--is-desktop & {
.hds-side-nav--is-not-minimized & {
visibility: visible;
opacity: 1;
transition:
Expand Down