Tabs
عرض شاملimport { Tabs, TabsContent, TabsDivider, TabsList, TabsTrigger } from '@nili/ui';هذه صفحة العرض الشامل الخاصة بالمكتبة، معروضة حيّة. غيّر اللغة أو السمة من الأعلى وسَتتبعك.
أفقي
الوضع الافتراضي. تسمّي label مجموعة الألسنة — وبدونها يعلن قارئ الشاشة «قائمة ألسنة» فقط، وهو بلا فائدة في صفحة فيها ثلاث منها.
اسمك وصورتك ونبذتك.
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@nili/ui"
export function Example() {
return (
<Tabs defaultValue="profile">
<TabsList label={t('settings.label')}>
<TabsTrigger value="profile">{t('tab.profile')}</TabsTrigger>
<TabsTrigger value="security">{t('tab.security')}</TabsTrigger>
<TabsTrigger value="alerts">{t('tab.alerts')}</TabsTrigger>
</TabsList>
<TabsContent value="profile">Your name, photo and bio.</TabsContent>
<TabsContent value="security">Password and two-factor.</TabsContent>
<TabsContent value="alerts">What we email you about.</TabsContent>
</Tabs>
)
}الأيقونات والشارات
startIcon وendIcon منطقيان، فيتقدّمان في كلا الاتجاهين. ويقبل badge أي عنصر — رقمًا مجرّدًا أو Badge كاملة.
اسمك وصورتك ونبذتك.
import { Tabs, TabsList, TabsTrigger, TabsContent, Badge, Icon } from "@nili/ui"
import { RiUser3Line, RiNotification3Line } from "@remixicon/react"
export function Example() {
return (
<Tabs defaultValue="profile">
<TabsList label="Account settings">
<TabsTrigger value="profile" startIcon={<Icon icon={RiUser3Line} />}>
{t('tab.profile')}
</TabsTrigger>
<TabsTrigger
value="alerts"
startIcon={<Icon icon={RiNotification3Line} />}
badge={<Badge size="small" color="red">3</Badge>}
>
{t('tab.alerts')}
</TabsTrigger>
</TabsList>
…
</Tabs>
)
}التمدّد
يجعل stretch الألسنة تتقاسم العرض بدل أن تلتصق بتسمياتها — وهو مناسب لعنصر مجزّأ داخل بطاقة أو ورقة على الهاتف.
الأيام السبعة الماضية.
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@nili/ui"
export function Example() {
return (
<Tabs defaultValue="week">
<TabsList stretch label={t('range.label')}>
<TabsTrigger value="day">{t('range.day')}</TabsTrigger>
<TabsTrigger value="week">{t('range.week')}</TabsTrigger>
<TabsTrigger value="month">{t('range.month')}</TabsTrigger>
</TabsList>
…
</Tabs>
)
}رأسي
تنطبق appearance على الألسنة الرأسية فقط — فالقائمة الأفقية بلا محور نمط في التصميم. ويفصل TabsDivider مجموعة ألسنة بخط.
اسمك وصورتك ونبذتك.
اسمك وصورتك ونبذتك.
import { Tabs, TabsList, TabsTrigger, TabsContent, TabsDivider } from "@nili/ui"
export function Example() {
return (
<Tabs defaultValue="profile" orientation="vertical" appearance="card">
<TabsList label="Settings">
<TabsTrigger value="profile">{t('tab.profile')}</TabsTrigger>
<TabsTrigger value="security">{t('tab.security')}</TabsTrigger>
<TabsDivider />
<TabsTrigger value="usage">Usage</TabsTrigger>
</TabsList>
…
</Tabs>
)
}وضع التفعيل وkeepMounted
يختار automatic اللسان بمجرّد وصول التركيز إليه — وهو افتراضي ARIA، ومناسب حين تكون اللوحات رخيصة. واستخدم manual حين يحمّل اللسان بيانات: فالمرور بالأسهم على أربعة ألسنة يجب ألا يطلق أربعة طلبات. ويحفظ keepMounted موضع التمرير وحالة النموذج في لوحة مخفية.
تنقّل بالأسهم بين الألسنة — مع `manual` لا يتغيّر شيء حتى تضغط Enter أو المسافة.
تبقى هذه اللوحة مركّبة وهي مخفية.
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@nili/ui"
export function Example() {
return (
<Tabs defaultValue="overview" activationMode="manual">
<TabsList label={t('report.label')}>
<TabsTrigger value="overview">{t('report.overview')}</TabsTrigger>
<TabsTrigger value="chart">{t('report.chart')}</TabsTrigger>
</TabsList>
<TabsContent value="overview">Cheap to render.</TabsContent>
{/* expensive to rebuild — keep it mounted */}
<TabsContent value="chart" keepMounted>
<RevenueChart />
</TabsContent>
</Tabs>
)
}Tabs
extends Omit< ComponentPropsWithoutRef<'div'>, 'onChange' | 'defaultValue' >
باقي الخصائص
| الخاصيّة | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| value | string | — | Selected tab. Controlled. |
| defaultValue | string | ||
| onValueChange | (value: string) => void | — | |
| orientation | horizontal | vertical | horizontal | |
| appearance | card | list | list | Figma's `Style (Card | List)`. Vertical only — the horizontal tab menu has no style axis in the design. |
| activationMode | automatic | manual | automatic |
TabsContent
extends ComponentPropsWithoutRef<'div'>
باقي الخصائص
| الخاصيّة | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| value* | string | — | |
| keepMounted | boolean | false | Keep the panel mounted while hidden. Off by default: an unmounted panel cannot run effects or hold stale data. Turn it on to preserve scroll position, form state or a chart that is expensive to rebuild. |
TabsDivider
TabsList
extends ComponentPropsWithoutRef<'div'>
محاور التنويع — من تعريف cva للمكوّن
| الخاصيّة | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
| stretch | boolean | false | Tabs share the width instead of hugging their labels. |
| orientation | horizontal | vertical | horizontal | |
| appearance | card | list | list |
باقي الخصائص
| الخاصيّة | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| label | string | — | Accessible name for the tab set, e.g. `'Account settings'`. |
TabsTrigger
extends Omit< ComponentPropsWithoutRef<'button'>, 'value' >
محاور التنويع — من تعريف cva للمكوّن
| الخاصيّة | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
| orientation | horizontal | vertical | horizontal | |
| appearance | card | list | list | |
| selected | 'true' | 'false' | false |
باقي الخصائص
| الخاصيّة | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
| children | ReactNode | — | |
| disabled | boolean | — | |
| required | boolean | — | |
| readOnly | boolean | — | |
| value* | string | — | Ties the tab to its panel. Must be unique within one `Tabs`. |
| defaultValue | string | — | |
| name | string | — | |
| aria-label | string | — | |
| startIcon | ReactNode | — | Figma's "Left Icon". Logical, so it leads in both directions. |
| endIcon | ReactNode | — | Figma's "Right Icon". |
| badge | ReactNode | — | Figma's "Number" — a count or a `<Badge>`, after the label. |