feat: responsive design grid (#1354)

* Responsive design grid

* Addressed PR feedback

* Bump Quartz version 4.3.1 => 4.4.0

* Moved page-header into center

* Updated docs with new layouts

* Sync updated version number with package-lock

* Table of Content scrollbar auto

* Reset node_modules

* Updated layout images

* Fixed tablet layout

* Finilazed layout images
This commit is contained in:
Emile Bangma 2024-09-23 22:40:12 +02:00 committed by GitHub
parent 9cefcd0dd1
commit 7d7e334976
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 247 additions and 92 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View file

@ -13,15 +13,19 @@ export interface FullPageLayout {
beforeBody: QuartzComponent[] // laid out vertically beforeBody: QuartzComponent[] // laid out vertically
pageBody: QuartzComponent // single component pageBody: QuartzComponent // single component
afterBody: QuartzComponent[] // laid out vertically afterBody: QuartzComponent[] // laid out vertically
left: QuartzComponent[] // vertical on desktop, horizontal on mobile left: QuartzComponent[] // vertical on desktop and tablet, horizontal on mobile
right: QuartzComponent[] // vertical on desktop, horizontal on mobile right: QuartzComponent[] // vertical on desktop, horizontal on tablet and mobile
footer: QuartzComponent // single component footer: QuartzComponent // single component
} }
``` ```
These correspond to following parts of the page: 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] > [!note]
> There are two additional layout fields that are _not_ shown in the above diagram. > There are two additional layout fields that are _not_ shown in the above diagram.
@ -33,6 +37,23 @@ Quartz **components**, like plugins, can take in additional properties as config
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. 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 ### 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. 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.

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "@jackyzha0/quartz", "name": "@jackyzha0/quartz",
"version": "4.3.1", "version": "4.4.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@jackyzha0/quartz", "name": "@jackyzha0/quartz",
"version": "4.3.1", "version": "4.4.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@clack/prompts": "^0.7.0", "@clack/prompts": "^0.7.0",

View file

@ -2,7 +2,7 @@
"name": "@jackyzha0/quartz", "name": "@jackyzha0/quartz",
"description": "🌱 publish your digital garden and notes as a website", "description": "🌱 publish your digital garden and notes as a website",
"private": true, "private": true,
"version": "4.3.1", "version": "4.4.0",
"type": "module", "type": "module",
"author": "jackyzha0 <j.zhao2k19@gmail.com>", "author": "jackyzha0 <j.zhao2k19@gmail.com>",
"license": "MIT", "license": "MIT",

View file

@ -242,8 +242,8 @@ export function renderPage(
</div> </div>
</div> </div>
{RightComponent} {RightComponent}
</Body>
<Footer {...componentData} /> <Footer {...componentData} />
</Body>
</div> </div>
</body> </body>
{pageResources.js {pageResources.js

View file

@ -1,5 +1,25 @@
@use "../../styles/variables.scss" as *;
.backlinks { .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));
}
&:has(> .overflow) {
position: unset;
}
& > h3 { & > h3 {
font-size: 1rem; font-size: 1rem;
@ -17,4 +37,15 @@
} }
} }
} }
& > .overflow {
max-height: unset;
& > li:last-of-type {
margin-bottom: 0;
}
&:after {
display: none;
}
}
}
} }

View file

@ -1,5 +1,23 @@
@use "../../styles/variables.scss" as *; @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 { button#explorer {
background-color: transparent; background-color: transparent;
border: none; border: none;
@ -58,10 +76,6 @@ button#explorer {
visibility: hidden; visibility: hidden;
} }
&.collapsed > .overflow::after {
opacity: 0;
}
& ul { & ul {
list-style: none; list-style: none;
margin: 0.08rem 0; margin: 0.08rem 0;
@ -76,6 +90,9 @@ button#explorer {
pointer-events: all; pointer-events: all;
} }
} }
> #explorer-ul {
max-height: none;
}
} }
svg { svg {

View file

@ -65,7 +65,7 @@
height: 80vh; height: 80vh;
width: 80vw; width: 80vw;
@media all and (max-width: $fullPageWidth) { @media all and ($desktop) {
width: 90%; width: 90%;
} }
} }

View file

@ -13,7 +13,7 @@ li.section-li {
display: grid; display: grid;
grid-template-columns: fit-content(8em) 3fr 1fr; grid-template-columns: fit-content(8em) 3fr 1fr;
@media all and (max-width: $mobileBreakpoint) { @media all and ($mobile) {
& > .tags { & > .tags {
display: none; display: none;
} }

View file

@ -70,7 +70,7 @@
opacity 0.3s ease, opacity 0.3s ease,
visibility 0.3s ease; visibility 0.3s ease;
@media all and (max-width: $mobileBreakpoint) { @media all and ($mobile) {
display: none !important; display: none !important;
} }
} }

View file

@ -3,7 +3,9 @@
.search { .search {
min-width: fit-content; min-width: fit-content;
max-width: 14rem; max-width: 14rem;
@media all and ($mobile) {
flex-grow: 0.3; flex-grow: 0.3;
}
& > .search-button { & > .search-button {
background-color: var(--lightgray); background-color: var(--lightgray);
@ -62,7 +64,7 @@
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
@media all and (max-width: $fullPageWidth) { @media all and ($desktop) {
width: 90%; width: 90%;
} }
@ -104,7 +106,7 @@
flex: 0 0 min(30%, 450px); flex: 0 0 min(30%, 450px);
} }
@media all and (min-width: $tabletBreakpoint) { @media all and not ($tablet) {
&[data-preview] { &[data-preview] {
& .result-card > p.preview { & .result-card > p.preview {
display: none; display: none;
@ -130,7 +132,7 @@
border-radius: 5px; border-radius: 5px;
} }
@media all and (max-width: $tabletBreakpoint) { @media all and ($tablet) {
& > #preview-container { & > #preview-container {
display: none !important; display: none !important;
} }

View file

@ -1,3 +1,7 @@
.toc {
overflow-y: auto;
}
button#toc { button#toc {
background-color: transparent; background-color: transparent;
border: none; border: none;

View file

@ -12,7 +12,6 @@ html {
body, body,
section { section {
margin: 0; margin: 0;
max-width: 100%;
box-sizing: border-box; box-sizing: border-box;
background-color: var(--light); background-color: var(--light);
font-family: var(--bodyFont); font-family: var(--bodyFont);
@ -109,25 +108,21 @@ a {
.desktop-only { .desktop-only {
display: initial; display: initial;
@media all and (max-width: $fullPageWidth) { @media all and ($mobile) {
display: none; display: none;
} }
} }
.mobile-only { .mobile-only {
display: none; display: none;
@media all and (max-width: $fullPageWidth) { @media all and ($mobile) {
display: initial; display: initial;
} }
} }
.page { .page {
@media all and (max-width: $fullPageWidth) { max-width: calc(#{map-get($breakpoints, desktop)} + 300px);
margin: 0 auto; margin: 0 auto;
padding: 0 1rem;
max-width: $pageWidth;
}
& article { & article {
& > h1 { & > h1 {
font-size: 2rem; font-size: 2rem;
@ -155,80 +150,118 @@ a {
} }
& > #quartz-body { & > #quartz-body {
width: 100%; display: grid;
display: flex; grid-template-columns: #{map-get($desktopGrid, templateColumns)};
@media all and (max-width: $fullPageWidth) { grid-template-rows: #{map-get($desktopGrid, templateRows)};
flex-direction: column; 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 { & .sidebar {
flex: 1;
display: flex;
flex-direction: column;
gap: 2rem; gap: 2rem;
top: 0; top: 0;
width: $sidePanelWidth;
margin-top: $topSpacing;
box-sizing: border-box; box-sizing: border-box;
padding: 0 4rem; padding: $topSpacing 2rem 2rem 2rem;
position: fixed; display: flex;
@media all and (max-width: $fullPageWidth) { height: 100vh;
position: initial; position: sticky;
flex-direction: row;
padding: 0;
width: initial;
margin-top: 2rem;
}
} }
& .sidebar.left { & .sidebar.left {
z-index: 1; z-index: 1;
left: calc(calc(100vw - $pageWidth) / 2 - $sidePanelWidth); grid-area: sidebar-left;
@media all and (max-width: $fullPageWidth) { flex-direction: column;
@media all and ($mobile) {
gap: 0; gap: 0;
align-items: center; align-items: center;
position: initial;
display: flex;
height: unset;
flex-direction: row;
padding: 0;
padding-top: 2rem;
} }
} }
& .sidebar.right { & .sidebar.right {
right: calc(calc(100vw - $pageWidth) / 2 - $sidePanelWidth); grid-area: sidebar-right;
flex-wrap: wrap; 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;
& > * { & > * {
@media all and (max-width: $fullPageWidth) {
flex: 1; flex: 1;
min-width: 140px; }
& > .toc {
display: none;
} }
} }
} }
}
& .page-header, & .page-header,
& .page-footer { & .page-footer {
width: $pageWidth;
margin-top: 1rem; margin-top: 1rem;
@media all and (max-width: $fullPageWidth) {
width: initial;
}
} }
& .page-header { & .page-header {
margin: $topSpacing auto 0 auto; grid-area: page-header;
@media all and (max-width: $fullPageWidth) { margin: $topSpacing 0 0 0;
margin-top: 2rem; @media all and ($mobile) {
margin-top: 0;
padding: 0;
} }
} }
& .center > article {
grid-area: page-center;
}
& .page-footer {
grid-area: page-footer;
}
& .center, & .center,
& footer { & footer {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
width: $pageWidth; @media all and ($desktop) {
@media all and (max-width: $fullPageWidth) {
width: initial;
margin-left: 0;
margin-right: 0; margin-right: 0;
} }
@media all and ($mobile) {
margin-left: 0;
}
}
& footer {
margin-left: 0;
}
} }
} }

View file

@ -1,9 +1,56 @@
$pageWidth: 750px; /**
$mobileBreakpoint: 600px; * Layout breakpoints
$tabletBreakpoint: 1000px; * $mobile: screen width below this value will use mobile styles
$sidePanelWidth: 380px; * $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; $topSpacing: 6rem;
$fullPageWidth: $pageWidth + 2 * $sidePanelWidth;
$boldWeight: 700; $boldWeight: 700;
$semiBoldWeight: 600; $semiBoldWeight: 600;
$normalWeight: 400; $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"',
);