Compare commits

...

2 Commits

Author SHA1 Message Date
faf8931f44 Merge pull request 'Tags folded at the end of a page; a how-to-use page instead of the hint' (#95) from anas/tags-help into main
Reviewed-on: #95
2026-10-09 22:16:23 +00:00
Anas Rashid
f20cc25080 Tags folded at the end of a page; a "how to use" page instead of the hint
- A page's tags (poem, book, poet) move from the top into a closed «ٹیگ» section with their count at the end of the content, above previous/next; couplets keep their own tags
- The line under each poem ("select a word…") is gone; /help (استعمال کا طریقہ, linked in the footer) explains the features: search and Roman typing, meanings and the selection menu, a couplet's tools (and ⋯ on phones), notes, saved items and the word book, reading mode, fonts and colours, e-books, tags and RSS

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:13:45 +02:00
6 changed files with 88 additions and 4 deletions

View File

@ -62,6 +62,7 @@ const PATHS = {
info: '<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>',
globe: '<circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/>',
database: '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14a9 3 0 0 0 18 0V5"/><path d="M3 12a9 3 0 0 0 18 0"/>',
help: '<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/>',
};
---
<svg class:list={['icon', cls]} viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" set:html={PATHS[name]} />

View File

@ -0,0 +1,12 @@
---
// a page's tags, folded away at the end of its content (#52): "ٹیگ" and how many; open to see the chips
import Tags from './Tags.astro';
import { ud } from '../lib/urdu';
const { tags } = Astro.props as { tags: { type: string; name: string }[] };
---
{tags.length > 0 && (
<details class="tags-box">
<summary>ٹیگ <small class="muted">{ud(tags.length)}</small></summary>
<Tags tags={tags} />
</details>
)}

View File

@ -147,6 +147,7 @@ import { brand } from '../lib/brand';
<nav class="footer-links" aria-label="سائٹ کے بارے میں">
<div><h2>{brand.name}</h2><ul>
<li><a href="/about"><Icon name="info" size={18} /><span>{brand.name} کے بارے میں<small>مقصد اور طریقۂ کار</small></span></a></li>
<li><a href="/help"><Icon name="help" size={18} /><span>استعمال کا طریقہ<small>سائٹ کی سہولتیں</small></span></a></li>
<li><a href="/tags"><Icon name="tag" size={18} /><span>ٹیگ<small>موضوعات سے کلام</small></span></a></li>
<li><a href="/rss.xml"><Icon name="rss" size={18} /><span>نئی تبدیلیاں<small>RSS: نئے ورژن اور ای بکس</small></span></a></li>
<li><a href="/privacy"><Icon name="lock" size={18} /><span>رازداری<small>ہم کیا محفوظ رکھتے ہیں</small></span></a></li>

View File

@ -89,6 +89,7 @@ const tagTarget = page.type === 'poem' ? `work/${poemId}` : `category/${page.cat
const bookmark = (c: number) => JSON.stringify({ kind: 'couplet', poemId, couplet: c });
const title = page.type === 'poem' ? page.poem.title : page.type === 'poet' ? page.poet.nickname : page.category.title;
import Icon from '../components/Icon.astro';
import TagsBox from '../components/TagsBox.astro';
---
<Base author={page.poet?.nickname} jsonld={page.type === 'poem' ? { '@context': 'https://schema.org', '@type': 'CreativeWork', name: page.poem.title, inLanguage: 'ur', author: { '@type': 'Person', name: page.poet.nickname }, isPartOf: crumbs.at(-1)?.title, url: Astro.url.href.split('?')[0] } : undefined} title={page.type === 'poem' ? `${page.poem.title} · ${page.poet.nickname}` : title} description={page.type === 'poet' ? page.poet.description?.slice(0, 160) : undefined}>
{page.type !== 'poet' && (
@ -105,14 +106,12 @@ import Icon from '../components/Icon.astro';
<div class="center"><button type="button" class="save" data-save={JSON.stringify({ kind: 'poet', poetId })} aria-pressed={String(!!saved.poet)} title="یہ شاعر محفوظ کریں">{label(saved.poet)}</button><button type="button" class="icon-btn small" data-reading-toggle title="مطالعے کا انداز: صرف متن" aria-label="مطالعے کا انداز"><Icon name="dict" size={17} /></button>{arrange && <> <form method="post" action={`/mod/order/${page.category.id}`} class="inline-form"><button class="mod-edit-btn"><Icon name="arrange" size={17} /> ترتیب دیں</button></form>
<a class="icon-btn small" href={`/mod/order/${page.category.id}`} title="ترتیب کا تاریخچہ" aria-label="ترتیب کا تاریخچہ"><Icon name="history" size={17} /></a></>}{tagCan && <> <form method="post" action={`/mod/tags/${tagTarget}`} class="inline-form"><button class="mod-edit-btn"><Icon name="tag" size={17} /> ٹیگ</button></form></>}</div>
<p class="muted">{years(page.poet)}</p>
<Tags tags={pageTags} />
{page.poet.description && <div class="intro">{page.poet.description}</div>}
</>
)}
{page.type === 'category' && (
<>
<h1 data-readable>{page.category.title}</h1>
<Tags tags={pageTags} />
<div class="center"><button type="button" class="save" data-save={JSON.stringify({ kind: 'category', categoryId: page.category.id })} aria-pressed={String(!!saved.category)} title="یہ کتاب یا باب محفوظ کریں">{label(saved.category)}</button><button type="button" class="icon-btn small" data-reading-toggle title="مطالعے کا انداز: صرف متن" aria-label="مطالعے کا انداز"><Icon name="dict" size={17} /></button>{arrange && <> <form method="post" action={`/mod/order/${page.category.id}`} class="inline-form"><button class="mod-edit-btn"><Icon name="arrange" size={17} /> ترتیب دیں</button></form>
<a class="icon-btn small" href={`/mod/order/${page.category.id}`} title="ترتیب کا تاریخچہ" aria-label="ترتیب کا تاریخچہ"><Icon name="history" size={17} /></a></>}{tagCan && <> <form method="post" action={`/mod/tags/${tagTarget}`} class="inline-form"><button class="mod-edit-btn"><Icon name="tag" size={17} /> ٹیگ</button></form></>}</div>
</>
@ -132,6 +131,7 @@ import Icon from '../components/Icon.astro';
<ol class="toc">{g.poems.map((p: any) => <li><a class={glyph(p.id)} href={p.url}>{p.title}</a></li>)}</ol>
</>
))}
{page.type !== 'poem' && <TagsBox tags={pageTags} />}
{page.type === 'poem' && (
<>
@ -146,7 +146,6 @@ import Icon from '../components/Icon.astro';
<div class="center"><button type="button" class="save" data-save={JSON.stringify({ kind: 'poem', poemId })} aria-pressed={String(!!saved.poem)} title="یہ کلام محفوظ کریں">{label(saved.poem)}</button><button type="button" class="icon-btn small" data-reading-toggle title="مطالعے کا انداز: صرف متن" aria-label="مطالعے کا انداز"><Icon name="dict" size={17} /></button>
{modCan.edit && <> <form method="post" action={`/mod/work/${poemId}`} class="inline-form"><button class="mod-edit-btn"><Icon name="edit" size={17} /> ترمیم کریں</button></form>
<a class="icon-btn small" href={`/mod/work/${poemId}`} title="تاریخچہ" aria-label="تاریخچہ"><Icon name="history" size={17} /></a></>}{tagCan && <> <form method="post" action={`/mod/tags/${tagTarget}`} class="inline-form"><button class="mod-edit-btn"><Icon name="tag" size={17} /> ٹیگ</button></form></>}</div>
<Tags tags={pageTags} />
{page.poem.radif != null && <p class="muted radif">{page.poem.radif ? `ردیف: ${page.poem.radif}` : 'غیر مردف'}</p>}
<div class="poem" data-cite={`${page.poet.nickname}، ${page.poem.title}`} data-poem={poemId}>
{blocks.map((b) => {
@ -168,7 +167,6 @@ import Icon from '../components/Icon.astro';
})}
</div>
</article>
<p class="muted hint">کسی لفظ کو منتخب کریں تو اس کے معنی اور تلفظ ساتھ نظر آئیں گے؛ کسی عبارت پر نوٹ بھی لکھ سکتے ہیں۔</p>
<div id="c-menu" class="c-menu" popover role="menu" aria-label="شعر">
<button type="button" role="menuitem" data-act="bm"><i class="g-bm" /><span>محفوظ کریں</span></button>
<button type="button" role="menuitem" data-act="nt"><i class="g-nt" /><span>نوٹ</span></button>
@ -191,6 +189,7 @@ import Icon from '../components/Icon.astro';
</form>
</dialog>
<script type="application/json" id="notes-data" set:html={JSON.stringify({ poemId, notes, phrases: saved.phrases, signedIn: !!token })} />
<TagsBox tags={pageTags} />
<nav class="poem-nav">
{page.prev && <a class="icon-btn" href={page.prev} rel="prev" title="پچھلا" aria-label="پچھلا"><Icon name="prev" /></a>}
{page.next && <a class="icon-btn" href={page.next} rel="next" title="اگلا" aria-label="اگلا"><Icon name="next" /></a>}

55
web/src/pages/help.astro Normal file
View File

@ -0,0 +1,55 @@
---
// How to use the site: each feature in a line or two, for readers (moderators have /mod/guide)
import Base from '../layouts/Base.astro';
import Icon from '../components/Icon.astro';
import { brand } from '../lib/brand';
const parts: [any, string, string[]][] = [
['search', 'تلاش', [
'اوپر کے خانے میں کوئی شعر، لفظ یا عبارت لکھیں: شاعر، کتابیں اور کلام الگ الگ ملیں گے، اور نتائج کو شاعر کے لحاظ سے محدود کر سکتے ہیں۔',
'اردو کی بورڈ نہ ہو تو «اب» دبا کر رومن حروف میں لکھیں (dil، ghazal)، یا کی بورڈ کا نشان دبا کر اسکرین والا اردو کی بورڈ کھولیں۔',
]],
['dict', 'لفظ کے معنی', [
'کلام میں کسی ایک لفظ کو منتخب کریں: ساتھ ہی اس کے معنی، تلفظ اور اصل (اردو، فارسی، عربی لغات سے) نظر آئیں گے۔',
'کوئی عبارت منتخب کریں تو ایک چھوٹا مینو کھلتا ہے: معنی، ذخیرۂ الفاظ، محفوظ کریں، نوٹ، تلاش، کاپی اور شیئر۔',
]],
['bookmark', 'شعر کے ساتھ والے نشان', [
'کسی شعر پر ماؤس لائیں تو اس کے نیچے بائیں طرف چار نشان آتے ہیں: محفوظ کریں، نوٹ، تصویر بنا کر بھیجیں، اور تصویر ڈاؤن لوڈ۔',
'فون پر شعر کو چھوئیں، پھر ⋯ دبائیں: یہی چاروں کام ایک مینو میں ملیں گے۔',
'تصویر میں شعر نستعلیق میں، شاعر کے نام اور دیوان کے نشان کے ساتھ بنتا ہے، واٹس ایپ یا انسٹاگرام پر بھیجنے کے لیے۔',
]],
['note', 'نوٹس', [
'کسی شعر یا منتخب عبارت پر اپنا نوٹ لکھیں، کسی بھی زبان میں۔ نوٹ محفوظ کرنے سے شعر محفوظ شدہ میں نہیں جاتا: دونوں الگ ہیں۔',
'آپ کے سب نوٹس «نوٹس» کے صفحے پر ہیں (اوپر کا نشان)، جہاں انھیں بدل یا ہٹا سکتے ہیں۔',
]],
['words', 'محفوظ شدہ اور ذخیرۂ الفاظ', [
'شاعر، کتابیں، کلام، اشعار، عبارتیں اور ای بکس کے صفحات «محفوظ شدہ» میں جمع ہوتے ہیں؛ پسندیدہ شعرا «پسندیدہ لکھاری» میں۔',
'جو الفاظ یاد رکھنے ہوں انھیں «ذخیرۂ الفاظ» میں ڈالیں: ہر لفظ اپنے شعر کے ساتھ رہتا ہے۔ ان سب کے لیے اکاؤنٹ چاہیے۔',
]],
['dict', 'مطالعے کا انداز', [
'کلام، کتاب یا شاعر کے صفحے پر کتاب کا نشان دبائیں: صرف متن، راستہ اور دیوان کا نشان رہ جاتے ہیں، بڑے حروف میں۔ اوپر ✕ سے واپس آئیں۔',
'براؤزر کا اپنا ریڈر (سفاری ریڈر، فائرفاکس ریڈر ویو) بھی کام کرتا ہے، اور پرنٹ کرنے پر صرف متن چھپتا ہے۔',
]],
['settings', 'خط اور رنگ', [
'اوپر کے ترتیبات والے نشان سے: نسخ یا نستعلیق، کئی رنگ، مشرقی (۱۲۳) یا مغربی (123) ہندسے، اور روشن، تاریک یا خودکار۔ آپ کی پسند یاد رہتی ہے۔',
]],
['upload', 'ای بکس', [
'ہر شاعر کے صفحے پر «ای بکس»: پی ڈی ایف دائیں سے بائیں صفحہ بہ صفحہ، ای پب اور سادہ متن۔ کسی صفحے کو بعد کے لیے محفوظ کر سکتے ہیں۔',
]],
['tag', 'ٹیگ اور نئی تبدیلیاں', [
'کلام موضوعات سے بھی ملتا ہے: ہر صفحے کے آخر میں «ٹیگ» کھولیں، یا ٹیگ کا صفحہ دیکھیں۔',
'نئے ورژن اور نئی ای بکس RSS میں آتی ہیں، کسی بھی فیڈ ریڈر میں۔',
]],
];
---
<Base title="استعمال کا طریقہ" description={`${brand.name} کی سہولتیں: تلاش، معنی، محفوظ، نوٹس، مطالعہ، ای بکس`}>
<h1>استعمال کا طریقہ</h1>
<p class="muted center">{brand.name} پر پڑھنے، ڈھونڈنے اور یاد رکھنے کی سب سہولتیں، مختصراً</p>
<div class="help">
{parts.map(([icon, title, lines]) => (
<section>
<h2><span class="help-icon" aria-hidden="true"><Icon name={icon} size={20} /></span>{title}</h2>
{lines.map((l) => <p>{l}</p>)}
</section>
))}
</div>
</Base>

View File

@ -912,3 +912,19 @@ p, li { text-wrap: pretty; }
.c-menu i { width: 17px; height: 17px; background-color: var(--text-muted); }
.c-menu .g-bm { --m: var(--bm-outline); } .c-menu [data-on] .g-bm { --m: var(--bm-filled); background-color: var(--active); }
.c-menu .g-nt { --m: var(--nt-outline); } .c-menu .g-sh { --m: var(--sh-mask); } .c-menu .g-dl { --m: var(--dl-mask); }
/* a page's tags, folded at the end of its content */
.tags-box { max-width: 760px; margin: 16px auto 10px; text-align: center; }
.tags-box > summary { display: inline-flex; align-items: center; gap: 6px; padding: 1px 14px; border: 1.5px solid var(--border); border-radius: var(--r-pill);
background: var(--surface-sunken); font: var(--fs-sm)/1.8 var(--font-ui); cursor: pointer; list-style: none; }
.tags-box > summary::-webkit-details-marker { display: none; }
.tags-box > summary::after { content: '⌄'; transition: transform .2s; }
.tags-box[open] > summary::after { transform: rotate(180deg); }
.tags-box > summary:hover { border-color: var(--active); color: var(--active); }
.tags-box .tag-chips { margin-top: 10px; }
/* how to use the site */
.help { max-width: 760px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
.help section { padding: 10px 16px 6px; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface-raised); }
.help h2 { display: flex; align-items: center; gap: 10px; text-align: start; font-size: var(--fs-lg); margin: 0 0 4px; }
.help h2::after { display: none; }
.help-icon { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--accent-soft); color: var(--accent); flex: none; }
.help p { margin: 0 0 8px; line-height: 2; }