Affix / Sticky
Preview: Default
Sticky element that knows when it's stuck (adds a shadow/border then), via a sentinel IntersectionObserver. Works inside any scroll container; `offset` is the sticky top in px.
Import
import { Affix } from '@marbleui/ui'Props
<Affix>
| Prop | Type | Default | Description |
|---|---|---|---|
| children *required | ReactNode | — | |
| className | string | — | |
| offset | number | 0 | |
| stuckClassName | string | 'shadow-md border-border' |
Usage notes
Sticky wrapper that knows when it’s stuck, for toolbars and section headers that should gain a shadow once content scrolls under them. If you don’t need the stuck styling, a plain sticky top-0 element is enough.
<Affix offset={64} className="bg-surface px-4 py-2">
<h2 className="text-sm font-semibold">March invoices</h2>
</Affix>
offsetis the sticky top in pixels, such as the height of a fixed header. While stuck it addsstuckClassName(defaultshadow-md border-border) and adata-stuckattribute.- It watches the nearest ancestor with
overflow-y: autoorscroll, or the viewport when there is none. - Like any
position: stickyelement, it only sticks within its parent, so place it directly in the scrolling content rather than in a short wrapper. - It renders a 1px sentinel element before itself, which takes up a slot in flex or grid layouts with
gap.
Example source · show· hide
import { Button } from '../button'
import { Affix } from './affix'
export const styles = {
Default: () => (
<div className="h-80 w-96 overflow-y-auto rounded-xl border border-border bg-bg">
<div className="p-4 text-sm text-fg-muted">Scroll down: the toolbar sticks and gains a shadow.</div>
<Affix className="mx-2 rounded-lg bg-surface"><div className="flex items-center gap-2 p-2"><span className="text-sm font-medium text-fg">3 selected</span><Button size="sm" variant="outline" className="ml-auto">Archive</Button><Button size="sm" variant="danger">Delete</Button></div></Affix>
<ul className="flex flex-col gap-2 p-4">{Array.from({ length: 20 }, (_, i) => <li key={i} className="rounded-lg border border-border bg-surface p-3 text-sm text-fg">Row {i + 1}</li>)}</ul>
</div>
),
}Source: packages/ui/src/affix/affix.tsx
Catalog
- Category
- utilities
- Priority
- Extra
- Primitive
- custom