Skip to content

Commit 5d72ec7

Browse files
authored
Foundations / Viewport breakpoints - Adoption in HDS (#2859)
1 parent d829257 commit 5d72ec7

File tree

9 files changed

+71
-55
lines changed

9 files changed

+71
-55
lines changed

.changeset/red-rice-refuse.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@hashicorp/design-system-components": minor
3+
---
4+
5+
`Pagination` - Replaced custom breakpoint (`1000px`) with standard `lg` (`1088px`) breakpoint
6+
7+
`Stepper::Nav` - Replaced custom breakpoint (`550px`) with standard `sm` (`480px`) breakpoint
8+
9+
`AppHeader` - Removed usage of `--hds-app-desktop-breakpoint` CSS variable and relied on the `@breakpoint` argument for override of mobile behaviour
10+
11+
`AppSideNav` - Removed usage of `--hds-app-desktop-breakpoint` CSS variable, added `@breakpoint` argument, and relied on it for override of mobile behaviour

packages/components/src/components/hds/app-header/index.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { tracked } from '@glimmer/tracking';
1010
import { registerDestructor } from '@ember/destroyable';
1111
import type Owner from '@ember/owner';
1212

13+
import { hdsBreakpoints } from '@hashicorp/design-system-components/utils/hds-breakpoints';
14+
1315
export interface HdsAppHeaderSignature {
1416
Args: {
1517
breakpoint?: string;
@@ -39,17 +41,8 @@ export default class HdsAppHeader extends Component<HdsAppHeaderSignature> {
3941
// Generates a unique ID for the Menu Content
4042
private _menuContentId = 'hds-menu-content-' + guidFor(this);
4143

42-
private _breakpoint = parseInt(
43-
getComputedStyle(document.documentElement).getPropertyValue(
44-
'--hds-app-desktop-breakpoint'
45-
)
46-
);
47-
48-
private _desktopMQVal =
49-
this.args.breakpoint ??
50-
getComputedStyle(document.documentElement).getPropertyValue(
51-
'--hds-app-desktop-breakpoint'
52-
);
44+
// we use the `lg` breakpoint for `desktop` viewports, but consumers can override its value
45+
private _desktopMQVal = this.args.breakpoint ?? hdsBreakpoints['lg'].px;
5346

5447
constructor(owner: Owner, args: Record<string, never>) {
5548
super(owner, args);

packages/components/src/components/hds/app-side-nav/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import { action } from '@ember/object';
99
import { registerDestructor } from '@ember/destroyable';
1010
import type Owner from '@ember/owner';
1111

12+
import { hdsBreakpoints } from '@hashicorp/design-system-components/utils/hds-breakpoints';
13+
1214
export interface HdsAppSideNavSignature {
1315
Args: {
1416
isResponsive?: boolean;
1517
isCollapsible?: boolean;
1618
isMinimized?: boolean;
19+
breakpoint?: string;
1720
onToggleMinimizedStatus?: (arg: boolean) => void;
1821
onDesktopViewportChange?: (arg: boolean) => void;
1922
};
@@ -33,9 +36,8 @@ export default class HdsAppSideNav extends Component<HdsAppSideNavSignature> {
3336
private _desktopMQ: MediaQueryList;
3437
private _containersToHide!: NodeListOf<Element>;
3538

36-
private _desktopMQVal = getComputedStyle(
37-
document.documentElement
38-
).getPropertyValue('--hds-app-desktop-breakpoint');
39+
// we use the `lg` breakpoint for `desktop` viewports, but consumers can override its value
40+
private _desktopMQVal = this.args.breakpoint ?? hdsBreakpoints['lg'].px;
3941

4042
constructor(owner: Owner, args: HdsAppSideNavSignature['Args']) {
4143
super(owner, args);

packages/components/src/styles/components/app-side-nav/vars.scss

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
// notice: they may be overwritten at consumer-level side if needed by re-defining the variables in a container element
1313

1414
:root {
15-
// breakpoint
16-
--hds-app-desktop-breakpoint: 1088px; // this is used only to read its value via JS and set the `hds-app-side-nav--is-desktop` class
1715
// widths
1816
--hds-app-side-nav-width-minimized: 16px;
1917
--hds-app-side-nav-width-expanded: 280px;

packages/components/src/styles/components/pagination.scss

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@
88
//
99

1010
@use "../mixins/focus-ring" as *;
11-
12-
// custom breakpoint for the pagination, swapping between horizontal and stacked layout
13-
// notice: the value is based on where the component layout potentially breaks down
14-
15-
$hds-pagination-layout-breakpoint: 1000px;
11+
@use "../mixins/breakpoints" as *;
1612

1713
// * Pagination Parent (wrapper) component
1814
// -------------------------------------------------------------------
@@ -25,7 +21,7 @@ $hds-pagination-layout-breakpoint: 1000px;
2521
align-items: center;
2622
margin: 0 auto;
2723

28-
@media screen and (max-width: $hds-pagination-layout-breakpoint) {
24+
@include hds-breakpoint-below("lg") {
2925
display: flex;
3026
flex-wrap: wrap;
3127
justify-content: center;
@@ -37,7 +33,7 @@ $hds-pagination-layout-breakpoint: 1000px;
3733
justify-self: flex-start;
3834
margin-right: var(--token-pagination-child-spacing-horizontal);
3935

40-
@media screen and (max-width: $hds-pagination-layout-breakpoint) {
36+
@include hds-breakpoint-below("lg") {
4137
margin-top: var(--token-pagination-child-spacing-vertical);
4238
margin-left: var(--token-pagination-child-spacing-horizontal);
4339
}
@@ -46,7 +42,7 @@ $hds-pagination-layout-breakpoint: 1000px;
4642
.hds-pagination-nav {
4743
grid-area: nav;
4844

49-
@media screen and (max-width: $hds-pagination-layout-breakpoint) {
45+
@include hds-breakpoint-below("lg") {
5046
justify-content: center;
5147
order: -1;
5248
// Force nav to occupy a full row so other components will wrap:
@@ -59,7 +55,7 @@ $hds-pagination-layout-breakpoint: 1000px;
5955
justify-self: flex-end;
6056
margin-left: var(--token-pagination-child-spacing-horizontal);
6157

62-
@media screen and (max-width: $hds-pagination-layout-breakpoint) {
58+
@include hds-breakpoint-below("lg") {
6359
margin-top: var(--token-pagination-child-spacing-vertical);
6460
margin-right: var(--token-pagination-child-spacing-horizontal);
6561
}

packages/components/src/styles/components/side-nav/vars.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77
// SIDE-NAV - VARS
88
//
99

10+
@use "sass:map";
1011
@use "../../mixins/interactive-dark-theme" as *;
12+
@use "../../mixins/breakpoints" as *;
1113

1214
// LOCAL VARIABLES
1315
// we use `hds-app` as prefix to distinguish them from the normal tokens
1416
// notice: they may be overwritten at consumer-level side if needed by re-defining the variables in a container element
1517

1618
:root {
1719
// breakpoint
18-
--hds-app-desktop-breakpoint: 1088px; // this is used only to read its value via JS and set the `hds-side-nav--is-desktop` class
20+
--hds-app-desktop-breakpoint: #{map.get($hds-breakpoints, "lg")}; // this is used only to read its value via JS and set the `hds-side-nav--is-desktop` class
1921
// widths
2022
--hds-app-sidenav-width-minimized: 48px;
2123
--hds-app-sidenav-width-expanded: 280px;

packages/components/src/styles/components/stepper/nav.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
@use "sass:map";
1111
@use "../../mixins/focus-ring" as *;
12+
@use "../../mixins/breakpoints" as *;
1213
@use "./step-indicator.scss" as *;
1314

1415
$progress-bar-animation-duration: 0.25s;
@@ -288,7 +289,7 @@ $progress-bar-animation-duration: 0.25s;
288289

289290
// MOBILE
290291

291-
@media screen and (width <= 550px) {
292+
@include hds-breakpoint-below("sm") {
292293
.hds-stepper-nav {
293294
&::before,
294295
&::after {

showcase/tests/integration/components/hds/app-header/index-test.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,28 @@ module('Integration | Component | hds/app-header/index', function (hooks) {
5252
// Note: We set a high breakpoint to force the component to render as "mobile"
5353

5454
test('it is "mobile" on narrow viewports', async function (assert) {
55-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10000px}</style>
56-
<Hds::AppHeader id='test-app-header' />`);
55+
await render(
56+
hbs`<Hds::AppHeader id='test-app-header' @breakpoint='10000px' />`
57+
);
5758
assert.dom('#test-app-header').hasClass('hds-app-header--is-mobile');
5859
});
5960

6061
test('it shows a menu button on narrow viewports', async function (assert) {
61-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10000px}</style>
62-
<Hds::AppHeader />`);
62+
await render(hbs`
63+
<Hds::AppHeader @breakpoint='10000px' />`);
6364
assert.dom('.hds-app-header__menu-button').exists();
6465
});
6566

6667
// Mobile menu functionality
6768
test(`the actions do not display by default on narrow viewports`, async function (assert) {
68-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10000px}</style>
69-
<Hds::AppHeader id='test-app-header' />`);
69+
await render(hbs`
70+
<Hds::AppHeader id='test-app-header' @breakpoint='10000px' />`);
7071
assert.dom('#test-app-header').hasClass('hds-app-header--menu-is-closed');
7172
});
7273

7374
test(`the actions show/hide when the menu button is pressed on narrow viewports`, async function (assert) {
74-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10000px}</style>
75-
<Hds::AppHeader id='test-app-header' />`);
75+
await render(hbs`
76+
<Hds::AppHeader id='test-app-header' @breakpoint='10000px' />`);
7677
assert.dom('#test-app-header').hasClass('hds-app-header--menu-is-closed');
7778

7879
await click('.hds-app-header__menu-button');
@@ -95,8 +96,7 @@ module('Integration | Component | hds/app-header/index', function (hooks) {
9596
// A11Y
9697

9798
test(`it displays the correct value for aria-expanded when actions are displayed vs hidden`, async function (assert) {
98-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10000px}</style>
99-
<Hds::AppHeader />`);
99+
await render(hbs`<Hds::AppHeader @breakpoint='10000px' />`);
100100
await click('.hds-app-header__menu-button');
101101
assert
102102
.dom('.hds-app-header__menu-button')
@@ -109,8 +109,9 @@ module('Integration | Component | hds/app-header/index', function (hooks) {
109109
});
110110

111111
test('the actions menu collapses when the ESC key is pressed on narrow viewports', async function (assert) {
112-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10000px}</style>
113-
<Hds::AppHeader id='test-app-header' />`);
112+
await render(
113+
hbs`<Hds::AppHeader id='test-app-header' @breakpoint='10000px' />`
114+
);
114115
assert.dom('#test-app-header').hasClass('hds-app-header--menu-is-closed');
115116

116117
await click('.hds-app-header__menu-button');
@@ -121,8 +122,7 @@ module('Integration | Component | hds/app-header/index', function (hooks) {
121122
});
122123

123124
test('the menu button has an aria-controls attribute with a value matching the menu id', async function (assert) {
124-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10000px}</style>
125-
<Hds::AppHeader />`);
125+
await render(hbs`<Hds::AppHeader @breakpoint='10000px' />`);
126126
await click('.hds-app-header__menu-button');
127127
assert.dom('.hds-app-header__menu-button').hasAttribute('aria-controls');
128128
assert.dom('.hds-app-header__actions').hasAttribute('id');

showcase/tests/integration/components/hds/app-side-nav/index-test.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,40 +88,54 @@ module('Integration | Component | hds/app-side-nav/index', function (hooks) {
8888
// MOBILE
8989

9090
test('it is "mobile" on narrow viewports', async function (assert) {
91-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10088px}</style>
92-
<Hds::AppSideNav id='test-app-side-nav' />`);
91+
await render(
92+
hbs`<Hds::AppSideNav id='test-app-side-nav' @breakpoint='10000px' />`
93+
);
9394
assert.dom('#test-app-side-nav').hasClass('hds-app-side-nav--is-mobile');
9495
});
9596

9697
test('it is minimized/collapsed on narrow viewports by default', async function (assert) {
97-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10088px}</style>
98-
<Hds::AppSideNav id='test-app-side-nav' />`);
98+
await render(
99+
hbs`<Hds::AppSideNav id='test-app-side-nav' @breakpoint='10000px' />`
100+
);
99101
assert.dom('#test-app-side-nav').hasClass('hds-app-side-nav--is-minimized');
100102
});
101103

102104
test('it is not minimized/collapsed on narrow viewports if `isResponsive` is false', async function (assert) {
103-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10088px}</style>
104-
<Hds::AppSideNav id='test-app-side-nav' @isResponsive={{false}} />`);
105+
await render(
106+
hbs`<Hds::AppSideNav
107+
id='test-app-side-nav'
108+
@isResponsive={{false}}
109+
@breakpoint='10000px'
110+
/>`
111+
);
105112
assert
106113
.dom('#test-app-side-nav')
107114
.hasClass('hds-app-side-nav--is-not-minimized');
108115
});
109116

110117
test('it shows a toggle button on narrow viewports by default', async function (assert) {
111-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10088px}</style>
112-
<Hds::AppSideNav id='test-app-side-nav' />`);
118+
await render(
119+
hbs`<Hds::AppSideNav id='test-app-side-nav' @breakpoint='10000px' />`
120+
);
113121
assert.dom('.hds-app-side-nav__toggle-button').exists();
114122
});
115123

116124
test('it does not show a toggle button on narrow viewports if `isResponsive` is false', async function (assert) {
117-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10088px}</style>
118-
<Hds::AppSideNav id='test-app-side-nav' @isResponsive={{false}} />`);
125+
await render(
126+
hbs`<Hds::AppSideNav
127+
id='test-app-side-nav'
128+
@isResponsive={{false}}
129+
@breakpoint='10000px'
130+
/>`
131+
);
119132
assert.dom('.hds-app-side-nav__toggle-button').doesNotExist();
120133
});
121134

122135
test('it expands/collapses when the toggle button is pressed on narrow viewports', async function (assert) {
123-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10088px}</style>
124-
<Hds::AppSideNav id='test-app-side-nav' />`);
136+
await render(
137+
hbs`<Hds::AppSideNav id='test-app-side-nav' @breakpoint='10000px' />`
138+
);
125139
assert.dom('#test-app-side-nav').hasClass('hds-app-side-nav--is-minimized');
126140

127141
await click('.hds-app-side-nav__toggle-button');
@@ -133,8 +147,7 @@ module('Integration | Component | hds/app-side-nav/index', function (hooks) {
133147
});
134148

135149
test('it collapses when the ESC key is pressed on narrow viewports', async function (assert) {
136-
await render(hbs`<style>:root {--hds-app-desktop-breakpoint: 10088px}</style>
137-
<Hds::AppSideNav id='test-app-side-nav'>
150+
await render(hbs`<Hds::AppSideNav id='test-app-side-nav' @breakpoint='10000px'>
138151
<span id='test-app-side-nav-body' />
139152
<span class='hds-app-side-nav-hide-when-minimized' />
140153
</Hds::AppSideNav>`);

0 commit comments

Comments
 (0)