Skip to content
    Style: Wireframe

    Components · Navigation

    Link list

    Links as rows with a line under the title and a chevron; the whole row is the target.

    30% of the 2,073 sites in The UI Index have a list (612 sites).

    Used in UI Pro: Services, Careers

    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/ui/r/link-list.json
    Astro
    npx shadcn@latest add https://www.themes.dev/ui/r/astro/link-list.json

    Or copy the files below into your project. They need clsx, tailwind-merge, and the themes.dev UI theme. The HTML needs only the compiled CSS.

    link-list.tsx
    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>
      );
    }
    link-list.variants.ts
    /** 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';