Components · Navigation
Link list
Links as rows with a line under the title and a chevron; the whole row is the target.
29% of the 2,062 sites in The UI Index have a list (604 sites).
Both previews render the same markup; the HTML tab below is that markup without a framework.
Install
- React
- npx shadcn@
latest add https:// www.themes.dev/ caseroom/ r/ link-list.json - Astro
- npx shadcn@
latest add https:// www.themes.dev/ caseroom/ r/ astro/ link-list.json
Or copy the files below into your project. They need clsx, tailwind-merge, and the Caseroom theme. The HTML needs only the compiled CSS.
import { cn } from '@/lib/utils';
import { CHEVRON_PATH, linkList, type LinkItem } from './link-list.variants';
export type { LinkItem };
export interface LinkListProps {
items: LinkItem[];
/** Names the list for screen readers when there is no heading right above it. */
label?: string;
className?: string;
}
/** Links as rows with a chevron; the whole row is the target. */
export function LinkList({ items, label, className }: LinkListProps) {
return (
<ul aria-label={label} className={cn(linkList.root, className)}>
{items.map((it) => (
<li key={it.href + it.title}>
<a href={it.href} className={linkList.link}>
<span className={linkList.text}>
<span className={linkList.title}>{it.title}</span>
{it.description && <span className={linkList.description}>{it.description}</span>}
</span>
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className={linkList.chevron}><path d={CHEVRON_PATH} /></svg>
</a>
</li>
))}
</ul>
);
}/** A list of links as rows (the "chevron link list"): a title, an optional line under it, a chevron that moves on
* hover. Rows are separated by hairlines: it is a list of destinations, like table rows. The whole row is the
* target. */
export const linkList = {
root: 'm-0 w-full list-none divide-y rounded-lg border p-0',
link: 'group flex min-h-14 items-center gap-4 px-4 py-3 transition-colors first:rounded-t-lg last:rounded-b-lg hover:bg-accent active:bg-pressed',
text: 'min-w-0 flex-1',
title: 'block text-sm font-medium',
description: 'mt-0.5 block text-sm text-pretty text-muted-foreground',
chevron: 'size-4 shrink-0 text-muted-foreground transition-transform duration-150 group-hover:translate-x-0.5 group-hover:text-foreground',
};
export type LinkItem = { title: string; href: string; description?: string };
export const CHEVRON_PATH = 'M6 3.5l4.5 4.5L6 12.5';---
import { cn } from '@/lib/utils';
import { CHEVRON_PATH, linkList, type LinkItem } from './link-list.variants';
interface Props {
items: LinkItem[];
/** Names the list for screen readers when there is no heading right above it. */
label?: string;
class?: string;
}
const { items, label, class: className } = Astro.props;
---
<ul aria-label={label} class={cn(linkList.root, className)}>
{
items.map((it) => (
<li>
<a href={it.href} class={linkList.link}>
<span class={linkList.text}>
<span class={linkList.title}>{it.title}</span>
{it.description && <span class={linkList.description}>{it.description}</span>}
</span>
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class={linkList.chevron}><path d={CHEVRON_PATH} /></svg>
</a>
</li>
))
}
</ul>/** A list of links as rows (the "chevron link list"): a title, an optional line under it, a chevron that moves on
* hover. Rows are separated by hairlines: it is a list of destinations, like table rows. The whole row is the
* target. */
export const linkList = {
root: 'm-0 w-full list-none divide-y rounded-lg border p-0',
link: 'group flex min-h-14 items-center gap-4 px-4 py-3 transition-colors first:rounded-t-lg last:rounded-b-lg hover:bg-accent active:bg-pressed',
text: 'min-w-0 flex-1',
title: 'block text-sm font-medium',
description: 'mt-0.5 block text-sm text-pretty text-muted-foreground',
chevron: 'size-4 shrink-0 text-muted-foreground transition-transform duration-150 group-hover:translate-x-0.5 group-hover:text-foreground',
};
export type LinkItem = { title: string; href: string; description?: string };
export const CHEVRON_PATH = 'M6 3.5l4.5 4.5L6 12.5';<ul aria-label="Next steps" class="m-0 w-full list-none divide-y rounded-lg border p-0 max-w-md">
<li>
<a href="#domain" class="group flex min-h-14 items-center gap-4 px-4 py-3 transition-colors first:rounded-t-lg last:rounded-b-lg hover:bg-accent active:bg-pressed">
<span class="min-w-0 flex-1">
<span class="block text-sm font-medium">Connect a domain</span>
<span class="mt-0.5 block text-sm text-pretty text-muted-foreground">Point a CNAME at it.</span>
</span>
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="size-4 shrink-0 text-muted-foreground transition-transform duration-150 group-hover:translate-x-0.5 group-hover:text-foreground"><path d="M6 3.5l4.5 4.5L6 12.5"></path></svg>
</a>
</li>
<li>
<a href="#team" class="group flex min-h-14 items-center gap-4 px-4 py-3 transition-colors first:rounded-t-lg last:rounded-b-lg hover:bg-accent active:bg-pressed">
<span class="min-w-0 flex-1">
<span class="block text-sm font-medium">Invite your team</span>
<span class="mt-0.5 block text-sm text-pretty text-muted-foreground">Edit rights for everyone.</span>
</span>
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="size-4 shrink-0 text-muted-foreground transition-transform duration-150 group-hover:translate-x-0.5 group-hover:text-foreground"><path d="M6 3.5l4.5 4.5L6 12.5"></path></svg>
</a>
</li>
<li>
<a href="#cli" class="group flex min-h-14 items-center gap-4 px-4 py-3 transition-colors first:rounded-t-lg last:rounded-b-lg hover:bg-accent active:bg-pressed">
<span class="min-w-0 flex-1"><span class="block text-sm font-medium">Read the CLI reference</span></span>
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="size-4 shrink-0 text-muted-foreground transition-transform duration-150 group-hover:translate-x-0.5 group-hover:text-foreground"><path d="M6 3.5l4.5 4.5L6 12.5"></path></svg>
</a>
</li>
</ul>