---
title: "React Event calendar Quarter and Year View Example | Mobiscroll"
component: "Event calendar"
framework: "React"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/react/eventcalendar/quarter-year-view"
---

# Quarter and Year View - React Event calendar demo

Show three months or a full year in the React event calendar — switch between quarter and year views to give users a planning-scale event overview. For React and Next.JS.

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

## Description

Besides the single month view, the calendar can be configured to render multiple months or a year. Controlled through the `calendar.type` and `calendar.size` properties of the [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) option.

Depending on the height of the parent container the calendar is rendered in, the header that can be used for navigation is sticky at the top while the months are vertically scrollable.

## What this demo shows

- An event calendar with a segmented control in the header that lets the user switch between quarter view and year view.
- **Header and segmented control** A segemnted control with `Quarter` and `Year` options is positioned in the center of the header, between the year navigation label (quick navigation picker) on the left and the prev/next arrows with a `Today` button on the right.
- **Quarter view** When the `Quarter` option is selected from the segmented control, that renders the three months of the current quarter as a compact multi-month grid.
- **Year view** When the `Year` option is selected from the segmented control, that renders all twelve months of the current year in a single scrollable layout.
- **Sticky header** The navigation bar and segmented control stay fixed at the top while the calendar months scroll vertically beneath it.
- **Event dots** Days that have at least one event show a small dot below the day number, giving a quick visual signal of activity.
- **Day popover** Clicking a day with events opens a popover above the day cell that lists the events for that date.
- **Popover event styling** Each listed event has a colored vertical marker on the left to help distinguish event categories.
- **Hover state** Hovering a date highlights the day number with a gray background.
- **Selection state** Clicking a date selects it and highlights the day number with a blue background.

## Best for

- **High-level event overviews** Giving users a bird's-eye view of activity across a quarter or full year, where the exact time of each event matters less than seeing which days are busy.
- **Aggregate and summary views** Dashboards or reports where totals, counts, or status indicators are shown per day, and users need to scan a large date range at once.
- **Planning and scheduling workflows** Letting users spot free stretches or busy periods across a quarter or year before drilling into a specific day or week.

## 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
- [`data`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-data) - option
- [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) - option
- [`height`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-height) - option
- [`renderHeader`](https://mobiscroll.com/docs/react/eventcalendar/api#renderer-renderHeader) - renderer

## Code

### JSX

```jsx
import {
  CalendarNav,
  CalendarNext,
  CalendarPrev,
  CalendarToday,
  Eventcalendar,
  getJson,
  Segmented,
  SegmentedGroup,
  setOptions,
} from '@mobiscroll/react';
import { useCallback, useEffect, useMemo, useState } from 'react';

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

function App() {
  const [calendarType, setCalendarType] = useState('quarter');
  const [myEvents, setEvents] = useState([]);

  const myView = useMemo(
    () => (calendarType === 'quarter' ? { calendar: { type: 'month', size: 3 } } : { calendar: { type: 'year' } }),
    [calendarType],
  );

  const calendarHeight = useMemo(() => (calendarType === 'quarter' ? 'auto' : '100%'), [calendarType]);

  const changeView = useCallback((event) => {
    setCalendarType(event.target.value);
  }, []);

  const calendarHeader = useCallback(
    () => (
      <>
        <CalendarNav />
        <div className="quarter-year-header-picker">
          <SegmentedGroup value={calendarType} onChange={changeView}>
            <Segmented value="quarter">Quarter</Segmented>
            <Segmented value="year">Year</Segmented>
          </SegmentedGroup>
        </div>
        <CalendarPrev />
        <CalendarToday />
        <CalendarNext />
      </>
    ),
    [calendarType, changeView],
  );

  useEffect(() => {
    getJson(
      'https://trial.mobiscroll.com/events/?vers=5',
      (events) => {
        setEvents(events);
      },
      'jsonp',
    );
  }, []);

  return <Eventcalendar data={myEvents} view={myView} height={calendarHeight} renderHeader={calendarHeader} />;
}

export default App;
```

### TSX

```tsx
import {
  CalendarNav,
  CalendarNext,
  CalendarPrev,
  CalendarToday,
  Eventcalendar,
  getJson,
  MbscCalendarEvent,
  MbscEventcalendarView,
  Segmented,
  SegmentedGroup,
  setOptions,
} from '@mobiscroll/react';
import { ChangeEvent, FC, useCallback, useEffect, useMemo, useState } from 'react';

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

const App: FC = () => {
  const [calendarType, setCalendarType] = useState<string>('quarter');
  const [myEvents, setEvents] = useState<MbscCalendarEvent[]>([]);

  const myView = useMemo<MbscEventcalendarView>(
    () =>
      calendarType === 'quarter'
        ? {
            calendar: {
              type: 'month',
              size: 3,
            },
          }
        : {
            calendar: {
              type: 'year',
            },
          },
    [calendarType],
  );

  const calHeight = useMemo<string>(() => (calendarType === 'quarter' ? 'auto' : 'height:100%'), [calendarType]);

  const changeView = useCallback((event: ChangeEvent<HTMLInputElement>) => {
    setCalendarType(event.target.value);
  }, []);

  const calendarHeader = useCallback(
    () => (
      <>
        <CalendarNav />
        <div className="quarter-year-header-picker">
          <SegmentedGroup value={calendarType} onChange={changeView}>
            <Segmented value="quarter">Quarter</Segmented>
            <Segmented value="year">Year</Segmented>
          </SegmentedGroup>
        </div>
        <CalendarPrev />
        <CalendarToday />
        <CalendarNext />
      </>
    ),
    [calendarType, changeView],
  );

  useEffect(() => {
    getJson(
      'https://trial.mobiscroll.com/events/?vers=5',
      (events: MbscCalendarEvent[]) => {
        setEvents(events);
      },
      'jsonp',
    );
  }, []);

  return <Eventcalendar data={myEvents} view={myView} height={calHeight} renderHeader={calendarHeader} />;
};

export default App;
```

### CSS

```css
.mbsc-calendar .quarter-year-header-picker .mbsc-segmented {
  max-width: 200px;
  margin: 0 auto;
}

.quarter-year-header-picker {
  flex: 1 0 auto;
}
```

## Implementation notes

- Define two view configs controlled by a state variable: quarter uses `{ calendar: { type: 'month', size: 3 } }` and year uses `{ calendar: { type: 'year' } }`. Also toggle `height` between `'auto'` (quarter) and `'100%'` (year) so the year grid fills the container.
- Use `renderHeader` (Angular: `headerTemplate`, Vue: `#header` slot) to build a custom header: `CalendarNav` on the left, a `SegmentedGroup` with `Quarter` and `Year` options in the center, and `CalendarPrev`, `CalendarToday`, `CalendarNext` on the right. When the segmented selection changes, update both the view config and the height.
- Load events from a remote endpoint using `getJson` and assign them to `data`; for the imperative API, call `inst.setEvents(events)` in the callback.

## 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: [Week and Month View](https://demo.mobiscroll.com/react/eventcalendar/month-week-view.md) - Display events in a React calendar with switchable week and month views — choose 1, 2, or 3 weeks and set a locale-aware or fixed week start day.
- Next: [Show All or Limit Event Labels](https://demo.mobiscroll.com/react/eventcalendar/show-more-all-labels.md) - Show all event labels with dynamic row heights or limit labels per day in a React month-view calendar — hidden events appear in a "show more" popover.
