---
title: "React Timeline Theme Customization Example | Mobiscroll"
component: "Timeline"
framework: "React"
library_version: "6.2.0"
url: "https://demo.mobiscroll.com/react/timeline/themes-ios-material-windows"
---

# Theme Customization - React Timeline demo

Style the React Timeline with iOS, Material, or Windows themes — switch light/dark variants, use the theme builder for colors, or apply CSS overrides. For React and Next.JS.

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

## Description

The look and feel of the timeline can be deeply customized. There are four levels of customization:

- **Base themes:** Choose between **iOS**, **Material** and **Windows**.
- **Light or dark:** Every theme has a `light` and `dark` variant. Setting the `themeVariant` to `'auto'` will switch based on system settings.
- **Custom themes:** Use the [theme builder](https://mobiscroll.com/themebuilder) to customize the colors and make it match your brand.
- **Custom CSS:** If you need further customization, the sky is the limit with CSS overrides.

You can also see how every example looks by changing the theme from the header.

## What this demo shows

- A desktop daily timeline where hours are arranged horizontally and resources arranged vertically on the left.
- **Theme controls** A segmented picker lets you switch between the `iOS`, `Material`, and `Windows` base themes, with `iOS` selected by default.
- **Theme variant** A dark-theme switch is enabled by default, showing how the same timeline can be previewed in a dark variant.
- **Custom theme option** A separate switch for theme builder or Sass-based customization is present but turned off by default.
- **Header navigation** The month and year label opens date navigation, while the previous and next arrows move between days and the Today button returns to the current date.
- **Day view** The strip below the header shows the selected days, with the current date highlighted. The timeline displays hourly columns from 12 AM to 12 PM.
- **Resources** Multiple resources are shown as separate timeline rows.
- **Current time** A vertical blue line with a time label marks the current time.
- **Hover behavior** Hovering over the time grid shows a time indicator that follows the cursor in 15-minute increments.
- **Event cards** Events are shown as colored cards with a left color stripe, a bold title, a description, and a bold time range.
- **Date positioning** Events are positioned by their assigned resource and exact date range.
- **Event interaction** Events highlight on hover and show drag and resize handles for repositioning or changing duration.
- **Event selection** Clicking an event selects and highlights it.
- **Event creation** New events can be created by double-clicking the timeline or by clicking and dragging across a time range.
- **Scrolling** The timeline supports horizontal and vertical scrolling for navigating through time and resources.

## Best for

- **Theme comparison** Evaluating how the timeline looks with the `iOS`, `Material`, and `Windows` base themes.
- **Light and dark mode previewing** Checking how a timeline setup behaves across light and dark theme variants.
- **Branded calendar experiences** Exploring how a base theme can be extended with theme builder, Sass, or custom CSS to match a product's visual style.

## Tutorial

### Pick a base theme

- (x) iOS
- ( ) Material
- ( ) Windows

### Then choose between light or dark theme variant

- [ ] Turn dark theme on

### Or build a custom theme based on any base theme

- [ ] Use the [theme builder](https://mobiscroll.com/themebuilder) or [Sass](https://mobiscroll.com/docs/react/eventcalendar/css-variables) to customize themes

```jsx
<Eventcalendar
    theme="ios"
    themeVariant="light"
/>
```

With "Material":

```jsx
<Eventcalendar
    theme="material"
    themeVariant="light"
/>
```

With "Windows":

```jsx
<Eventcalendar
    theme="windows"
    themeVariant="light"
/>
```

## API used in this demo

- [`data`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-data) - option
- [`resources`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-resources) - option
- [`theme`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-themeVariant) - option
- [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) - option

## Code

### JSX

```jsx
import { Dropdown, Eventcalendar, getJson, Page, setOptions } from '@mobiscroll/react';
import { useCallback, useEffect, useMemo, useState } from 'react';

setOptions({
});

function App() {
  const [myEvents, setEvents] = useState([]);
  const [myTheme, setTheme] = useState();
  const [myThemeVariant, setThemeVariant] = useState();

  const myView = useMemo(() => ({ timeline: { type: 'day' } }), []);

  const myResources = useMemo(
    () => [
      {
        id: 1,
        name: 'Ryan',
        color: '#fdf500',
      },
      {
        id: 2,
        name: 'Kate',
        color: '#ff4600',
      },
      {
        id: 3,
        name: 'John',
        color: '#ff0101',
      },
      {
        id: 4,
        name: 'Mark',
        color: '#239a21',
      },
      {
        id: 5,
        name: 'Sharon',
        color: '#8f1ed6',
      },
      {
        id: 6,
        name: 'Ashley',
        color: '#01adff',
      },
    ],
    [],
  );

  const handleThemeChange = useCallback((ev) => {
    setTheme(ev.target.value);
  }, []);

  const handleThemeVariantChange = useCallback((ev) => {
    setThemeVariant(ev.target.value);
  }, []);

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

  return (
    <Page className="mds-full-height">
      <div className="mds-full-height mbsc-flex-col">
        <div className="mbsc-grid">
          <div className="mbsc-row">
            <div className="mbsc-col-sm-6">
              <Dropdown inputStyle="box" label="Theme" labelStyle="stacked" value={myTheme} onChange={handleThemeChange}>
                <option value="auto">Auto</option>
                <option value="ios">iOS</option>
                <option value="material">Material</option>
                <option value="windows">Windows</option>
              </Dropdown>
            </div>
            <div className="mbsc-col-sm-6">
              <Dropdown
                inputStyle="box"
                label="Theme variant"
                labelStyle="stacked"
                value={myThemeVariant}
                onChange={handleThemeVariantChange}
              >
                <option value="auto">Auto</option>
                <option value="light">Light</option>
                <option value="dark">Dark</option>
              </Dropdown>
            </div>
          </div>
        </div>
        <div className="mds-overflow-hidden mbsc-flex-1-1">
          <Eventcalendar data={myEvents} resources={myResources} theme={myTheme} themeVariant={myThemeVariant} view={myView} />
        </div>
      </div>
    </Page>
  );
}

export default App;
```

### TSX

```tsx
import {
  Dropdown,
  Eventcalendar,
  getJson,
  MbscCalendarEvent,
  MbscEventcalendarView,
  MbscResource,
  Page,
  setOptions,
} from '@mobiscroll/react';
import { FC, useCallback, useEffect, useMemo, useState } from 'react';

setOptions({
});

const App: FC = () => {
  const [myEvents, setEvents] = useState<MbscCalendarEvent[]>([]);
  const [myTheme, setTheme] = useState();
  const [myThemeVariant, setThemeVariant] = useState();

  const myView = useMemo<MbscEventcalendarView>(() => ({ timeline: { type: 'day' } }), []);

  const myResources = useMemo<MbscResource[]>(
    () => [
      {
        id: 1,
        name: 'Ryan',
        color: '#fdf500',
      },
      {
        id: 2,
        name: 'Kate',
        color: '#ff4600',
      },
      {
        id: 3,
        name: 'John',
        color: '#ff0101',
      },
      {
        id: 4,
        name: 'Mark',
        color: '#239a21',
      },
      {
        id: 5,
        name: 'Sharon',
        color: '#8f1ed6',
      },
      {
        id: 6,
        name: 'Ashley',
        color: '#01adff',
      },
    ],
    [],
  );

  const handleThemeChange = useCallback((ev: MbscCalendarEvent) => {
    setTheme(ev.target.value);
  }, []);

  const handleThemeVariantChange = useCallback((ev: MbscCalendarEvent) => {
    setThemeVariant(ev.target.value);
  }, []);

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

  return (
    <Page className="mds-full-height">
      <div className="mds-full-height mbsc-flex-col">
        <div className="mbsc-grid">
          <div className="mbsc-row">
            <div className="mbsc-col-sm-6">
              <Dropdown inputStyle="box" label="Theme" labelStyle="stacked" value={myTheme} onChange={handleThemeChange}>
                <option value="auto">Auto</option>
                <option value="ios">iOS</option>
                <option value="material">Material</option>
                <option value="windows">Windows</option>
              </Dropdown>
            </div>
            <div className="mbsc-col-sm-6">
              <Dropdown
                inputStyle="box"
                label="Theme variant"
                labelStyle="stacked"
                value={myThemeVariant}
                onChange={handleThemeVariantChange}
              >
                <option value="auto">Auto</option>
                <option value="light">Light</option>
                <option value="dark">Dark</option>
              </Dropdown>
            </div>
          </div>
        </div>
        <div className="mds-overflow-hidden mbsc-flex-1-1">
          <Eventcalendar data={myEvents} resources={myResources} view={myView} theme={myTheme} themeVariant={myThemeVariant} />
        </div>
      </div>
    </Page>
  );
};
export default App;
```

### CSS

```css
.mds-full-height {
  height: 100%;
}

.mds-overflow-hidden {
  overflow: hidden;
}
```

## Implementation notes

- Use `timeline: { type: 'day' }` - a single-day timeline view.
- Define 6 resources, each with `id`, `name`, and `color`.
- Load events from `https://trial.mobiscroll.com/timeline-events/` via JSONP using `getJson(url, callback, 'jsonp')`. In the callback, call `inst.setEvents(events)` for the imperative API.
- Pass `theme` and `themeVariant` as props to the `Eventcalendar`. Both default to `'auto'` - `theme: 'auto'` lets Mobiscroll pick the theme based on the platform, and `themeVariant: 'auto'` follows the OS light/dark preference.
- `theme` accepts `'auto'`, `'ios'`, `'material'`, or `'windows'`; `themeVariant` accepts `'auto'`, `'light'`, or `'dark'`. Both can be changed at runtime: declaratively by updating the `theme`/`themeVariant` prop, or imperatively via `inst.setOptions({ theme: value })` / `inst.setOptions({ themeVariant: value })`.
- Wrap the whole page in a Mobiscroll `Page` component. Use a flex column layout (`mbsc-flex-col`) so the dropdowns sit above the calendar and the calendar fills the remaining height (`mbsc-flex-1-1`).
- Add a `.mds-full-height { height: 100%; }` CSS rule to make the page and calendar fill the available viewport height.

## 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 Time Range Backgrounds](https://demo.mobiscroll.com/react/timeline/colors-invalids-css-class.md) - Style time range backgrounds and blocked periods on a React Timeline using CSS classes — mark recurring hours or special days.
- Next: [Resource Row Styling](https://demo.mobiscroll.com/react/timeline/resource-background.md) - Highlight resource rows on a React Timeline using background colors or CSS classes — differentiate teams, show status, or style headers and grid sections.
