@payfit/unity-components
Version:
116 lines (101 loc) • 4.03 kB
Markdown
# Unity navigation patterns
### Raw and integration map
| Base entry (`@payfit/unity-components`) | Integration (`@payfit/unity-components/integrations/tanstack-router`) | Prop |
| --------------------------------------- | --------------------------------------------------------------------- | --------------------------------------- |
| `RawLink` | `Link` | `href` (raw) / `to` (integration) |
| `RawNavItem` | `NavItem` | same |
| `RawBreadcrumbLink` | `BreadcrumbLink` | same |
| `RawPaginationLink` | `PaginationLink` | same |
| `RawTab` (+ `Tabs`) | `Tab` (+ `Tabs`) | route-aware `to` selects the active tab |
| `RawLinkButton` | `LinkButton` | same |
The integration components are produced via `createLink(RawLink)`. They render
exactly the same DOM as the raw versions but accept Tanstack's typed `to`,
`params`, `search`, and `preload` props.
### Compose Breadcrumbs / Pagination / Tabs
Each navigation composite has a strict child contract. Direct children of the
container must be the wrapper part — loose children are silently filtered.
```tsx
import {
Breadcrumb,
BreadcrumbLink,
Breadcrumbs,
Pagination,
PaginationContent,
PaginationItem,
RawPaginationLink,
RawTab,
TabList,
TabPanel,
Tabs,
} from '@payfit/unity-components'
export function CompositionExamples({
page,
pageCount,
onPageChange,
}: {
page: number
pageCount: number
onPageChange: (next: number, prev: number, dir: -1 | 1) => void
}) {
return (
<>
<Breadcrumbs>
<Breadcrumb>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</Breadcrumb>
<Breadcrumb>
<BreadcrumbLink href="/employees">Employees</BreadcrumbLink>
</Breadcrumb>
</Breadcrumbs>
<Pagination
currentPage={page}
pageCount={pageCount}
onPageChange={onPageChange}
>
<PaginationContent>
{Array.from({ length: pageCount }, (_, i) => i + 1).map(n => (
<PaginationItem key={n}>
<RawPaginationLink value={n} isActive={n === page}>
{n}
</RawPaginationLink>
</PaginationItem>
))}
</PaginationContent>
</Pagination>
<Tabs>
<TabList>
<RawTab id="active">Active</RawTab>
<RawTab id="archived">Archived</RawTab>
</TabList>
<TabPanel id="active">Active rows</TabPanel>
<TabPanel id="archived">Archived rows</TabPanel>
</Tabs>
</>
)
}
```
### RouterProvider for Raw\* in non-Tanstack apps
When you use `Raw*` components in an app that uses a different router (e.g.
React Router), wrap the app once in `RouterProvider` so `isActive` and
client-side navigation work. The Tanstack integration entry does NOT need
this — it reads from Tanstack hooks directly.
```tsx
import { RouterProvider } from '@payfit/unity-components'
import { matchPath, useLocation, useNavigate } from 'react-router-dom'
export function UnityRouterBridge({ children }: { children: React.ReactNode }) {
const navigate = useNavigate()
const location = useLocation()
return (
<RouterProvider
navigate={to => navigate(to)}
isActive={(to, isExact) =>
Boolean(
matchPath({ path: to, end: Boolean(isExact) }, location.pathname),
)
}
>
{children}
</RouterProvider>
)
}
```