Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Menu / Split button #1800

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3079,6 +3079,7 @@ possible breaking changes to any direct/custom use of AG Grid APIs and props wit

### 🎁 New Features

* New `SplitButton` component added to button component collection.
* GridModel `groupSortFn` now accepts `null` to turn off sorting of group rows.
* `DockViewModel` now supports optional `width`, `height` and `collapsedWidth` configs.
* The `appMenuButton.extraItems` prop now accepts `MenuItem` configs (as before) but also React
Expand Down
4 changes: 2 additions & 2 deletions desktop/cmp/button/Button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@
border-radius: 0;
&.xh-button--standard,
&.xh-button--outlined {
&:first-child {
&:first-child:not(.xh-split-button__trigger-right) {
border-bottom-left-radius: var(--xh-button-border-radius-px);
border-top-left-radius: var(--xh-button-border-radius-px);
}

&:last-child {
&:last-child:not(.xh-split-button__trigger-left) {
border-bottom-right-radius: var(--xh-button-border-radius-px);
border-top-right-radius: var(--xh-button-border-radius-px);
}
Expand Down
6 changes: 6 additions & 0 deletions desktop/cmp/button/SplitButton.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.xh-split-button {
&__trigger {
width: 22px;
min-width: 22px;
}
}
110 changes: 110 additions & 0 deletions desktop/cmp/button/SplitButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {hoistCmp, MenuItemLike} from '@xh/hoist/core';
import {button, buttonGroup, ButtonProps} from '@xh/hoist/desktop/cmp/button';
import {Icon} from '@xh/hoist/icon';
import {menu, menuItem, popover} from '@xh/hoist/kit/blueprint';
import {wait} from '@xh/hoist/promise';
import classNames from 'classnames';
import {castArray} from 'lodash';
import './SplitButton.scss';

/**
* A split button combines a primary action button with an integrated menu of secondary actions.
*/

export interface SplitButtonProps extends ButtonProps {
menuItems: MenuItemLike[];
menuSide?: 'left' | 'right';
}
export const [SplitButton, splitButton] = hoistCmp.withFactory<SplitButtonProps>({
displayName: 'SplitButton',
model: false,
memo: false,
observer: false,

render({
menuItems = [],
menuSide = 'right',
disabled,
intent,
minimal = false,
className,
...rest
}) {
menuItems = castArray(menuItems);
const noMenu = !menuItems.length;

return buttonGroup({
className: classNames(className, 'xh-split-button'),
items: [
menuTriggerButton({
omit: noMenu || menuSide == 'right',
menuItems,
menuSide,
className,
disabled,
intent,
minimal
}),
primaryButton({disabled, intent, minimal, ...rest}),
menuTriggerButton({
omit: noMenu || menuSide == 'left',
menuItems,
menuSide,
className,
disabled,
intent,
minimal
})
]
});
}
});

const primaryButton = hoistCmp.factory<ButtonProps>({
displayName: 'SplitButtonPrimary',
model: false,
memo: false,
observer: false,

render(props) {
return button({
className: 'xh-split-button__primary',
...props
});
}
});

const menuTriggerButton = hoistCmp.factory({
displayName: 'SplitButtonTrigger',
model: false,
memo: false,
observer: false,

render({menuItems, menuSide, className, disabled, intent, minimal}) {
return popover({
position: `bottom-${menuSide}`,
minimal: true,
disabled,
target: button({
icon: Icon.chevronDown({prefix: 'fas'}),
className: `xh-split-button__trigger-${menuSide}`,
disabled,
intent,
minimal
}),
content: menu({
className: classNames(className, 'xh-split-button__menu'),
items: menuItems.map((item, idx) => {
const {actionFn, ...rest} = item;

return menuItem({
key: idx,
className: classNames(item.className, 'xh-split-button__menu-item'),
onClick: actionFn ? () => wait().then(actionFn) : null, // do async to allow menu to close
...rest
});
})
})
});
}
});
1 change: 1 addition & 0 deletions desktop/cmp/button/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export * from './ModalToggleButton';
export * from './OptionsButton';
export * from './RefreshButton';
export * from './RestoreDefaultsButton';
export * from './SplitButton';
export * from './ThemeToggleButton';
Loading