Group buttons in the thread toolbar for nicer layout
|
@ -1,83 +0,0 @@
|
||||||
const { Actions, AccountStore, React, PropTypes, WorkspaceStore } = require('mailspring-exports');
|
|
||||||
const { RetinaImg, KeyCommandsRegion } = require('mailspring-component-kit');
|
|
||||||
|
|
||||||
const LabelPickerPopover = require('./label-picker-popover').default;
|
|
||||||
|
|
||||||
// This changes the category on one or more threads.
|
|
||||||
class LabelPicker extends React.Component {
|
|
||||||
static displayName = 'LabelPicker';
|
|
||||||
static containerRequired = false;
|
|
||||||
static propTypes = { items: PropTypes.array };
|
|
||||||
static contextTypes = { sheetDepth: PropTypes.number };
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this._account = AccountStore.accountForItems(this.props.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the threads we're picking categories for change, (like when they
|
|
||||||
// get their categories updated), we expect our parents to pass us new
|
|
||||||
// props. We don't listen to the DatabaseStore ourselves.
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
return (this._account = AccountStore.accountForItems(nextProps.items));
|
|
||||||
}
|
|
||||||
|
|
||||||
_keymapHandlers() {
|
|
||||||
return { 'core:change-labels': this._onOpenCategoryPopover };
|
|
||||||
}
|
|
||||||
|
|
||||||
_onOpenCategoryPopover = () => {
|
|
||||||
if (!(this.props.items.length > 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const buttonRect = this._buttonEl.getBoundingClientRect();
|
|
||||||
Actions.openPopover(<LabelPickerPopover threads={this.props.items} account={this._account} />, {
|
|
||||||
originRect: buttonRect,
|
|
||||||
direction: 'down',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (!this._account) {
|
|
||||||
return <span />;
|
|
||||||
}
|
|
||||||
if (!this._account.usesLabels()) {
|
|
||||||
return <span />;
|
|
||||||
}
|
|
||||||
const btnClasses = 'btn btn-toolbar btn-category-picker';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<KeyCommandsRegion
|
|
||||||
style={{ order: -103 }}
|
|
||||||
globalHandlers={this._keymapHandlers()}
|
|
||||||
globalMenuItems={[
|
|
||||||
{
|
|
||||||
label: 'Thread',
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: 'Apply Labels...',
|
|
||||||
command: 'core:change-labels',
|
|
||||||
position: 'endof=thread-actions',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
tabIndex={-1}
|
|
||||||
ref={el => (this._buttonEl = el)}
|
|
||||||
title={'Apply Labels'}
|
|
||||||
onClick={this._onOpenCategoryPopover}
|
|
||||||
className={btnClasses}
|
|
||||||
>
|
|
||||||
<RetinaImg name={'toolbar-tag.png'} mode={RetinaImg.Mode.ContentIsMask} />
|
|
||||||
</button>
|
|
||||||
</KeyCommandsRegion>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = LabelPicker;
|
|
|
@ -1,17 +1,12 @@
|
||||||
const MovePicker = require('./move-picker');
|
const ToolbarCategoryPicker = require('./toolbar-category-picker');
|
||||||
const LabelPicker = require('./label-picker');
|
|
||||||
|
|
||||||
const { ComponentRegistry } = require('mailspring-exports');
|
const { ComponentRegistry } = require('mailspring-exports');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
activate(state = {}) {
|
activate() {
|
||||||
this.state = state;
|
ComponentRegistry.register(ToolbarCategoryPicker, { role: 'ThreadActionsToolbarButton' });
|
||||||
ComponentRegistry.register(MovePicker, { role: 'ThreadActionsToolbarButton' });
|
|
||||||
ComponentRegistry.register(LabelPicker, { role: 'ThreadActionsToolbarButton' });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
deactivate() {
|
deactivate() {
|
||||||
ComponentRegistry.unregister(MovePicker);
|
ComponentRegistry.unregister(ToolbarCategoryPicker);
|
||||||
ComponentRegistry.unregister(LabelPicker);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
const { Actions, React, PropTypes, AccountStore, WorkspaceStore } = require('mailspring-exports');
|
|
||||||
const { RetinaImg, KeyCommandsRegion } = require('mailspring-component-kit');
|
|
||||||
|
|
||||||
const MovePickerPopover = require('./move-picker-popover').default;
|
|
||||||
|
|
||||||
// This sets the folder / label on one or more threads.
|
|
||||||
class MovePicker extends React.Component {
|
|
||||||
static displayName = 'MovePicker';
|
|
||||||
static containerRequired = false;
|
|
||||||
|
|
||||||
static propTypes = { items: PropTypes.array };
|
|
||||||
static contextTypes = { sheetDepth: PropTypes.number };
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this._account = AccountStore.accountForItems(this.props.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the threads we're picking categories for change, (like when they
|
|
||||||
// get their categories updated), we expect our parents to pass us new
|
|
||||||
// props. We don't listen to the DatabaseStore ourselves.
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
this._account = AccountStore.accountForItems(nextProps.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
_keymapHandlers() {
|
|
||||||
return { 'core:change-folders': this._onOpenCategoryPopover };
|
|
||||||
}
|
|
||||||
|
|
||||||
_onOpenCategoryPopover = () => {
|
|
||||||
if (!(this.props.items.length > 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const buttonRect = this._buttonEl.getBoundingClientRect();
|
|
||||||
Actions.openPopover(<MovePickerPopover threads={this.props.items} account={this._account} />, {
|
|
||||||
originRect: buttonRect,
|
|
||||||
direction: 'down',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (!this._account) {
|
|
||||||
return <span />;
|
|
||||||
}
|
|
||||||
const btnClasses = 'btn btn-toolbar btn-category-picker';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<KeyCommandsRegion
|
|
||||||
style={{ order: -103 }}
|
|
||||||
globalHandlers={this._keymapHandlers()}
|
|
||||||
globalMenuItems={[
|
|
||||||
{
|
|
||||||
label: 'Thread',
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: 'Move to Folder...',
|
|
||||||
command: 'core:change-folders',
|
|
||||||
position: 'endof=thread-actions',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
tabIndex={-1}
|
|
||||||
ref={el => (this._buttonEl = el)}
|
|
||||||
title={'Move to Folder'}
|
|
||||||
onClick={this._onOpenCategoryPopover}
|
|
||||||
className={btnClasses}
|
|
||||||
>
|
|
||||||
<RetinaImg name={'toolbar-movetofolder.png'} mode={RetinaImg.Mode.ContentIsMask} />
|
|
||||||
</button>
|
|
||||||
</KeyCommandsRegion>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = MovePicker;
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
const { Actions, React, PropTypes, AccountStore, WorkspaceStore } = require('mailspring-exports');
|
||||||
|
const { RetinaImg, KeyCommandsRegion } = require('mailspring-component-kit');
|
||||||
|
|
||||||
|
const MovePickerPopover = require('./move-picker-popover').default;
|
||||||
|
const LabelPickerPopover = require('./label-picker-popover').default;
|
||||||
|
|
||||||
|
// This sets the folder / label on one or more threads.
|
||||||
|
class MovePicker extends React.Component {
|
||||||
|
static displayName = 'MovePicker';
|
||||||
|
static containerRequired = false;
|
||||||
|
|
||||||
|
static propTypes = { items: PropTypes.array };
|
||||||
|
static contextTypes = { sheetDepth: PropTypes.number };
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._account = AccountStore.accountForItems(this.props.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the threads we're picking categories for change, (like when they
|
||||||
|
// get their categories updated), we expect our parents to pass us new
|
||||||
|
// props. We don't listen to the DatabaseStore ourselves.
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
this._account = AccountStore.accountForItems(nextProps.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onOpenLabelsPopover = () => {
|
||||||
|
if (!(this.props.items.length > 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Actions.openPopover(<LabelPickerPopover threads={this.props.items} account={this._account} />, {
|
||||||
|
originRect: this._labelEl.getBoundingClientRect(),
|
||||||
|
direction: 'down',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_onOpenMovePopover = () => {
|
||||||
|
if (!(this.props.items.length > 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Actions.openPopover(<MovePickerPopover threads={this.props.items} account={this._account} />, {
|
||||||
|
originRect: this._moveEl.getBoundingClientRect(),
|
||||||
|
direction: 'down',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (!this._account) {
|
||||||
|
return <span />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlers = {
|
||||||
|
'core:change-folders': this._onOpenMovePopover,
|
||||||
|
};
|
||||||
|
const submenu = [
|
||||||
|
{
|
||||||
|
label: 'Move to Folder...',
|
||||||
|
command: 'core:change-folders',
|
||||||
|
position: 'endof=thread-actions',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (this._account.usesLabels()) {
|
||||||
|
Object.assign(handlers, {
|
||||||
|
'core:change-labels': this._onOpenLabelsPopover,
|
||||||
|
});
|
||||||
|
|
||||||
|
submenu.push({
|
||||||
|
label: 'Apply Labels...',
|
||||||
|
command: 'core:change-labels',
|
||||||
|
position: 'endof=thread-actions',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="button-group" style={{ order: -103 }}>
|
||||||
|
<KeyCommandsRegion
|
||||||
|
globalHandlers={handlers}
|
||||||
|
globalMenuItems={[{ label: 'Thread', submenu: submenu }]}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
tabIndex={-1}
|
||||||
|
ref={el => (this._moveEl = el)}
|
||||||
|
title={'Move to Folder'}
|
||||||
|
onClick={this._onOpenMovePopover}
|
||||||
|
className={'btn btn-toolbar btn-category-picker'}
|
||||||
|
>
|
||||||
|
<RetinaImg name={'toolbar-movetofolder.png'} mode={RetinaImg.Mode.ContentIsMask} />
|
||||||
|
</button>
|
||||||
|
{this._account.usesLabels() && (
|
||||||
|
<button
|
||||||
|
tabIndex={-1}
|
||||||
|
ref={el => (this._labelEl = el)}
|
||||||
|
title={'Apply Labels'}
|
||||||
|
onClick={this._onOpenLabelsPopover}
|
||||||
|
className={'btn btn-toolbar btn-category-picker'}
|
||||||
|
>
|
||||||
|
<RetinaImg name={'toolbar-tag.png'} mode={RetinaImg.Mode.ContentIsMask} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</KeyCommandsRegion>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = MovePicker;
|
|
@ -6,15 +6,7 @@ import ThreadListEmptyFolderBar from './thread-list-empty-folder-bar';
|
||||||
import MessageListToolbar from './message-list-toolbar';
|
import MessageListToolbar from './message-list-toolbar';
|
||||||
import SelectedItemsStack from './selected-items-stack';
|
import SelectedItemsStack from './selected-items-stack';
|
||||||
|
|
||||||
import {
|
import { UpButton, DownButton, MoveButtons, FlagButtons } from './thread-toolbar-buttons';
|
||||||
UpButton,
|
|
||||||
DownButton,
|
|
||||||
TrashButton,
|
|
||||||
ArchiveButton,
|
|
||||||
MarkAsSpamButton,
|
|
||||||
ToggleUnreadButton,
|
|
||||||
ToggleStarredButton,
|
|
||||||
} from './thread-toolbar-buttons';
|
|
||||||
|
|
||||||
export function activate() {
|
export function activate() {
|
||||||
ComponentRegistry.register(ThreadListEmptyFolderBar, {
|
ComponentRegistry.register(ThreadListEmptyFolderBar, {
|
||||||
|
@ -50,23 +42,11 @@ export function activate() {
|
||||||
modes: ['list'],
|
modes: ['list'],
|
||||||
});
|
});
|
||||||
|
|
||||||
ComponentRegistry.register(ArchiveButton, {
|
ComponentRegistry.register(MoveButtons, {
|
||||||
role: 'ThreadActionsToolbarButton',
|
role: 'ThreadActionsToolbarButton',
|
||||||
});
|
});
|
||||||
|
|
||||||
ComponentRegistry.register(TrashButton, {
|
ComponentRegistry.register(FlagButtons, {
|
||||||
role: 'ThreadActionsToolbarButton',
|
|
||||||
});
|
|
||||||
|
|
||||||
ComponentRegistry.register(MarkAsSpamButton, {
|
|
||||||
role: 'ThreadActionsToolbarButton',
|
|
||||||
});
|
|
||||||
|
|
||||||
ComponentRegistry.register(ToggleStarredButton, {
|
|
||||||
role: 'ThreadActionsToolbarButton',
|
|
||||||
});
|
|
||||||
|
|
||||||
ComponentRegistry.register(ToggleUnreadButton, {
|
|
||||||
role: 'ThreadActionsToolbarButton',
|
role: 'ThreadActionsToolbarButton',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -76,11 +56,8 @@ export function deactivate() {
|
||||||
ComponentRegistry.unregister(SelectedItemsStack);
|
ComponentRegistry.unregister(SelectedItemsStack);
|
||||||
ComponentRegistry.unregister(ThreadListToolbar);
|
ComponentRegistry.unregister(ThreadListToolbar);
|
||||||
ComponentRegistry.unregister(MessageListToolbar);
|
ComponentRegistry.unregister(MessageListToolbar);
|
||||||
ComponentRegistry.unregister(ArchiveButton);
|
ComponentRegistry.unregister(MoveButtons);
|
||||||
ComponentRegistry.unregister(TrashButton);
|
ComponentRegistry.unregister(FlagButtons);
|
||||||
ComponentRegistry.unregister(MarkAsSpamButton);
|
|
||||||
ComponentRegistry.unregister(ToggleUnreadButton);
|
|
||||||
ComponentRegistry.unregister(ToggleStarredButton);
|
|
||||||
ComponentRegistry.unregister(UpButton);
|
ComponentRegistry.unregister(UpButton);
|
||||||
ComponentRegistry.unregister(DownButton);
|
ComponentRegistry.unregister(DownButton);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { RetinaImg } from 'mailspring-component-kit';
|
import { RetinaImg, CreateButtonGroup } from 'mailspring-component-kit';
|
||||||
import {
|
import {
|
||||||
Actions,
|
Actions,
|
||||||
TaskFactory,
|
TaskFactory,
|
||||||
|
@ -33,17 +33,11 @@ export class ArchiveButton extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const allowed = FocusedPerspectiveStore.current().canArchiveThreads(this.props.items);
|
const allowed = FocusedPerspectiveStore.current().canArchiveThreads(this.props.items);
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
return <span />;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button tabIndex={-1} className="btn btn-toolbar" title="Archive" onClick={this._onArchive}>
|
||||||
tabIndex={-1}
|
|
||||||
style={{ order: -107 }}
|
|
||||||
className="btn btn-toolbar"
|
|
||||||
title="Archive"
|
|
||||||
onClick={this._onArchive}
|
|
||||||
>
|
|
||||||
<RetinaImg name="toolbar-archive.png" mode={RetinaImg.Mode.ContentIsMask} />
|
<RetinaImg name="toolbar-archive.png" mode={RetinaImg.Mode.ContentIsMask} />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -72,13 +66,12 @@ export class TrashButton extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const allowed = FocusedPerspectiveStore.current().canMoveThreadsTo(this.props.items, 'trash');
|
const allowed = FocusedPerspectiveStore.current().canMoveThreadsTo(this.props.items, 'trash');
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
return <span />;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
style={{ order: -106 }}
|
|
||||||
className="btn btn-toolbar"
|
className="btn btn-toolbar"
|
||||||
title="Move to Trash"
|
title="Move to Trash"
|
||||||
onClick={this._onRemove}
|
onClick={this._onRemove}
|
||||||
|
@ -129,7 +122,6 @@ export class MarkAsSpamButton extends React.Component {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
style={{ order: -105 }}
|
|
||||||
className="btn btn-toolbar"
|
className="btn btn-toolbar"
|
||||||
title="Not Spam"
|
title="Not Spam"
|
||||||
onClick={this._onNotSpam}
|
onClick={this._onNotSpam}
|
||||||
|
@ -141,12 +133,11 @@ export class MarkAsSpamButton extends React.Component {
|
||||||
|
|
||||||
const allowed = FocusedPerspectiveStore.current().canMoveThreadsTo(this.props.items, 'spam');
|
const allowed = FocusedPerspectiveStore.current().canMoveThreadsTo(this.props.items, 'spam');
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
return <span />;
|
return false;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
style={{ order: -105 }}
|
|
||||||
className="btn btn-toolbar"
|
className="btn btn-toolbar"
|
||||||
title="Mark as Spam"
|
title="Mark as Spam"
|
||||||
onClick={this._onMarkAsSpam}
|
onClick={this._onMarkAsSpam}
|
||||||
|
@ -182,13 +173,7 @@ export class ToggleStarredButton extends React.Component {
|
||||||
const imageName = postClickStarredState ? 'toolbar-star.png' : 'toolbar-star-selected.png';
|
const imageName = postClickStarredState ? 'toolbar-star.png' : 'toolbar-star-selected.png';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button tabIndex={-1} className="btn btn-toolbar" title={title} onClick={this._onStar}>
|
||||||
tabIndex={-1}
|
|
||||||
style={{ order: -103 }}
|
|
||||||
className="btn btn-toolbar"
|
|
||||||
title={title}
|
|
||||||
onClick={this._onStar}
|
|
||||||
>
|
|
||||||
<RetinaImg name={imageName} mode={RetinaImg.Mode.ContentIsMask} />
|
<RetinaImg name={imageName} mode={RetinaImg.Mode.ContentIsMask} />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -222,7 +207,6 @@ export class ToggleUnreadButton extends React.Component {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
style={{ order: -104 }}
|
|
||||||
className="btn btn-toolbar"
|
className="btn btn-toolbar"
|
||||||
title={`Mark as ${fragment}`}
|
title={`Mark as ${fragment}`}
|
||||||
onClick={this._onClick}
|
onClick={this._onClick}
|
||||||
|
@ -284,6 +268,18 @@ class ThreadArrowButton extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const FlagButtons = CreateButtonGroup(
|
||||||
|
'FlagButtons',
|
||||||
|
[ToggleStarredButton, ToggleUnreadButton],
|
||||||
|
{ order: -103 }
|
||||||
|
);
|
||||||
|
|
||||||
|
export const MoveButtons = CreateButtonGroup(
|
||||||
|
'MoveButtons',
|
||||||
|
[ArchiveButton, MarkAsSpamButton, TrashButton],
|
||||||
|
{ order: -107 }
|
||||||
|
);
|
||||||
|
|
||||||
export const DownButton = () => {
|
export const DownButton = () => {
|
||||||
const getStateFromStores = () => {
|
const getStateFromStores = () => {
|
||||||
const selectedId = FocusedContentStore.focusedId('thread');
|
const selectedId = FocusedContentStore.focusedId('thread');
|
||||||
|
|
13
app/src/components/decorators/create-button-group.jsx
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function CreateButtonGroup(name, buttons, { order = 0 }) {
|
||||||
|
const fn = props => {
|
||||||
|
return (
|
||||||
|
<div className="button-group" style={{ order }}>
|
||||||
|
{buttons.map(Component => <Component key={Component.displayName} {...props} />)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
fn.displayName = name;
|
||||||
|
return fn;
|
||||||
|
}
|
|
@ -130,3 +130,4 @@ lazyLoad('ListensToObservable', 'decorators/listens-to-observable');
|
||||||
lazyLoad('ListensToFluxStore', 'decorators/listens-to-flux-store');
|
lazyLoad('ListensToFluxStore', 'decorators/listens-to-flux-store');
|
||||||
lazyLoad('ListensToMovementKeys', 'decorators/listens-to-movement-keys');
|
lazyLoad('ListensToMovementKeys', 'decorators/listens-to-movement-keys');
|
||||||
lazyLoad('HasTutorialTip', 'decorators/has-tutorial-tip');
|
lazyLoad('HasTutorialTip', 'decorators/has-tutorial-tip');
|
||||||
|
lazyLoad('CreateButtonGroup', 'decorators/create-button-group');
|
||||||
|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 455 B After Width: | Height: | Size: 48 KiB |
|
@ -269,6 +269,32 @@ body.is-blurred {
|
||||||
.btn-toolbar:only-of-type {
|
.btn-toolbar:only-of-type {
|
||||||
margin-right: @spacing-three-quarters;
|
margin-right: @spacing-three-quarters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
margin-left: @spacing-three-quarters;
|
||||||
|
.btn.btn-toolbar {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
|
||||||
|
// Using these (slower) selectors to avoid redeclaring any constants
|
||||||
|
// like default-case border radius that themes might be overriding.
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-right: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
&:not(:first-child) {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
border-left: 0;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.opacity-125ms-enter {
|
.opacity-125ms-enter {
|
||||||
|
|