List
Styled list with dash and numbered marker options.
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 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>- 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>import { List, ListItem } from "@/ui";
<List>
<ListItem>First</ListItem>
<ListItem>Second</ListItem>
</List>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>
);
}