Note: We are using ES6 + JSX and transpile using Babel in the following examples. You might want to read through React docs for more details.

Starting Project

Note: For more details to use Onsen UI in your project, please refer to Getting Started.

To use Onsen UI in React apps, Onsen UI Core and React Components should be installed to the project. These modules can be installed via NPM package: onsenui and react-onsenui.

To quickly setup the project, Monaca CLI will solve all dependencies including TypeScript, Webpack and polyfills if necessary.

Using Onsen UI toolkit - Monaca CLI

$ npm install -g monaca # Install Monaca CLI - Onsen UI toolkit
$ monaca create helloworld # Choose React template
$ cd helloworld; monaca preview # Run preview, or "monaca debug" to run on your device

Download via npm

# The "react-onsenui" library requires the "onsenui" library.
$ npm install --save-dev onsenui react-onsenui

Use Kitchensink Code

Onsen UI React Components Kitchensink contains almost all components in Onsen UI as one application package. Link to Kitchensink Demo.

The code in this example is transpiled using Babel and bundled with Browserify.

Loading Onsen UI for React

Onsen UI for React is an extension to Onsen UI core, a Web components based UI framework. You need to load the following two JavaScript modules.

You can load with a normal <script> tag as follows:

<script src="react.js"></script>
<script src="react-dom.js"></script>
<script src="onsenui.js"></script>
<script src="react-onsenui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/6.1.19/browser.min.js"></script>

Or, you can use React and Onsen UI from npm with CommonJS module system like Browserify or Webpack. In this case, use the onsenui and react-onsenui packages, in addition to react and react-dom npm packages. In the example below ons contains Onsen UI core instance, and Ons contains React components.

var React = require('react');
var ReactDOM = require('react-dom');
var ons = require('onsenui');
var Ons = require('react-onsenui');

Alternatively, you can also use ES6 imports to specify the modules you want to use in react-onsenui package.

import {Page, Toolbar, Button} from 'react-onsenui';

Onsen UI HelloWorld with React

To get started, let’s create a simple Hello World application. The following sample code is a React version of Onsen UI HelloWorld.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="css/onsenui.css">
    <link rel="stylesheet" href="css/onsen-css-components.css">
    <script src="react.js"></script>
    <script src="react-dom.js"></script>
    <script src="onsenui.js"></script>
    <script src="react-onsenui.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/6.1.19/browser.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
  </body>
  <script type="text/babel">
    var App = React.createClass({
      handleClick: function() {
        ons.notification.alert('Hello world!');
      },

      render: function() {
        return (
          <Ons.Page>
            <Ons.Button onClick={this.handleClick}>Tap me!</Ons.Button>
          </Ons.Page>
        );
      }
    });
    ReactDOM.render(<App />, document.getElementById('app'));
  </script>
</html>

This example is loading the following JS libraries, react.js, react-dom.js, onsenui.js and react-onsenui.js. For stylesheets, it is loading onsenui.css and onsen-css-components.css which are bundled in Onsen UI distribution package. To know the details about Onsen UI stylesheets, please refer to our Style Sheets Guide document.

<link rel="stylesheet" href="css/onsenui.css">
<link rel="stylesheet" href="css/onsen-css-components.css">

In <body> tag, there is only a <div> tag having app id. This is where React will render the content into, and you can see it in the very bottom of JS code.

Also notice <script></script> tag has text/babel type. This means this script is not a pure JavaScript that browser supports (most commonly ECMAScript5), but is a ECMAScript6 (ES2015) with JSX format. Babel will transpile this code into ES5 in the browser. To get better performance, we can use node.js to transpile the code.

Inside the script, React.createClass() function defines a React Component called App. It has one method called render, and this is the function that is called when the app is rendered. The returning object is described in JSX, which is a XML like language that extends JavaScript. In this case, it is returning <Ons.Page> component that has an <Ons.Button> component. The onClick prop is used to call the handleClick method when the user taps the button.

return (
  <Ons.Page>
    <Ons.Button onClick={this.handleClick}>Tap me!</Ons.Button>
  </Ons.Page>
);

As you can see in this example, all <Ons.*> components are React Components, and they are loaded by react-onsenui.js. Click here to see our full Onsen UI React Components Reference.

Putting together, when index.html is loaded into the browser, it will compile JSX code, inject into the body, and render the content.

This is a basic introduction of how Onsen UI and React works together. If you want to further learn React, we recommend to read the official React docs.

Creating a page

The root of a page is created using the <Page> element. It covers the whole screen and is used as a container for the other elements.

Adding a toolbar

A toolbar is defined as a <Toolbar> or <BottomToolbar> component. Here is the typical example of a toolbar.

<Page renderToolbar={() =>
  <Toolbar>
    <div className="left">
      <BackButton>Back</BackButton>
    </div>
    <div className="center">Title</div>
    <div className="right">
      <ToolbarButton>
        <Icon icon="md-menu" />
      </ToolbarButton>
    </div>
  </Toolbar> }
>
  Static page app
</Page>

The toolbar is divided into 3 sections that can be specified as class names (left, center, and right). You can use <Icon> to display an icon, <ToolbarButton> or <BackButton> to place an button, or insert any HTML content.

Event Handling

Onsen UI components are capable of handling events. For instance, you can catch a tap event by using the onClick prop, or text input change with the onChange prop.

class MyPage extends React.Component {
  handleClick() {
    ons.notification.alert('Hello, world!');
  }
  render() {
    return() (
      <Page>
         <Button onClick={this.handleClick}>Click me!</Button>
      </Page>
    );
  }
}

The ons object

Onsen UI not only provides custom elements, it also exposes an object called Ons with a lot of useful functions attached to it. The ons object is part of the core library and can be imported in the bindings.

The following example uses ons.ready(fn) which waits until the app is completely loaded before executing a callback function. Inside the callback, it is calling ons.notification.alert() to display a alert dialog.

ons.ready(function() {
  // Onsen UI is now initialized
  ons.notification.alert('Welcome to Onsen UI!');
});

See also Ons.platform, Ons.notification and Ons.orientation for more utilities.

Importing ons object in React

Simply use ES6 imports:

import ons from `onsenui`;
import { platfrom, notification } from `onsenui`;

Adding page content

For a full list of components please check the reference page.

Form elements

Onsen UI provides a rich set of form components. Apart from <Button>, <Switch>,<Select> and <Range>, perhaps the <Input> component is the most common one since it supports different shapes: checkbox, radio, password, etc.

<Input
  value={this.state.text} float
  onChange={(event) => { this.setState({text: event.target.value})} }
  modifier='material'
  placeholder='Username' />

<Input type="checkbox" checked={this.state.checked} onChange={this.onChange} />

Lists

Lists are a very common pattern in mobile apps and thus Onsen UI provides abstraction for it. By using <List>, <ListItem> and <ListHeader> you can make simple or complex lists of items. Every list item is by default divided into three sections, just like <Toolbar>, and some CSS classes are provided for default styles (list-item__icon, list-item__thumbnail, list-item__title and list-item__subtitle).

<List
  dataSource={['Row 1', 'Row 2']}
  renderRow={(row, idx) => (
    <ListItem modifier={idx === this.state.data.length - 1 ? 'longdivider' : null}>
      <div className="left">
        <Icon icon="md-face" className="list-item__icon" />
      </div>
      <div className="center">
        <span className="list-item__title">{row}</span>
        <span className="list-item__subtitle">Subtitle</span>
      </div>
      <label className="right">
        <Switch />
      </label>
    </ListItem>
  )}
/>

Dialogs

There are multiple types of dialog components available in Onsen UI: <Dialog> for displaying a page inside a centered dialog; <AlertDialog> for displaying a simple message inside an alert style dialog; <Popover> for showing some content next to a specified element or a context menu; <Toast> for displaying a dismissable short message at the bottom or top of the page; <ActionSheet> (bottom sheet in Material Design) for letting users choose among a list of options that comes from the bottom side; and <Modal> for displaying a fullscreen dialog that forbids user interaction.

Apart from that, Ons object offers a more handy solution for simple dialogs:

ons.notification.alert('Hello world!'); // Basic alert
ons.notification.confirm('Are you ready?'); // OK - Cancel buttons
ons.notification.prompt('What is your name?'); // Text input
ons.notification.toast('New password saved.'); // Toast - Snackbar

ons.openActionSheet({ title: 'Actions', buttons: ['Copy', 'Cut', 'Delete'] }); // Options list

Multiple page navigation

In Onsen UI there are three navigation patterns based on three different components: <Navigator>, <Tabbar> and <Splitter>. These components supply “frames” able to change their inner content. The content of these frames will normally be <Page> components but it is also possible to nest navigation components in order to combine them.

More information is provided in the “Docs” tab of the Live Example section of each component.

The main pattern uses <Navigator> component to provide a stack where you can push and pop pages with transition animations. This is the basic and most used navigation pattern and can be combined with the other two.

Use this pattern when you have a sequential flow where a page depends on the previous one. Data can be optionally passed from one page to another.

Tabbar

In this case, by using <Tabbar> component a visible tabbar is displayed at the bottom or the top of the page with tabs associated to different pages. The component will load content depending on the selected tab (<Tab>). This pattern is commonly used to sepparate different sections in the app.

A menu can be added using the <Splitter> component. For small devices it can be used to create a swipeable menu, but for larger screens it can automatically display a column layout.

Splitter provides two frames that can load different content: <SplitterSide> and <SplitterContent>. A common usecase is to show a list in the side menu where each item loads a different page in the content frame. Notice that loading new content in any of these frames will completely remove the previous loaded content. For more complex navigation consider nesting <ons-navigator> inside <ons-splitter-content>.

Using Modifier

Modifier is a cross-component way to provide customizability for Onsen UI components. When a component is defined with a modifier, it will have a separate class namespace so that you can apply custom styles to the component. Also, some components have several preset modifiers to change the appearance.

For example, each of the following buttons have different look. To change modifiers dynamically, please manipulate modifier attribute from JavaScript.

<Button modifier="quiet">Quiet</Button>
<Button modifier="light">Light</Button>
<Button modifier="large">Large</Button>
<Button modifier="cta">Call To Action</Button>
<Button modifier="material">Material Design</Button>

Cross platform styling

Onsen UI components are automatically styled depending on the platform where the app runs. You can easily test this feature with your browser Dev Tools by switching between iOS and Android views.

Automatic styling simply applies modifier="material" to the components when ons.platform.isAndroid() is true. You can disable this feature by running ons.disableAutoStyling() right after including onsenui.js (i.e. before the app is initialized). If you disable it you may need to manually specify modifier="material" in every component you want to display with Material Design. You can also specify disable-auto-styling attribute in specific components that you don’t want to auto style.

Some tools are provided to give a more accurate customization.

Platform utilities

Ons.platform object is available with methods such as ons.platform.isIOS(), ons.platform.isWebView(), etc.

You can set a platform with ons.platform.select('android'), for example, in order to display Material Design on every platform. This must be called before the app is initialized (right after including onsenui.js).

With this, for example, you can display <Fab> for Material Design and other type of button for iOS flat design.

Icons shortcut

<Icon> component provides a shortcut to make auto styling easier:

<Icon icon="ion-navicon, material:md-menu" size="24px, material:20px" />

The second icon will be displayed when material modifier is present (other modifiers can be used).

CSS Definitions

Onsen UI styles are defined in onsenui.css and onsen-css-components.css. They are written in pure CSS using some extra features provided by cssnext.

onsenui.css is a core CSS module that defines styles for the custom elements. The source code exists under core/css directory. onsen-css-components.css contains CSS definitions for CSS components. The source code exists in css-components/src.

A local tool is included in Onsen UI core (onsenui) for previewing changes in Onsen CSS Component. This tool, located under onsenui/css-components-src/ directory in a local instalation, is also able to generate a new onsenui-css-components.css file that must be imported in the project.

Overriding CSS style

If you want to apply a different style to a specific component, you can use modifier attribute to override its style definition.

For example, if you want to apply a thick border only to a specific button, you can define like the one below.

<ons-button modifier="thick">Thick Button</ons-button>

Then, write the appropriate style code under the style tag or in the css file.

<style>
.button--thick {
  border: 10px;
}
</style>

Extending animations

Onsen UI already provides multiple built-in animations for its routing components and dialogs. However, it is also possible to create custom animations for specific components or even extend existing animations and change part of them. This is a relatively advanced topic since it requires digging a bit in Onsen UI core code.

Animit

Onsen UI relies on Animit, a minimal animation library for managing CSS transtions on mobile browsers.

Animit can be accessed with ons.animit or import { animit } from ons;, depending on the type of the app. It exposes methods to queue CSS animations, apply delays and run callbacks as follows:

let animation1 = animit(myElement) // This defines the animation for the provided element
  .saveStyle() // Saves the original style of the element
  .queue({ // Original position/style in the animation
    css: {
      transform: 'translate3D(0, 100%, 0)'
    },
    duration: 0
  })
  .wait(0.2) // Delay applied before the transition starts
  .queue({ // Next step in the animation
    css: {
      transform: 'translate3D(0, 0, 0)',
    },
    duration: 0.6,
    timing: 'linear'
  })
  .restoreStyle() // Restores the original style of the element
  .queue(done => { // Optional "On transition end" callback
    callback();
    done();
  }
);

animation1.play(); // Run the animation

Since Animit modifies the element’s style property, it provides saveStyle() and restoreStyle() methods to ensure the previous styles are not lost. queue({css: {...}, duration: 0, timing: 'linear'}) or queue({...}, {duration: 0, timing: 'linear'}) method is provided to add transitions to the queue. The first one will be the first style applied in the animation that will transition into the following styles. In the provided example, we are moving a new page inside the view from right to left. Therefore, it needs to start at position translate3d(0, 100%, 0) and move to translate3d(0, 0, 0). Method wait(...) can be used to apply a delay between transitions. Finally, we can optionally call queue(function(done) { ...; done(); }) again to run a callback if necessary.

It is also possible to pass an array of HTML elements to animit if performing the same animation on multiple elements is required: animit([el1, el2]).saveStyle()....

It is very common to have more than one animation running at the same time. animit.runAll(animation1, animation2, animation3); method can be used for this behavior instead of animation1.play(); animation2.play(); animation3.play();.

Creating animators

Animators can be created from scratch by extending the necessary animator classes that Onsen UI provides. Every component exposes a minimum animator interface that must be extended and implemented: NavigatorTransitionAnimator, AlertDialogAnimator, DialogAnimator, PopoverAnimator, ModalAnimator, TabbarAnimator and SplitterAnimator. This is the desired way to implement animators if you want to build a custom version of Onsen UI or want to make a pull request to the repository. For more information, please have a look at the existing animators for every component.

ES2015 (ES6) is preffered but not strictly required for this to work. An example in ES5 can be found here.

Extending animators

Another way to make new animators is extending an existing animator and modifiying part of its behavior (or all). This is in general easier if you just want to tweak the appearance or timing, or even if you want to create a whole new thing starting from another animator. For this it is also required to have a look at the existing animators, choose one and check its properties and methods. Every animator provides a extend({...}) class method that returns a new animator. Animators are exposed in every component class: ons.NavigatorElement.animators or ons.AlertDialogElement.animators are some examples. These objects contain all the registered animators and can be extended as follows.

var fadeIOS = ons.NavigatorElement.animators['fade-ios'];
var customAnimator = fadeIOS.extend({
  timing: 'cubic-bezier(.1, .7, .1, 1)',
  delay: 0.1,
  push: function(enterPage, leavePage, callback) {
    ons.animit.runAll(
      ons.animit(enterPage)...,
      ons.animit(leavePage)...
    );
  }
});

// This step is mandatory
ons.NavigatorElement.registerAnimator('customAnimationName', customAnimator);

This overwrites the push animation but uses the original pop animation. timing and delay properties will still affect both animations. Some animators have extra properties, such as backgroundMask. Please check the animator you want to extend to see all the properties.

After the new animator is created and registered, we can simply specify the animation with its name: myNavigator.pushPage('page.html', {animation: 'customAnimationName'}). Or make it default: <ons-navigator animation="customAnimationName">. The same applies to the other components.

Need Help?

If you have any questions, use our Community Forum or talk to us via Gitter chat. The Onsen UI team and your peers in the community will work together to help solve your issues.

For bug reports and feature requests use our GitHub Issues page.