Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
60 changes: 49 additions & 11 deletions assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,13 @@ button:disabled { cursor: default; opacity: 0.6; }
gap: 0.8rem;
}

.footer-bottom-links {
display: flex;
flex-wrap: wrap;
gap: 0.5rem 1rem;
font-size: 0.875rem;
}

.cookie-notice {
position: fixed;
right: 1rem;
Expand Down Expand Up @@ -1462,18 +1469,33 @@ button:disabled { cursor: default; opacity: 0.6; }
margin: 0.25rem 0;
}

@media (max-width: 980px) {
.content-grid,
.feature-split,
.page-hero-grid,
.person-hero,
.personal-grid,
.personal-hero-grid,
.news-layout,
.footer-grid {
grid-template-columns: 1fr;
/* Keep the full navigation on smaller desktop viewports, including scaled
displays and browser windows narrowed by sidebars. Compact the branding
before switching to the phone menu; touch capability does not choose layout. */
@media (max-width: 1100px) {
.site-header .site-shell {
gap: 1rem;
}

.brand-row {
flex-shrink: 0;
gap: 0.6rem;
}

.brand-wordmark {
height: 3.4rem;
}

.uoft-mark img {
height: 2.5rem;
}

.site-nav {
column-gap: 0.75rem;
}
}

@media (max-width: 980px) {
.card-grid,
.card-grid-wide {
grid-template-columns: repeat(2, minmax(0, 1fr));
Expand All @@ -1482,9 +1504,25 @@ button:disabled { cursor: default; opacity: 0.6; }
.meta-card-soft {
grid-template-columns: 1fr;
}

.footer-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}

@media (max-width: 980px) {
/* Keep this breakpoint in sync with mobileNav in assets/js/site.js. */
@media (max-width: 760px) {
.content-grid,
.feature-split,
.page-hero-grid,
.person-hero,
.personal-grid,
.personal-hero-grid,
.news-layout,
.footer-grid {
grid-template-columns: 1fr;
}

:root {
--sticky-header-offset: 4.25rem;
}
Expand Down
3 changes: 2 additions & 1 deletion assets/js/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ document.addEventListener("DOMContentLoaded", () => {
const navPanel = document.querySelector("[data-nav-panel]");

if (navButton && navPanel) {
const mobileNav = window.matchMedia("(max-width: 980px)");
// Match the phone navigation breakpoint in assets/css/main.css.
const mobileNav = window.matchMedia("(max-width: 760px)");
const setNavOpen = (open) => {
navButton.setAttribute("aria-expanded", String(open));
navPanel.classList.toggle("is-open", open);
Expand Down
5 changes: 4 additions & 1 deletion layouts/partials/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ <h2>Contact</h2>
</div>
<div class="site-shell footer-bottom">
<p>&copy; {{ now.Year }} Middleware Systems Research Group.</p>
<p><a href="https://www.utoronto.ca/privacy">Privacy notice</a></p>
<p class="footer-bottom-links">
<a href="https://github.com/MSRG/msrg.github.io">Members: propose edits on GitHub</a>
<a href="https://www.utoronto.ca/privacy">Privacy notice</a>
</p>
</div>
</footer>
69 changes: 67 additions & 2 deletions scripts/browser_check.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ let browser;
}
report.baseURL = base;
browser = await ({ chromium, firefox, webkit }[engine]).launch(
process.env.BROWSER_EXECUTABLE ? { executablePath: process.env.BROWSER_EXECUTABLE } : {},
process.env.BROWSER_EXECUTABLE ? { executablePath: process.env.BROWSER_EXECUTABLE } :
process.env.BROWSER_CHANNEL ? { channel: process.env.BROWSER_CHANNEL } : {},
);
const createContext = async (options = {}, dismissNotice = true) => {
const context = await browser.newContext(options);
Expand All @@ -49,6 +50,70 @@ let browser;
context.on('page', page => page.on('pageerror', error => report.errors.push(error.message)));
return context;
};

// Width is measured in CSS pixels: a scaled desktop can be below 980px.
// Pixel density and a touchscreen must not independently collapse its menu.
report.navigation = [];
for (const options of [
{ deviceScaleFactor: 1 },
{ deviceScaleFactor: 1.25 },
{ deviceScaleFactor: 1.5 },
{ deviceScaleFactor: 2, hasTouch: true },
{ javaScriptEnabled: false },
]) {
const responsiveContext = await createContext(options);
const responsive = await responsiveContext.newPage();
for (const width of [1440, 1100, 1024, 981, 980, 911, 853, 800, 768, 761, 760, 700, 390, 320]) {
await responsive.setViewportSize({ width, height: 900 });
await responsive.goto(base + '/');
const desktop = width > 760;
const scripted = options.javaScriptEnabled !== false;
const label = `${width}px ${JSON.stringify(options)}`;
assert.equal(await responsive.locator('[data-nav-toggle]').isVisible(), !desktop && scripted, `${label}: wrong menu layout`);
assert.equal(await responsive.locator('#site-nav').isVisible(), desktop || !scripted, `${label}: wrong navigation visibility`);
const layout = await responsive.evaluate(() => {
const header = document.querySelector('.site-header').getBoundingClientRect();
const brand = document.querySelector('.brand-row').getBoundingClientRect();
const links = [...document.querySelectorAll('#site-nav > .nav-item > a')].map(link => {
const rect = link.getBoundingClientRect();
return { top: rect.top, bottom: rect.bottom, left: rect.left, right: rect.right };
});
return {
overflow: document.documentElement.scrollWidth > innerWidth + 1,
columns: getComputedStyle(document.querySelector('.content-grid')).gridTemplateColumns.split(' ').length,
linksFit: links.every(rect => rect.left >= brand.right && rect.right <= innerWidth && rect.top >= header.top && rect.bottom <= header.bottom),
oneRow: links.every(rect => Math.abs(rect.top - links[0].top) < 1),
};
});
assert.equal(layout.overflow, false, `${label}: horizontal overflow`);
assert.equal(layout.columns, desktop ? 2 : 1, `${label}: wrong content layout`);
if (desktop) {
assert(layout.linksFit && layout.oneRow, `${label}: desktop links must fit beside the branding in one row`);
}
report.navigation.push({ width, ...options, desktop });
}
if (options.javaScriptEnabled !== false) {
// Crossing the breakpoint must reset state in both directions without a reload.
await responsive.locator('[data-nav-toggle]').click();
await responsive.setViewportSize({ width: 800, height: 900 });
await responsive.waitForFunction(() => document.querySelector('[data-nav-toggle]').getAttribute('aria-expanded') === 'false');
assert(await responsive.locator('#site-nav').isVisible(), 'Resizing to desktop must reveal navigation');
await responsive.setViewportSize({ width: 760, height: 900 });
assert.equal(await responsive.locator('#site-nav').isVisible(), false, 'Returning to mobile must close the menu');
await responsive.locator('[data-nav-toggle]').click();
assert(await responsive.locator('#site-nav').isVisible(), 'Mobile menu must still open after resizing');
await responsive.keyboard.press('Escape');
assert.equal(await responsive.locator('#site-nav').isVisible(), false, 'Escape must close the mobile menu');
}
await responsiveContext.close();
}
console.log(`${engine}: ${report.navigation.length} desktop/mobile layout configurations passed`);
if (process.env.RESPONSIVE_ONLY) {
assert.deepEqual(report.errors, [], 'JavaScript errors found');
fs.writeFileSync(path.join(output, 'report.json'), JSON.stringify(report, null, 2));
console.log(`Artifacts: ${output}`);
return;
}
for (const width of process.env.SKIP_PAGE_CRAWL ? [] : report.widths) {
const context = await createContext({ viewport: { width, height: 900 } });
const page = await context.newPage();
Expand Down Expand Up @@ -82,7 +147,7 @@ let browser;
await menu.click();
await page.locator('#site-nav a[href="/data-sets/"]').click();
await page.waitForURL('**/data-sets/');
await page.setViewportSize({ width: 844, height: 390 });
await page.setViewportSize({ width: 740, height: 390 });
await menu.click();
assert(await page.locator('#site-nav').evaluate(element => element.getBoundingClientRect().bottom <= innerHeight + 1), 'Landscape menu must fit the viewport');
await page.locator('#site-nav a[href="/publications/"]').click();
Expand Down