Tabs
לוחות בלשוניות עם ניווט מקלדת בין הלשוניות.
- דפדפנים
- Chrome 123+Firefox 121+Safari 17.5+
- שכבה
- 0
- גודל חבילה דחוסה
- 1.32 kB
- מגבלת פריסה כפויה
- 0 ms
- מגבלת Axe
- 0
- תואם SSR
- כן
- מבוסס על
- elements/choice
- חוזה מפורסם
- סביבת בדיקות
מגרש ניסויים
import { Tabs } from "@gunkin/uiify";
export default function Example() {
return (
<Tabs
className=""
id="account-tabs"
defaultValue="profile"
slotProps={{
item: { className: "" },
input: { className: "" },
trigger: { className: "" },
panel: { className: "" },
}}
items={[
{
value: "profile",
label: <span>Profile</span>,
panel: <>Profile settings</>,
},
{
value: "security",
label: <span>Security</span>,
panel: <>Security settings</>,
},
]}
/>
);
}/* Tabs — list of triggers with an active underline; content panels below.
Adapts to [data-orientation]; active state from [data-state="active"]. */
@layer components {
[data-uiify-tabs] > [data-part="item"] > [data-part="trigger"] {
padding-block: var(--space-sm);
padding-inline: var(--space-md);
border: none;
background: none;
color: var(--muted-foreground);
font-size: var(--text-sm);
line-height: var(--leading-normal);
font-weight: var(--weight-medium);
cursor: pointer;
border-block-end: 2px solid transparent;
margin-block-end: calc(-1 * var(--border-width));
transition: var(--transition-colors);
}
[data-uiify-tabs] > [data-part="item"] > [data-part="trigger"]:hover {
color: var(--foreground);
}
[data-uiify-tabs] > [data-part="item"] > [data-part="trigger"][data-state="active"] {
border-block-end-color: var(--primary);
color: var(--foreground);
}
/* Panel visibility is owned by @gunkin/uiify/components/behavior.css (radio :checked). */
[data-uiify-tabs] > [data-part="item"] {
display: contents;
}
[data-uiify-tabs] {
display: grid;
grid-template-rows: auto auto;
grid-auto-flow: column;
grid-auto-columns: max-content;
align-items: start;
gap: 0;
}
[data-uiify-tabs] > [data-part="item"] > input {
position: absolute;
inline-size: 1px;
block-size: 1px;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
[data-uiify-tabs] > [data-part="item"] > label {
display: inline-flex;
grid-row: 1;
padding-block: var(--space-sm);
padding-inline: var(--space-md);
border-block-end: 2px solid transparent;
color: var(--muted-foreground);
font-size: var(--text-sm);
line-height: var(--leading-normal);
font-weight: var(--weight-medium);
cursor: pointer;
}
[data-uiify-tabs] > [data-part="item"] > label:hover {
color: var(--foreground);
}
[data-uiify-tabs] > [data-part="item"]:has(> input:checked) > label {
border-block-end-color: var(--primary);
color: var(--foreground);
}
[data-uiify-tabs] > [data-part="item"] > input:focus-visible + label {
outline: none;
box-shadow: 0 0 0 var(--ring-width) color-mix(in oklch, var(--ring) 20%, transparent);
}
[data-uiify-tabs] > [data-part="item"] > [data-part="panel"] {
grid-column: 1 / -1;
grid-row: 2;
font-size: var(--text-sm);
line-height: var(--leading-normal);
}
/* Shared presence fade for the newly selected panel; the previous one leaves at once. */
@media (prefers-reduced-motion: no-preference) {
[data-uiify-tabs] > [data-part="item"] > [data-part="panel"] {
transition: opacity var(--duration-fast) var(--ease-out);
}
@starting-style {
[data-uiify-tabs] > [data-part="item"] > [data-part="control"]:checked ~ [data-part="panel"] {
opacity: 0;
}
}
}
}import { Tabs } from "@gunkin/uiify";
export default function Example() {
return (
<Tabs
className="
grid w-full max-w-[38rem] min-w-0 mx-auto [grid-template-rows:auto_auto] [align-items:start] gap-0
"
id="account-tabs"
defaultValue="profile"
slotProps={{
item: { className: "contents" },
input: {
className:
"peer/tabs absolute [inline-size:1px] [block-size:1px] [margin:-1px] " +
"overflow-hidden [clip-path:inset(50%)] whitespace-nowrap",
},
trigger: {
className:
"inline-flex [grid-row:1] py-sm px-md [border-block-end:2px_solid_transparent] " +
"text-muted-foreground text-sm [line-height:var(--leading-normal)] " +
"font-[number:var(--weight-medium)] cursor-pointer hover:text-foreground " +
"peer-checked/tabs:[border-block-end-color:var(--primary)] " +
"peer-checked/tabs:text-foreground peer-focus-visible/tabs:[outline:none] " +
"peer-focus-visible/tabs:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_20%,_transparent)]",
},
panel: {
className:
"[grid-column:1_/_-1] [grid-row:2] text-sm [line-height:var(--leading-normal)] " +
"motion-safe:[transition:opacity_var(--duration-fast)_var(--ease-out)] " +
"motion-safe:starting:peer-checked/tabs:opacity-0",
},
}}
items={[
{
value: "profile",
label: <span>Profile</span>,
panel: <>Profile settings</>,
},
{
value: "security",
label: <span>Security</span>,
panel: <>Security settings</>,
},
]}
/>
);
}API
Tabs
| מאפיין | טיפוס | ברירת מחדל | תיאור |
|---|---|---|---|
id* | string | — | מזהה בסיס המשמש למתן שם לקבוצת הרדיו ולקישור כל לשונית ללוח שלה. |
items* | TabsItem[] | — | הלשוניות להצגה, כל אחת עם ערך, תווית ולוח אופציונלי המוצג כשהלשונית נבחרת. |
defaultValue | string | — | ערך הלשונית המסומנת ב-HTML שנוצר בשרת, כך שהלשונית הראשונית נבחרת לפני הפעלת JavaScript כלשהו. |
orientation | "horizontal" | "vertical" | "horizontal" | הכיוון שבו שורת הלשוניות מסודרת. |
className | string | — | המחלקה המוחלת על אלמנט השורש. |
append | ReactNode | — | תוכן המוצג בסוף שורת הלשוניות, אחרי הלשוניות. |
slotProps | TabsSlotProps | — | מאפיינים מובנים לפריט, לקלט, לאלמנט הפתיחה, ללוח ולתוספת שנוצרים; ניתן למקד משבצות חוזרות בפריט לפי ערכו. |
מקלדת
| מקש | פעולה |
|---|---|
| ← / → | מעבר בין לשוניות (אופקית) |
| Home / End | לשונית ראשונה או אחרונה |
| Space / Enter | הפעלת לשונית |
נגישות
Tablist עם כפתורי רדיו מובנים, או דפוס tabindex נודד בגרסה המשופרת.
נקודות חיבור לעיצוב
data-state