List

The RhListContainer and RhListItem components are used to create sequential lists of text or images with primary and secondary actions represented by icons and text. These customizable components make it easy to build lists quickly and efficiently.

Usage

Once installed, you can import the RhListContainer component into your React application:

copy
import {RhListContainer,RhListItem} from "@rhythm-ui/react"

Then, you can use the RhListContainer component in your JSX code:

copy
function PrimaryText() {
  const CustomPrimary = () => (
    <RhGrid container className="text-red-500" alignItems="items-center">
      <RhGrid item className="mr-1">
        Tasks
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        <RhIcon
          icon="heroicons:clipboard-document-check-solid"
          className="text-lg"
        />
      </RhGrid>
    </RhGrid>
  );
  return (
    <RhListContainer className="w-80 m-auto border  dark:border-transparent">
      <RhListItem>
        <RhListItemText primary="Inbox" />
      </RhListItem>

      <RhListItem onClick={() => null}>
        <RhListItemText primary="Drafts" />
      </RhListItem>

      <RhListItem>
        <RhListItemText primary={<CustomPrimary />} />
      </RhListItem>
    </RhListContainer>
  );
}

List Container Props

headerReact.ReactNodeProvide header for the RhList
classNamestringUse this to override RhList's styles using custom classes
styleCSSPropertiesProvide inline styling
childrenReact.ReactNodeProvide children to RhList

List Item Props

childrenReact.ReactNodeProvide children to RhListItem
onClick(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => voidonClick handler of RhListItem
styleCSSPropertiesProvide inline styling
classNamestringUse this to override RhListItem's styles using custom classes

Secondary Text

The sequential lists of primary and secondary text

copy
function SecondaryText() {
  const CustomSecondary = () => (
    <RhGrid container alignItems="items-center">
      <RhGrid item container alignItems="items-center" className="mr-1">
        <RhIcon
          icon="heroicons:check-circle-solid"
          className="text-lg text-[#33b864]"
        />
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        Everthing Done
      </RhGrid>
    </RhGrid>
  );
  const CustomPrimary = () => (
    <RhGrid container className="text-red-500" alignItems="items-center">
      <RhGrid item className="mr-1">
        Tasks
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        <RhIcon
          icon="heroicons:clipboard-document-check-solid"
          className="text-lg"
        />
      </RhGrid>
    </RhGrid>
  );

  return (
    <RhListContainer className="w-80 m-auto border dark:border-transparent">
      <RhListItem>
        <RhListItemText primary="Inbox" secondary="7+ unread emails" />
      </RhListItem>

      <RhListItem onClick={() => null}>
        <RhListItemText primary="Drafts" secondary="Deleting soon..." />
      </RhListItem>

      <RhListItem>
        <RhListItemText
          primary={<CustomPrimary />}
          secondary={<CustomSecondary />}
        />
      </RhListItem>
    </RhListContainer>
  );
}

Primary Icon

The sequential lists of primary icons along with the primary and secondary text.

copy
function PrimaryIcon() {
  const CustomPrimary = () => (
    <RhGrid container className="text-red-500" alignItems="items-center">
      <RhGrid item className="mr-1">
        Tasks
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        <RhIcon
          icon="heroicons:clipboard-document-check-solid"
          className="text-lg"
        />
      </RhGrid>
    </RhGrid>
  );

  const CustomSecondary = () => (
    <RhGrid container alignItems="items-center">
      <RhGrid item container alignItems="items-center" className="mr-1">
        <RhIcon
          icon="heroicons:check-circle-solid"
          className="text-lg text-[#33b864]"
        />
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        Everthing Done
      </RhGrid>
    </RhGrid>
  );
  return (
    <RhListContainer className="w-80 m-auto border dark:border-transparent">
      <RhListItem>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-solid"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Inbox" secondary="7+ unread emails" />
      </RhListItem>

      <RhListItem onClick={() => null}>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-open"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Drafts" secondary="Deleting soon..." />
      </RhListItem>

      <RhListItem className="flex items-center">
        <RhListItemIcon variant="primary" align="start">
          <RhAvatar
            name="primary"
            type="image"
            size="sm"
            src="https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250"
          />
        </RhListItemIcon>

        <RhListItemText
          primary={<CustomPrimary />}
          secondary={<CustomSecondary />}
        />
      </RhListItem>
    </RhListContainer>
  );
}

Secondary Icon

The sequential lists of primary and secondary icons along with the primary and secondary text.

copy
function CustomSecondary() {
  const CustomPrimary = () => (
    <RhGrid container className="text-red-500" alignItems="items-center">
      <RhGrid item className="mr-1">
        Tasks
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        <RhIcon
          icon="heroicons:clipboard-document-check-solid"
          className="text-lg"
        />
      </RhGrid>
    </RhGrid>
  );

  const CustomSecondary = () => (
    <RhGrid container alignItems="items-center">
      <RhGrid item container alignItems="items-center" className="mr-1">
        <RhIcon
          icon="heroicons:check-circle-solid"
          className="text-lg text-[#33b864]"
        />
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        Everthing Done
      </RhGrid>
    </RhGrid>
  );

  return (
    <RhListContainer className="w-80 m-auto border dark:border-transparent">
      <RhListItem>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-solid"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Inbox" secondary="7+ unread emails" />
        <RhListItemIcon variant="secondary">
          <RhIcon icon="heroicons:star" className="text-lg text-gray-400" />
        </RhListItemIcon>
      </RhListItem>

      <RhListItem onClick={() => null}>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-open"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Drafts" secondary="Deleting soon..." />
        <RhListItemIcon variant="secondary">
          <RhIcon icon="heroicons:star" className="text-lg text-gray-400" />
        </RhListItemIcon>
      </RhListItem>

      <RhListItem className="flex items-center">
        <RhListItemIcon variant="primary" align="start">
          <RhAvatar
            name="primary"
            type="image"
            size="sm"
            src="https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250"
          />
        </RhListItemIcon>

        <RhListItemText
          primary={<CustomPrimary />}
          secondary={<CustomSecondary />}
        />
        <RhListItemIcon onClick={() => null} variant="secondary">
          <RhIcon
            icon="heroicons:trash-solid"
            className="text-lg text-gray-400"
          />
        </RhListItemIcon>
      </RhListItem>
    </RhListContainer>
  );
}

List Header

The sequential lists of primary and secondary text and icons with header

copy
function ListHeader() {
  const CustomPrimary = () => (
    <RhGrid container className="text-red-500" alignItems="items-center">
      <RhGrid item className="mr-1">
        Tasks
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        <RhIcon
          icon="heroicons:clipboard-document-check-solid"
          className="text-lg"
        />
      </RhGrid>
    </RhGrid>
  );

  const CustomSecondary = () => (
    <RhGrid container alignItems="items-center">
      <RhGrid item container alignItems="items-center" className="mr-1">
        <RhIcon
          icon="heroicons:check-circle-solid"
          className="text-lg text-[#33b864]"
        />
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        Everthing Done
      </RhGrid>
    </RhGrid>
  );
  const Header = () => (
    <div className="bg-black dark:bg-white dark:bg-opacity-60 dark:text-black text-white text-xl text-semibold px-4 py-4">
      Header
    </div>
  );
  return (
    <RhListContainer
      className="w-80 m-auto border dark:border-transparent"
      header={<Header />}
    >
      <RhListItem>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-solid"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Inbox" secondary="7+ unread emails" />
        <RhListItemIcon variant="secondary">
          <RhIcon icon="heroicons:star" className="text-lg text-gray-400" />
        </RhListItemIcon>
      </RhListItem>

      <RhListItem onClick={() => null}>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-open"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Drafts" secondary="Deleting soon..." />
        <RhListItemIcon variant="secondary">
          <RhIcon icon="heroicons:star" className="text-lg text-gray-400" />
        </RhListItemIcon>
      </RhListItem>

      <RhListItem className="flex items-center">
        <RhListItemIcon variant="primary" align="start">
          <RhAvatar
            name="primary"
            type="image"
            size="sm"
            src="https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250"
          />
        </RhListItemIcon>

        <RhListItemText
          primary={<CustomPrimary />}
          secondary={<CustomSecondary />}
        />
        <RhListItemIcon onClick={() => null} variant="secondary">
          <RhIcon
            icon="heroicons:trash-solid"
            className="text-lg text-gray-400"
          />
        </RhListItemIcon>
      </RhListItem>
    </RhListContainer>
  );
}

Nested List

Creating a sequential list of primary and secondary text and icons with a header, as well as primary and secondary actions, using dropdown menus.

copy
function NestedList() {
  const CustomPrimary = () => (
    <RhGrid container className="text-red-500" alignItems="items-center">
      <RhGrid item className="mr-1">
        Tasks
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        <RhIcon
          icon="heroicons:clipboard-document-check-solid"
          className="text-lg"
        />
      </RhGrid>
    </RhGrid>
  );

  const CustomSecondary = () => (
    <RhGrid container alignItems="items-center">
      <RhGrid item container alignItems="items-center" className="mr-1">
        <RhIcon
          icon="heroicons:check-circle-solid"
          className="text-lg text-[#33b864]"
        />
      </RhGrid>
      <RhGrid item container alignItems="items-center">
        Everthing Done
      </RhGrid>
    </RhGrid>
  );

  const Header = () => (
    <div className="bg-black dark:bg-white dark:bg-opacity-60 dark:text-black text-white text-xl text-semibold px-4 py-4">
      Header
    </div>
  );

  return (
    <RhListContainer
      className="w-80 m-auto border dark:border-transparent"
      header={<Header />}
    >
      <RhListItem>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-solid"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Inbox" secondary="7+ unread emails" />
        <RhListContainer>
          <RhListItem style={{ paddingLeft: "2rem" }}>
            <RhListItemIcon variant="primary">
              <RhIcon
                icon="akar-icons:circle"
                className="text-lg text-gray-400"
              />
            </RhListItemIcon>

            <RhListItemText primary="Item 1" />
          </RhListItem>
          <RhListItem style={{ paddingLeft: "2rem" }}>
            <RhListItemIcon variant="primary">
              <RhIcon
                icon="akar-icons:circle"
                className="text-lg text-gray-400"
              />
            </RhListItemIcon>

            <RhListItemText primary="Item 2" />
          </RhListItem>
        </RhListContainer>
      </RhListItem>

      <RhListItem onClick={() => null}>
        <RhListItemIcon variant="primary">
          <RhIcon
            icon="heroicons:envelope-open"
            className="text-2xl text-gray-400"
          />
        </RhListItemIcon>
        <RhListItemText primary="Drafts" secondary="Deleting soon..." />
        <RhListItemIcon variant="secondary">
          <RhIcon icon="heroicons:star" className="text-lg text-gray-400" />
        </RhListItemIcon>
      </RhListItem>

      <RhListItem className="flex items-center">
        <RhListItemIcon variant="primary" align="start">
          <RhAvatar
            name="primary"
            type="image"
            size="sm"
            src="https://www.gravatar.com/avatar/2c7d99fe281ecd3bcd65ab915bac6dd5?s=250"
          />
        </RhListItemIcon>

        <RhListItemText
          primary={<CustomPrimary />}
          secondary={<CustomSecondary />}
        />
        <RhListItemIcon onClick={() => null} variant="secondary">
          <RhIcon
            icon="heroicons:trash-solid"
            className="text-lg text-gray-400"
          />
        </RhListItemIcon>
      </RhListItem>
    </RhListContainer>
  );
}