The Trans Directory
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: reader mode

+139 -1
+44
docs/features/reader mode.md
··· 1 + --- 2 + title: Reader Mode 3 + tags: 4 + - component 5 + --- 6 + 7 + Reader Mode is a feature that allows users to focus on the content by hiding the sidebars and other UI elements. When enabled, it provides a clean, distraction-free reading experience. 8 + 9 + ## Configuration 10 + 11 + Reader Mode is enabled by default. To disable it, you can remove the component from your layout configuration in `quartz.layout.ts`: 12 + 13 + ```ts 14 + // Remove or comment out this line 15 + Component.ReaderMode(), 16 + ``` 17 + 18 + ## Usage 19 + 20 + The Reader Mode toggle appears as a button with a book icon. When clicked: 21 + 22 + - Sidebars are hidden 23 + - Hovering over the content area reveals the sidebars temporarily 24 + 25 + Unlike Dark Mode, Reader Mode state is not persisted between page reloads but is maintained during SPA navigation within the site. 26 + 27 + ## Customization 28 + 29 + You can customize the appearance of Reader Mode through CSS variables and styles. The component uses the following classes: 30 + 31 + - `.readermode`: The toggle button 32 + - `.readerIcon`: The book icon 33 + - `[reader-mode="on"]`: Applied to the root element when Reader Mode is active 34 + 35 + Example customization in your custom CSS: 36 + 37 + ```scss 38 + .readermode { 39 + // Customize the button 40 + svg { 41 + stroke: var(--custom-color); 42 + } 43 + } 44 + ```
+1
index.d.ts
··· 8 8 prenav: CustomEvent<{}> 9 9 nav: CustomEvent<{ url: FullSlug }> 10 10 themechange: CustomEvent<{ theme: "light" | "dark" }> 11 + readermodechange: CustomEvent<{ mode: "on" | "off" }> 11 12 } 12 13 13 14 type ContentIndex = Record<FullSlug, ContentDetails>
+1
quartz.layout.ts
··· 35 35 grow: true, 36 36 }, 37 37 { Component: Component.Darkmode() }, 38 + { Component: Component.ReaderMode() }, 38 39 ], 39 40 }), 40 41 Component.Explorer(),
+32
quartz/components/ReaderMode.tsx
··· 1 + // @ts-ignore 2 + import readerModeScript from "./scripts/readermode.inline" 3 + import styles from "./styles/readermode.scss" 4 + import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" 5 + import { classNames } from "../util/lang" 6 + 7 + const ReaderMode: QuartzComponent = ({ displayClass }: QuartzComponentProps) => { 8 + return ( 9 + <button class={classNames(displayClass, "readermode")}> 10 + <svg 11 + xmlns="http://www.w3.org/2000/svg" 12 + class="readerIcon" 13 + viewBox="0 0 24 24" 14 + fill="none" 15 + stroke="currentColor" 16 + stroke-width="2" 17 + stroke-linecap="round" 18 + stroke-linejoin="round" 19 + > 20 + <rect x="6" y="4" width="12" height="16" rx="1"></rect> 21 + <line x1="9" y1="8" x2="15" y2="8"></line> 22 + <line x1="9" y1="12" x2="15" y2="12"></line> 23 + <line x1="9" y1="16" x2="13" y2="16"></line> 24 + </svg> 25 + </button> 26 + ) 27 + } 28 + 29 + ReaderMode.beforeDOMLoaded = readerModeScript 30 + ReaderMode.css = styles 31 + 32 + export default (() => ReaderMode) satisfies QuartzComponentConstructor
+2
quartz/components/index.ts
··· 4 4 import NotFound from "./pages/404" 5 5 import ArticleTitle from "./ArticleTitle" 6 6 import Darkmode from "./Darkmode" 7 + import ReaderMode from "./ReaderMode" 7 8 import Head from "./Head" 8 9 import PageTitle from "./PageTitle" 9 10 import ContentMeta from "./ContentMeta" ··· 29 30 TagContent, 30 31 FolderContent, 31 32 Darkmode, 33 + ReaderMode, 32 34 Head, 33 35 PageTitle, 34 36 ContentMeta,
+25
quartz/components/scripts/readermode.inline.ts
··· 1 + let isReaderMode = false 2 + 3 + const emitReaderModeChangeEvent = (mode: "on" | "off") => { 4 + const event: CustomEventMap["readermodechange"] = new CustomEvent("readermodechange", { 5 + detail: { mode }, 6 + }) 7 + document.dispatchEvent(event) 8 + } 9 + 10 + document.addEventListener("nav", () => { 11 + const switchReaderMode = () => { 12 + isReaderMode = !isReaderMode 13 + const newMode = isReaderMode ? "on" : "off" 14 + document.documentElement.setAttribute("reader-mode", newMode) 15 + emitReaderModeChangeEvent(newMode) 16 + } 17 + 18 + for (const readerModeButton of document.getElementsByClassName("readermode")) { 19 + readerModeButton.addEventListener("click", switchReaderMode) 20 + window.addCleanup(() => readerModeButton.removeEventListener("click", switchReaderMode)) 21 + } 22 + 23 + // Set initial state 24 + document.documentElement.setAttribute("reader-mode", isReaderMode ? "on" : "off") 25 + })
+1 -1
quartz/components/styles/darkmode.scss
··· 6 6 border: none; 7 7 width: 20px; 8 8 height: 20px; 9 - margin: 0 10px; 9 + margin: 0; 10 10 text-align: inherit; 11 11 flex-shrink: 0; 12 12
+33
quartz/components/styles/readermode.scss
··· 1 + .readermode { 2 + cursor: pointer; 3 + padding: 0; 4 + position: relative; 5 + background: none; 6 + border: none; 7 + width: 20px; 8 + height: 20px; 9 + margin: 0; 10 + text-align: inherit; 11 + flex-shrink: 0; 12 + 13 + & svg { 14 + position: absolute; 15 + width: 20px; 16 + height: 20px; 17 + top: calc(50% - 10px); 18 + stroke: var(--darkgray); 19 + transition: opacity 0.1s ease; 20 + } 21 + } 22 + 23 + :root[reader-mode="on"] { 24 + & .sidebar.left, 25 + & .sidebar.right { 26 + opacity: 0; 27 + transition: opacity 0.2s ease; 28 + 29 + &:hover { 30 + opacity: 1; 31 + } 32 + } 33 + }