List

Styled list with dash and numbered marker options.

API Reference

PropTypeDefault
as"ul" | "ol""ul"
marker"dash" | "numbered""dash"
subtlebooleanfalse
nestedbooleanfalse

Markers

Dash

default
  • First item
  • Second item
  • Third item
<List>
  <ListItem>First item</ListItem>
  <ListItem>Second item</ListItem>
  <ListItem>Third item</ListItem>
</List>

Numbered

  • First item
  • Second item
  • Third item
<List marker="numbered">
  <ListItem>First item</ListItem>
  <ListItem>Second item</ListItem>
  <ListItem>Third item</ListItem>
</List>

Subtle

  • Subtle first item
  • Subtle second item
  • Subtle third item
<List subtle>
  <ListItem>Subtle first item</ListItem>
  <ListItem>Subtle second item</ListItem>
  <ListItem>Subtle third item</ListItem>
</List>

Nested

  • Top level item
    • Nested child
    • Another nested child
  • Another top level item
<List>
  <ListItem>
    Top level item
    <List nested>
      <ListItem>Nested child</ListItem>
      <ListItem>Another nested child</ListItem>
    </List>
  </ListItem>
  <ListItem>Another top level item</ListItem>
</List>

Basic Usage

import { List, ListItem } from "@/ui";

<List>
  <ListItem>First</ListItem>
  <ListItem>Second</ListItem>
</List>

Source

src/ui/List.tsx
import { cn } from "@/utils";

const markerClass = {
  dash: "[&>li]:before:content-['—_']",
  numbered: "list-decimal pl-5",
} as const;

interface ListProps extends React.HTMLAttributes<
  HTMLUListElement | HTMLOListElement
> {
  as?: "ul" | "ol";
  marker?: "dash" | "numbered";
  subtle?: boolean;
  nested?: boolean;
  children: React.ReactNode;
}

export function List({
  as: Tag = "ul",
  marker = "dash",
  subtle = false,
  nested = false,
  className,
  children,
  ...props
}: ListProps) {
  return (
    <Tag
      className={cn(
        "space-y-2 text-sm",
        subtle ? "text-root-contrast-subtle" : "text-root-contrast",
        markerClass[marker],
        nested && "mt-2 pl-6",
        className,
      )}
      {...props}
    >
      {children}
    </Tag>
  );
}

interface ListItemProps extends React.HTMLAttributes<HTMLLIElement> {
  children: React.ReactNode;
}

export function ListItem({ className, children, ...props }: ListItemProps) {
  return (
    <li className={cn(className)} {...props}>
      {children}
    </li>
  );
}