Hub Link
betaA place to go: a spot icon or an icon, a title, and a line under it, washed on hover.
Preview
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the component.
npx shadcn@latest add @txbrendan/hub-link
Use it for
- The links on a hub or home page: Calendar, People, Payments, each with a line saying what is there.
- Use spot when the link names a place to go. Use icon, in iconTone, for a quieter list.
- Use tone when the line under the title says something needs you, like "Due today" in warning.
- The wash hangs 10px past each side, so the icon and words keep the column's edge. Leave the column that room.
- Pass href for a link. Without it, the hub link is a button, for onClick.
Avoid it for
- A row in a list. Use ListRow.
- A call to action. Use Button.
- Color alone for something that needs you. The line must say it in words.
Props
- title
Required. Where it goes, like "Calendar".
string
- description
The line under the title.
string
- spot
The icon for a 32px SpotIcon. It takes the place of icon.
ReactNode
- icon
A plain 20px icon, in iconTone.
ReactNode
- iconTone
The plain icon's color role. A spot is always the brand's.
"neutral" | "brand" | "danger" | "success" | "warning" · default "brand"
- tone
Colors the description. neutral is muted.
"neutral" | "brand" | "danger" | "success" | "warning" · default "neutral"
- href
Makes it a link. Without it, it is a button.
string
- onClick
Runs on press.
(event) => void
- className
Extra classes on the link. Later classes win.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| title | string | - | Required. Where it goes, like "Calendar". |
| description | string | - | The line under the title. |
| spot | ReactNode | - | The icon for a 32px SpotIcon. It takes the place of icon. |
| icon | ReactNode | - | A plain 20px icon, in iconTone. |
| iconTone | "neutral" | "brand" | "danger" | "success" | "warning" | "brand" | The plain icon's color role. A spot is always the brand's. |
| tone | "neutral" | "brand" | "danger" | "success" | "warning" | "neutral" | Colors the description. neutral is muted. |
| href | string | - | Makes it a link. Without it, it is a button. |
| onClick | (event) => void | - | Runs on press. |
| className | string | - | Extra classes on the link. Later classes win. |
Accessibility
- A link with href, and a button without it, named by its title and description.
- The spot and the icon are hidden from screen readers, since the title names the place.
- A toned description keeps its words, so color is never the only signal.
- The focus ring goes around the whole wash.
Examples
Two links, one with a warning
import { CalendarDays, CreditCard } from "lucide-react";
<nav className="flex flex-col gap-1 px-3">
<HubLink spot={<CalendarDays />} title="Calendar" description="Next: Sat 3 Oct · Demo day" href="/calendar" />
<HubLink spot={<CreditCard />} title="Payments" description="Due today" tone="warning" href="/payments" />
</nav>