calendar-tsx

Overflow

Count hidden events and show them on demand.

A day-grid cell fits maxEventsPerDay rows of bars. Bars in further rows are hidden, and each day they cross counts them:

Day fieldDescription
hiddenCountHidden bars crossing this day.
hasMorehiddenCount > 0, or the view's dayOverflow returned true.
eventsEvery event on the day, including hidden ones, in order.

DayGridViewOverflow renders a button only when hasMore is true. It does nothing by itself: open a popover, a drawer or the day view from its click. The calendar has no built-in popover.

Example

Render the overflow button inside each DayGridViewDay, and show the day's events in a dialog:

day-overflow.tsx
export const DayOverflow = ({ day }: { day: Calendar_DayGridDay<Booking> }) => {
  const [open, setOpen] = useState(false);

  return (
    <>
      <DayGridViewOverflow day={day} onClick={() => setOpen(true)}>
        {day.hiddenCount > 0 ? `${day.hiddenCount} more` : 'More'}
      </DayGridViewOverflow>
      {open && (
        <dialog open onClose={() => setOpen(false)}>
          <h3>{day.date.toLocaleString('en-US', { dateStyle: 'full' })}</h3>
          <ul>
            {day.events.map(event => (
              <li key={event.id}>{event.data.title}</li>
            ))}
          </ul>
          <button onClick={() => setOpen(false)}>Close</button>
        </dialog>
      )}
    </>
  );
};

More than you loaded

If you load a limited number of events per day, the calendar cannot count the rest. Mark those days with dayOverflow, and hasMore turns on even when nothing is hidden:

export const month = dayGridView({
  period: 'month',
  maxEventsPerDay: 3,
  dayOverflow: (date: Temporal.PlainDate) => truncatedDays.has(date.toString()),
});

hiddenCount then stays 0, so label the button without a number for those days.