app-ui / data-display / calendars
Borderless Side By Side
08-borderless-side-by-side.jsx
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/20/solid'
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
import { EllipsisVerticalIcon } from '@heroicons/react/24/outline'
const meetings = [
{
id: 1,
name: 'Leslie Alexander',
imageUrl:
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
start: '1:00 PM',
startDatetime: '2022-01-21T13:00',
end: '2:30 PM',
endDatetime: '2022-01-21T14:30',
},
{
id: 2,
name: 'Michael Foster',
imageUrl:
'https://images.unsplash.com/photo-1519244703995-f4e0f30006d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
start: '3:00 PM',
startDatetime: '2022-01-21T15:00',
end: '4:30 PM',
endDatetime: '2022-01-21T16:30',
},
{
id: 3,
name: 'Dries Vincent',
imageUrl:
'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
start: '5:00 PM',
startDatetime: '2022-01-21T17:00',
end: '6:30 PM',
endDatetime: '2022-01-21T18:30',
},
{
id: 4,
name: 'Lindsay Walton',
imageUrl:
'https://images.unsplash.com/photo-1517841905240-472988babdf9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
start: '7:00 PM',
startDatetime: '2022-01-21T19:00',
end: '8:30 PM',
endDatetime: '2022-01-21T20:30',
},
{
id: 5,
name: 'Courtney Henry',
imageUrl:
'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
start: '9:00 PM',
startDatetime: '2022-01-21T21:00',
end: '10:30 PM',
endDatetime: '2022-01-21T22:30',
},
]
const days = [
{ date: '2021-12-27' },
{ date: '2021-12-28' },
{ date: '2021-12-29' },
{ date: '2021-12-30' },
{ date: '2021-12-31' },
{ date: '2022-01-01', isCurrentMonth: true },
{ date: '2022-01-02', isCurrentMonth: true },
{ date: '2022-01-03', isCurrentMonth: true },
{ date: '2022-01-04', isCurrentMonth: true },
{ date: '2022-01-05', isCurrentMonth: true },
{ date: '2022-01-06', isCurrentMonth: true },
{ date: '2022-01-07', isCurrentMonth: true },
{ date: '2022-01-08', isCurrentMonth: true },
{ date: '2022-01-09', isCurrentMonth: true },
{ date: '2022-01-10', isCurrentMonth: true },
{ date: '2022-01-11', isCurrentMonth: true },
{ date: '2022-01-12', isCurrentMonth: true, isToday: true },
{ date: '2022-01-13', isCurrentMonth: true },
{ date: '2022-01-14', isCurrentMonth: true },
{ date: '2022-01-15', isCurrentMonth: true },
{ date: '2022-01-16', isCurrentMonth: true },
{ date: '2022-01-17', isCurrentMonth: true },
{ date: '2022-01-18', isCurrentMonth: true },
{ date: '2022-01-19', isCurrentMonth: true },
{ date: '2022-01-20', isCurrentMonth: true },
{ date: '2022-01-21', isCurrentMonth: true, isSelected: true },
{ date: '2022-01-22', isCurrentMonth: true },
{ date: '2022-01-23', isCurrentMonth: true },
{ date: '2022-01-24', isCurrentMonth: true },
{ date: '2022-01-25', isCurrentMonth: true },
{ date: '2022-01-26', isCurrentMonth: true },
{ date: '2022-01-27', isCurrentMonth: true },
{ date: '2022-01-28', isCurrentMonth: true },
{ date: '2022-01-29', isCurrentMonth: true },
{ date: '2022-01-30', isCurrentMonth: true },
{ date: '2022-01-31', isCurrentMonth: true },
{ date: '2022-02-01' },
{ date: '2022-02-02' },
{ date: '2022-02-03' },
{ date: '2022-02-04' },
{ date: '2022-02-05' },
{ date: '2022-02-06' },
]
export default function Example() {
return (
<div className="md:grid md:grid-cols-2 md:divide-x md:divide-gray-200 dark:md:divide-white/10">
<div className="md:pr-14">
<div className="flex items-center">
<h2 className="flex-auto text-sm font-semibold text-gray-900 dark:text-white">January 2022</h2>
<button
type="button"
className="-my-1.5 flex flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 dark:text-gray-400 dark:hover:text-white"
>
<span className="sr-only">Previous month</span>
<ChevronLeftIcon aria-hidden="true" className="size-5" />
</button>
<button
type="button"
className="-my-1.5 -mr-1.5 ml-2 flex flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 dark:text-gray-400 dark:hover:text-white"
>
<span className="sr-only">Next month</span>
<ChevronRightIcon aria-hidden="true" className="size-5" />
</button>
</div>
<div className="mt-10 grid grid-cols-7 text-center text-xs/6 text-gray-500 dark:text-gray-400">
<div>M</div>
<div>T</div>
<div>W</div>
<div>T</div>
<div>F</div>
<div>S</div>
<div>S</div>
</div>
<div className="mt-2 grid grid-cols-7 text-sm">
{days.map((day, dayIdx) => (
<div
key={day.date}
data-first-line={dayIdx <= 6 ? '' : undefined}
className="py-2 not-data-first-line:border-t not-data-first-line:border-gray-200 dark:not-data-first-line:border-white/10"
>
<button
type="button"
data-is-today={day.isToday ? '' : undefined}
data-is-selected={day.isSelected ? '' : undefined}
data-is-current-month={day.isCurrentMonth ? '' : undefined}
className="mx-auto flex size-8 items-center justify-center rounded-full not-data-is-selected:not-data-is-today:not-data-is-current-month:text-gray-400 not-data-is-selected:hover:bg-gray-200 not-data-is-selected:not-data-is-today:data-is-current-month:text-gray-900 data-is-selected:font-semibold data-is-selected:text-white data-is-selected:not-data-is-today:bg-gray-900 data-is-today:font-semibold not-data-is-selected:data-is-today:text-indigo-600 data-is-selected:data-is-today:bg-indigo-600 dark:not-data-is-selected:not-data-is-today:not-data-is-current-month:text-gray-500 dark:not-data-is-selected:hover:bg-white/10 dark:not-data-is-selected:not-data-is-today:data-is-current-month:text-white dark:data-is-selected:not-data-is-today:bg-white dark:data-is-selected:not-data-is-today:text-gray-900 dark:not-data-is-selected:data-is-today:text-indigo-400 dark:data-is-selected:data-is-today:bg-indigo-500"
>
<time dateTime={day.date}>{day.date.split('-').pop().replace(/^0/, '')}</time>
</button>
</div>
))}
</div>
</div>
<section className="mt-12 md:mt-0 md:pl-14">
<h2 className="text-base font-semibold text-gray-900 dark:text-white">
Schedule for <time dateTime="2022-01-21">January 21, 2022</time>
</h2>
<ol className="mt-4 flex flex-col gap-y-1 text-sm/6 text-gray-500 dark:text-gray-400">
{meetings.map((meeting) => (
<li
key={meeting.id}
className="group flex items-center gap-x-4 rounded-xl px-4 py-2 focus-within:bg-gray-100 hover:bg-gray-100 dark:focus-within:bg-white/5 dark:hover:bg-white/5"
>
<img
alt=""
src={meeting.imageUrl}
className="size-10 flex-none rounded-full dark:outline dark:-outline-offset-1 dark:outline-white/10"
/>
<div className="flex-auto">
<p className="text-gray-900 dark:text-white">{meeting.name}</p>
<p className="mt-0.5">
<time dateTime={meeting.startDatetime}>{meeting.start}</time> -{' '}
<time dateTime={meeting.endDatetime}>{meeting.end}</time>
</p>
</div>
<Menu as="div" className="relative opacity-0 group-hover:opacity-100 focus-within:opacity-100">
<MenuButton className="relative flex items-center rounded-full text-gray-500 outline-offset-6 hover:text-gray-600 dark:text-gray-400 dark:hover:text-white">
<span className="absolute -inset-2" />
<span className="sr-only">Open options</span>
<EllipsisVerticalIcon aria-hidden="true" className="size-6" />
</MenuButton>
<MenuItems
transition
className="absolute right-0 z-10 mt-2 w-36 origin-top-right rounded-md bg-white shadow-lg outline-1 outline-black/5 transition data-closed:scale-95 data-closed:transform data-closed:opacity-0 data-enter:duration-100 data-enter:ease-out data-leave:duration-75 data-leave:ease-in dark:bg-gray-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10"
>
<div className="py-1">
<MenuItem>
<a
href="#"
className="block px-4 py-2 text-sm text-gray-700 data-focus:bg-gray-100 data-focus:text-gray-900 data-focus:outline-hidden dark:text-gray-300 dark:data-focus:bg-white/5 dark:data-focus:text-white"
>
Edit
</a>
</MenuItem>
<MenuItem>
<a
href="#"
className="block px-4 py-2 text-sm text-gray-700 data-focus:bg-gray-100 data-focus:text-gray-900 data-focus:outline-hidden dark:text-gray-300 dark:data-focus:bg-white/5 dark:data-focus:text-white"
>
Cancel
</a>
</MenuItem>
</div>
</MenuItems>
</Menu>
</li>
))}
</ol>
</section>
</div>
)
}