شريط التنقّل
ترويسة مثبّتة روابطها HTML من الخادم، ويكتب جزء صغير واحد في المتصفح ارتفاعها في --tc-sticky-top.
split - الحجم لم يُقَس بعد
شريط التنقّل
split - الحجم لم يُقَس بعدترويسة مثبّتة روابطها HTML من الخادم، ويكتب جزء صغير واحد في المتصفح ارتفاعها في --tc-sticky-top.
جرّبه
sticky
current
الشيفرة
navbar.tsx
import { Button } from 'topclassui/button'
import { NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarRoot } from 'topclassui/navbar'
<NavbarRoot>
<NavbarBrand href="/">TopClass UI</NavbarBrand>
<NavbarLinks>
<NavbarLink href="/docs">Docs</NavbarLink>
<NavbarLink href="/components">Components</NavbarLink>
<NavbarLink href="/icons">Icons</NavbarLink>
</NavbarLinks>
<NavbarActions>
<Button render={<a href="/login" />}>Sign in</Button>
</NavbarActions>
</NavbarRoot>يكتب الشريط ارتفاعه في --tc-sticky-top، فيتوقف هدف الرابط #anchor تحته لا خلفه.
كل الحالات، بدون تمرير الفأرة
حالتانأمثلة
- خمسة أجزاء بأسماء مسطّحة، ولا يوجد
Navbarوحده:NavbarRoot(عنصر header) وNavbarBrandوNavbarLinks(عنصر nav) وNavbarLinkوNavbarActions. - في Next.js مرّر رابط الإطار عبر
render={<Link href="/docs" />}علىNavbarBrandأوNavbarLink. عنصرًا فقط، لا دالة. - مع
sticky={false}يمرّ الشريط مع الصفحة، ولا يرسل حينها أي JavaScript إلى المتصفح. - دون سكربت يبقى المتغير 0px. اكتب
:root { --tc-sticky-top: 3.75rem }في CSS لصف واحد، ويستبدله الشريط بالقيمة المقيسة. - شريط مثبّت واحد في الصفحة: شريطان يكتبان المتغير نفسه، فأعطِ الثاني
sticky={false}. - الصفحة التي تمرّر داخل صندوق من صنعك تحتاج
scroll-padding-top: var(--tc-sticky-top)على ذلك الصندوق. - على الشاشة الضيقة تمرّر الروابط أفقيًا داخل الشريط، وتنزل الإجراءات إلى صف ثانٍ. الصفحة نفسها لا تمرّر أفقيًا أبدًا.
basic
basic.tsx
import { Button } from 'topclassui/button'
import { NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarRoot } from 'topclassui/navbar'
/** The drawn bar: the brand, four links with the page being read marked, and one action.
* Each link is the anchor the part renders; a Next.js app passes render={<Link href="/docs" />}. */
export default function Demo() {
return (
<NavbarRoot>
<NavbarBrand href="/">TopClass UI</NavbarBrand>
<NavbarLinks>
<NavbarLink href="/docs" current>Docs</NavbarLink>
<NavbarLink href="/components">Components</NavbarLink>
<NavbarLink href="/icons">Icons</NavbarLink>
<NavbarLink href="/theming">Theming</NavbarLink>
</NavbarLinks>
<NavbarActions>
<Button render={<a href="/login" />}>Sign in</Button>
</NavbarActions>
</NavbarRoot>
)
}
with-search
with-search.tsx
import { AvatarFallback, AvatarRoot } from 'topclassui/avatar'
import { Input } from 'topclassui/input'
import { NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarRoot } from 'topclassui/navbar'
/** A search field and the account at the end of the bar. NavbarActions styles neither: the
* form is the caller's, and it works with no script because it is a plain GET. */
export default function Demo() {
return (
<NavbarRoot>
<NavbarBrand href="/">TopClass UI</NavbarBrand>
<NavbarLinks>
<NavbarLink href="/docs" current>Docs</NavbarLink>
<NavbarLink href="/components">Components</NavbarLink>
<NavbarLink href="/icons">Icons</NavbarLink>
</NavbarLinks>
<NavbarActions>
<form role="search" action="/search" className="min-w-0">
<Input type="search" name="q" size="sm" placeholder="Search" aria-label="Search the docs" />
</form>
<AvatarRoot size="sm" aria-label="Omar Abed">
<AvatarFallback>OA</AvatarFallback>
</AvatarRoot>
</NavbarActions>
</NavbarRoot>
)
}
many-links
many-links.tsx
import { githubLogo } from 'topclassui/icons/github-logo'
import { Button } from 'topclassui/button'
import { Svg } from 'topclassui/svg'
import { NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarRoot } from 'topclassui/navbar'
/** Six links and two actions: more than a phone has room for. The links scroll sideways
* inside the bar, and the page stays as wide as the screen. */
export default function Demo() {
return (
<NavbarRoot>
<NavbarBrand href="/">TopClass UI</NavbarBrand>
<NavbarLinks>
<NavbarLink href="/docs">Docs</NavbarLink>
<NavbarLink href="/components" current>Components</NavbarLink>
<NavbarLink href="/icons">Icons</NavbarLink>
<NavbarLink href="/theming">Theming</NavbarLink>
<NavbarLink href="/connectors">Connectors</NavbarLink>
<NavbarLink href="/changelog">Changelog</NavbarLink>
</NavbarLinks>
<NavbarActions>
<Button variant="ghost" aria-label="GitHub" render={<a href="https://github.com/TopClassUI/topclassui" />}>
<Svg icon={githubLogo} />
</Button>
<Button render={<a href="/login" />}>Sign in</Button>
</NavbarActions>
</NavbarRoot>
)
}
not-sticky
not-sticky.tsx
import { NavbarBrand, NavbarLink, NavbarLinks, NavbarRoot } from 'topclassui/navbar'
/** sticky={false}: the bar scrolls away with the page, sends no JavaScript to the browser
* and leaves --tc-sticky-top alone. */
export default function Demo() {
return (
<NavbarRoot sticky={false}>
<NavbarBrand href="/">TopClass UI</NavbarBrand>
<NavbarLinks>
<NavbarLink href="/docs">Docs</NavbarLink>
<NavbarLink href="/blog" current>Blog</NavbarLink>
<NavbarLink href="/changelog">Changelog</NavbarLink>
</NavbarLinks>
</NavbarRoot>
)
}
tall-page
Install
Go on to the next partUsage
Go on to the next partTheming
Go on to the next partQuestions
Go on to the next parttall-page.tsx
import { Button } from 'topclassui/button'
import { NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarRoot } from 'topclassui/navbar'
const SECTIONS = [
{ id: 'install', title: 'Install', next: 'usage' },
{ id: 'usage', title: 'Usage', next: 'theming' },
{ id: 'theming', title: 'Theming', next: 'questions' },
{ id: 'questions', title: 'Questions', next: 'install' },
] as const
/** A page longer than the screen under a sticky bar. Each link goes to a heading further
* down, which stops below the bar and not under it; so does a link that Tab scrolls to. */
export default function Demo() {
return (
<div>
<NavbarRoot>
<NavbarBrand href="#install">Handbook</NavbarBrand>
<NavbarLinks aria-label="On this page">
{SECTIONS.map((section) => (
<NavbarLink key={section.id} href={`#${section.id}`}>{section.title}</NavbarLink>
))}
</NavbarLinks>
<NavbarActions>
<Button variant="outline" render={<a href="/handbook/edit" />}>Edit this page</Button>
</NavbarActions>
</NavbarRoot>
{SECTIONS.map((section) => (
<section key={section.id} aria-labelledby={section.id} className="min-h-dvh px-5 pb-6">
<h2 id={section.id} className="text-base font-semibold text-body">{section.title}</h2>
<Button variant="link" render={<a href={`#${section.next}`} />}>Go on to the next part</Button>
</section>
))}
</div>
)
}
بالعربية، من اليمين إلى اليسار
rtl.tsx
import { Button } from 'topclassui/button'
import { ar } from 'topclassui/labels/ar'
import { NavbarActions, NavbarBrand, NavbarLink, NavbarLinks, NavbarRoot } from 'topclassui/navbar'
/** Arabic: the brand sits at the right, the action at the left, and the nav takes its name
* from the Arabic labels. No class of its own does it: every one is logical. */
export default function Demo() {
return (
<div dir="rtl" lang="ar">
<NavbarRoot>
<NavbarBrand href="/">توب كلاس</NavbarBrand>
<NavbarLinks labels={ar}>
<NavbarLink href="/docs" current>المستندات</NavbarLink>
<NavbarLink href="/components">المكوّنات</NavbarLink>
<NavbarLink href="/icons">الأيقونات</NavbarLink>
<NavbarLink href="/theming">السمات</NavbarLink>
</NavbarLinks>
<NavbarActions>
<Button render={<a href="/login" />}>تسجيل الدخول</Button>
</NavbarActions>
</NavbarRoot>
</div>
)
}
الخصائص
NavbarRoot
NavbarBrand
NavbarLinks
NavbarLink
NavbarActions
لوحة المفاتيح وإمكانية الوصول
currentعلى رابطNavbarLinkواحد يضعaria-current="page". يصبح الرابط أثقل وأغمق معًا، وتحته خط في وضع الألوان القسرية.NavbarLinksمعلم تنقّل اسمه «التنقل الرئيسي» منlabels.navbar.label. إن وُجد اثنان في الصفحة فأعطِ أحدهماaria-label، واسمك هو الغالب.- الرابط الذي عليه تركيز لوحة المفاتيح يظهر كاملًا داخل القائمة التي تمرّر.
من اليمين إلى اليسار
مع dir="rtl" يجلس الشعار على اليمين والإجراءات على اليسار. مرّر labels={ar} إلى NavbarLinks ليأخذ اسمه بالعربية.
الخادم والمتصفح
يُعرض على الخادم، والجزء التفاعلي مكوّن متصفح لا يُرسل إلا عند استخدامه.
الملفات: index.tsx, client.tsx.
على الشارة: split - الحجم لم يُقَس بعد.