DataView Menu is designed to show menu elements focused in icons in form of button. The items property can be object with ‘defaults’ and ‘items’ configs or just array of items, similar to other ExtJS component items property. Here implemented only one new ‘iconItemClick’ event. I hope the code of ‘app.view.toolbar.cmp.application.Button’ is enough simple and you will be able to redesign it to your according to your needs.

To use it you will need button class (‘app.view.toolbar.cmp.application.Button’) and DataView class (‘app.view.toolbar.cmp.application.DataView’). I have not implemented it in one class to keep the code simple and readable.

Button class:

Ext.define('app.view.toolbar.cmp.application.Button', {
    extend: 'Ext.button.Button',
    requires: [
        'app.view.toolbar.cmp.application.DataView'
    ],

    initComponent: function () {
        this.on('click', this.showDataView, this);
        this.callParent();
    },

    showDataView: function (button, e, eOpt) {
        var dataView = this.getApplicationDataView(),
            isPointerEvent = !e || e.pointerType;

        if (dataView && this.rendered) {
            if (this.tooltip && Ext.quickTipsActive && this.getTipAttr() !== 'title') {
                Ext.tip.QuickTipManager.getQuickTip().cancelShow(this.el);
            }

            if (dataView.isVisible()) {
                if (isPointerEvent) {
                    dataView.hide();
                } else {
                    dataView.focus();
                }
            } else if (!e || this.showEmptyMenu || dataView.getStore().getCount() > 0) {
                dataView.autoFocus = !isPointerEvent;
                dataView.showBy(this.el, this.menuAlign);
                dataView.show();
            }
        }
        return this;
    },

    getApplicationDataView: function () {
        if (!this.applicationDataView) {
            var dataViewConfig = Ext.apply({
                items: this.items,
                hidden: true,
                listeners: {
                    'iconItemClick': {
                        fn: this.onIconItemClick,
                        scope: this
                    }
                },
            }, this.dataViewConfig);
            this.applicationDataView = Ext.create('app.view.toolbar.cmp.application.DataView', dataViewConfig);
        }
        return this.applicationDataView;
    },

    onIconItemClick: function(record, item) {
        this.fireEvent('iconitemclick', this, record, item);
    },

    handler: Ext.emptyFn
});

DataView class:

Ext.define('app.view.toolbar.cmp.application.DataView', {
    extend: 'Ext.view.View',

    floating: true,
    numbderOfColumns: 3,
    scrollable: true,
    cls: Ext.baseCSSPrefix + 'panel-body-default',
    itemSelector: 'div.thumb-wrap',

    initComponent: function () {
        this.tpl = this.createXTempalte();
        this.store = this.createStore();
        this.initEvents();
        this.callParent();
    },

    initEvents: function() {
        this.on('itemclick', this.onIconItemClick, this);
        this.on('blur', this.onBlur, this);
    },

    onIconItemClick: function(dataView, record, item, index, e, eOpt) {
        this.fireEvent('iconItemClick', record, item);
        this.hide();
        e.stopEvent();
    },

    onBlur: function(cmp, e, eOpt) {
        this.hide();
    },

    createXTempalte: function() {
        var me = this;
        var xTemplate = new Ext.XTemplate(
            '<table>',
            '<tpl for=".">',
                '<tpl if="this.showOpenTr(xindex)">',
                    '<tr>',
                '</tpl>',
                    '<td style="padding: 10px; text-align: center;" >',
                        '<div style="cursor: pointer;" class="thumb-wrap">',
                            '<span style="font-family: {fontFamily}; font-size: {iconSize}; color: {iconColor}">&#{uniCode};</span>',
                            '<br/><span style="">{text}</span>',
                        '</div>',
                    '</td>',
                '<tpl if="this.showCloseTr(xindex, xcount)">',
                    '</tr>',
                '</tpl>',

            '</tpl>',
            '</table>',
            {
                showOpenTr: function(xIndex) {
                    return xIndex === 0 && xIndex % me.numbderOfColumns === 0;
                },

                showCloseTr: function(xIndex, xCount) {
                    return xIndex === xCount || xIndex % me.numbderOfColumns === 0;
                }
            }
        );
        return xTemplate;
    },

    createStore: function () {
        var store = Ext.create('Ext.data.Store', {
            fields: [
                'text',
                'uniCode',
                'fontFamily',
                'iconSize',
                'iconColor'
            ]
        }), items = [], unicode, fontFamily;

        if(this.items && Ext.isObject(this.items) && Ext.isArray(this.items.items)) {
            this.items.defaults = this.items.defaults || {};
            Ext.Array.each(this.items.items, function(item, index) {
                items.push(Ext.apply(item, this.items.defaults));
            }, this);
        } else {
            items = this.items;
        }
        Ext.Array.each(items, function(item) {
            [unicode, fontFamily] = item.glyph.split('@');
            store.add({
                text: item.text,
                uniCode: unicode,
                fontFamily: fontFamily,
                iconSize: item.iconSize,
                iconColor: item.iconColor,
                glyph: item.glyph,
                handler: item.handler || false,
                scope: item.scope
            });
        });
        return store;
    },

    setOwnerCmp: function (comp, instanced) {},

    getCount() {
        return this.getStore().getCount();
    }
});

And the fiddle application.