Pinned item list
Pinned and unpinned sections with layout animation.
Preview & code
PINNED ITEMS
- API contract draft
Backend + web
- Design review
Thursday · 45 min
ALL ITEMS
- Sprint planning
Friday morning
- Release notes
v0.4.0
- Usability study
3 participant sessions
Installation
CLI
GFA Studio CLI — Coming soon
The `npx gfa-studio` installer is not published yet. Use Manual install below or download the artifact JSON.
https://ui.gkhn.dev/gfa/pinned-item-list.jsonManual
- Download the component source from https://ui.gkhn.dev/gfa/pinned-item-list.json (or copy from this repo: apps/web/src/blocks/gfa/pinned-item-list.tsx).
- Place it in your project (for example: ./src/blocks/gfa/pinned-item-list.tsx) and adjust imports/aliases.
- Ensure cn from @/lib/utils exists.
- Theme tokens and utilities should align with globals.css.
Dependencies
Uses Motion (motion/react, LazyMotion, m, LayoutGroup, AnimatePresence), Lucide (Pin, PinOff), and GFA Button. Pin order and cross-list moves are client state; reproduce in your stack if you drop React.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items | readonly PinnedListItem[] | — | Rows to render; each needs a stable string id. |
| defaultPinnedIds | readonly string[] | — | Uncontrolled mode: initial pinned ids (MRU order is applied internally). |
| pinnedIds | ReadonlySet<string> | readonly string[] | — | Controlled mode: current pinned set; keeps stack in sync via effect. |
| onPinnedChange | (pinned: Set<string>) => void | — | Fired after every pin change with the next pinned id set. |
| className | string | — | Optional wrapper classes on the root layout. |
| emptyLabel | string | "No items yet." | Copy when items is empty. |
| pinAriaLabel | (pinned: boolean) => string | — | Accessible name factory for the pin toggle (aria-label). |
| pinnedSectionTitle | string | "PINNED ITEMS" | Heading above the pinned list. |
| allSectionTitle | string | "ALL ITEMS" | Heading above the unpinned list. |
| pinnedEmptyLabel | string | — | Placeholder when nothing is pinned. |
| allEmptyLabel | string | — | Placeholder when every item is pinned. |
Note: if light/dark looks wrong and you are not sure where it is controlled, this block has no theme prop. Adjust site-wide CSS variables and dark-mode toggles—often class .dark or [data-theme="dark"] on the document root or an ancestor.