---
title: Reference
description: An inline mention that carries a hover card with the target's own summary.
source: https://adamjurek.com/components/reference
---

## Home


Prose that names `Showcase` and prose that links to it used to be two different
sentences the author had to choose between.

A reference is both: it reads inline like code, and hovering it raises a card
with the component's title, summary and package - so the reader decides whether
the mention is worth a page visit before paying for one. Entering the mention
follows the link.

<!-- ::start:showcase demo="reference" height="340" -->
<!-- ::end:showcase -->

## Why it is built this way

The card is server markup that a stylesheet reveals - no JavaScript positions
it and none opens it, so a page full of references costs nothing at hydration.
`:focus-within` keeps it reachable by keyboard, and on coarse pointers the
first tap opens and the second follows, which is native anchor behaviour left
alone.

`MarkdownView` applies these automatically: pass it a `references` map keyed by
the exact inline-code text to match, and every `` `Showcase` `` in a document
becomes a walkable mention with zero authoring changes. The map is supplied by
the host, so matching stays a lookup rather than entity extraction.

## What it does not do

It does not guess. A mention resolves because the host said it does, and an
unmatched mention stays ordinary inline code. It does not nest inside an
existing link - a hover card inside somebody's chosen anchor would be two
navigations fighting over one word.

> [!NOTE] Install commands are not written here
> Anything in `packages/ui/registry.ts` gets its TanStack and shadcn commands
> attached automatically, so there is nothing to keep in sync.


## Install

<!-- ::start:tabs -->

### TanStack

```shell
tanstack add https://adamjurek.com/r/tanstack/reference.json
```

### shadcn

```shell
pnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/reference.json
```

### pnpm

```shell
pnpm add @sushindustries/ui @sushindustries/atoms
```

<!-- ::end:tabs -->

## What you get

| | |
| --- | --- |
| Version | 0.1.0 |
| Category | content · Rendering |
| Files | `reference.tsx` |
| Dependencies | None |
| Tags | hover, link, docs |

> [!NOTE] No runtime dependencies
> It brings nothing with it beyond the stylesheet.

## Get Started


Install commands are on Home, attached from the registry - they are not written
here, because a second copy is a copy that goes stale. This tab starts after the
install worked.

## Use it

```tsx
import { Ref } from "@sushindustries/ui";

const showcase = {
	title: "Showcase",
	href: "/components/showcase",
	summary: "The live component at three widths, with source.",
	meta: "@sushindustries/ui",
};

export function Paragraph() {
	return (
		<p>
			Wrap any component in <Ref reference={showcase}>Showcase</Ref> to render
			it live.
		</p>
	);
}
```

## What you should see

`Showcase` inline as a link, styled like code. Hovering or focusing it raises
a card above the word with the reference's title, summary and meta line - the
card disappears the moment focus or the pointer leaves. Clicking the word
itself follows `reference.href`, same as any link.

## If nothing happens

The hover card needs no JavaScript to show, so if hovering does nothing the
usual cause is the reference itself: `Ref` renders exactly whatever
`reference` object it's handed, nothing is looked up or fetched, so a stale
or missing `title`/`summary` shows up as blank space in the card rather than
as an error.


## Guides


## Composing it

Every element inside is a `<span>`, on purpose - a reference lives inside a
paragraph, and a `<div>` inside a `<p>` is markup the HTML parser will hoist
out from under it. Nest `Ref` in running text, not as a block on its own.

## When not to use it

When the target isn't already known - `Ref` never fetches, it only displays
whatever `Reference` object it's handed. A mention that needs a network call
to resolve its title and summary belongs in a loader, not in this component.


## API


<!-- generated:api -->

## Props

| Prop | Type | Default | Does |
| --- | --- | --- | --- |
| `reference` | `Reference` | - | The target, resolved by the caller. The card is built from this, never fetched. |
| `children` | `ReactNode` | - |  |

<!-- /generated:api -->

## Notes

`reference` is never re-derived from `children` - the two are independent.
Passing `children` that don't match `reference.title` (calling it "the
pagination component" while linking a `Reference` titled "Pagination") is
legal and renders exactly that mismatch; nothing checks them against each
other.

Nesting a `Ref` inside another link, or inside another `Ref`, isn't
handled - anchors don't nest in valid HTML, and the browser's own parsing
behaviour decides which one wins, not this component.


## Examples


Examples are the tab where the component is shown doing a job, not
demonstrating a prop. The API tab already lists the props.

<!-- ::start:showcase demo="reference" height="420" -->
<!-- ::end:showcase -->

Press Compare. The frames are real viewports, so a layout that breaks at 320
breaks here too rather than in somebody's hands.

## In a page

```tsx
import { Ref, type ReferenceMap } from "@sushindustries/ui";

const references: ReferenceMap = {
	Pagination: {
		title: "Pagination",
		href: "/components/pagination",
		summary: "Pages as links, first and last always reachable.",
		meta: "@sushindustries/ui",
	},
};

export function ChangelogEntry() {
	return (
		<p>
			<Ref reference={references.Pagination}>Pagination</Ref> now clamps
			nothing, so a stale page number is the caller's problem again.
		</p>
	);
}
```

## What this example is not

The automatic version. `MarkdownView` matches every backtick-quoted mention
against a `references` map on its own; this example builds the same map and
wires one `Ref` by hand, which is what you'd do outside Markdown.
