UIPackage
Menu

Framework

Change language

Boilerplate repo

List

list ui
Boilerplate repo

Plain content list with `<ul>` / `<li>` semantics. List, ListItem, and ListSubheader for menu items, navigation lists, or any vertical sequence of small rows. Supports active/disabled states and polymorphic as props.

Also available for Vue ->

Installation

$ npx shadcn@latest add https://uipkge.dev/r/react/list.json
Named registry: npx shadcn@latest add @uipkge-react/list Installs to: components/ui/list/

Examples

Loading interactive previews…

Props

Name Type / Values Default Required
as 'ul' | 'ol' | 'div' optional

Files installed (2)

  • components/ui/list/list.tsx 2.6 kB
    import * as React from 'react'
    import { cn } from '@/lib/utils'
    
    export interface ListProps extends React.HTMLAttributes<HTMLElement> {
      as?: 'ul' | 'ol' | 'div'
    }
    
    const List = React.forwardRef<HTMLElement, ListProps>(({ as: Comp = 'ul', className, children, ...props }, ref) => (
      <Comp
        ref={ref as never}
        data-uipkge=""
        data-slot="list"
        className={cn('list-none space-y-1', className)}
        {...props}
      >
        {children}
      </Comp>
    ))
    List.displayName = 'List'
    
    export interface ListItemProps extends React.HTMLAttributes<HTMLElement> {
      as?: 'li' | 'div' | 'a'
      active?: boolean
      disabled?: boolean
      href?: string
    }
    
    const ListItem = React.forwardRef<HTMLElement, ListItemProps>(
      ({ as: Comp = 'li', active, disabled, className, children, onClick, href, ...props }, ref) => {
        // Only show pointer/hover affordances when the item is actually interactive.
        const isInteractive = !disabled && (Comp === 'a' || href != null || typeof onClick === 'function')
    
        return (
          <Comp
            ref={ref as never}
            {...props}
            data-uipkge=""
            data-slot="list-item"
            data-active={active ? '' : undefined}
            data-disabled={disabled ? '' : undefined}
            aria-disabled={disabled ? 'true' : undefined}
            aria-current={active ? 'true' : undefined}
            tabIndex={disabled ? -1 : undefined}
            href={Comp === 'a' && !disabled ? href : undefined}
            className={cn(
              'rounded-md px-2 py-1.5 text-sm transition-colors duration-200 select-none focus-visible:outline-none',
              isInteractive && 'hover:bg-accent focus-visible:bg-accent cursor-pointer',
              active && 'bg-accent text-accent-foreground',
              disabled && 'pointer-events-none cursor-not-allowed opacity-50',
              className,
            )}
            onClick={
              disabled
                ? (e: React.MouseEvent) => {
                    e.preventDefault()
                    e.stopPropagation()
                  }
                : onClick
            }
          >
            {children}
          </Comp>
        )
      },
    )
    ListItem.displayName = 'ListItem'
    
    export interface ListSubheaderProps extends React.LiHTMLAttributes<HTMLLIElement> {
      inset?: boolean
    }
    
    const ListSubheader = React.forwardRef<HTMLLIElement, ListSubheaderProps>(
      ({ inset, className, children, ...props }, ref) => (
        <li
          ref={ref}
          data-uipkge=""
          data-slot="list-subheader"
          className={cn(
            'text-muted-foreground px-2 py-1.5 text-xs font-semibold tracking-wide uppercase',
            inset && 'pl-8',
            className,
          )}
          {...props}
        >
          {children}
        </li>
      ),
    )
    ListSubheader.displayName = 'ListSubheader'
    
    export { List, ListItem, ListSubheader }
  • components/ui/list/index.ts 0.1 kB
    export { List, ListItem, ListSubheader, type ListProps, type ListItemProps, type ListSubheaderProps } from './list'

Raw manifest: https://uipkge.dev/r/react/list.json