-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
draft: mobile burger menu #754
Conversation
quartz.layout.ts
Outdated
@@ -47,3 +47,59 @@ export const defaultListPageLayout: PageLayout = { | |||
], | |||
right: [], | |||
} | |||
|
|||
/** Example of a valid layout for mobile, allowing burger menu |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems to be a lot of duplicate code. Is it possible if we can use conditional displayClass === 'mobile-only'
?
only drawback is that explorer would have to be on the left container for this to wor, and set display: grid
🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like this
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
constructFileTree(allFiles)
return (
<div class={`explorer ${displayClass ?? ""}`}>
<button
type="button"
id="explorer"
class={displayClass === "mobile-only" ? "collapsed" : ""}
data-behavior={opts.folderClickBehavior}
data-collapsed={opts.folderDefaultState}
data-savestate={opts.useSavedState}
data-tree={jsonTree}
>
{displayClass === "desktop-only" ? (
<>
<h1>{opts.title}</h1>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="5 8 14 8"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="fold"
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide-menu"
>
<line x1="4" x2="20" y1="12" y2="12" />
<line x1="4" x2="20" y1="6" y2="6" />
<line x1="4" x2="20" y1="18" y2="18" />
</svg>
)}
</button>
<div id="explorer-content">
<ul class="overflow" id="explorer-ul">
<ExplorerNode node={fileTree} opts={opts} fileData={fileData} />
<li id="explorer-end" />
</ul>
</div>
</div>
)
}
Explorer.css = explorerStyle
Explorer.afterDOMLoaded = script
return Explorer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it can't works as the button is disabled if the title is empty!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did some revision on this
so the explorer function looks like
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
constructFileTree(allFiles)
return (
<div class={classNames(displayClass, "explorer")}>
<button
type="button"
id="explorer"
data-behavior={opts.folderClickBehavior}
data-collapsed={opts.folderDefaultState}
data-savestate={opts.useSavedState}
data-tree={jsonTree}
data-mobileonly={displayClass === "mobile-only"}
>
{displayClass === "desktop-only" ? (
<>
<h1>{opts.title}</h1>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="5 8 14 8"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="fold"
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide-menu"
>
<line x1="4" x2="20" y1="12" y2="12" />
<line x1="4" x2="20" y1="6" y2="6" />
<line x1="4" x2="20" y1="18" y2="18" />
</svg>
)}
</button>
<div id="explorer-content">
<ul class="overflow" id="explorer-ul">
<ExplorerNode node={fileTree} opts={opts} fileData={fileData} />
<li id="explorer-end" />
</ul>
</div>
</div>
)
}
with the inline script where I update setupExplorer
and toggleExplorer
...
function toggleExplorer(this: HTMLElement) {
this.classList.toggle("collapsed")
const content = this.nextElementSibling as MaybeHTMLElement
if (!content) return
content.classList.toggle("collapsed")
content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px"
// prevent scroll under on mobile-only explorer
if (this.dataset.mobileonly === "true") {
const center = document.querySelector("#quartz-body .center")
if (document.querySelector(".mobile-only #explorer")) {
const queries = [".popover-hint", "footer", "#progress", ".backlinks", ".graph", ".toc"]
queries.map((query) => {
document.querySelectorAll(query)?.forEach((element) => {
element.classList.toggle("no-scroll")
})
})
}
}
}
function setupExplorer() {
for (const explorer of document.querySelectorAll("#explorer") as NodeListOf<HTMLElement>) {
const isMobileOnly = explorer.dataset.mobileonly === "true"
if (isMobileOnly) {
explorer.classList.add("collapsed")
const content = explorer.nextElementSibling as HTMLElement
content.classList.add("collapsed")
content.style.maxHeight = "0px"
}
if (explorer.dataset.behavior === "collapse") {
for (const item of document.getElementsByClassName(
"folder-button",
) as HTMLCollectionOf<HTMLElement>) {
item.removeEventListener("click", toggleFolder)
item.addEventListener("click", toggleFolder)
}
}
...
}
}
...
and then the custom.scss
.left,
.right {
display: grid !important;
gap: 1.5rem !important;
grid-template-columns: 1fr;
grid-template-rows: repeat(4, min-content);
.mobile-only.explorer & {
grid-area: 1 / 1 / 2 / 2;
}
.search {
grid-area: 1 / 1 / 2 / 2;
}
.darkmode {
grid-area: 1 / 2 / 2 / 3;
}
.graph {
grid-area: 1 / 1 / 1 / 3;
}
.backlinks {
grid-area: 3 / 1 / 3 / 3;
}
.toc {
grid-area: 2 / 1 / 3 / 3;
}
.recent-notes:nth-last-child(1) {
grid-area: 2 / 1 / 2 / 3;
}
.recent-notes:nth-last-child(2) {
grid-area: 3 / 1 / 4 / 3;
}
@media all and (max-width: $fullPageWidth) {
display: flex !important;
}
}
.mobile-only.explorer {
ul.overflow {
height: inherit;
&:after {
background: none;
}
}
#explorer-content:not(.collapsed) {
width: 100%;
min-height: 80vh;
position: absolute;
z-index: 100;
margin-top: 2rem;
transform: translateX(0);
overflow: auto;
}
#explorer-content.collapsed {
left: 0;
width: 0;
height: inherit;
position: absolute;
z-index: 100;
opacity: 0.35;
transition:
0.5s ease opacity,
0.3s ease color;
}
#explorer .lucide-menu {
stroke: var(--darkgray);
&:hover {
stroke: var(--dark);
}
}
}
.no-scroll {
display: none;
overflow: hidden;
}
Works pretty well. you can tested out on my website.
But then I understand where you come from, this could get hard to maintain pretty quick, since the .no-scroll
is pretty hacky ngl.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with display none is to, if you open the burger menu, the page will automatically goes up, and you lost your progression. Also, as I said earlier, I want to disable the collapsing of explorer if no title is set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It still save the previous state right? Or am I missing something here?
edit: Ah I see what you mean now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I see the difference. On my side, I tweaked my own blog to add a sticky header, and it's not the default behavior. In the default behavior, this question is ignored as you need to scroll to open the menu.
I tried with this, where i moved the Explorer to the right and it worked perfectly fine. export const defaultContentPageLayout: PageLayout = { |
My link: notes.mayurbn.site |
any idea why this PR hasn't accepted? |
Because it's more a proof of concept than something usable, who needs a specific setup and a lot of edit to works. Also, I don't think the way i created that is good. Pretty sure that anyone can do a better works tbh (maybe with some library?) |
Superceded by #1441 |
I wanted to add a mobile layout that allow to have the explorer, as a lot of my fellow mate only use phone or use phone more than they computer.
I tweaked a lot and choose to use separate file for drafting, to prevent broke something (and merge error…), and if people want to use the old behavior while testing this.
I think we can (and need) to do better than I have, they are some errors (like the scrolling I can't fully disabled) and some seems to be too much hacky.
The burgerMenu layout needs a specific layout structure (as example) in a docstring in the layout.ts file. Feel free to ask for edit or add PR to my repository directly.
By the way, you can check and test here; https://www.mara-li.fr/ (repository: https://github.com/Lisandra-dev/mara-quartz)