Skip to content

Commit

Permalink
account for hidden footers, no layout rounding, header track to use m…
Browse files Browse the repository at this point in the history
…inmax (#709)

* account for hidden footers, remove unnecessary rounding

* inverses are hard

* okay next try

* changesets

* update
  • Loading branch information
wibjorn authored Oct 25, 2024
1 parent 9894bb9 commit 6de95c8
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 70 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilly-cobras-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@microsoft/atlas-css': patch
---

For the layout component, the height of the header's grid track should be minmax(auto, max-content) to ensure proper height constraint happens.
5 changes: 5 additions & 0 deletions .changeset/famous-chefs-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@microsoft/atlas-js': patch
---

Fix bug where a hidden footer element would still register a height. Layout now always expects a header, but not necessarily a footer, since footers can be rendered within containers too.
5 changes: 5 additions & 0 deletions .changeset/pink-lizards-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@microsoft/atlas-css': patch
---

Stop accounting for rounding in calculations and remove -1px in the --atlas-contained-height property.
5 changes: 5 additions & 0 deletions .changeset/shaggy-numbers-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@microsoft/atlas-js': minor
---

Export a `dispatchAtlasLayoutUpdateEvent` function for easier use downstream.
5 changes: 5 additions & 0 deletions .changeset/strong-owls-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@microsoft/atlas-js': patch
---

Move footer border to child element of layout.
102 changes: 64 additions & 38 deletions css/src/components/layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -104,28 +104,29 @@ $default-flyout-width-widescreen: 480px;
.layout,
.layout.layout-single {
.layout-body {
grid-template: auto auto auto 1fr auto auto / minmax(0, 1fr);
grid-template: minmax(auto, max-content) auto auto 1fr auto auto / minmax(0, 1fr);
grid-template-areas: 'header' 'hero' 'menu' 'main' 'aside' 'footer';
}

&.layout-flyout-active .layout-body {
@include desktop {
grid-template: auto auto auto 1fr auto auto / minmax(0, 1fr) var(#{$layout-flyout-width-name});
grid-template: minmax(auto, max-content) auto auto 1fr auto auto / minmax(0, 1fr) var(
#{$layout-flyout-width-name}
);
grid-template-areas: 'header header' 'hero flyout' 'menu flyout' 'main flyout' 'aside flyout' 'footer footer';
}
}
}

.layout.layout-holy-grail {
.layout-body {
grid-template: auto auto auto 1fr auto auto / minmax(0, 1fr);
grid-template: minmax(auto, max-content) auto auto 1fr auto auto / minmax(0, 1fr);
grid-template-areas: 'header' 'hero' 'menu' 'main' 'aside' 'footer';

@include tablet {
grid-template: auto auto var(--atlas-contained-height) auto auto / minmax(0, 1fr) minmax(
0,
2fr
);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto auto / minmax(0, 1fr)
minmax(0, 2fr);
grid-template-areas:
'header header'
'hero hero'
Expand All @@ -135,10 +136,12 @@ $default-flyout-width-widescreen: 480px;
}

@include desktop {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(0, 2fr) minmax(
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(
0,
1fr
);
2fr
)
minmax(0, 1fr);
grid-template-areas:
'header header header'
'hero hero hero'
Expand All @@ -147,7 +150,7 @@ $default-flyout-width-widescreen: 480px;
}

@include widescreen {
grid-template: auto auto var(--atlas-contained-height) auto / auto #{$quarter-widescreen} #{$half-widescreen} #{$quarter-widescreen} auto;
grid-template: minmax(auto, max-content) auto var(--atlas-contained-height) auto / auto #{$quarter-widescreen} #{$half-widescreen} #{$quarter-widescreen} auto;
grid-template-areas:
'header header header header header'
'hero hero hero hero hero'
Expand Down Expand Up @@ -187,11 +190,13 @@ $default-flyout-width-widescreen: 480px;
}

.layout-body {
grid-template: auto auto auto 1fr auto / minmax(0, 1fr);
grid-template: minmax(auto, max-content) auto auto 1fr auto / minmax(0, 1fr);
grid-template-areas: 'header' 'hero' 'menu' 'main' 'footer';

@include tablet {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(0, 2fr);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 1fr)
minmax(0, 2fr);
grid-template-areas:
'header header'
'hero hero'
Expand All @@ -200,7 +205,9 @@ $default-flyout-width-widescreen: 480px;
}

@include desktop {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(0, 3fr);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 1fr)
minmax(0, 3fr);
grid-template-areas:
'header header'
'hero hero'
Expand All @@ -209,7 +216,7 @@ $default-flyout-width-widescreen: 480px;
}

@include widescreen {
grid-template: auto auto var(--atlas-contained-height) auto / auto #{$quarter-widescreen} #{$three-quarters-widescreen} auto;
grid-template: minmax(auto, max-content) auto var(--atlas-contained-height) auto / auto #{$quarter-widescreen} #{$three-quarters-widescreen} auto;
grid-template-areas:
'header header header header'
'hero hero hero hero'
Expand All @@ -220,19 +227,25 @@ $default-flyout-width-widescreen: 480px;

&.layout-flyout-active .layout-body {
@include desktop {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(0, 3fr) var(
#{$layout-flyout-width-name}
);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(
0,
3fr
)
var(#{$layout-flyout-width-name});
grid-template-areas:
'header header header'
'hero hero flyout'
'menu main flyout'
'footer footer footer';
}
@include widescreen {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(0, 3fr) var(
#{$layout-flyout-width-name}
);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(
0,
3fr
)
var(#{$layout-flyout-width-name});
grid-template-areas:
'header header header'
'hero hero flyout'
Expand All @@ -248,11 +261,13 @@ $default-flyout-width-widescreen: 480px;
}

.layout-body {
grid-template: auto auto auto 1fr auto / minmax(0, 1fr);
grid-template: minmax(auto, max-content) auto auto 1fr auto / minmax(0, 1fr);
grid-template-areas: 'header' 'hero' 'main' 'aside' 'footer';

@include tablet {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 2fr) minmax(0, 1fr);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 2fr)
minmax(0, 1fr);
grid-template-areas:
'header header'
'hero hero'
Expand All @@ -261,7 +276,9 @@ $default-flyout-width-widescreen: 480px;
}

@include desktop {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 3fr) minmax(0, 1fr);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 3fr)
minmax(0, 1fr);
grid-template-areas:
'header header'
'hero hero'
Expand All @@ -270,7 +287,7 @@ $default-flyout-width-widescreen: 480px;
}

@include widescreen {
grid-template: auto auto var(--atlas-contained-height) auto / auto #{$three-quarters-widescreen} #{$quarter-widescreen} auto;
grid-template: minmax(auto, max-content) auto var(--atlas-contained-height) auto / auto #{$three-quarters-widescreen} #{$quarter-widescreen} auto;
grid-template-areas:
'header header header header'
'hero hero hero hero'
Expand All @@ -281,9 +298,12 @@ $default-flyout-width-widescreen: 480px;

&.layout-flyout-active .layout-body {
@include desktop {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 3fr) minmax(0, 1fr) var(
#{$layout-flyout-width-name}
);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 3fr) minmax(
0,
1fr
)
var(#{$layout-flyout-width-name});
grid-template-areas:
'header header header'
'hero hero flyout'
Expand All @@ -292,9 +312,12 @@ $default-flyout-width-widescreen: 480px;
}

@include widescreen {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 3fr) minmax(0, 1fr) var(
#{$layout-flyout-width-name}
);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 3fr) minmax(
0,
1fr
)
var(#{$layout-flyout-width-name});
grid-template-areas:
'header header header'
'hero hero flyout'
Expand All @@ -310,12 +333,14 @@ $default-flyout-width-widescreen: 480px;
}

.layout-body {
grid-template: auto auto auto 1fr auto / minmax(0, 1fr);
grid-template: minmax(auto, max-content) auto auto 1fr auto / minmax(0, 1fr);
grid-template-areas: 'header' 'hero' 'main' 'aside' 'footer';

// note that to make some extra room this layout is not constrained by the widescreen breakpoint like others
@include tablet {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(0, 1fr);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 1fr)
minmax(0, 1fr);
grid-template-areas:
'header header'
'hero hero'
Expand All @@ -326,9 +351,12 @@ $default-flyout-width-widescreen: 480px;

&.layout-flyout-active .layout-body {
@include desktop {
grid-template: auto auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(0, 1fr) var(
#{$layout-flyout-width-name}
);
grid-template:
minmax(auto, max-content) auto var(--atlas-contained-height) auto / minmax(0, 1fr) minmax(
0,
1fr
)
var(#{$layout-flyout-width-name});
grid-template-areas:
'header header header'
'hero hero flyout'
Expand Down Expand Up @@ -363,7 +391,6 @@ $default-flyout-width-widescreen: 480px;
&.layout-twin,
&.layout-sidecar-left,
&.layout-sidecar-right {
// 👇 minus a pixel at the end to account for percentage points and rounding
--atlas-contained-height: calc(
var(--window-inner-height) - var(--atlas-header-height) - var(--atlas-footer-height) - 1px
);
Expand All @@ -389,7 +416,6 @@ $default-flyout-width-widescreen: 480px;
// Because the holy grail has two rows (containing menu main, menu aside) on tablet, we cannot apply height constraints at that size
@include desktop {
.layout.layout-constrained.layout-holy-grail {
// 👇 minus a pixel at the end to account for percentage points and rounding
--atlas-contained-height: calc(
var(--window-inner-height) - var(--atlas-header-height) - var(--atlas-footer-height) - 1px
);
Expand Down
47 changes: 21 additions & 26 deletions js/src/behaviors/layout.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
let frame: number;

const root = document.documentElement;

const setLayoutCssVariables = () => {
const header = document.querySelector('.layout-body-header');
const headerHeight = header?.clientHeight || 0;
const headerCssProp = headerHeight ? `${headerHeight}px` : '0px';
const headerY = header?.getBoundingClientRect().y || 0; // determine if header is visible, assign visible heights as well
const visibleHeaderHeight = Math.round(Math.max(0, headerY + headerHeight));
const visibleHeaderHeight = Math.max(0, headerY + headerHeight);
const visibleHeaderCssProp = `${visibleHeaderHeight}px`;

const footer = document.querySelector('.layout-body-footer');
const footerHeight = footer?.clientHeight || 0;
const footerCssProp = footerHeight ? `${footerHeight}px` : '0px';
const footerY = footer?.getBoundingClientRect().y || 0; // determine if header and footer are visible, assign visible heights as well

const visibleFooterHeight = Math.round(
footerY < window.innerHeight ? Math.min(window.innerHeight - footerY, footerHeight) : 0
);
const visibleFooterHeight =
footerY < window.innerHeight ? Math.min(window.innerHeight - footerY, footerHeight) : 0;
const visibleFooterCssProp = `${visibleFooterHeight}px`;

root.style.setProperty('--window-inner-height', `${window.innerHeight}px`, 'important');
Expand All @@ -27,32 +24,30 @@ const setLayoutCssVariables = () => {
root.style.setProperty('--atlas-footer-visible-height', visibleFooterCssProp, 'important');
};

let animationFrame = 0;

function scheduleUpdate(update: typeof setLayoutCssVariables) {
cancelAnimationFrame(animationFrame);
animationFrame = requestAnimationFrame(update);
}

export const dispatchAtlasLayoutUpdateEvent = () => {
window.dispatchEvent(new CustomEvent('atlas-layout-change-event'));
};

export function initLayout() {
window.addEventListener('atlas-layout-change-event', () => {
if (frame) {
cancelAnimationFrame(frame);
}

frame = requestAnimationFrame(setLayoutCssVariables);
scheduleUpdate(setLayoutCssVariables);
});

window.addEventListener(
'resize',
() => window.dispatchEvent(new CustomEvent('atlas-layout-change-event')),
{ passive: true }
);
window.addEventListener('resize', dispatchAtlasLayoutUpdateEvent, { passive: true });

root.style.setProperty('--window-inner-height', `${window.innerHeight}px`);

window.addEventListener('DOMContentLoaded', setLayoutCssVariables, { passive: true });
window.addEventListener('DOMContentLoaded', dispatchAtlasLayoutUpdateEvent);

// determine if header/footer are visible below the top of the viewport

window.addEventListener(
'scroll',
() => window.dispatchEvent(new CustomEvent('atlas-layout-change-event')),
{
passive: true
}
);
// determine if header/footer are visible below the top of the viewport - remove with atlas-js 1.13.1
window.addEventListener('scroll', dispatchAtlasLayoutUpdateEvent, {
passive: true
});
}
8 changes: 5 additions & 3 deletions site/src/scaffold/standard.html
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,11 @@ <h2 class="font-size-h2 margin-bottom-md">Figma</h2>
<p>Flying flyout</p>
</section>

<footer id="footer" class="layout-body-footer border-top padding-md">
<div class="layout-margin">
<p>© Microsoft 2024</p>
<footer id="footer" class="layout-body-footer">
<div class="border-top padding-md">
<div class="layout-margin">
<p>© Microsoft 2024</p>
</div>
</div>
</footer>
</body>
Expand Down
8 changes: 5 additions & 3 deletions site/src/scaffold/token.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,11 @@ <h2 class="font-size-h2 margin-bottom-m">Figma</h2>
<!-- empty for now -->
</aside>

<footer id="footer" class="layout-body-footer border-top padding-md">
<div class="layout-margin">
<p>© Microsoft 2024</p>
<footer id="footer" class="layout-body-footer">
<div class="border-top padding-md">
<div class="layout-margin">
<p>© Microsoft 2024</p>
</div>
</div>
</footer>
</body>
Expand Down

0 comments on commit 6de95c8

Please sign in to comment.