app-ui / lists / feeds
With Multiple Item Types
03-with-multiple-item-types.jsx
import { Fragment } from 'react'
import { ChatBubbleLeftEllipsisIcon, TagIcon, UserCircleIcon } from '@heroicons/react/20/solid'
const activity = [
{
id: 1,
type: 'comment',
person: { name: 'Eduardo Benz', href: '#' },
imageUrl:
'https://images.unsplash.com/photo-1520785643438-5bf77931f493?ixlib=rb-=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=256&h=256&q=80',
comment:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Tincidunt nunc ipsum tempor purus vitae id. Morbi in vestibulum nec varius. Et diam cursus quis sed purus nam.',
date: '6d ago',
},
{
id: 2,
type: 'assignment',
person: { name: 'Hilary Mahy', href: '#' },
assigned: { name: 'Kristin Watson', href: '#' },
date: '2d ago',
},
{
id: 3,
type: 'tags',
person: { name: 'Hilary Mahy', href: '#' },
tags: [
{ name: 'Bug', href: '#', color: 'fill-red-500' },
{ name: 'Accessibility', href: '#', color: 'fill-indigo-500' },
],
date: '6h ago',
},
{
id: 4,
type: 'comment',
person: { name: 'Jason Meyers', href: '#' },
imageUrl:
'https://images.unsplash.com/photo-1531427186611-ecfd6d936c79?ixlib=rb-=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=256&h=256&q=80',
comment:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Tincidunt nunc ipsum tempor purus vitae id. Morbi in vestibulum nec varius. Et diam cursus quis sed purus nam. Scelerisque amet elit non sit ut tincidunt condimentum. Nisl ultrices eu venenatis diam.',
date: '2h ago',
},
]
function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}
export default function Example() {
return (
<div className="flow-root">
<ul role="list" className="-mb-8">
{activity.map((activityItem, activityItemIdx) => (
<li key={activityItem.id}>
<div className="relative pb-8">
{activityItemIdx !== activity.length - 1 ? (
<span
aria-hidden="true"
className="absolute top-5 left-5 -ml-px h-full w-0.5 bg-gray-200 dark:bg-white/10"
/>
) : null}
<div className="relative flex items-start space-x-3">
{activityItem.type === 'comment' ? (
<>
<div className="relative">
<img
alt=""
src={activityItem.imageUrl}
className="flex size-10 items-center justify-center rounded-full bg-gray-400 ring-8 ring-white outline -outline-offset-1 outline-black/5 dark:ring-gray-900 dark:outline-white/10"
/>
<span className="absolute -right-1 -bottom-0.5 rounded-tl bg-white px-0.5 py-px dark:bg-gray-900">
<ChatBubbleLeftEllipsisIcon aria-hidden="true" className="size-5 text-gray-400" />
</span>
</div>
<div className="min-w-0 flex-1">
<div>
<div className="text-sm">
<a href={activityItem.person.href} className="font-medium text-gray-900 dark:text-white">
{activityItem.person.name}
</a>
</div>
<p className="mt-0.5 text-sm text-gray-500 dark:text-gray-400">Commented {activityItem.date}</p>
</div>
<div className="mt-2 text-sm text-gray-700 dark:text-gray-200">
<p>{activityItem.comment}</p>
</div>
</div>
</>
) : activityItem.type === 'assignment' ? (
<>
<div>
<div className="relative px-1">
<div className="flex size-8 items-center justify-center rounded-full bg-gray-100 ring-8 ring-white dark:bg-gray-800 dark:ring-gray-900">
<UserCircleIcon aria-hidden="true" className="size-5 text-gray-500 dark:text-gray-400" />
</div>
</div>
</div>
<div className="min-w-0 flex-1 py-1.5">
<div className="text-sm text-gray-500 dark:text-gray-400">
<a href={activityItem.person.href} className="font-medium text-gray-900 dark:text-white">
{activityItem.person.name}
</a>{' '}
assigned{' '}
<a href={activityItem.assigned.href} className="font-medium text-gray-900 dark:text-white">
{activityItem.assigned.name}
</a>{' '}
<span className="whitespace-nowrap">{activityItem.date}</span>
</div>
</div>
</>
) : activityItem.type === 'tags' ? (
<>
<div>
<div className="relative px-1">
<div className="flex size-8 items-center justify-center rounded-full bg-gray-100 ring-8 ring-white dark:bg-gray-800 dark:ring-gray-900">
<TagIcon aria-hidden="true" className="size-5 text-gray-500 dark:text-gray-400" />
</div>
</div>
</div>
<div className="min-w-0 flex-1 py-0">
<div className="text-sm/8 text-gray-500 dark:text-gray-400">
<span className="mr-0.5">
<a href={activityItem.person.href} className="font-medium text-gray-900 dark:text-white">
{activityItem.person.name}
</a>{' '}
added tags
</span>{' '}
<span className="mr-0.5">
{activityItem.tags.map((tag) => (
<Fragment key={tag.name}>
<a
href={tag.href}
className="inline-flex items-center gap-x-1.5 rounded-full px-2 py-1 text-xs font-medium text-gray-900 inset-ring inset-ring-gray-200 dark:bg-white/5 dark:text-gray-100 dark:inset-ring-white/10"
>
<svg viewBox="0 0 6 6" aria-hidden="true" className={classNames(tag.color, 'size-1.5')}>
<circle r={3} cx={3} cy={3} />
</svg>
{tag.name}
</a>{' '}
</Fragment>
))}
</span>
<span className="whitespace-nowrap">{activityItem.date}</span>
</div>
</div>
</>
) : null}
</div>
</div>
</li>
))}
</ul>
</div>
)
}