Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
Fix Utility Menu auto closing issue (#315)
Browse files Browse the repository at this point in the history
* Fix Utility Menu Closing issue

* correction to this change https://github.com/cerner/terra-application/pull/306/files#diff-0ef2540a6737a57efa50a1f308a16a67b07f6b8f765027bdf9df1ef3a0e602c6

* Fix build issuee

* upadated selector

* removed additional function added for addding closingcallback for userAction

* jest update
  • Loading branch information
supreethmr authored Nov 10, 2022
1 parent 2906c4e commit ab98952
Show file tree
Hide file tree
Showing 23 changed files with 132 additions and 38 deletions.
2 changes: 2 additions & 0 deletions packages/terra-application/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Changelog

## Unreleased
* Fixed
* Fixed utility menu to close on userAction button click.

## 1.54.0 - (November 2, 2022)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ const ApplicationNavigation = ({
className={cx('drawer-menu-focus-trap-container')}
>
<DrawerMenu
menuClosingCallback={generateMenuClosingCallback}
titleConfig={titleConfig}
userConfig={userConfig}
userActionConfig={userActionConfig}
Expand Down Expand Up @@ -274,6 +275,7 @@ const ApplicationNavigation = ({
isContentFocusDisabled
>
<UtilityMenu
menuClosingCallback={generateMenuClosingCallback}
hero={hero}
userConfig={userConfig}
userActionConfig={userActionConfig}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ const propTypes = {
* A configuration object to render an action button for user Config.
*/
userActionConfig: userActionConfigPropType,
/**
* @private
* Given a callback function, menuClosingCallback will return a new function
* that will ensure that the various menu states are reset before the callback function
* is executed.
*/
menuClosingCallback: PropTypes.func,
};

const defaultProps = {
Expand All @@ -117,7 +124,19 @@ const defaultProps = {
};

const PopupMenu = ({
title, footerText, id, onSelectFooterItem, onSelectMenuItem, customContent, userConfig, menuItems, isHeightBounded, showSelections, role, userActionConfig,
title,
footerText,
id,
onSelectFooterItem,
menuClosingCallback,
onSelectMenuItem,
customContent,
userConfig,
menuItems,
isHeightBounded,
showSelections,
role,
userActionConfig,
}) => {
const listRef = useRef();
const buttonRef = useRef();
Expand Down Expand Up @@ -209,7 +228,7 @@ const PopupMenu = ({
{customContent}
</div>
) : undefined}
{userConfig ? <PopupMenuUser id={id && userActionItemId(id)} userActionConfig={userActionConfig} userConfig={userConfig} /> : null}
{userConfig ? <PopupMenuUser id={id && userActionItemId(id)} menuClosingCallback={menuClosingCallback} userActionConfig={userActionConfig} userConfig={userConfig} /> : null}
<ul className={cx('utility-list')} aria-label={title} ref={listRef} role={role} tabIndex="0" onKeyDown={handleKeyDown}>
{menuItems.map(item => (
<PopupMenuListItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,18 @@ const propTypes = {
* A configuration object with information pertaining to the application's user.
*/
userConfig: userConfigPropType.isRequired,
/**
* @private
* Given a callback function, menuClosingCallback will return a new function
* that will ensure that the various menu states are reset before the callback function
* is executed.
*/
menuClosingCallback: PropTypes.func,
};

const PopupMenuUser = ({ userConfig, userActionConfig, id }) => {
const PopupMenuUser = ({
userConfig, userActionConfig, id, menuClosingCallback,
}) => {
const theme = React.useContext(ThemeContext);

return (
Expand All @@ -43,15 +52,15 @@ const PopupMenuUser = ({ userConfig, userActionConfig, id }) => {
<div aria-hidden className={cx('name')}>{userConfig.name}</div>
{userConfig.detail ? <div className={cx('detail')}>{userConfig.detail}</div> : null}
{ userActionConfig && (
<Button
id={id || undefined}
text={userActionConfig.text}
onClick={userActionConfig.userActionCallback}
data-navigation-utility-item-logout
className={cx('action-button')}
variant="ghost"
isCompact
/>
<Button
id={id || undefined}
text={userActionConfig.text}
onClick={menuClosingCallback(userActionConfig.userActionCallback)}
data-navigation-popupmenu-item-user-action
className={cx('action-button')}
variant="ghost"
isCompact
/>
)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ const propTypes = {
* A configuration object to render an action button for user Config.
*/
userActionConfig: userActionConfigPropType,
/**
* @private
* Given a callback function, menuClosingCallback will return a new function
* that will ensure that the various menu states are reset before the callback function
* is executed.
*/
menuClosingCallback: PropTypes.func,
};

const defaultProps = {
Expand All @@ -116,9 +123,18 @@ const DrawerMenu = ({
notifications,
intl,
userActionConfig,
menuClosingCallback,
}) => {
const titleComponent = titleConfig && !(titleConfig.element || titleConfig.hideTitleWithinDrawerMenu) ? <DrawerMenuTitle titleConfig={titleConfig} /> : undefined;
const userComponent = userConfig ? <DrawerMenuUser id={id && userActionItemId(id)} userActionConfig={userActionConfig} userConfig={userConfig} variant={hero ? 'small' : 'large'} /> : undefined;
const userComponent = userConfig ? (
<DrawerMenuUser
id={id && userActionItemId(id)}
menuClosingCallback={menuClosingCallback}
userActionConfig={userActionConfig}
userConfig={userConfig}
variant={hero ? 'small' : 'large'}
/>
) : undefined;
const logoutButton = onSelectLogout ? (
<div className={cx('footer')}>
<DrawerMenuFooterButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,21 @@ const propTypes = {
* Size variant of the user. One of values [`small`, `large`].
*/
variant: PropTypes.oneOf(['small', 'large']),
/**
* @private
* Given a callback function, menuClosingCallback will return a new function
* that will ensure that the various menu states are reset before the callback function
* is executed.
*/
menuClosingCallback: PropTypes.func,
};

const defaultProps = {
variant: 'small',
};

const DrawerMenuUser = ({
userConfig, variant, userActionConfig, id,
userConfig, variant, userActionConfig, id, menuClosingCallback,
}) => {
const theme = React.useContext(ThemeContext);

Expand All @@ -54,17 +61,18 @@ const DrawerMenuUser = ({
<div aria-hidden className={cx('name')}>{userConfig.name}</div>
{userConfig.detail ? <div className={cx('detail')}>{userConfig.detail}</div> : null}
{ userActionConfig && (
<button
id={id || undefined}
className={cx('drawer-menu-action-button', theme.className)}
type="button"
onClick={userActionConfig.userActionCallback}
onBlur={enableFocusStyles}
onMouseDown={disableFocusStyles}
data-focus-styles-enabled
>
{userActionConfig.text}
</button>
<button
id={id || undefined}
className={cx('drawer-menu-action-button', theme.className)}
type="button"
onClick={menuClosingCallback(userActionConfig.userActionCallback)}
onBlur={enableFocusStyles}
onMouseDown={disableFocusStyles}
data-focus-styles-enabled
data-navigation-drawermenu-item-user-action
>
{userActionConfig.text}
</button>
)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ const propTypes = {
* A configuration object to render an action button for user Config.
*/
userActionConfig: userActionConfigPropType,
/**
* @private
* Given a callback function, menuClosingCallback will return a new function
* that will ensure that the various menu states are reset before the callback function
* is executed.
*/
menuClosingCallback: PropTypes.func,
};

const defaultProps = {
Expand All @@ -71,7 +78,7 @@ const utilityMenuSettingsKey = 'terra-application-navigation.utility-menu.settin
const utilityMenuHelpKey = 'terra-application-navigation.utility-menu.help';

const UtilityMenu = ({
userConfig, hero, onSelectSettings, onSelectHelp, onSelectLogout, utilityItems, id, onSelectUtilityItem, isHeightBounded, intl, userActionConfig,
userConfig, hero, onSelectSettings, onSelectHelp, menuClosingCallback, onSelectLogout, utilityItems, id, onSelectUtilityItem, isHeightBounded, intl, userActionConfig,
}) => {
let menuItems = [];
menuItems = utilityItems.map(item => ({
Expand Down Expand Up @@ -109,6 +116,7 @@ const UtilityMenu = ({
title={intl.formatMessage({ id: 'terraApplication.navigation.utilityMenu.headerTitle' })}
footerText={intl.formatMessage({ id: 'terraApplication.navigation.utilityMenu.logout' })}
onSelectFooterItem={onSelectLogout}
menuClosingCallback={menuClosingCallback}
userConfig={userConfig}
userActionConfig={userActionConfig}
customContent={hero}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ const userConfig = {
initials: 'TN',
};

const userActionConfig = {
text: 'Edit Photo',
// eslint-disable-next-line no-console
userActionCallback: () => console.log('Button Clicked'),
};

const extensionItems = [
{
icon: <IconSearch />,
Expand Down Expand Up @@ -141,6 +135,12 @@ function ApplicationNavigationTest() {
const [isDrawerOpen, setDrawerOpen] = useState(false);
const [functionType, setFunctionType] = useState('');

const userActionConfig = {
text: 'Edit Photo',
// eslint-disable-next-line no-alert
userActionCallback: () => setFunctionType('userActionButton was clicked'),
};

/* eslint-disable no-alert */
const handleItemSelection = (key, metaData) => {
alert(`itemKey: ${key}, metaData: ${metaData.test}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ exports[`ApplicationNavigation correctly applies the theme context className 1`]
className="drawer-menu-focus-trap-container"
>
<InjectIntl(DrawerMenu)
menuClosingCallback={[Function]}
notifications={Object {}}
utilityItems={Array []}
>
Expand Down Expand Up @@ -105,6 +106,7 @@ exports[`ApplicationNavigation correctly applies the theme context className 1`]
"timeZone": null,
}
}
menuClosingCallback={[Function]}
navigationItems={Array []}
notifications={Object {}}
utilityItems={Array []}
Expand Down Expand Up @@ -355,6 +357,7 @@ exports[`ApplicationNavigation should render default element 1`] = `
targetRef={[Function]}
>
<InjectIntl(UtilityMenu)
menuClosingCallback={[Function]}
utilityItems={Array []}
/>
</Popup>
Expand Down Expand Up @@ -501,6 +504,7 @@ exports[`ApplicationNavigation should render with prop data at large breakpoint
my test hero
</div>
}
menuClosingCallback={[Function]}
onSelectHelp={[Function]}
onSelectLogout={[Function]}
onSelectSettings={[Function]}
Expand Down Expand Up @@ -565,6 +569,7 @@ exports[`ApplicationNavigation should render with prop data at medium breakpoint
my test hero
</div>
}
menuClosingCallback={[Function]}
navigationItems={
Array [
Object {
Expand Down Expand Up @@ -734,6 +739,7 @@ exports[`ApplicationNavigation should render with prop data at medium breakpoint
my test hero
</div>
}
menuClosingCallback={[Function]}
onSelectHelp={[Function]}
onSelectLogout={[Function]}
onSelectSettings={[Function]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe('DrawerMenuUser', () => {
it('should render default element', () => {
const shallowComponent = shallow(
<DrawerMenuUser
menuClosingCallback={() => jest.fn()}
userConfig={{
name: 'user-name',
detail: 'user-detail',
Expand All @@ -26,6 +27,7 @@ describe('DrawerMenuUser', () => {
it('should render with small variant', () => {
const shallowComponent = shallow(
<DrawerMenuUser
menuClosingCallback={() => jest.fn()}
userConfig={{
name: 'user-name',
detail: 'user-detail',
Expand All @@ -43,6 +45,7 @@ describe('DrawerMenuUser', () => {
it('should render with large variant', () => {
const shallowComponent = shallow(
<DrawerMenuUser
menuClosingCallback={() => jest.fn()}
userConfig={{
name: 'user-name',
detail: 'user-detail',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ exports[`DrawerMenuUser should render default element 1`] = `
<button
className="drawer-menu-action-button"
data-focus-styles-enabled={true}
data-navigation-drawermenu-item-user-action={true}
onBlur={[Function]}
onClick={[Function]}
onClick={[MockFunction]}
onMouseDown={[Function]}
type="button"
>
Expand Down Expand Up @@ -91,8 +92,9 @@ exports[`DrawerMenuUser should render with large variant 1`] = `
<button
className="drawer-menu-action-button"
data-focus-styles-enabled={true}
data-navigation-drawermenu-item-user-action={true}
onBlur={[Function]}
onClick={[Function]}
onClick={[MockFunction]}
onMouseDown={[Function]}
type="button"
>
Expand Down Expand Up @@ -142,8 +144,9 @@ exports[`DrawerMenuUser should render with small variant 1`] = `
<button
className="drawer-menu-action-button"
data-focus-styles-enabled={true}
data-navigation-drawermenu-item-user-action={true}
onBlur={[Function]}
onClick={[Function]}
onClick={[MockFunction]}
onMouseDown={[Function]}
type="button"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('UtilityMenu', () => {
it('should render with function callbacks', () => {
const mountComponent = mountWithIntl(
<UtilityMenu.WrappedComponent
menuClosingCallback={() => jest.fn()}
hero={<div>my test hero</div>}
userConfig={{
name: 'user-name',
Expand Down
Loading

0 comments on commit ab98952

Please sign in to comment.