---
title: "React Event calendar Add Event on Hover Example | Mobiscroll"
component: "Event calendar"
framework: "React"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/react/eventcalendar/cell-template-on-hover"
---

# Add Event on Hover - React Event calendar demo

Show an "Add event" button on day cell hover in a React event calendar — reveal event creation without cluttering the calendar interface. For React and Next.JS.

- [Live demo](https://demo.mobiscroll.com/react/eventcalendar/cell-template-on-hover)
- [View React JS code on GitHub](https://github.com/acidb/mobiscroll-demos-react/tree/main/src/demos/eventcalendar/calendar-view/cell-template-on-hover)
- [View React TS code on GitHub](https://github.com/acidb/mobiscroll-demos-react-ts/tree/main/src/demos/eventcalendar/calendar-view/cell-template-on-hover)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/eventcalendar/cell-template-on-hover.md), [jQuery](https://demo.mobiscroll.com/jquery/eventcalendar/cell-template-on-hover.md), [Angular](https://demo.mobiscroll.com/angular/eventcalendar/cell-template-on-hover.md), [Vue](https://demo.mobiscroll.com/vue/eventcalendar/cell-template-on-hover.md)

## Description

Hover-based interactions can be simple yet elegant. Using the [`onCellHoverIn`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onCellHoverIn) and [`onCellHoverOut`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onCellHoverOut) events, the calendar dynamically displays an "Add event" button when users hover over day cells, providing an intuitive way to create new events with minimal interface clutter.

For customizing the cell content appearance, the [`renderCalendarDayContent`](https://mobiscroll.com/docs/react/eventcalendar/api#renderer-renderCalendarDayContent) is the perfect candidate, as it holds the basic structure of the day cell.

## What this demo shows

- A desktop month view Event Calendar with a full month grid, event labels inside day cells, and a header with month navigation controls.
- **Event labels** Day cells with events display label-style event entries with a colored marker on the left, the event title, and the event time.
- **Event selection** Clicking an event label highlights it to show the selected state.
- **Cell hover state** Hovering a day cell highlights the day number in the top-right corner with a gray background.
- **Add event action** When a day cell is hovered, an `Add event` button appears inside the cell so event creation is available only where the user is interacting.
- **Add event button state** Hovering the `Add event` button highlights the button before creation.
- **Event creation** Clicking the `Add event` button creates a new event in that day cell with the title `New event`.
- **Creation feedback** After a new event is created, a toast appears at the bottom of the calendar showing the exact date of the new event.
- **Day selection** Clicking a day cell selects that date and highlights the day number with a blue background.
- **Header** The top-left side of the header shows the currently displayed month and year.
- **Navigation** The top-right side of the header includes previous and next month arrows with a `Today` button between them for returning to the current date.

## Best for

- **Desktop month planning** Reviewing and managing events in a full month grid where users need a broad overview of the schedule.
- **Lightweight event creation** Adding events directly from day cells without opening persistent controls in every cell.
- **Dense calendar layouts** Showing multiple event labels with clear visual separation using colored markers, titles, and times.
- **Interactive calendar workflows** Desktop experiences where hover states can reveal contextual actions without adding interface clutter.
- **Click-first scheduling flows** Use cases where users need to select a day, inspect existing events, and create a new event from the same month view.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-themeVariant) - option
- [`labels`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-labels) - option
- [`data`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-data) - option
- [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) - option
- [`renderCalendarDayContent`](https://mobiscroll.com/docs/react/eventcalendar/api#renderer-renderCalendarDayContent) - renderer
- [`onCellHoverIn`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onCellHoverIn) - event
- [`onCellHoverOut`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onCellHoverOut) - event
- [`onClose`](https://mobiscroll.com/docs/react/notifications/toast#event-onClose) - event

## Code

### JSX

```jsx
import { Eventcalendar, formatDate, setOptions, Toast } from '@mobiscroll/react';
import { useCallback, useMemo, useState } from 'react';

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

function App() {
  const [hoveredDate, setHoveredDate] = useState(null);
  const [isToastOpen, setToastOpen] = useState(false);
  const [toastMessage, setToastMessage] = useState('');
  const [myEvents, setEvents] = useState(
    () => [
      {
        start: '2026-10-02T12:00',
        end: '2026-10-02T16:00',
        title: 'Company Strategy Offsite',
        color: '#90bcff',
      },
      {
        start: '2026-10-07T09:00',
        end: '2026-10-07T17:00',
        title: 'R&D Innovation Workshop',
        color: '#ffdfaf',
      },
      {
        start: '2026-10-15T10:00',
        end: '2026-10-15T15:00',
        title: 'Client Feedback Review',
        color: '#ffb9ad',
      },
      {
        start: '2026-10-19T09:00',
        end: '2026-10-19T19:00',
        title: 'Team Building Adventure',
        color: '#f3c1ff',
      },
      {
        start: '2026-10-23T11:00',
        end: '2026-10-23T15:00',
        title: 'Sales Summit & Training',
        color: '#b5eff8',
      },
      {
        start: '2026-10-25T10:00',
        end: '2026-10-25T15:00',
        title: 'Executive Planning Retreat',
        color: '#c7ffbb',
      },
      {
        start: '2026-10-29T14:00',
        end: '2026-10-29T17:00',
        title: 'Marketing Team Conference',
        color: '#ffeeb6',
      },
    ],
    [],
  );

  const myView = useMemo(
    () => ({
      calendar: {
        labels: 2,
      },
    }),
    [],
  );

  const addEvent = useCallback(() => {
    const newEvent = {
      start: hoveredDate,
      title: 'New Event',
    };

    setEvents((myEvents) => [...myEvents, newEvent]);
    setToastMessage('Event added on ' + formatDate('YYYY-MM-DD', hoveredDate));
    setToastOpen(true);
  }, [hoveredDate]);

  const customDayContent = useCallback(
    (args) => {
      const isHovered = hoveredDate && hoveredDate.getTime() === args.date.getTime();

      return (
        isHovered && (
          <button onClick={addEvent} className="mds-cell-summary-btn">
            Add event
          </button>
        )
      );
    },
    [hoveredDate, addEvent],
  );

  const handleCellHoverIn = useCallback((args) => {
    setHoveredDate(args.date);
  }, []);

  const handleCellHoverOut = useCallback(() => {
    setHoveredDate(null);
  }, []);

  const handleToastClose = useCallback(() => {
    setToastOpen(false);
  }, []);

  return (
    <>
      <Eventcalendar
        data={myEvents}
        view={myView}
        className="mds-cell-summary"
        renderCalendarDayContent={customDayContent}
        onCellHoverIn={handleCellHoverIn}
        onCellHoverOut={handleCellHoverOut}
      />
      <Toast isOpen={isToastOpen} message={toastMessage} onClose={handleToastClose} />
    </>
  );
}

export default App;
```

### TSX

```tsx
import {
  Eventcalendar,
  formatDate,
  MbscCalendarDayData,
  MbscCalendarEvent,
  MbscCellHoverEvent,
  setOptions,
  Toast,
} from '@mobiscroll/react';
import { FC, useCallback, useMemo, useState } from 'react';

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

const App: FC = () => {
  const [hoveredDate, setHoveredDate] = useState<Date | null>(null);
  const [isToastOpen, setToastOpen] = useState<boolean>(false);
  const [toastMessage, setToastMessage] = useState<string>('');
  const [myEvents, setEvents] = useState<MbscCalendarEvent[]>(() => [
    {
      start: '2026-10-02T12:00',
      end: '2026-10-02T16:00',
      title: 'Company Strategy Offsite',
      color: '#90bcff',
    },
    {
      start: '2026-10-07T09:00',
      end: '2026-10-07T17:00',
      title: 'R&D Innovation Workshop',
      color: '#ffdfaf',
    },
    {
      start: '2026-10-15T10:00',
      end: '2026-10-15T15:00',
      title: 'Client Feedback Review',
      color: '#ffb9ad',
    },
    {
      start: '2026-10-19T09:00',
      end: '2026-10-19T19:00',
      title: 'Team Building Adventure',
      color: '#f3c1ff',
    },
    {
      start: '2026-10-23T11:00',
      end: '2026-10-23T15:00',
      title: 'Sales Summit & Training',
      color: '#b5eff8',
    },
    {
      start: '2026-10-25T10:00',
      end: '2026-10-25T15:00',
      title: 'Executive Planning Retreat',
      color: '#c7ffbb',
    },
    {
      start: '2026-10-29T14:00',
      end: '2026-10-29T17:00',
      title: 'Marketing Team Conference',
      color: '#ffeeb6',
    },
  ]);

  const myView = useMemo(
    () => ({
      calendar: {
        labels: 2,
      },
    }),
    [],
  );

  const addEvent = useCallback(() => {
    const newEvent: MbscCalendarEvent = {
      start: hoveredDate!,
      title: 'New Event',
    };

    setEvents((myEvents) => [...myEvents, newEvent]);
    setToastMessage('Event added on ' + formatDate('YYYY-MM-DD', hoveredDate!));
    setToastOpen(true);
  }, [hoveredDate]);

  const customDayContent = useCallback(
    (args: MbscCalendarDayData) => {
      const isHovered = hoveredDate && hoveredDate.getTime() === args.date.getTime();

      return (
        isHovered && (
          <button onClick={addEvent} className="mds-cell-summary-btn">
            Add event
          </button>
        )
      );
    },
    [hoveredDate, addEvent],
  );

  const handleCellHoverIn = useCallback((args: MbscCellHoverEvent) => {
    setHoveredDate(args.date);
  }, []);

  const handleCellHoverOut = useCallback(() => {
    setHoveredDate(null);
  }, []);

  const handleToastClose = useCallback(() => {
    setToastOpen(false);
  }, []);

  return (
    <>
      <Eventcalendar
        data={myEvents}
        view={myView}
        className="mds-cell-summary"
        renderCalendarDayContent={customDayContent}
        onCellHoverIn={handleCellHoverIn}
        onCellHoverOut={handleCellHoverOut}
      />
      <Toast isOpen={isToastOpen} message={toastMessage} onClose={handleToastClose} />
    </>
  );
};
export default App;
```

### CSS

```css
.mds-cell-summary .mbsc-calendar-cell {
  min-height: 145px;
}
.mds-cell-summary-btn {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 8px;
  z-index: 3;
  font-size: 10px;
  padding: 8px;
  background: transparent;
  border-radius: 4px;
  border: 1px solid #5584b5;
  color: #5584b5;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.1s ease-out;
}
.mds-cell-summary-btn:hover {
  background: #5584b5;
  color: white;
  box-shadow: 0 2px 8px rgba(85, 132, 181, 0.3);
}
.mds-cell-summary-btn:active {
  box-shadow: 0 1px 4px rgba(85, 132, 181, 0.3);
}
```

## Implementation notes

- Set `view: { calendar: { labels: 2 } }` for a month grid that shows up to 2 event labels per day cell; extra events collapse into an "X more" indicator.
- Track the hovered day in a `hoveredDate` state variable: `onCellHoverIn` (Vue: `@cell-hover-in`) sets it to `args.date`; `onCellHoverOut` (Vue: `@cell-hover-out`) clears it.
- Use `renderCalendarDayContent` (Angular: `calendarDayContentTemplate`, Vue: `calendarDayContent` slot) to inject content into each day cell. In the renderer, compare `args.date` with `hoveredDate` by timestamp and render an "Add event" button only for the matching cell; return nothing for all other cells.
- `addEvent()` appends `{ start: hoveredDate, title: 'New Event' }` to the events array and shows a `Toast` with `'Event added on ' + formatDate('YYYY-MM-DD', hoveredDate)` as the message.
- JS/jQuery: since `renderCalendarDayContent` is not reactive, call `setOptions({ renderCalendarDayContent: ... })` inside both hover handlers to force a re-render when the hovered cell changes. Handle button clicks via event delegation on the calendar container. Use `calendar.addEvent()` to add the new event instead of mutating a data array.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-react.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config react
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config react --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/react/getting-started/installation

## Related demos

- Previous: [Custom Event Tooltip](https://demo.mobiscroll.com/react/eventcalendar/custom-event-tooltip.md) - Add custom hover tooltips to a React event calendar — show appointment details, status, location, and confirm or delete actions to each event.
