diff --git a/web/src/components/LibraryNav.astro b/web/src/components/LibraryNav.astro index 4a857715..9afb2990 100644 --- a/web/src/components/LibraryNav.astro +++ b/web/src/components/LibraryNav.astro @@ -3,7 +3,7 @@ const { current } = Astro.props as { current: 'bookmarks' | 'words' }; --- diff --git a/web/src/layouts/Base.astro b/web/src/layouts/Base.astro index 79703140..a04bbc0e 100644 --- a/web/src/layouts/Base.astro +++ b/web/src/layouts/Base.astro @@ -145,7 +145,7 @@ const fullTitle = title ? `${title} · دیوان` : 'دیوان · اردو ک return e; }; let current = ''; - // reader's library: 🔖 bookmarks (poets, books/chapters, poems, couplets, phrases) and the word book (+); + // reader's library: bookmarks (poets, books/chapters, poems, couplets, phrases) and the word book (+); // signed-out readers go to sign-in let source = {}; // the couplet the selected word came from async function save(item) { diff --git a/web/src/pages/[...path].astro b/web/src/pages/[...path].astro index f15f15a4..8cec4d80 100644 --- a/web/src/pages/[...path].astro +++ b/web/src/pages/[...path].astro @@ -47,13 +47,13 @@ for (const p of page.poems ?? []) { groups.at(-1)!.poems.push(p); } const crumbs = page.breadcrumbs ?? []; -// what the signed-in reader has bookmarked on this page (🔖 poet, book/chapter, poem, couplets, phrases) +// what the signed-in reader has bookmarked on this page (poet, book/chapter, poem, couplets, phrases) const token = Astro.locals.user ? Astro.cookies.get(COOKIE)?.value : undefined; const poetId = page.poet?.id, poemId = page.type === 'poem' ? page.poem.id : undefined; const categoryId = page.type === 'category' ? page.category.id : undefined; const saved = token ? (await asUser(token, `/api/library/state?poet=${poetId ?? ''}&category=${categoryId ?? ''}&poem=${poemId ?? ''}`)).data : { poet: false, category: false, poem: false, couplets: [], phrases: [] }; -// on contents pages: which works are bookmarked or hold bookmarks (🔖), and which books/chapters do +// on contents pages: which works are bookmarked or hold bookmarks, and which books/chapters do const marks = token && page.type !== 'poem' ? (await asUser(token, '/api/library/marks')).data : { poems: {}, categories: [] }; const glyph = (poemId: number) => (marks.poems[poemId]?.fav ? ' mark-fav' : '') + (marks.poems[poemId]?.bm ? ' mark-bm' : ''); // the marked part of each line of a block, for its bookmarked phrases diff --git a/web/src/pages/api/library.ts b/web/src/pages/api/library.ts index 8516242c..f67a8fc4 100644 --- a/web/src/pages/api/library.ts +++ b/web/src/pages/api/library.ts @@ -1,4 +1,4 @@ -// Browser -> API for the 🔖 bookmark buttons and the word book: the reader's session cookie becomes the Bearer token. +// Browser -> API for the bookmark buttons and the word book: the reader's session cookie becomes the Bearer token. // JSON posts from other sites are refused: the Origin must be this site (and SameSite cookies are not sent). import type { APIRoute } from 'astro'; import { asUser, COOKIE } from '../../lib/auth'; diff --git a/web/src/pages/library.astro b/web/src/pages/library.astro index 77c633f7..e631408c 100644 --- a/web/src/pages/library.astro +++ b/web/src/pages/library.astro @@ -33,7 +33,7 @@ const at = (item: any) => (item.poem ? `${item.poem.url}${item.poem.couplet != n

{ud(total)} نشانات

{total === 0 && ( -

ابھی کوئی نشان نہیں۔ کسی شاعر، کتاب، باب یا کلام پر 🔖 "نشان" دبائیں، کسی شعر کے ساتھ 🔖 لگائیں، یا کوئی عبارت منتخب کر کے "نشان" لگائیں۔

+

ابھی کوئی نشان نہیں۔ کسی شاعر، کتاب، باب یا کلام پر "نشان" دبائیں، کسی شعر کے ساتھ نشان لگائیں، یا کوئی عبارت منتخب کر کے "نشان" لگائیں۔

)} {lib.poets.length > 0 && ( diff --git a/web/src/styles/global.css b/web/src/styles/global.css index 218ac768..1504553a 100644 --- a/web/src/styles/global.css +++ b/web/src/styles/global.css @@ -214,11 +214,17 @@ h1 + .muted { text-align: center; margin-top: 0; } .grant-form legend { font-size: .85rem; padding: 0 6px; } .grant-form label.check { flex-direction: row; align-items: center; gap: 6px; } -/* bookmarks (🔖): poets, books/chapters, poems, couplets; the word book is separate (+) */ +/* bookmarks: an Android-style bookmark icon (Material Design 'bookmark', Apache-2.0), grey outline when not set, + filled in the brand colour when set; drawn as a mask so it follows the theme. The word book is separate (+). */ +:root { --bm-outline: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 3H7c-1.1 0-2 .9-2 2v16l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15-5-2.18L7 18V5h10v13z'/%3E%3C/svg%3E"); --bm-filled: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 3H7c-1.1 0-2 .9-2 2v16l7-3 7 3V5c0-1.1-.9-2-2-2z'/%3E%3C/svg%3E"); } +.bm-icon, .save::before, .bm::before, .bmk::after, .mark-fav::after, .mark-bm::after { + content: ''; display: inline-block; width: 1.05em; height: 1.05em; vertical-align: -.18em; background-color: var(--muted); + -webkit-mask: var(--bm-outline) center / contain no-repeat; mask: var(--bm-outline) center / contain no-repeat; user-select: none; } +.save[aria-pressed='true']::before, .bm[aria-pressed='true']::before, .bmk::after, .mark-fav::after, .mark-bm::after, .bm-icon.on { + background-color: var(--brand); -webkit-mask-image: var(--bm-filled); mask-image: var(--bm-filled); } .save { font: inherit; font-size: .85rem; padding: 1px 14px; border: 1.5px solid var(--border); border-radius: 999px; background: var(--inner); color: var(--ink); cursor: pointer; } -.save::before { content: '🔖 '; filter: grayscale(1); opacity: .6; } +.save::before { margin-inline-end: 4px; } .save[aria-pressed='true'] { border-color: var(--brand); color: var(--brand); } -.save[aria-pressed='true']::before { filter: none; opacity: 1; } /* word book (ذخیرۂ الفاظ): + to add, ✓ when added (hearts are for poets and works) */ .wordbook { font: inherit; font-size: .85rem; padding: 1px 14px; margin-bottom: 6px; border: 1.5px solid var(--border); border-radius: 999px; background: var(--inner); color: var(--ink); cursor: pointer; } .wordbook::before { content: '+ '; font-weight: 700; color: var(--gold); } @@ -227,9 +233,8 @@ h1 + .muted { text-align: center; margin-top: 0; } .couplet, .poem .para, .poem .single { position: relative; } .bm { position: absolute; inset-inline-end: -26px; top: .5em; width: 20px; height: 22px; padding: 0; border: 0; background: none; cursor: pointer; opacity: 0; transition: opacity .15s; user-select: none; } -.bm::before { content: '🔖'; font-size: .85rem; filter: grayscale(1); opacity: .6; } +.bm::before { width: 18px; height: 18px; } .bm[aria-pressed='true'] { opacity: 1; } -.bm[aria-pressed='true']::before { filter: none; opacity: 1; } .couplet:hover .bm, .poem .para:hover .bm, .poem .single:hover .bm, .bm:focus-visible { opacity: 1; } @media (hover: none) { .bm { opacity: 1; } } @media (max-width: 700px) { .bm { inset-inline-end: -4px; top: 0; } } @@ -251,8 +256,7 @@ h1 + .muted { text-align: center; margin-top: 0; } .lib-remove { position: absolute; left: 8px; top: 8px; margin: 0; } .lib-remove button { color: var(--brand); } -/* bookmarked phrases, and 🔖 where the reader's bookmarks are */ +/* bookmarked phrases, and the bookmark icon where the reader's bookmarks are */ .bmk { text-decoration: underline dotted var(--brand) 2px; text-underline-offset: 6px; cursor: pointer; background: var(--gold-subtle); border-radius: 4px; } -.bmk::after { content: '🔖'; font-size: .55em; vertical-align: super; margin-inline-start: 1px; user-select: none; } -.mark-fav::after, .mark-bm::after { font-size: .65em; margin-inline-start: 6px; vertical-align: middle; user-select: none; } -.mark-fav::after, .mark-bm::after { content: '🔖'; } +.bmk::after { width: .7em; height: .7em; vertical-align: super; margin-inline-start: 2px; } +.mark-fav::after, .mark-bm::after { width: .85em; height: .85em; margin-inline-start: 6px; vertical-align: -.1em; }