From 7d7e3349763b0c1ade94b8a6d13986e171861bc1 Mon Sep 17 00:00:00 2001
From: Emile Bangma <github@emilebangma.com>
Date: Mon, 23 Sep 2024 20:40:12 +0000
Subject: [PATCH] feat: responsive design grid (#1354)
---
quartz/styles/variables.scss | 57 ++++++++
quartz/styles/base.scss | 147 +++++++++++++++---------
package-lock.json | 4
quartz/components/styles/search.scss | 10 +
quartz/components/styles/explorer.scss | 25 +++
quartz/components/styles/graph.scss | 2
quartz/components/styles/listPage.scss | 2
docs/images/quartz-layout-desktop.png | 0
/dev/null | 0
quartz/components/styles/backlinks.scss | 55 +++++++--
docs/images/quartz-layout-tablet.png | 0
docs/layout.md | 27 ++++
package.json | 2
quartz/components/renderPage.tsx | 2
docs/images/quartz-layout-mobile.png | 0
quartz/components/styles/toc.scss | 4
quartz/components/styles/popover.scss | 2
17 files changed, 247 insertions(+), 92 deletions(-)
diff --git a/docs/images/quartz layout.png b/docs/images/quartz layout.png
deleted file mode 100644
index 71ef3ac..0000000
--- a/docs/images/quartz layout.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/quartz-layout-desktop.png b/docs/images/quartz-layout-desktop.png
new file mode 100644
index 0000000..461d791
--- /dev/null
+++ b/docs/images/quartz-layout-desktop.png
Binary files differ
diff --git a/docs/images/quartz-layout-mobile.png b/docs/images/quartz-layout-mobile.png
new file mode 100644
index 0000000..ad6c09e
--- /dev/null
+++ b/docs/images/quartz-layout-mobile.png
Binary files differ
diff --git a/docs/images/quartz-layout-tablet.png b/docs/images/quartz-layout-tablet.png
new file mode 100644
index 0000000..6349f29
--- /dev/null
+++ b/docs/images/quartz-layout-tablet.png
Binary files differ
diff --git a/docs/layout.md b/docs/layout.md
index 686b2f2..d8427c4 100644
--- a/docs/layout.md
+++ b/docs/layout.md
@@ -13,15 +13,19 @@
beforeBody: QuartzComponent[] // laid out vertically
pageBody: QuartzComponent // single component
afterBody: QuartzComponent[] // laid out vertically
- left: QuartzComponent[] // vertical on desktop, horizontal on mobile
- right: QuartzComponent[] // vertical on desktop, horizontal on mobile
+ left: QuartzComponent[] // vertical on desktop and tablet, horizontal on mobile
+ right: QuartzComponent[] // vertical on desktop, horizontal on tablet and mobile
footer: QuartzComponent // single component
}
```
These correspond to following parts of the page:
-![[quartz layout.png|800]]
+| Layout | Preview |
+| ------------------------------- | ----------------------------------- |
+| Desktop (width > 1200px) | ![[quartz-layout-desktop.png\|800]] |
+| Tablet (800px < width < 1200px) | ![[quartz-layout-tablet.png\|800]] |
+| Mobile (width < 800px) | ![[quartz-layout-mobile.png\|800]] |
> [!note]
> There are two additional layout fields that are _not_ shown in the above diagram.
@@ -33,6 +37,23 @@
See [a list of all the components](component.md) for all available components along with their configuration options. You can also checkout the guide on [[creating components]] if you're interested in further customizing the behaviour of Quartz.
+### Layout breakpoints
+
+Quartz has different layouts depending on the width the screen viewing the website.
+
+The breakpoints for layouts can be configured in `variables.scss`.
+
+- `mobile`: screen width below this size will use mobile layout.
+- `desktop`: screen width above this size will use desktop layout.
+- Screen width between `mobile` and `desktop` width will use the tablet layout.
+
+```scss
+$breakpoints: (
+ mobile: 800px,
+ desktop: 1200px,
+);
+```
+
### Style
Most meaningful style changes like colour scheme and font can be done simply through the [[configuration#General Configuration|general configuration]] options. However, if you'd like to make more involved style changes, you can do this by writing your own styles. Quartz 4, like Quartz 3, uses [Sass](https://sass-lang.com/guide/) for styling.
diff --git a/package-lock.json b/package-lock.json
index 89287e6..b53f28f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@jackyzha0/quartz",
- "version": "4.3.1",
+ "version": "4.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@jackyzha0/quartz",
- "version": "4.3.1",
+ "version": "4.4.0",
"license": "MIT",
"dependencies": {
"@clack/prompts": "^0.7.0",
diff --git a/package.json b/package.json
index b24f667..44d7bb3 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "@jackyzha0/quartz",
"description": "🌱 publish your digital garden and notes as a website",
"private": true,
- "version": "4.3.1",
+ "version": "4.4.0",
"type": "module",
"author": "jackyzha0 <j.zhao2k19@gmail.com>",
"license": "MIT",
diff --git a/quartz/components/renderPage.tsx b/quartz/components/renderPage.tsx
index ec5124f..f2dccea 100644
--- a/quartz/components/renderPage.tsx
+++ b/quartz/components/renderPage.tsx
@@ -242,8 +242,8 @@
</div>
</div>
{RightComponent}
+ <Footer {...componentData} />
</Body>
- <Footer {...componentData} />
</div>
</body>
{pageResources.js
diff --git a/quartz/components/styles/backlinks.scss b/quartz/components/styles/backlinks.scss
index 04302f2..3b7ab5b 100644
--- a/quartz/components/styles/backlinks.scss
+++ b/quartz/components/styles/backlinks.scss
@@ -1,19 +1,50 @@
+@use "../../styles/variables.scss" as *;
+
.backlinks {
- position: relative;
+ @media all and not ($desktop) {
+ overflow-y: auto;
+ display: initial;
+ &:after {
+ pointer-events: none;
+ content: "";
+ width: 100%;
+ height: 50px;
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ opacity: 1;
+ transition: opacity 0.3s ease;
+ background: linear-gradient(transparent 0px, var(--light));
+ }
- & > h3 {
- font-size: 1rem;
- margin: 0;
- }
+ &:has(> .overflow) {
+ position: unset;
+ }
- & > ul {
- list-style: none;
- padding: 0;
- margin: 0.5rem 0;
+ & > h3 {
+ font-size: 1rem;
+ margin: 0;
+ }
- & > li {
- & > a {
- background-color: transparent;
+ & > ul {
+ list-style: none;
+ padding: 0;
+ margin: 0.5rem 0;
+
+ & > li {
+ & > a {
+ background-color: transparent;
+ }
+ }
+ }
+
+ & > .overflow {
+ max-height: unset;
+ & > li:last-of-type {
+ margin-bottom: 0;
+ }
+ &:after {
+ display: none;
}
}
}
diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss
index 2f94b15..710d7a5 100644
--- a/quartz/components/styles/explorer.scss
+++ b/quartz/components/styles/explorer.scss
@@ -1,5 +1,23 @@
@use "../../styles/variables.scss" as *;
+.explorer {
+ &.desktop-only {
+ overflow-y: auto;
+ }
+ &:after {
+ pointer-events: none;
+ content: "";
+ width: 100%;
+ height: 50px;
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ opacity: 1;
+ transition: opacity 0.3s ease;
+ background: linear-gradient(transparent 0px, var(--light));
+ }
+}
+
button#explorer {
background-color: transparent;
border: none;
@@ -58,10 +76,6 @@
visibility: hidden;
}
- &.collapsed > .overflow::after {
- opacity: 0;
- }
-
& ul {
list-style: none;
margin: 0.08rem 0;
@@ -76,6 +90,9 @@
pointer-events: all;
}
}
+ > #explorer-ul {
+ max-height: none;
+ }
}
svg {
diff --git a/quartz/components/styles/graph.scss b/quartz/components/styles/graph.scss
index 188907d..1f4aa97 100644
--- a/quartz/components/styles/graph.scss
+++ b/quartz/components/styles/graph.scss
@@ -65,7 +65,7 @@
height: 80vh;
width: 80vw;
- @media all and (max-width: $fullPageWidth) {
+ @media all and ($desktop) {
width: 90%;
}
}
diff --git a/quartz/components/styles/listPage.scss b/quartz/components/styles/listPage.scss
index 44de70a..e86c39d 100644
--- a/quartz/components/styles/listPage.scss
+++ b/quartz/components/styles/listPage.scss
@@ -13,7 +13,7 @@
display: grid;
grid-template-columns: fit-content(8em) 3fr 1fr;
- @media all and (max-width: $mobileBreakpoint) {
+ @media all and ($mobile) {
& > .tags {
display: none;
}
diff --git a/quartz/components/styles/popover.scss b/quartz/components/styles/popover.scss
index b1694f9..38d6126 100644
--- a/quartz/components/styles/popover.scss
+++ b/quartz/components/styles/popover.scss
@@ -70,7 +70,7 @@
opacity 0.3s ease,
visibility 0.3s ease;
- @media all and (max-width: $mobileBreakpoint) {
+ @media all and ($mobile) {
display: none !important;
}
}
diff --git a/quartz/components/styles/search.scss b/quartz/components/styles/search.scss
index cc2daca..b0df6c8 100644
--- a/quartz/components/styles/search.scss
+++ b/quartz/components/styles/search.scss
@@ -3,7 +3,9 @@
.search {
min-width: fit-content;
max-width: 14rem;
- flex-grow: 0.3;
+ @media all and ($mobile) {
+ flex-grow: 0.3;
+ }
& > .search-button {
background-color: var(--lightgray);
@@ -62,7 +64,7 @@
margin-left: auto;
margin-right: auto;
- @media all and (max-width: $fullPageWidth) {
+ @media all and ($desktop) {
width: 90%;
}
@@ -104,7 +106,7 @@
flex: 0 0 min(30%, 450px);
}
- @media all and (min-width: $tabletBreakpoint) {
+ @media all and not ($tablet) {
&[data-preview] {
& .result-card > p.preview {
display: none;
@@ -130,7 +132,7 @@
border-radius: 5px;
}
- @media all and (max-width: $tabletBreakpoint) {
+ @media all and ($tablet) {
& > #preview-container {
display: none !important;
}
diff --git a/quartz/components/styles/toc.scss b/quartz/components/styles/toc.scss
index 6845812..13d6d3f 100644
--- a/quartz/components/styles/toc.scss
+++ b/quartz/components/styles/toc.scss
@@ -1,3 +1,7 @@
+.toc {
+ overflow-y: auto;
+}
+
button#toc {
background-color: transparent;
border: none;
diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss
index 1b3d122..c70d8b6 100644
--- a/quartz/styles/base.scss
+++ b/quartz/styles/base.scss
@@ -12,7 +12,6 @@
body,
section {
margin: 0;
- max-width: 100%;
box-sizing: border-box;
background-color: var(--light);
font-family: var(--bodyFont);
@@ -109,25 +108,21 @@
.desktop-only {
display: initial;
- @media all and (max-width: $fullPageWidth) {
+ @media all and ($mobile) {
display: none;
}
}
.mobile-only {
display: none;
- @media all and (max-width: $fullPageWidth) {
+ @media all and ($mobile) {
display: initial;
}
}
.page {
- @media all and (max-width: $fullPageWidth) {
- margin: 0 auto;
- padding: 0 1rem;
- max-width: $pageWidth;
- }
-
+ max-width: calc(#{map-get($breakpoints, desktop)} + 300px);
+ margin: 0 auto;
& article {
& > h1 {
font-size: 2rem;
@@ -155,79 +150,117 @@
}
& > #quartz-body {
- width: 100%;
- display: flex;
- @media all and (max-width: $fullPageWidth) {
- flex-direction: column;
+ display: grid;
+ grid-template-columns: #{map-get($desktopGrid, templateColumns)};
+ grid-template-rows: #{map-get($desktopGrid, templateRows)};
+ column-gap: #{map-get($desktopGrid, columnGap)};
+ row-gap: #{map-get($desktopGrid, rowGap)};
+ grid-template-areas: #{map-get($desktopGrid, templateAreas)};
+ @media all and ($desktop) {
+ grid-template-columns: #{map-get($tabletGrid, templateColumns)};
+ grid-template-rows: #{map-get($tabletGrid, templateRows)};
+ column-gap: #{map-get($tabletGrid, columnGap)};
+ row-gap: #{map-get($tabletGrid, rowGap)};
+ grid-template-areas: #{map-get($tabletGrid, templateAreas)};
+ }
+ @media all and ($mobile) {
+ grid-template-columns: #{map-get($mobileGrid, templateColumns)};
+ grid-template-rows: #{map-get($mobileGrid, templateRows)};
+ column-gap: #{map-get($mobileGrid, columnGap)};
+ row-gap: #{map-get($mobileGrid, rowGap)};
+ grid-template-areas: #{map-get($mobileGrid, templateAreas)};
+ }
+
+ @media all and ($desktop) {
+ padding: 0 1rem;
+ }
+ @media all and ($mobile) {
+ margin: 0 auto;
}
& .sidebar {
- flex: 1;
- display: flex;
- flex-direction: column;
gap: 2rem;
top: 0;
- width: $sidePanelWidth;
- margin-top: $topSpacing;
box-sizing: border-box;
- padding: 0 4rem;
- position: fixed;
- @media all and (max-width: $fullPageWidth) {
- position: initial;
- flex-direction: row;
- padding: 0;
- width: initial;
- margin-top: 2rem;
- }
+ padding: $topSpacing 2rem 2rem 2rem;
+ display: flex;
+ height: 100vh;
+ position: sticky;
}
& .sidebar.left {
z-index: 1;
- left: calc(calc(100vw - $pageWidth) / 2 - $sidePanelWidth);
- @media all and (max-width: $fullPageWidth) {
+ grid-area: sidebar-left;
+ flex-direction: column;
+ @media all and ($mobile) {
gap: 0;
align-items: center;
+ position: initial;
+ display: flex;
+ height: unset;
+ flex-direction: row;
+ padding: 0;
+ padding-top: 2rem;
}
}
& .sidebar.right {
- right: calc(calc(100vw - $pageWidth) / 2 - $sidePanelWidth);
- flex-wrap: wrap;
- & > * {
- @media all and (max-width: $fullPageWidth) {
+ grid-area: sidebar-right;
+ margin-right: 0;
+ flex-direction: column;
+ @media all and ($mobile) {
+ margin-left: inherit;
+ margin-right: inherit;
+ }
+ @media all and ($desktop) {
+ position: initial;
+ height: unset;
+ width: 100%;
+ flex-direction: row;
+ padding: 0;
+ & > * {
flex: 1;
- min-width: 140px;
+ }
+ & > .toc {
+ display: none;
}
}
}
- }
-
- & .page-header,
- & .page-footer {
- width: $pageWidth;
- margin-top: 1rem;
-
- @media all and (max-width: $fullPageWidth) {
- width: initial;
+ & .page-header,
+ & .page-footer {
+ margin-top: 1rem;
}
- }
- & .page-header {
- margin: $topSpacing auto 0 auto;
- @media all and (max-width: $fullPageWidth) {
- margin-top: 2rem;
+ & .page-header {
+ grid-area: page-header;
+ margin: $topSpacing 0 0 0;
+ @media all and ($mobile) {
+ margin-top: 0;
+ padding: 0;
+ }
}
- }
- & .center,
- & footer {
- margin-left: auto;
- margin-right: auto;
- width: $pageWidth;
- @media all and (max-width: $fullPageWidth) {
- width: initial;
+ & .center > article {
+ grid-area: page-center;
+ }
+
+ & .page-footer {
+ grid-area: page-footer;
+ }
+
+ & .center,
+ & footer {
+ margin-left: auto;
+ margin-right: auto;
+ @media all and ($desktop) {
+ margin-right: 0;
+ }
+ @media all and ($mobile) {
+ margin-left: 0;
+ }
+ }
+ & footer {
margin-left: 0;
- margin-right: 0;
}
}
}
diff --git a/quartz/styles/variables.scss b/quartz/styles/variables.scss
index e45cc91..3ac5a8b 100644
--- a/quartz/styles/variables.scss
+++ b/quartz/styles/variables.scss
@@ -1,9 +1,56 @@
-$pageWidth: 750px;
-$mobileBreakpoint: 600px;
-$tabletBreakpoint: 1000px;
-$sidePanelWidth: 380px;
+/**
+ * Layout breakpoints
+ * $mobile: screen width below this value will use mobile styles
+ * $desktop: screen width above this value will use desktop styles
+ * Screen width between $mobile and $desktop width will use the tablet layout.
+ * assuming mobile < desktop
+ */
+$breakpoints: (
+ mobile: 800px,
+ desktop: 1200px,
+);
+
+$mobile: "(max-width: #{map-get($breakpoints, mobile)})";
+$tablet: "(min-width: #{map-get($breakpoints, mobile)}) and (max-width: #{map-get($breakpoints, desktop)})";
+$desktop: "(max-width: #{map-get($breakpoints, desktop)})";
+
+$pageWidth: #{map-get($breakpoints, mobile)};
+$sidePanelWidth: 320px; //380px;
$topSpacing: 6rem;
-$fullPageWidth: $pageWidth + 2 * $sidePanelWidth;
$boldWeight: 700;
$semiBoldWeight: 600;
$normalWeight: 400;
+
+$mobileGrid: (
+ templateRows: "auto auto auto auto auto",
+ templateColumns: "auto",
+ rowGap: "5px",
+ columnGap: "5px",
+ templateAreas:
+ '"sidebar-left"\
+ "page-header"\
+ "page-center"\
+ "sidebar-right"\
+ "page-footer"',
+);
+$tabletGrid: (
+ templateRows: "auto auto auto auto",
+ templateColumns: "#{$sidePanelWidth} auto",
+ rowGap: "5px",
+ columnGap: "5px",
+ templateAreas:
+ '"sidebar-left page-header"\
+ "sidebar-left page-center"\
+ "sidebar-left sidebar-right"\
+ "sidebar-left page-footer"',
+);
+$desktopGrid: (
+ templateRows: "auto auto auto",
+ templateColumns: "#{$sidePanelWidth} auto #{$sidePanelWidth}",
+ rowGap: "5px",
+ columnGap: "5px",
+ templateAreas:
+ '"sidebar-left page-header sidebar-right"\
+ "sidebar-left page-center sidebar-right"\
+ "sidebar-left page-footer sidebar-right"',
+);
--
Gitblit v1.10.0