Header
כותרת אתר מובנית עם שיפור גלילה אופציונלי.
- דפדפנים
- Chrome 123+Firefox 121+Safari 17.5+
- שכבה
- 0
- גודל חבילה דחוסה
- 141 B
- מגבלת פריסה כפויה
- 0 ms
- מגבלת Axe
- 0
- תואם SSR
- כן
- חוזה מפורסם
- סביבת בדיקות
מגרש ניסויים
import { Breadcrumb, Button, Header } from "@gunkin/uiify";
import { HeaderClient } from "@gunkin/uiify/components/header/client";
import {
ModalBody,
ModalClose,
ModalContent,
ModalHeader,
ModalTitle,
ModalTrigger,
} from "@gunkin/uiify/components/modal";
// Native by default. Replace Header.Root with HeaderClient to hide on scroll.
// HeaderClient defaults to sticky + hideOnScroll. For a panel, pass its scrollport id.
export default function Example() {
return (
<>
<Header.Root placement="sticky" className="">
<a href="/">Logo</a>
<nav aria-label="Workspace">
<a href="/overview" aria-current="page">
Overview
</a>
<a href="/projects">Projects</a>
<a href="/activity">Activity</a>
</nav>
<ModalTrigger target="logo-navigation" className="">
Menu
</ModalTrigger>
<ModalContent className="" id="logo-navigation" size="full" aria-labelledby="logo-navigation-title">
<ModalHeader>
<ModalTitle id="logo-navigation-title">Logo navigation</ModalTitle>
<ModalClose target="logo-navigation" aria-label="Close navigation">
×
</ModalClose>
</ModalHeader>
<ModalBody>
<nav aria-label="Mobile workspace">
<a href="/overview" aria-current="page">
Overview
</a>
<a href="/projects">Projects</a>
<a href="/activity">Activity</a>
<a href="/help">Help</a>
<Button as="a" href="/projects/new" variant="link" className="">
New project
</Button>
</nav>
</ModalBody>
</ModalContent>
</Header.Root>
<Breadcrumb.Root className="">
<Breadcrumb.List
items={[
{ key: "workspace", label: "Workspace", href: "/" },
{ key: "overview", label: "Overview", current: true },
]}
className=""
slotProps={{
item: { className: "" },
link: { className: "" },
}}
separator={<Breadcrumb.Separator className="" />}
/>
</Breadcrumb.Root>
</>
);
}
// Optional client entry; SSR remains visible and scroll behavior attaches after hydration.
export function ScrollHeader() {
return (
<HeaderClient className="">
<a href="/">Logo</a>
<nav aria-label="Workspace">
<a href="/overview" aria-current="page">
Overview
</a>
<a href="/projects">Projects</a>
<a href="/activity">Activity</a>
</nav>
</HeaderClient>
);
}/* ---- Header demo (homepage card + detail playground) ---- */
.docs-header-demo {
inline-size: 100%;
color: var(--foreground);
font-size: 0.82rem;
}
.docs-header-demo--playground {
display: flex;
flex-direction: column;
gap: calc(var(--docs-space-unit) * 2.5);
block-size: 100%;
min-block-size: 0;
}
.docs-header-demo__scroll-hint {
margin: 0;
color: var(--muted-foreground);
font-size: var(--docs-text-xs);
line-height: var(--docs-leading-snug);
}
.docs-header-demo__viewport {
container: header-demo / size;
flex: 1;
min-block-size: 0;
block-size: 22rem;
overflow: auto;
overscroll-behavior: contain;
border: 1px solid var(--border);
border-radius: var(--radius-xl);
background: var(--background);
}
.docs-header-demo__viewport--mobile {
inline-size: min(100%, 24rem);
margin-inline: auto;
}
.docs-header-demo__viewport--desktop {
inline-size: 100%;
}
.docs-playground__stage--header {
display: flex;
flex-direction: column;
min-block-size: 26rem;
block-size: 26rem;
padding: calc(var(--docs-space-unit) * 4);
overflow: hidden;
align-items: stretch;
}
.docs-header-demo [data-uiify-header] {
z-index: 2;
background: var(--card);
color: var(--card-foreground);
border-block-end: 1px solid var(--border);
}
.docs-header-demo__bar {
position: relative;
display: flex;
align-items: center;
gap: calc(var(--docs-space-unit) * 3);
min-block-size: 4rem;
padding-inline: calc(var(--docs-space-unit) * 4);
}
.docs-header-demo__brand {
color: inherit;
font-size: var(--docs-text-base);
font-weight: var(--docs-weight-bold);
text-decoration: none;
white-space: nowrap;
}
.docs-header-demo__desktop-actions,
.docs-header-demo__nav {
display: none;
}
.docs-header-demo__menu {
gap: 0;
padding: 0;
background: var(--card);
color: var(--card-foreground);
}
.docs-header-demo__menu-header {
display: grid;
grid-template-columns: 2.5rem 1fr 2.5rem;
align-items: center;
min-block-size: 4rem;
padding-block: env(safe-area-inset-top) 0;
padding-inline: env(safe-area-inset-left) env(safe-area-inset-right);
border-block-end: 1px solid var(--border);
}
.docs-header-demo__menu-title {
grid-column: 2;
margin: 0;
font-size: var(--docs-text-base);
font-weight: var(--docs-weight-bold);
}
.docs-header-demo__menu-header .docs-header-demo__close {
position: static;
grid-column: 3;
display: grid;
place-items: center;
inline-size: 2.5rem;
block-size: 2.5rem;
padding: 0;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--card);
color: inherit;
cursor: pointer;
font-size: var(--docs-text-2xl);
}
.docs-header-demo__actions {
display: flex;
align-items: center;
gap: calc(var(--docs-space-unit) * 2);
}
.docs-header-demo__cta {
display: inline-flex;
align-items: center;
justify-content: center;
min-block-size: 2.5rem;
padding-inline: calc(var(--docs-space-unit) * 3);
border: 1px solid var(--primary);
border-radius: var(--radius-md);
background: var(--primary);
color: var(--primary-foreground);
font: inherit;
font-weight: var(--docs-weight-semibold);
gap: calc(var(--docs-space-unit) * 1.5);
text-decoration: none;
}
.docs-header-demo__toggle {
margin-inline-start: auto;
background: var(--card);
color: inherit;
font: inherit;
display: flex;
align-items: center;
gap: calc(var(--docs-space-unit) * 2.5);
min-block-size: 2.5rem;
padding-inline: calc(var(--docs-space-unit) * 3);
border: 1px solid var(--border);
border-radius: var(--radius-md);
cursor: pointer;
list-style: none;
}
.docs-header-demo__card-navigation {
margin-inline-start: auto;
}
.docs-header-demo__card-menu {
position: absolute;
inset-block-start: 100%;
inset-inline: 0;
display: grid;
gap: calc(var(--docs-space-unit) * 2);
/* Reserve the header bar within the card viewport's 240px minimum height. */
max-block-size: calc(240px - 4rem);
overflow: auto;
overscroll-behavior: contain;
padding: calc(var(--docs-space-unit) * 2);
border-block-end: 1px solid var(--border);
background: var(--card);
color: var(--card-foreground);
}
.docs-header-demo__card-menu .docs-header-demo__mobile-nav a {
min-block-size: 2.25rem;
}
.docs-header-demo__mobile-content {
display: flex;
flex-direction: column;
gap: calc(var(--docs-space-unit) * 4);
padding-block: calc(var(--docs-space-unit) * 4)
max(calc(var(--docs-space-unit) * 4), env(safe-area-inset-bottom));
padding-inline: max(calc(var(--docs-space-unit) * 4), env(safe-area-inset-left))
max(calc(var(--docs-space-unit) * 4), env(safe-area-inset-right));
}
.docs-header-demo__mobile-nav {
display: flex;
flex-direction: column;
}
.docs-header-demo__mobile-nav a,
.docs-header-demo__nav a,
.docs-header-demo__help {
display: inline-flex;
align-items: center;
min-block-size: 2.5rem;
padding-inline: calc(var(--docs-space-unit) * 2);
color: inherit;
text-decoration: none;
}
.docs-header-demo__mobile-nav [aria-current="page"],
.docs-header-demo__nav [aria-current="page"] {
background: var(--accent);
color: var(--accent-foreground);
border-radius: var(--radius-sm);
font-weight: var(--docs-weight-semibold);
}
.docs-header-demo a {
text-decoration: none;
}
.docs-header-demo a:not(.docs-header-demo__cta):hover {
color: var(--primary);
}
.docs-header-demo__toggle:hover {
border-color: var(--ring);
}
.docs-header-demo :focus-visible {
outline: 2px solid var(--ring);
outline-offset: 3px;
}
.docs-header-demo__breadcrumb {
padding-block: calc(var(--docs-space-unit) * 3);
padding-inline: calc(var(--docs-space-unit) * 4);
font-size: var(--docs-text-xs);
}
.docs-header-demo__breadcrumb ol {
display: flex;
gap: calc(var(--docs-space-unit) * 2);
margin: 0;
padding: 0;
list-style: none;
}
.docs-header-demo__breadcrumb li {
display: flex;
gap: calc(var(--docs-space-unit) * 2);
}
.docs-header-demo__breadcrumb a {
color: var(--muted-foreground);
}
.docs-header-demo__workspace {
padding-inline: calc(var(--docs-space-unit) * 4);
padding-block-end: calc(var(--docs-space-unit) * 5);
}
.docs-header-demo__workspace h3 {
line-height: var(--docs-leading-tight);
margin-block: calc(var(--docs-space-unit) * 2);
font-size: var(--docs-text-lg);
font-weight: var(--docs-weight-semibold);
}
.docs-header-demo__workspace p {
margin: 0;
color: var(--muted-foreground);
}
.docs-header-demo__metrics {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: calc(var(--docs-space-unit) * 3);
margin-block-start: calc(var(--docs-space-unit) * 4);
}
.docs-header-demo__metrics div {
display: grid;
gap: calc(var(--docs-space-unit) * 1);
padding: calc(var(--docs-space-unit) * 3);
border: 1px solid var(--border);
border-radius: var(--radius-xs);
background: var(--card);
}
.docs-header-demo__metrics strong {
font-size: var(--docs-text-xl);
font-variant-numeric: tabular-nums;
}
.docs-header-demo__metrics span {
color: var(--muted-foreground);
font-size: var(--docs-text-xs);
}
.docs-header-demo__scroll-body {
display: grid;
gap: calc(var(--docs-space-unit) * 3);
padding-block-end: calc(var(--docs-space-unit) * 4);
padding-inline: calc(var(--docs-space-unit) * 4);
}
.docs-header-demo__scroll-section {
min-block-size: 8rem;
padding: calc(var(--docs-space-unit) * 4);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
background: var(--card);
color: var(--card-foreground);
scroll-margin-block-start: calc(var(--docs-space-unit) * 20);
}
.docs-header-demo__scroll-section h3 {
line-height: var(--docs-leading-tight);
margin-block: 0 calc(var(--docs-space-unit) * 1.5);
font-size: var(--docs-text-base);
}
.docs-header-demo__scroll-section p {
margin: 0;
color: var(--muted-foreground);
line-height: var(--docs-leading-normal);
}
.docs-header-demo--card .docs-header-demo__viewport {
inline-size: 100%;
block-size: 100%;
min-block-size: 240px;
border: none;
border-radius: 0;
}
@container header-demo (min-width: 40rem) {
.docs-header-demo__brand {
position: static;
translate: none;
}
.docs-header-demo__desktop-actions {
display: flex;
align-items: center;
gap: calc(var(--docs-space-unit) * 4);
margin-inline-start: auto;
}
.docs-header-demo__toggle,
.docs-header-demo__card-navigation {
display: none;
}
.docs-header-demo__nav {
display: flex;
gap: calc(var(--docs-space-unit) * 0.5);
}
}import { Breadcrumb, Button, Header } from "@gunkin/uiify";
import { HeaderClient } from "@gunkin/uiify/components/header/client";
import {
ModalBody,
ModalClose,
ModalContent,
ModalHeader,
ModalTitle,
ModalTrigger,
} from "@gunkin/uiify/components/modal";
// Native by default. Replace Header.Root with HeaderClient to hide on scroll.
// HeaderClient defaults to sticky + hideOnScroll. For a panel, pass its scrollport id.
export default function Example() {
return (
<>
<Header.Root
placement="sticky"
className="
grid gap-md w-max max-w-[min(28rem,calc(100vw_-_2_*_var(--space-lg)))] p-6 border border-border rounded-xl
bg-card text-card-foreground shadow-popover [&[popover]:not(:popover-open)]:hidden
motion-safe:[&[popover]]:[transition:var(--transition-presence)]
motion-safe:[&[popover]:not(:popover-open)]:opacity-0
motion-safe:[&[popover]:not(:popover-open)]:[scale:var(--presence-scale)]
motion-safe:starting:[&[popover]:popover-open]:opacity-0
motion-safe:starting:[&[popover]:popover-open]:[scale:var(--presence-scale)]
"
>
<a href="/">Logo</a>
<nav aria-label="Workspace">
<a href="/overview" aria-current="page">
Overview
</a>
<a href="/projects">Projects</a>
<a href="/activity">Activity</a>
</nav>
<ModalTrigger
target="logo-navigation"
className={
"relative isolate inline-flex items-center justify-center gap-1.5 min-h-10 min-w-10 px-5 py-px border-[l" +
"ength:var(--border-width)] border-solid border-transparent rounded-full bg-clip-padding text-base font-" +
"medium leading-6 no-underline cursor-pointer [transition:var(--transition-colors)] focus-visible:[outli" +
"ne:none] focus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_20%,_transpa" +
"rent)] disabled:opacity-50 disabled:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:curso" +
"r-not-allowed [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:[--uiify-button-rim:rgb(2" +
"55_255_255_/_20%)] [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:[--uiify-button-wash" +
":rgb(255_255_255_/_15%)] [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:border-transpa" +
"rent [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:bg-primary [&:is([data-selected],[" +
"aria-pressed=true],[aria-current=page])]:text-primary-foreground [:checked+&]:[--uiify-button-rim:rgb(2" +
"55_255_255_/_20%)] [:checked+&]:[--uiify-button-wash:rgb(255_255_255_/_15%)] [:checked+&]:border-transp" +
"arent [:checked+&]:bg-primary [:checked+&]:text-primary-foreground [@media_(any-hover:_hover)_and_(any-" +
"pointer:_fine)]:[&:is([data-selected],[aria-pressed=true],[aria-current=page]):hover:not(:disabled,[dat" +
"a-disabled])]:[background-color:color-mix(in_oklch,_var(--primary)_88%,_var(--primary-foreground))] [@m" +
"edia_(any-hover:_hover)_and_(any-pointer:_fine)]:[:checked:not(:disabled)+&:hover]:[background-color:co" +
"lor-mix(in_oklch,_var(--primary)_88%,_var(--primary-foreground))] bg-transparent text-foreground before" +
":content-none after:content-none hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(i" +
"n_oklch,_var(--foreground)_10%,_transparent)] active:[&:not(:disabled,[data-disabled])]:[background-col" +
"or:color-mix(in_oklch,_var(--foreground)_16%,_transparent)]"
}
>
Menu
</ModalTrigger>
<ModalContent
className={
"[&[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)] [&_[data-positioning=native]]:[--u" +
"iify-anchor-offset:var(--space-sm)] [&[popover]:popover-open:not([data-positioning=native])]:[margin:re" +
"vert] [&_[popover]:popover-open:not([data-positioning=native])]:[margin:revert] [&[data-part=content]]:" +
"m-auto [&[data-part=content]]:[inline-size:min(28rem,_calc(100vw_-_2_*_var(--space-lg)))] [&[data-part=" +
"content]]:p-xl [&[data-part=content]]:border-[length:var(--border-width)] [&[data-part=content]]:border" +
"-solid [&[data-part=content]]:border-border [&[data-part=content]]:rounded-xl [&[data-part=content]]:bg" +
"-popover [&[data-part=content]]:text-popover-foreground [&[data-part=content]]:shadow-modal [&[data-par" +
"t=content]::backdrop]:[background-color:rgb(0_0_0_/_45%)] motion-safe:[&[data-part=content]]:[transitio" +
"n:var(--transition-presence)] motion-safe:[&[data-part=content]::backdrop]:[transition:var(--transition" +
"-presence)] motion-safe:[&[data-part=content]:not([open])]:opacity-0 motion-safe:[&[data-part=content]:" +
"not([open])]:[scale:var(--presence-scale)] motion-safe:[&[data-part=content]:not([open])::backdrop]:opa" +
"city-0 motion-safe:starting:[&[data-part=content][open]]:opacity-0 motion-safe:starting:[&[data-part=co" +
"ntent][open]]:[scale:var(--presence-scale)] motion-safe:starting:[&[data-part=content][open]::backdrop]" +
":opacity-0 data-[part=content]:[--uiify-modal-inline-size:28rem] data-[part=content]:flex-col data-[par" +
"t=content]:gap-md data-[part=content]:[inline-size:min(var(--uiify-modal-inline-size),_calc(100vw_-_2_*" +
"_var(--space-lg)))] data-[part=content]:[max-block-size:calc(100dvh_-_2_*_var(--space-lg))] data-[part=" +
"content]:[&[open]]:flex data-[part=content]:data-[size=sm]:[--uiify-modal-inline-size:24rem] data-[part" +
"=content]:data-[size=lg]:[--uiify-modal-inline-size:40rem] data-[part=content]:data-[size=full]:inset-0" +
" data-[part=content]:data-[size=full]:m-0 data-[part=content]:data-[size=full]:[inline-size:100%] data-" +
"[part=content]:data-[size=full]:[block-size:100%] data-[part=content]:data-[size=full]:[max-inline-size" +
":none] data-[part=content]:data-[size=full]:[max-block-size:none] data-[part=content]:data-[size=full]:" +
"[padding-block:max(var(--space-xl),_env(safe-area-inset-top))_max(var(--space-xl),_env(safe-area-inset-" +
"bottom))] data-[part=content]:data-[size=full]:[padding-inline:max(var(--space-xl),_env(safe-area-inset" +
"-left))_max(var(--space-xl),_env(safe-area-inset-right))] data-[part=content]:data-[size=full]:border-0" +
" data-[part=content]:data-[size=full]:border-current data-[part=content]:data-[size=full]:border-none d" +
"ata-[part=content]:data-[size=full]:rounded-none [@media_(width_>=_40rem)]:data-[part=content]:data-[al" +
"ign=start]:[&:not([data-size=full])]:[margin-block:var(--space-xl)_auto] [@media_(width_<_40rem)]:data-" +
"[part=content]:[&:not([data-size=full])]:[inline-size:100%] [@media_(width_<_40rem)]:data-[part=content" +
"]:[&:not([data-size=full])]:[max-inline-size:100%] [@media_(width_<_40rem)]:data-[part=content]:[&:not(" +
"[data-size=full])]:[min-block-size:50dvh] [@media_(width_<_40rem)]:data-[part=content]:[&:not([data-siz" +
"e=full])]:[max-block-size:80dvh] [@media_(width_<_40rem)]:data-[part=content]:[&:not([data-size=full])]" +
":[margin-block:auto_0] [@media_(width_<_40rem)]:data-[part=content]:[&:not([data-size=full])]:[margin-i" +
"nline:0] [@media_(width_<_40rem)]:data-[part=content]:[&:not([data-size=full])]:[padding-block-end:calc" +
"(var(--space-xl)_+_env(safe-area-inset-bottom))] [@media_(width_<_40rem)]:data-[part=content]:[&:not([d" +
"ata-size=full])]:[border-block-end-width:0] [@media_(width_<_40rem)]:data-[part=content]:[&:not([data-s" +
"ize=full])]:[border-end-start-radius:0] [@media_(width_<_40rem)]:data-[part=content]:[&:not([data-size=" +
"full])]:[border-end-end-radius:0] [@media_(width_<_40rem)]:data-[part=content]:[&:not([data-size=full])" +
":has(>[data-uiify-modal][data-part=body])]:[touch-action:none] [@media_(width_<_40rem)]:data-[part=cont" +
"ent]:[&:not([data-size=full])_[data-uiify-modal][data-part=header]]:[touch-action:none] [@media_(width_" +
"<_40rem)]:data-[part=content]:[&:not([data-size=full])>[data-part=grabber]]:block [@media_(width_<_40re" +
"m)_and_(prefers-reduced-motion:_no-preference)]:data-[part=content]:[&:not([data-size=full])]:[transiti" +
"on:translate_var(--duration-fast)_var(--ease-out),_opacity_var(--duration-fast)_var(--ease-out),_displa" +
"y_var(--duration-fast)_allow-discrete,_overlay_var(--duration-fast)_allow-discrete] [@media_(width_<_40" +
"rem)_and_(prefers-reduced-motion:_no-preference)]:data-[part=content]:[&:not([data-size=full],[open])]:" +
"[translate:0_100%] [@media_(width_<_40rem)_and_(prefers-reduced-motion:_no-preference)]:data-[part=cont" +
"ent]:[&:not([data-size=full],[open])]:[scale:1] [@media_(width_<_40rem)_and_(prefers-reduced-motion:_no" +
"-preference)]:starting:data-[part=content]:[&:not([data-size=full])[open]]:[translate:0_100%] [@media_(" +
"width_<_40rem)_and_(prefers-reduced-motion:_no-preference)]:starting:data-[part=content]:[&:not([data-s" +
"ize=full])[open]]:[scale:1] data-[part=content]:data-[dragging]:[&[open]:not([data-size=full])]:[transi" +
"tion:none] data-[part=content]:data-[dragging]:[&[open]:not([data-size=full])]:[translate:0_var(--uiify" +
"-sheet-offset,_0)] data-[part=content]:data-[backdrop=blur]:backdrop:[backdrop-filter:blur(4px)] data-[" +
"part=content]:data-[backdrop=none]:backdrop:bg-transparent [&[data-part=content]_[data-uiify-modal][dat" +
"a-part=content]::backdrop]:bg-transparent [&[data-part=content]_[data-uiify-modal][data-part=content]::" +
"backdrop]:[backdrop-filter:none] data-[part=content]:[&:has([data-uiify-modal][data-part=content]:modal" +
")]:[filter:brightness(0.9)] [@media_(width_>=_40rem)]:data-[part=content]:[&:has([data-uiify-modal][dat" +
"a-part=content]:modal)]:[scale:0.97]"
}
id="logo-navigation"
size="full"
aria-labelledby="logo-navigation-title"
>
<ModalHeader>
<ModalTitle id="logo-navigation-title">Logo navigation</ModalTitle>
<ModalClose target="logo-navigation" aria-label="Close navigation">
×
</ModalClose>
</ModalHeader>
<ModalBody>
<nav aria-label="Mobile workspace">
<a href="/overview" aria-current="page">
Overview
</a>
<a href="/projects">Projects</a>
<a href="/activity">Activity</a>
<a href="/help">Help</a>
<Button
as="a"
href="/projects/new"
variant="link"
className={
"relative isolate inline-flex items-center justify-center gap-1.5 min-h-10 py-px border-transparen" +
"t bg-clip-padding text-base font-medium leading-6 cursor-pointer [transition:var(--transition-col" +
"ors)] focus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_20%,_tran" +
"sparent)] disabled:opacity-50 disabled:cursor-not-allowed data-[disabled]:opacity-50 data-[disabl" +
"ed]:cursor-not-allowed [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:[--uiify-b" +
"utton-rim:rgb(255_255_255_/_20%)] [&:is([data-selected],[aria-pressed=true],[aria-current=page])]" +
":[--uiify-button-wash:rgb(255_255_255_/_15%)] [&:is([data-selected],[aria-pressed=true],[aria-cur" +
"rent=page])]:border-transparent [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:b" +
"g-primary [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:text-primary-foreground" +
" [:checked+&]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [:checked+&]:[--uiify-button-wash:rgb(2" +
"55_255_255_/_15%)] [:checked+&]:border-transparent [:checked+&]:bg-primary [:checked+&]:text-prim" +
"ary-foreground [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&:is([data-selected],[aria-pr" +
"essed=true],[aria-current=page]):hover:not(:disabled,[data-disabled])]:[background-color:color-mi" +
"x(in_oklch,_var(--primary)_88%,_var(--primary-foreground))] [@media_(any-hover:_hover)_and_(any-p" +
"ointer:_fine)]:[:checked:not(:disabled)+&:hover]:[background-color:color-mix(in_oklch,_var(--prim" +
"ary)_88%,_var(--primary-foreground))] min-w-0 px-0 border-0 border-none rounded-none bg-transpare" +
"nt text-primary underline [text-underline-offset:0.2em] before:content-none after:content-none [&" +
":is(a)]:underline-offset-4 hover:bg-transparent focus-visible:[outline:2px_solid_var(--ring)] foc" +
"us-visible:[outline-offset:3px]"
}
>
New project
</Button>
</nav>
</ModalBody>
</ModalContent>
</Header.Root>
<Breadcrumb.Root className="">
<Breadcrumb.List
items={[
{ key: "workspace", label: "Workspace", href: "/" },
{ key: "overview", label: "Overview", current: true },
]}
className="flex flex-wrap items-center [gap:0.5rem] list-none p-0 m-0"
slotProps={{
item: { className: "flex items-center [gap:0.5rem]" },
link: {
className:
"text-primary no-underline hover:underline data-[current]:text-foreground " +
"data-[current]:font-semibold",
},
}}
separator={<Breadcrumb.Separator className="text-muted-foreground" />}
/>
</Breadcrumb.Root>
</>
);
}
// Optional client entry; SSR remains visible and scroll behavior attaches after hydration.
export function ScrollHeader() {
return (
<HeaderClient
className="
grid gap-md w-max max-w-[min(28rem,calc(100vw_-_2_*_var(--space-lg)))] p-6 border border-border rounded-xl
bg-card text-card-foreground shadow-popover [&[popover]:not(:popover-open)]:hidden
motion-safe:[&[popover]]:[transition:var(--transition-presence)]
motion-safe:[&[popover]:not(:popover-open)]:opacity-0
motion-safe:[&[popover]:not(:popover-open)]:[scale:var(--presence-scale)]
motion-safe:starting:[&[popover]:popover-open]:opacity-0
motion-safe:starting:[&[popover]:popover-open]:[scale:var(--presence-scale)]
"
>
<a href="/">Logo</a>
<nav aria-label="Workspace">
<a href="/overview" aria-current="page">
Overview
</a>
<a href="/projects">Projects</a>
<a href="/activity">Activity</a>
</nav>
</HeaderClient>
);
}API
Header.Root
| מאפיין | טיפוס | ברירת מחדל | תיאור |
|---|---|---|---|
placement | "static" | "sticky" | "static" | מיקום מובנה של הכותרת העליונה הסמנטית. מיקום נצמד נשאר בתוך מכל הגלילה הקרוב ביותר. |
ref | Ref<HTMLElement> | — | ה-ref המועבר לאלמנט הכותרת העליונה המובנה. |
HeaderClient
| מאפיין | טיפוס | ברירת מחדל | תיאור |
|---|---|---|---|
placement | "static" | "sticky" | "sticky" | מיקום סטטי משבית הסתרה. ברירת המחדל של Root המובנה היא static. |
hideOnScroll | boolean | true | הסתרה לאחר גלילה ממושכת מטה מעבר לגובה Header; חשיפה בגלילה מעלה או בראש העמוד. |
scrollTarget | string | — | מזהה אלמנט אזור הגלילה. כשהוא מושמט, נעשה שימוש בחלון שאליו הוא שייך. יעד שאינו נמצא משאיר את Header גלוי ללא מעבר לחלון כחלופה. |
ref | Ref<HTMLElement> | — | ה-ref המועבר לאותה כותרת עליונה מובנית; המאפיינים המובנים, className, style והאירועים נשמרים. |
מקלדת
| מקש | פעולה |
|---|---|
| Tab | מעבר בין קישורים לפעולות; מיקוד בתוך HeaderClient חושף אותו |
| Enter / Space | פתיחת Modal המובנה שהורכב, באמצעות המפעיל שלו |
| Escape | סגירת Modal של הניווט והחזרת המיקוד למפעיל שלו |
נגישות
Header.Root מרנדר <header> סמנטי ללא JavaScript בצד הלקוח; HeaderClient מוסיף הסתרה בגלילה. שניהם גלויים לפני הידרציה. מיקוד פנימי, או רכיב צאצא פתוח מסוג מודאל, חלונית קופצת או אזור חשיפה, משאירים אותו גלוי; תנועה מופחתת מסירה את ההחלקה. בנו ניווט לנייד מחלקי Modal עם מזהים ייחודיים. תנו תוויות לאלמנטי nav, סמנו את הקישור הנוכחי ב-aria-current וסגרו את תיבת הדו-שיח לפני ניווט למקטע.
נקודות חיבור לעיצוב
data-uiify-headerdata-placement="static|sticky"data-state="top|visible|hidden" (HeaderClient only)