mirror of
https://github.com/priyanshujain/margin.git
synced 2026-10-02 11:07:04 +00:00
feat(fonts): apply per-book body and heading fonts on screen
Split heading typography onto a new --font-heading token and set both --font-book and --font-heading from the active book's fonts when it opens or its setup changes. Declare @font-face for the new bundled fonts.
This commit is contained in:
1 parent
124c1947c1
commit
28367b6670
5 files changed
+101
-6
No files matched your search
@@ -0,0 +1,13 @@
|
||||
import { type BookFonts, fontStack } from "./model/fonts";
|
||||
|
||||
export function applyBookFonts(fonts: BookFonts): void {
|
||||
const root = document.documentElement;
|
||||
root.style.setProperty("--font-book", fontStack(fonts.body));
|
||||
root.style.setProperty("--font-heading", fontStack(fonts.heading));
|
||||
}
|
||||
|
||||
export function resetBookFonts(): void {
|
||||
const root = document.documentElement;
|
||||
root.style.removeProperty("--font-book");
|
||||
root.style.removeProperty("--font-heading");
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from "../model/book";
|
||||
import { loadActiveChapter, saveActiveChapter } from "../editor/positions";
|
||||
import { saveBook } from "../library";
|
||||
import { applyBookFonts, resetBookFonts } from "../book-style";
|
||||
|
||||
export const COVER_ID = "__cover__";
|
||||
|
||||
@@ -60,10 +61,12 @@ export const useBook = create<BookState>((set, get) => ({
|
||||
const saved = loadActiveChapter(normalized.id);
|
||||
const valid = saved === COVER_ID || normalized.chapters.some((c) => c.id === saved);
|
||||
const activeChapterId = valid ? (saved as string) : normalized.chapters[0]?.id ?? "";
|
||||
applyBookFonts(normalized.settings.fonts);
|
||||
set({ book: normalized, activeChapterId, dirty: false });
|
||||
},
|
||||
closeBook: () => {
|
||||
flushOutgoing(get().book, get().dirty);
|
||||
resetBookFonts();
|
||||
set({ book: null, activeChapterId: "", dirty: false });
|
||||
},
|
||||
setActiveChapter: (id) => set({ activeChapterId: id }),
|
||||
@@ -140,7 +143,12 @@ export const useBook = create<BookState>((set, get) => ({
|
||||
setMetadata: (patch) =>
|
||||
set((s) => (s.book ? { dirty: true, book: { ...s.book, metadata: { ...s.book.metadata, ...patch } } } : {})),
|
||||
setSettings: (patch) =>
|
||||
set((s) => (s.book ? { dirty: true, book: { ...s.book, settings: { ...s.book.settings, ...patch } } } : {})),
|
||||
set((s) => {
|
||||
if (!s.book) return {};
|
||||
const book = { ...s.book, settings: { ...s.book.settings, ...patch } };
|
||||
if (patch.fonts) applyBookFonts(book.settings.fonts);
|
||||
return { dirty: true, book };
|
||||
}),
|
||||
setCover: (patch) =>
|
||||
set((s) => (s.book ? { dirty: true, book: { ...s.book, cover: { ...s.book.cover, ...patch } } } : {})),
|
||||
markSaved: () => set({ dirty: false }),
|
||||
|
||||
+14
-5
@@ -427,6 +427,7 @@ body.resizing {
|
||||
}
|
||||
|
||||
.chapter-title {
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 500;
|
||||
font-size: 31px;
|
||||
line-height: 1.16;
|
||||
@@ -434,6 +435,10 @@ body.resizing {
|
||||
margin: 15px 0 0;
|
||||
}
|
||||
|
||||
.prose :is(h1, h2, h3) {
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
|
||||
.prose p {
|
||||
font-size: 19px;
|
||||
line-height: 1.68;
|
||||
@@ -565,11 +570,15 @@ body.resizing {
|
||||
}
|
||||
|
||||
.page .p-title {
|
||||
font-family: var(--font-book);
|
||||
font-family: var(--font-heading);
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.page :is(h2, h3) {
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
|
||||
.page p {
|
||||
font-family: var(--font-book);
|
||||
font-size: 6.6px;
|
||||
@@ -620,7 +629,7 @@ body.resizing {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
font-family: var(--font-book);
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 500;
|
||||
font-size: 31px;
|
||||
line-height: 1.16;
|
||||
@@ -1432,7 +1441,7 @@ body.resizing {
|
||||
}
|
||||
|
||||
.cover-title {
|
||||
font-family: var(--font-book);
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 500;
|
||||
font-size: 9.5cqw;
|
||||
line-height: 1.08;
|
||||
@@ -2108,7 +2117,7 @@ body.resizing {
|
||||
}
|
||||
|
||||
.device-title {
|
||||
font-family: var(--font-book);
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 500;
|
||||
font-size: calc(24 * var(--dv-scale));
|
||||
line-height: 1.2;
|
||||
@@ -2138,7 +2147,7 @@ body.resizing {
|
||||
.device-body h1,
|
||||
.device-body h2,
|
||||
.device-body h3 {
|
||||
font-family: var(--font-book);
|
||||
font-family: var(--font-heading);
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
margin: 1.2em 0 0.5em;
|
||||
|
||||
@@ -29,3 +29,67 @@
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "EB Garamond";
|
||||
src: url("/fonts/EBGaramond-VF.ttf") format("truetype-variations");
|
||||
font-weight: 400 800;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "EB Garamond";
|
||||
src: url("/fonts/EBGaramond-Italic-VF.ttf") format("truetype-variations");
|
||||
font-weight: 400 800;
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Lora";
|
||||
src: url("/fonts/Lora-VF.ttf") format("truetype-variations");
|
||||
font-weight: 400 700;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Lora";
|
||||
src: url("/fonts/Lora-Italic-VF.ttf") format("truetype-variations");
|
||||
font-weight: 400 700;
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
src: url("/fonts/SourceSerif4-VF.ttf") format("truetype-variations");
|
||||
font-weight: 200 900;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
src: url("/fonts/SourceSerif4-Italic-VF.ttf") format("truetype-variations");
|
||||
font-weight: 200 900;
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fraunces";
|
||||
src: url("/fonts/Fraunces-VF.ttf") format("truetype-variations");
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fraunces";
|
||||
src: url("/fonts/Fraunces-Italic-VF.ttf") format("truetype-variations");
|
||||
font-weight: 100 900;
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
:root {
|
||||
--font-ui: "Hanken Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;
|
||||
--font-book: "Literata", Georgia, "Times New Roman", serif;
|
||||
--font-heading: "Literata", Georgia, "Times New Roman", serif;
|
||||
|
||||
--r-sm: 5px;
|
||||
--r-md: 8px;
|
||||
|
||||
Reference in new issue
Block a user