Components
Base Components
List View
List item component with multiple layout variants and optional background. Use for rows with icon, title, secondary text, and value.
Example
List view renders rows with optional icon, title, secondary info, and value. UseList as a wrapper that takes list view components (e.g. ListItem children). Choose a variant for the layout and set withBackground for the optional rounded background.
Variants
TitleSecondary info
ValueTitleSecondary info
ValueTitle
ValueTitle
ValueValue
With background
TitleSecondary info
ValueTitleSecondary info
ValueTitle
ValueTitle
ValueValue
Installation
Install the following dependencies:
npm install class-variance-authorityCreate a list-view.tsx file and paste the following code into it.
"use client"import * as React from "react"import { cva, type VariantProps } from "class-variance-authority"import { cn } from "@/lib/utils"const listItemVariants = cva( "flex w-full min-w-0 gap-3 border-b border-border py-2.5 text-left last:border-b-0", { variants: { variant: { iconTitleSecondaryValue: "items-start", titleSecondaryValue: "items-start", iconTitleValue: "items-center", titleValue: "items-center", valueOnly: "items-center", }, withBackground: { true: "rounded-lg bg-[#F9F6F1] px-3 dark:bg-muted/50", false: "", }, }, defaultVariants: { variant: "iconTitleSecondaryValue", withBackground: false, }, })export interface ListItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, VariantProps<typeof listItemVariants> { icon?: React.ReactNode title?: React.ReactNode secondary?: React.ReactNode value?: React.ReactNode asChild?: boolean}const ListItem = React.forwardRef<HTMLDivElement, ListItemProps>( ( { className, variant = "iconTitleSecondaryValue", withBackground = false, icon, title, secondary, value, children, ...props }, ref ) => { const showIcon = variant === "iconTitleSecondaryValue" || variant === "iconTitleValue" const showTitle = variant === "iconTitleSecondaryValue" || variant === "titleSecondaryValue" || variant === "iconTitleValue" || variant === "titleValue" const showSecondary = variant === "iconTitleSecondaryValue" || variant === "titleSecondaryValue" const showValue = variant === "iconTitleSecondaryValue" || variant === "titleSecondaryValue" || variant === "iconTitleValue" || variant === "titleValue" || variant === "valueOnly" const hasMainBlock = showTitle || showSecondary return ( <div ref={ref} data-slot="list-item" data-variant={variant} data-with-background={withBackground} className={cn(listItemVariants({ variant, withBackground }), className)} {...props} > {showIcon && icon != null && ( <span className="flex shrink-0 text-muted-foreground [&>svg]:size-5"> {icon} </span> )} {hasMainBlock && ( <div className="flex min-w-0 flex-1 flex-col gap-0.5"> {showTitle && title != null && ( <span className="truncate text-sm font-medium text-foreground"> {title} </span> )} {showSecondary && secondary != null && ( <span className="truncate text-xs text-muted-foreground"> {secondary} </span> )} </div> )} {showValue && value != null && ( <span className={cn( "shrink-0 text-sm text-muted-foreground", hasMainBlock && "text-right" )} > {value} </span> )} {children} </div> ) })ListItem.displayName = "ListItem"function ListView({ className, ...props}: React.HTMLAttributes<HTMLDivElement>) { return ( <div data-slot="list-view" role="list" className={cn("flex flex-col", className)} {...props} /> )}ListView.displayName = "ListView"export interface ListProps extends React.HTMLAttributes<HTMLDivElement> { /** Optional header content (e.g. title) rendered above the list */ header?: React.ReactNode}const List = React.forwardRef<HTMLDivElement, ListProps>( ({ className, header, children, ...props }, ref) => { return ( <div ref={ref} data-slot="list" className={cn("flex flex-col", className)} {...props} > {header != null && ( <div className="mb-2 text-sm font-medium text-foreground"> {header} </div> )} <ListView>{children}</ListView> </div> ) })List.displayName = "List"export { List, ListItem, ListView, listItemVariants }Check the import paths to ensure they match your project setup.
Usage
UseList as the wrapper (optionally with a header) and pass ListItem children. You can also use ListView directly. Set variant and withBackground on each item as needed.
import { List, ListItem } from "@/components/ui/list-view";
import { FileText } from "lucide-react";
<List header="Documents">
<ListItem
variant="iconTitleSecondaryValue"
icon={<FileText />}
title="Report.pdf"
secondary="Last edited 2h ago"
value="12 KB"
/>
<ListItem
variant="iconTitleSecondaryValue"
icon={<FileText />}
title="Notes.txt"
secondary="Updated yesterday"
value="2 KB"
/>
</List>Variants
| Variant | Shows |
|---|---|
iconTitleSecondaryValue | Icon, title, secondary, value (default) |
titleSecondaryValue | Title, secondary, value |
iconTitleValue | Icon, title, value |
titleValue | Title, value |
valueOnly | Value only |
withBackground to true to add a rounded background (e.g. #F9F6F1 in light mode).
Examples
List wrapper
List wraps list view components and can show an optional header above the items.
Recent files
Report.pdfLast edited 2h ago
12 KBNotes.txtUpdated yesterday
2 KBDraft.docxCreated today
24 KBiconTitleSecondaryValue (full)
TitleSecondary info
ValueAnother rowExtra detail
123titleSecondaryValue
TitleSecondary info
ValueSecond itemMore details
ValueiconTitleValue
Title
ValueAnother
ValuetitleValue
Title
ValueSecond
ValuevalueOnly
Value
Value
With background (all variants)
TitleSecondary
ValueTitleSecondary
ValueTitle
ValueTitle
ValueValue
API Reference
List
Wrapper that renders an optionalheader and a ListView containing its children. Pass ListItem (or other list view components) as children.
| Prop | Type | Description |
|---|---|---|
header | React.ReactNode | Optional title/content above the list |
className | string | Applied to the wrapper div |
ListItem
iconReactNode
Default: -
titleReactNode
Default: -
secondaryReactNode
Default: -
valueReactNode
Default: -
asChildboolean
Default: -
variant"iconTitleSecondaryValue" | "titleSecondaryValue" | "iconTitleValue" | "titleValue" | "valueOnly" | null
Default: iconTitleSecondaryValue
withBackgroundboolean | null
Default: false
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | ReactNode | - | - |
| title | ReactNode | - | - |
| secondary | ReactNode | - | - |
| value | ReactNode | - | - |
| asChild | boolean | - | - |
| variant | "iconTitleSecondaryValue" | "titleSecondaryValue" | "iconTitleValue" | "titleValue" | "valueOnly" | null | iconTitleSecondaryValue | - |
| withBackground | boolean | null | false | - |
List, ListView, ListItem, listItemVariants.