Linking
Pass href and you're done. Roadie picks the right element, applies the right target / rel defaults, and routes through your app's configured client router via RoadieLinkProvider. Use onClick instead of href and you get a real <button> back. Everything that's link-shaped — Button, IconButton, Card, Breadcrumb.Link, Carousel.TitleLink, Tabs.Tab — speaks the same vocabulary.
Quick start
Mount RoadieLinkProvider once at your app root, alongside ThemeProvider. Pass next/link directly, or any wrapper that takes href + children.
Now every Roadie component that accepts href routes through Next's client navigation automatically — prefetch, scroll restoration, view transitions all preserved.
How href is resolved
The same rules apply to every link-bearing component. The decision is pure and SSR-safe — no hydration mismatches, no client-only checks.
| href shape | Renders as | Defaults applied |
|---|---|---|
undefined | <button> (or <div> for Card without onClick) | — |
/events/123, ./local, #section | Configured Link (or <a> if no provider) | — |
https://…, http://…, //… | <a> | target='_blank' rel='noopener noreferrer' |
mailto:, tel:, sms: | <a> | None — no target, no rel |
Override per call with external (boolean), target, or rel. Pass external={false} on an https://oztix.com.au/x URL to force internal routing through the provider; pass external on an internal redirect path to open in a new tab.
Components
Every link-bearing component below accepts the same href / external / target / rel props. The escape hatch column shows the API for cases where href isn't enough (custom elements, full render control).
| Component | Default element | Escape hatch |
|---|---|---|
Button, IconButton | <button> | render prop |
Card | <div> (or routed <a> when href is set) | render prop |
Breadcrumb.Link | <a> | render prop |
Carousel.TitleLink | <a> | render prop |
Tabs.Tab | <button> (or routed <a> when href is set) | render prop |
Examples
Internal navigation
<Button href='/events/123'>View event</Button><Card href='/events/123'>{/* whole-card link */}</Card><Breadcrumb.Link href='/events'>Events</Breadcrumb.Link>
External link
<Button href='https://stripe.com/docs'>Stripe docs</Button>// Renders <a target='_blank' rel='noopener noreferrer'>
Email / phone
<Button href='mailto:hello@oztix.com.au'>Email us</Button><IconButton aria-label='Call' href='tel:+61400000000'><PhoneIcon /></IconButton>
Force external / internal
Escape hatch — render
The href path covers the happy case. For full control over the rendered element, every Roadie component accepts the same render prop — element form, component form, or function form. The contract mirrors Base UI's render prop.
Element form
Function form
Receive the default props and return any element. Useful for state-aware rendering or attribute composition.
When you pass both href and render, render wins — Roadie's smart routing is silently disabled for that call. Button logs a one-shot dev warning so the conflict can't ship by accident. Pick one.
Legacy as prop: Card, Breadcrumb.Link, and Carousel.TitleLink previously exposed an as prop for polymorphism. It continues to work for back-compat but is @deprecated as of v2.6 and will be removed in v3.0.0 — migrate to render.
Link tabs — Tabs.Tab href
Tabs work as link-tabs out of the box — pass href on each Tabs.Tab and the rendered anchor participates in the tab list's roving tabindex group. Arrow keys still move focus across mixed button + anchor tabs.
Gotcha: pressing Enter on a focused link-tab triggers native browser navigation immediately. If you derive Tabs.value from controlled local state, you can see a brief flicker between selection and route change. Recommended pattern: derive value from the route itself (e.g. via usePathname()) so route is the source of truth.
Tracking actions
Roadie ships zero analytics code — tracking taxonomy is product-shaped (event names, page sections, vendor choices). The recommended pattern is a small consumer-app wrapper that reads currentTarget.href / aria-label off the rendered element, so a single <Tracked> works on top of every Roadie action.
Migration
LinkButton and LinkIconButton remain exported and continue to work, but new code should prefer Button / IconButton with href. They are scheduled for removal in v3.0.0.