List Group

Grouped list items with active, disabled, and link variants — ideal for menus, settings, and navigation lists.

Preview

Basic list group

import { ListGroup, ListGroupItem } from '@/registry/ui-kit/tailwind-list-group/react'

function Example() {
  return (
    <ListGroup>
      <ListGroupItem>Profile</ListGroupItem>
      <ListGroupItem active>Settings</ListGroupItem>
      <ListGroupItem>Notifications</ListGroupItem>
      <ListGroupItem disabled>Billing</ListGroupItem>
    </ListGroup>
  )
}

Component API

PropDefaultDescription
ListGroupRoot <ul> wrapper with border and divide styling.
ListGroupItemIndividual <li> item with optional active, disabled, and href props.
activefalseHighlights the item with an indigo active state.
disabledfalseReduces opacity and disables pointer events.
hrefRenders the item as an anchor link when provided.

Source Code

"use client";

import { forwardRef } from "react";

/* ── ListGroup ── */

const ListGroup = forwardRef<HTMLUListElement, React.HTMLAttributes<HTMLUListElement>>(
  ({ className = "", children, ...props }, ref) => (
    <ul
      ref={ref}
      className={`rounded-lg border border-zinc-200 divide-y divide-zinc-200 dark:border-zinc-800 dark:divide-zinc-800 ${className}`}
      {...props}
    >
      {children}
    </ul>
  )
);
ListGroup.displayName = "ListGroup";

/* ── ListGroupItem ── */

interface ListGroupItemProps extends React.LiHTMLAttributes<HTMLLIElement> {
  active?: boolean;
  disabled?: boolean;
  href?: string;
  className?: string;
  children: React.ReactNode;
}

const ListGroupItem = forwardRef<HTMLLIElement, ListGroupItemProps>(
  ({ active = false, disabled = false, href, className = "", children, ...props }, ref) => {
    const baseStyles = "px-4 py-3 text-sm text-zinc-900 dark:text-zinc-100";
    const activeStyles = active
      ? "bg-indigo-50 text-indigo-700 dark:bg-indigo-500/10 dark:text-indigo-300"
      : "";
    const disabledStyles = disabled ? "opacity-50 pointer-events-none" : "";
    const hoverStyles = !active && !disabled ? "hover:bg-zinc-50 dark:hover:bg-zinc-800/50" : "";

    const combinedClassName = `${baseStyles} ${activeStyles} ${disabledStyles} ${hoverStyles} ${className}`.trim();

    if (href && !disabled) {
      return (
        <li ref={ref} className={combinedClassName} {...props}>
          <a href={href} className="block -mx-4 -my-3 px-4 py-3">
            {children}
          </a>
        </li>
      );
    }

    return (
      <li ref={ref} className={combinedClassName} {...props}>
        {children}
      </li>
    );
  }
);
ListGroupItem.displayName = "ListGroupItem";

export { ListGroup, ListGroupItem };
export default ListGroup;