Skip to content

Modus-Logo-Long-BlackCreated with Sketch.

  • Services
  • Work
  • Blog
  • Resources

    OUR RESOURCES

    Innovation Podcast

    Explore transformative innovation with industry leaders.

    Guides & Playbooks

    Implement leading digital innovation with our strategic guides.

    Practical guide to building an effective AI strategy
  • Who we are

    Our story

    Learn about our values, vision, and commitment to client success.

    Open Source

    Discover how we contribute to and benefit from the global open source ecosystem.

    Careers

    Join our dynamic team and shape the future of digital transformation.

    How we built our unique culture
  • Let's talk
  • EN
  • FR

Ext JS to React: Button

Published on March 13, 2018
Last Updated on April 23, 2021
Application Development

This is part of the Ext JS to React blog series. You can review the code from this article on the Ext JS to React Git repo.

Buttons are one of the more elemental components used in an application. Most of us have likely never constructed an Ext JS application without them. You may have a button to trigger adding a new user to a grid. Or perhaps a “submit” button to send a form up to your server. Buttons can stand alone, have a partnering menu for additional UI, or be grouped together in a connected relationship. Let’s take a look at each of these use cases in the sections below.

Note: While not a requirement for React, this article’s code examples assume you’re starting with a starter app generated by create-react-app.

Simple React Button

Buttons can be a single element having just text and/or an icon. The React approach uses new component syntax along with JSX, but is structurally somewhat similar to Ext JS. Below is a simple button component that we’ll define at src/Button.js. A click handler can be passed in via an onClick prop:

import React from 'react';

export default props => <button onClick={props.onClick}>Add User</button>;

In the following example, we’ll create a div with a “top-toolbar” container holding a single “Add User” button:

import React, { Component } from 'react';
import Button from './Button';
import './App.css';

class App extends Component {
  render () {
    return (
      <div className="top-toolbar">
        <Button onClick={this.handleAddUser}>Add User</Button>
      </div>
    );
  }
  handleAddUser = () => {
    // handle button click
    console.log('add user');
  };
}

export default App;

Some CSS to round out our example:

.top-toolbar {
  padding: 8px 12px;
  background: #3d76b5;
}
Ext JS to React: Button, Simple

Here, using pure HTML, we define a view with a child toolbar that contains the button. The button also has an onClick handler that executes a method on the main view.

You can review the sample code on the Git repo.

Adding an Icon to Button in React

To configure an Ext JS button with an icon, you’d add the iconCls config to the button:

tbar: [{
    text: 'Add User',
    iconCls: 'x-fa fa-user-plus',
    handler: 'onAddUser'
}]

React doesn’t contain an icon set. You’ll have to define your own or use one a pre-build solution such as FontAwesome. Luckily, FontAwesome has a React module available to lend a hand. First, install the necessary modules:

npm i --save @fortawesome/fontawesome
npm i --save @fortawesome/react-fontawesome
npm i --save @fortawesome/fontawesome-free-solid

Next, we can create our button using FontAwesome icons:

import React, { Component } from 'react';
import FontAwesome from '@fortawesome/react-fontawesome';
import { faUserPlus } from '@fortawesome/fontawesome-free-solid';
import './App.css';

class App extends Component {
  render () {
    const style = {
      marginRight: '12px' // inline style example
    };

    return (
      <div className="top-toolbar">
        <button onClick={this.handleAddUser}>
          <FontAwesome icon={faUserPlus} style={style} />
          Add User
        </button>
      </div>
    );
  }
  handleAddUser = () => {
    // handle button click
    console.log('add user');
  }
}

export default App;
Ext JS to React: Button, Icon

You can review the sample code on the Git repo.

React Button with a Child Menu

Buttons can be more than just text and an icon. It’s common for buttons to have a menu attached to allow the user to select from different options. In Ext JS, you can do something like:

tbar: [{
    text: 'User Controls',
    iconCls: 'x-fa fa-user-plus',
    menu: [{
        text: 'Add User',
        handler: 'onAddUser'
    }, '-', {
        text: 'Remove User',
        handler: 'onRemoveUser'
    }]
}]

With React, you can create a menu component and position it with a positioning library like react-popper. However, you may also opt to use a pre-built solution such as semantic-ui-react. Semantic UI is a larger component library that has, amongst other things, a set of button controls we can put to good use here. Let’s take a look at the Semantic UI button / menu combo in the following example:

// install the following packages
// npm install semantic-ui-react
// npm install semantic-ui-css

import React, { Component } from 'react';
import { Dropdown } from 'semantic-ui-react';
import 'semantic-ui-css/semantic.min.css';
import './App.css';

const { Divider, Item, Menu } = Dropdown;

class App extends Component {
  render () {
    return (
      <div className="top-toolbar">
        <Dropdown
          text="User Controls"
          icon="add user"
          className="icon"
          floating labeled button
        >
          <Menu>
            <Item onClick={this.handleAddUser}>Add User</Item>
            <Divider />
            <Item onClick={this.handleRemoveUser}>Remove User</Item>
          </Menu>
        </Dropdown>
      </div>
    );
  }
  
  handleAddUser = () => {
    // handle menu item click
    console.log('add user')
  }
  handleRemoveUser = () => {
    // handle menu item click
    console.log('remove user');
  }
}

export default App;
Ext JS to React: Buttons, Advanced

Writing your own button and menu views is certainly a viable option, but Semantic UI shows us there’s some great pre-built solutions in the React ecosystem you may want to check out when considering a move from Ext JS. The kendo-react-ui and react-bootstrap libraries also have similar controls and are definitely worth investigating.

You can review the sample code on the Git repo.

React Segmented Button

Another popular use of buttons is to group them and show them as pressed or not pressed. To coordinate the pressed state we’ll define a SegmentedButton component as a container with any number of button child nodes.

import React, {Component} from 'react';
import './SegmentedButton.css';

class SegmentedButton extends Component {
  static defaultProps = {
    pressed: [],
    allowDepress: false
  }
  state = {
    pressed: this.props.pressed
  }
  componentWillReceiveProps ({ pressed }) {
    this.setState({ pressed });
  }
  render() {
    const { pressed } = this.state;
    const { onClick } = this.props;
    return (
      <div
        className="button-group"
        onClick={this.onClick.bind(this, onClick)}
      >
        {/* loop over the child buttons and decorate pressed
        buttons with the className of "btn-pressed" */}
        {this.props.children.map(btn => {
          const { props } = btn;
          const { value } = props;
          const className = pressed.includes(value) ? 'btn-pressed' : '';
          
          // use cloneElement to apply our own
          // props over the button's props
          return React.cloneElement(btn, {
            ...props,
            key: value,
            className
          });
        })}
      </div>
    );
  }
  onClick (handler, e) {
    // call the onClick handler if one was passed in
    if (handler && typeof handler === 'function') {
      handler.call(this, e);
    }
    const { allowDepress } = this.props;
    const { target: btn } = e;
    const { tagName } = btn;
    let pressedState = this.state.pressed.slice(0);
    
    if (tagName === 'BUTTON') {
      const { value } = btn;
      const valIndex = pressedState.indexOf(value);
      const isPressed = valIndex !== -1;
      // toggle the "pressed" button state
      if (isPressed) {
        if (allowDepress || (!allowDepress && pressedState.length > 1)) {
          pressedState = pressedState.filter(item => item !== value);
        }
      } else {
        pressedState = [...pressedState, value];
      }
      this.setState({
        pressed: pressedState 
      });
    }
  }
}

export default SegmentedButton;

Segmented Button Class Explained

Our class’s defaultProps, state, and componentWillReceiveProps members set the state of the component based on passed props or user interaction with the component. The render method creates a container for the buttons passed in and applies the “pressed” className to any buttons whose values are found in this.state.pressed. Finally, we have the onClick handler that sets the “pressed” state of the button. Additionally, it will call any onClick handler passed to SegmentedButton so that our click handler doesn’t stomp any onClick prop passed in on the component instance.

Creating an instance of our SegmentedButton is then very straightforward. The allowDepress, pressed array, and onClick handler props are all optionally available.

import React from 'react';
import SegmentedButton from './SegmentedButton';
import './App.css';

const App = () => {
  return (
    <SegmentedButton>
      <button value="one">One</button>
      <button value="two">Two</button>
      <button value="three">Three</button>
    </SegmentedButton>
  );
}

export default App;

Segmented Button CSS

Below is the {appRoot}/src/SegmentedButton.css used to style the segmented buttons:

.button-group {
  display: inline-block;
}
.button-group button {
  background-color: #3094bb;
  border: 1px solid #166e90;
  color: white;
  padding: 8px 22px;
  cursor: pointer;
  border-radius: 0;
  font-size: 14px;
}
.button-group > button:not(:last-child) {
  border-right: none;
}
.button-group > button:first-of-type {
  border-top-left-radius: 3px;
  border-bottom-left-radius: 3px;
}.button-group > button:last-child {
  border-top-right-radius: 3px;
  border-bottom-right-radius: 3px;
}
.button-group button:hover {
  background-color: #40a4cc;
}
.btn-pressed {
  background-color: #267696 !important;
}
Ext JS to React: Button, Segmented

You can review the sample code on the Git repo.

Conclusion

Buttons are often one of the more underappreciated components in our grab bag of views used all over our applications. At first blush you might think “yes, a button… I get it.” But with a little creativity, we see how buttons can play well together to control / reveal the state of a view in a segmented configuration. It can open a menu or other context popup, revealing fresh real estate for the user to engage. In this article, we’ve revealed a few of the ways you can recreate various Ext JS button types in React. However, there’s certainly more implementations that could be explored: cycle button, split button, etc. Perhaps you’ve found an existing third-party solution yourself you’d like to share? Please, feel free to post your own successes and findings in the comments below!

Posted in Application Development
Share this

Mitchell Simoens

Mitchell Simoens is a Senior Front End Engineer at Modus Create. Mitchell has spent the last 10 years working with Ext JS including developing core functionality, Sencha Fiddle and (I hope your insurance covers blown minds) supporting the online community with over 40,000 posts on the Sencha Forums. Before working with Ext JS, Mitchell used Perl and PHP but loves spending time with Node JS for today's needs. When not working, you can find Mitchell relaxing with his wife and daughter, or developing his talents as an amateur furniture maker.
Follow

Related Posts

  • React Landing
    Ext JS to React: Migration to Open Source

    Worried about Migrating from Ext JS? Modus has the Answers Idera’s acquisition of Sencha has…

  • Ext JS to React: FAQ
    Ext JS to React: FAQ

    This is part of the Ext JS to React blog series. React is Facebook's breakout…

Want more insights to fuel your innovation efforts?

Sign up to receive our monthly newsletter and exclusive content about digital transformation and product development.

What we do

Our services
AI and data
Product development
Design and UX
IT modernization
Platform and MLOps
Developer experience
Security

Our partners
Atlassian
AWS
GitHub
Other partners

Who we are

Our story
Careers
Open source

Our work

Our case studies

Our resources

Blog
Innovation podcast
Guides & playbooks

Connect with us

Get monthly insights on AI adoption

© 2025 Modus Create, LLC

Privacy PolicySitemap
Scroll To Top
  • Services
  • Work
  • Blog
  • Resources
    • Innovation Podcast
    • Guides & Playbooks
  • Who we are
    • Our story
    • Careers
  • Let’s talk
  • EN
  • FR