![]()
diff --git a/website/scripts/main.js b/website/scripts/main.js
index a8efa0ddf..d92a16d05 100644
--- a/website/scripts/main.js
+++ b/website/scripts/main.js
@@ -8,48 +8,49 @@ import {
} from "./panes/chart.js";
import { init as initExplorer } from "./explorer/index.js";
import { init as initSearch } from "./panes/search.js";
-import { idle } from "./utils/timing.js";
import { readStored, removeStored, writeToStorage } from "./utils/storage.js";
import {
asideElement,
asideLabelElement,
- bodyElement,
chartElement,
explorerElement,
frameSelectorsElement,
mainElement,
navElement,
navLabelElement,
- pinButtonElement,
searchElement,
+ layoutButtonElement,
style,
} from "./utils/elements.js";
+import { idle } from "./utils/timing.js";
const DESKTOP_QUERY = window.matchMedia("(min-width: 768px)");
-let sidebarPinned = readStored("sidebar-pinned") !== "false";
+
+const SPLIT = "split";
function updateLayout() {
- const layout = DESKTOP_QUERY.matches && sidebarPinned ? "desktop" : "mobile";
- document.documentElement.dataset.layout = layout;
- if (layout === "desktop") {
- asideElement.parentElement !== bodyElement &&
- bodyElement.append(asideElement);
- } else {
- asideElement.parentElement !== mainElement &&
- mainElement.append(asideElement);
- }
+ const pref = readStored("split-view") !== "false";
+ const wasSplit = isSplit();
+ document.documentElement.dataset.layout =
+ DESKTOP_QUERY.matches && pref ? "split" : "full";
+ if (isSplit() !== wasSplit) syncFrame();
+}
+
+function isSplit() {
+ return document.documentElement.dataset.layout === SPLIT;
+}
+
+function syncFrame() {
+ if (isSplit()) navLabelElement.click();
+ else asideLabelElement.click();
}
DESKTOP_QUERY.addEventListener("change", updateLayout);
updateLayout();
-pinButtonElement.addEventListener("click", () => {
- sidebarPinned = !sidebarPinned;
- writeToStorage("sidebar-pinned", String(sidebarPinned));
- pinButtonElement.textContent = sidebarPinned ? "Unpin" : "Pin";
- pinButtonElement.title = sidebarPinned ? "Unpin sidebar" : "Pin sidebar";
+layoutButtonElement.addEventListener("click", () => {
+ writeToStorage("split-view", String(!isSplit()));
updateLayout();
- if (!sidebarPinned) asideLabelElement.click();
});
function initFrameSelectors() {
@@ -101,19 +102,7 @@ function initFrameSelectors() {
}
}
- asideLabelElement.click();
-
- new IntersectionObserver((entries) => {
- for (let i = 0; i < entries.length; i++) {
- if (
- !entries[i].isIntersecting &&
- entries[i].target === asideLabelElement &&
- focusedFrame == asideElement
- ) {
- navLabelElement.click();
- }
- }
- }).observe(asideLabelElement);
+ syncFrame();
}
initFrameSelectors();
@@ -206,62 +195,54 @@ onFirstIntersection(navElement, () => {
});
});
-onFirstIntersection(searchElement, () => {
- initSearch(options);
-});
+function initResizeBar() {
+ const bar = getElementById("resize-bar");
+ const key = "bar-width";
+ const max = () => parseFloat(style.getPropertyValue("--max-main-width")) / 100 * window.innerWidth;
-function initDesktopResizeBar() {
- const resizeBar = getElementById("resize-bar");
- let resize = false;
- let startingWidth = 0;
- let startingClientX = 0;
+ const saved = readStored(key);
+ if (saved) mainElement.style.width = `${saved}px`;
- const barWidthLocalStorageKey = "bar-width";
-
- /**
- * @param {number | null} width
- */
- function setBarWidth(width) {
- try {
- if (typeof width === "number") {
- mainElement.style.width = `${width}px`;
- writeToStorage(barWidthLocalStorageKey, String(width));
- } else {
- mainElement.style.width = style.getPropertyValue(
- "--default-main-width",
- );
- removeStored(barWidthLocalStorageKey);
- }
- } catch (_) {}
- }
-
- /**
- * @param {MouseEvent} event
- */
- function mouseMoveEvent(event) {
- if (resize) {
- setBarWidth(startingWidth + (event.clientX - startingClientX));
+ /** @param {number | null} width */
+ function setWidth(width) {
+ if (width != null) {
+ const clamped = Math.min(width, max());
+ mainElement.style.width = `${clamped}px`;
+ writeToStorage(key, String(clamped));
+ } else {
+ mainElement.style.width = "";
+ removeStored(key);
}
}
- resizeBar.addEventListener("mousedown", (event) => {
- startingClientX = event.clientX;
- startingWidth = mainElement.clientWidth;
- resize = true;
- window.document.documentElement.dataset.resize = "";
- window.addEventListener("mousemove", mouseMoveEvent);
+ bar.addEventListener("pointerdown", (e) => {
+ e.preventDefault();
+ bar.setPointerCapture(e.pointerId);
+ const startX = e.clientX;
+ const startW = mainElement.clientWidth;
+ document.documentElement.dataset.resize = "";
+
+ /** @param {PointerEvent} e */
+ function onMove(e) {
+ setWidth(startW + (e.clientX - startX));
+ }
+
+ function onUp() {
+ delete document.documentElement.dataset.resize;
+ bar.removeEventListener("pointermove", onMove);
+ bar.removeEventListener("pointerup", onUp);
+ bar.removeEventListener("pointercancel", onUp);
+ }
+
+ bar.addEventListener("pointermove", onMove);
+ bar.addEventListener("pointerup", onUp);
+ bar.addEventListener("pointercancel", onUp);
});
- resizeBar.addEventListener("dblclick", () => {
- setBarWidth(null);
- });
-
- const setResizeFalse = () => {
- resize = false;
- delete window.document.documentElement.dataset.resize;
- window.removeEventListener("mousemove", mouseMoveEvent);
- };
- window.addEventListener("mouseup", setResizeFalse);
- window.addEventListener("mouseleave", setResizeFalse);
+ bar.addEventListener("dblclick", () => setWidth(null));
}
-initDesktopResizeBar();
+initResizeBar();
+
+onFirstIntersection(searchElement, () => {
+ initSearch(options);
+});
diff --git a/website/scripts/utils/elements.js b/website/scripts/utils/elements.js
index e1a14061e..6fbba6e61 100644
--- a/website/scripts/utils/elements.js
+++ b/website/scripts/utils/elements.js
@@ -20,4 +20,4 @@ export const searchInput = /** @type {HTMLInputElement} */ (
);
export const searchResultsElement = getElementById("search-results");
export const frameSelectorsElement = getElementById("frame-selectors");
-export const pinButtonElement = getElementById("pin-button");
+export const layoutButtonElement = getElementById("layout-button");
diff --git a/website/styles/elements.css b/website/styles/elements.css
index 5d7206fe5..f7edc10e6 100644
--- a/website/styles/elements.css
+++ b/website/styles/elements.css
@@ -48,35 +48,35 @@ a {
aside {
min-width: 0;
+ min-height: 0;
position: relative;
- /*height: 100%;*/
- /*width: 100%;*/
- /*overflow-y: auto;*/
- flex: 1;
+ grid-row: 1;
+ grid-column: 1;
+ z-index: 1;
+ overflow: hidden;
+ background: var(--background-color);
- html[data-layout="mobile"] & {
- padding-bottom: calc(var(--main-padding) + 0.5rem);
- }
-
- html[data-layout="desktop"] & {
+ html[data-layout="split"] & {
+ grid-column: 2;
+ grid-row: 1 / -1;
border-left: 1px;
- order: 2;
- }
- body > &[hidden] {
- display: block !important;
+ &[hidden] {
+ display: block !important;
+ }
}
}
body {
font-weight: var(--font-weight-base);
height: 100dvh;
- display: flex;
- flex-direction: column;
+ display: grid;
+ grid-template-rows: 1fr auto;
+ grid-template-columns: 1fr;
position: relative;
- html[data-layout="desktop"] & {
- flex-direction: row;
+ html[data-layout="split"] & {
+ grid-template-columns: minmax(min-content, auto) 1fr;
html[data-display="standalone"] & {
border-top: 1px;
@@ -267,14 +267,23 @@ summary {
}
}
-html[data-layout="desktop"] .md\:hidden {
+
+html[data-layout="split"] .full-only {
display: none !important;
}
-#pin-button {
+#layout-button {
@media (max-width: 767px) {
display: none;
}
+
+ &::after {
+ content: "Split";
+ }
+
+ html[data-layout="split"] &::after {
+ content: "Full";
+ }
}
[data-resize] {
diff --git a/website/styles/main.css b/website/styles/main.css
index 10027c5cb..37015e611 100644
--- a/website/styles/main.css
+++ b/website/styles/main.css
@@ -1,7 +1,9 @@
main {
- order: 1;
+ grid-row: 1;
+ grid-column: 1;
position: relative;
display: flex;
+ min-height: 0;
&::before,
&::after {
@@ -34,16 +36,13 @@ main {
);
}
- html[data-layout="mobile"] & {
- flex: 1;
- min-height: 0;
+ html[data-layout="full"] & {
width: 100% !important;
}
- html[data-layout="desktop"] & {
- min-width: 300px;
- width: var(--default-main-width);
- max-width: 65dvw;
+ html[data-layout="split"] & {
+ min-width: 100%;
+ max-width: var(--max-main-width);
}
> nav,
@@ -57,85 +56,109 @@ main {
flex-direction: column;
padding-bottom: var(--bottom-area);
}
+}
- > footer {
+#resize-bar {
+ display: none;
+ grid-column: 1;
+ grid-row: 1 / -1;
+ justify-self: end;
+ width: 8px;
+ margin: 0 -4px;
+ z-index: 50;
+ position: relative;
+ cursor: col-resize;
+ touch-action: none;
+
+ &::after {
+ content: "";
position: absolute;
+ top: 0;
bottom: 0;
- right: 0;
- left: 0;
- text-transform: uppercase;
- z-index: 100;
- padding-bottom: var(--main-padding);
+ left: 50%;
+ width: 2px;
+ translate: -50% 0;
+ background: transparent;
+ transition: background 0.15s;
+ }
- &::before,
- &::after {
- content: "";
- position: absolute;
- top: 0;
- bottom: 0;
- width: var(--main-padding);
- z-index: 1;
- pointer-events: none;
- }
-
- &::before {
- left: 0;
- background-image: linear-gradient(
- to left,
- transparent,
- var(--background-color)
- );
- }
+ &:hover {
+ background: var(--border-color);
&::after {
- right: 0;
- background-image: linear-gradient(
- to right,
- transparent,
- var(--background-color)
- );
- }
-
- > fieldset {
- display: flex;
- gap: 1.125rem;
- overflow-x: auto;
- scrollbar-width: thin;
- min-width: 0;
- margin: -0.5rem 0;
- padding: 0.5rem var(--main-padding);
- pointer-events: auto;
-
- > label,
- > button {
- flex-shrink: 0;
- }
-
- > button {
- color: var(--off-color);
- }
+ background: var(--color);
}
}
- > #resize-bar {
- display: none;
+ html[data-resize] &::after {
+ background: var(--color);
+ }
+
+ html[data-layout="split"] & {
+ display: block;
+ }
+}
+
+footer {
+ grid-row: 2;
+ grid-column: 1 / -1;
+ position: relative;
+ z-index: 2;
+ min-width: 0;
+ overflow: hidden;
+ text-transform: uppercase;
+ padding-bottom: var(--main-padding);
+
+ html[data-layout="split"] & {
+ grid-column: 1;
+ }
+
+ &::before,
+ &::after {
+ content: "";
position: absolute;
- right: 0;
top: 0;
bottom: 0;
- width: 4px;
- margin: 0 -2px;
- z-index: 50;
+ width: var(--main-padding);
+ z-index: 1;
+ pointer-events: none;
+ }
- html[data-resize] &,
- &:hover {
- border-right: 4px;
- cursor: col-resize;
- border-color: var(--off-color) !important;
+ &::before {
+ left: 0;
+ background-image: linear-gradient(
+ to left,
+ transparent,
+ var(--background-color)
+ );
+ }
+
+ &::after {
+ right: 0;
+ background-image: linear-gradient(
+ to right,
+ transparent,
+ var(--background-color)
+ );
+ }
+
+ > fieldset {
+ display: flex;
+ gap: 1.125rem;
+ overflow-x: auto;
+ scrollbar-width: thin;
+ min-width: 0;
+ margin: -0.5rem 0;
+ padding: 0.5rem var(--main-padding);
+ pointer-events: auto;
+
+ > label,
+ > button {
+ flex-shrink: 0;
}
- html[data-layout="desktop"] & {
- display: block;
+ > button {
+ color: var(--off-color);
}
}
}
diff --git a/website/styles/variables.css b/website/styles/variables.css
index ea49e42f0..7fb7b430f 100644
--- a/website/styles/variables.css
+++ b/website/styles/variables.css
@@ -55,6 +55,6 @@
}*/
--negative-main-padding: calc(-1 * var(--main-padding));
--font-weight-base: 400;
- --default-main-width: 25rem;
+ --max-main-width: 70dvw;
--bottom-area: 69vh;
}