Skip to content

Commit

Permalink
Merge pull request #9123 from weseek/fix/114434-153937-pagelistmodal-…
Browse files Browse the repository at this point in the history
…navtab

fix: Make CustomNavTab responsive
  • Loading branch information
mergify[bot] authored Sep 24, 2024
2 parents cd2110a + 461ca6a commit d68a7dd
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { toastError } from '~/client/util/toastr';
import { toArrayIfNot } from '~/utils/array-utils';
import loggerFactory from '~/utils/logger';

import { CustomNavTab } from '../../CustomNavigation/CustomNav';
import CustomNav from '../../CustomNavigation/CustomNav';
import { withUnstatedContainers } from '../../UnstatedUtils';


Expand Down Expand Up @@ -155,7 +155,13 @@ function NotificationSetting(props) {

<h2 className="admin-setting-header mt-5">{t('notification_settings.notification_settings')}</h2>

<CustomNavTab activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={switchActiveTab} hideBorderBottom />
<CustomNav
activeTab={activeTab}
navTabMapping={navTabMapping}
onNavSelected={switchActiveTab}
hideBorderBottom
breakpointToSwitchDropdownDown="md"
/>

<TabContent activeTab={activeTab} className="p-5">
<TabPane tabId="user_trigger_notification">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@
border-bottom: 3px solid;
transition: 0.3s ease-in-out;
}

}
22 changes: 19 additions & 3 deletions apps/app/src/client/components/CustomNavigation/CustomNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,42 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element =>

const { Icon, i18n } = navTabMapping[activeTab];

const [isDropdownOpen, setIsDropdownOpen] = useState(false);

const dropdownButtonRef = useRef<HTMLButtonElement>(null);

const toggleDropdown = () => {
setIsDropdownOpen(prev => !prev);
};

const menuItemClickHandler = useCallback((key) => {
if (onNavSelected != null) {
onNavSelected(key);
}
// Manually close the dropdown
setIsDropdownOpen(false);
if (dropdownButtonRef.current) {
dropdownButtonRef.current.classList.remove('show');
}
}, [onNavSelected]);

return (
<div className="btn-group">
<button
ref={dropdownButtonRef}
className="btn btn-outline-primary btn-lg dropdown-toggle text-end"
type="button"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
aria-expanded={isDropdownOpen}
onClick={toggleDropdown}
data-testid="custom-nav-dropdown"
>
<span className="float-start">
{ Icon != null && <Icon /> } {i18n}
</span>
</button>
<div className="dropdown-menu dropdown-menu-right">
<div className={`dropdown-menu dropdown-menu-right w-100 ${isDropdownOpen ? 'show' : ''} ${styles['dropdown-menu']}`}>
{Object.entries(navTabMapping).map(([key, value]) => {

const isActive = activeTab === key;
Expand Down Expand Up @@ -167,7 +183,7 @@ export const CustomNavTab = (props: CustomNavTabProps): JSX.Element => {
}

return (
<div className={`grw-custom-nav-tab ${styles['grw-custom-nav-tab']}`}>
<div data-testid="custom-nav-tab" className={`grw-custom-nav-tab ${styles['grw-custom-nav-tab']}`}>
<div ref={navContainerRef} className="d-flex justify-content-between">
<Nav className="nav-title">
{Object.entries(navTabMapping).map(([key, value]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
padding: 25px 30px;
}

.grw-tab-content-style-md-down {
padding-top: 25px;
}

.grw-modal-body-style {
max-height: calc(100vh - 100px);
}
Expand Down
70 changes: 70 additions & 0 deletions apps/app/src/client/components/DescendantsPageListModal.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { render, screen, fireEvent } from '@testing-library/react';

import { DescendantsPageListModal } from './DescendantsPageListModal';

const mockClose = vi.hoisted(() => vi.fn());
const useIsDeviceLargerThanLg = vi.hoisted(() => vi.fn().mockReturnValue({ data: true }));

vi.mock('next/router', () => ({
useRouter: () => ({
events: {
on: vi.fn(),
off: vi.fn(),
},
}),
}));

vi.mock('~/stores/modal', () => ({
useDescendantsPageListModal: vi.fn().mockReturnValue({
data: { isOpened: true },
close: mockClose,
}),
}));

vi.mock('~/stores/ui', () => ({
useIsDeviceLargerThanLg,
}));

describe('DescendantsPageListModal.tsx', () => {

it('should render the modal when isOpened is true', () => {
render(<DescendantsPageListModal />);
expect(screen.getByTestId('descendants-page-list-modal')).not.toBeNull();
});

it('should call close function when close button is clicked', () => {
render(<DescendantsPageListModal />);
const closeButton = screen.getByLabelText('Close');
fireEvent.click(closeButton);
expect(mockClose).toHaveBeenCalled();
});

describe('when device is larger than lg', () => {

it('should render CustomNavTab', () => {
render(<DescendantsPageListModal />);
expect(screen.getByTestId('custom-nav-tab')).not.toBeNull();
});

it('should not render CustomNavDropdown', () => {
render(<DescendantsPageListModal />);
expect(screen.queryByTestId('custom-nav-dropdown')).toBeNull();
});
});

describe('when device is smaller than lg', () => {
beforeEach(() => {
useIsDeviceLargerThanLg.mockReturnValue({ data: false });
});

it('should render CustomNavDropdown on devices smaller than lg', () => {
render(<DescendantsPageListModal />);
expect(screen.getByTestId('custom-nav-dropdown')).not.toBeNull();
});

it('should not render CustomNavTab', () => {
render(<DescendantsPageListModal />);
expect(screen.queryByTestId('custom-nav-tab')).toBeNull();
});
});
});
34 changes: 25 additions & 9 deletions apps/app/src/client/components/DescendantsPageListModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import {

import { useIsSharedUser } from '~/stores-universal/context';
import { useDescendantsPageListModal } from '~/stores/modal';
import { useIsDeviceLargerThanLg } from '~/stores/ui';

import { CustomNavTab } from './CustomNavigation/CustomNav';
import { CustomNavDropdown, CustomNavTab } from './CustomNavigation/CustomNav';
import CustomTabContent from './CustomNavigation/CustomTabContent';
import type { DescendantsPageListProps } from './DescendantsPageList';
import ExpandOrContractButton from './ExpandOrContractButton';
Expand All @@ -34,6 +35,8 @@ export const DescendantsPageListModal = (): JSX.Element => {

const { events } = useRouter();

const { data: isDeviceLargerThanLg } = useIsDeviceLargerThanLg();

useEffect(() => {
events.on('routeChangeStart', close);
return () => {
Expand Down Expand Up @@ -93,17 +96,30 @@ export const DescendantsPageListModal = (): JSX.Element => {
data-testid="descendants-page-list-modal"
className={`grw-descendants-page-list-modal ${styles['grw-descendants-page-list-modal']} ${isWindowExpanded ? 'grw-modal-expanded' : ''} `}
>
<ModalHeader className="p-0" toggle={close} close={buttons}>
<CustomNavTab
<ModalHeader className={isDeviceLargerThanLg ? 'p-0' : ''} toggle={close} close={buttons}>
{isDeviceLargerThanLg && (
<CustomNavTab
activeTab={activeTab}
navTabMapping={navTabMapping}
breakpointToHideInactiveTabsDown="md"
onNavSelected={v => setActiveTab(v)}
hideBorderBottom
/>
)}
</ModalHeader>
<ModalBody>
{!isDeviceLargerThanLg && (
<CustomNavDropdown
activeTab={activeTab}
navTabMapping={navTabMapping}
onNavSelected={v => setActiveTab(v)}
/>
)}
<CustomTabContent
activeTab={activeTab}
navTabMapping={navTabMapping}
breakpointToHideInactiveTabsDown="md"
onNavSelected={v => setActiveTab(v)}
hideBorderBottom
additionalClassNames={!isDeviceLargerThanLg ? ['grw-tab-content-style-md-down'] : undefined}
/>
</ModalHeader>
<ModalBody>
<CustomTabContent activeTab={activeTab} navTabMapping={navTabMapping} />
</ModalBody>
</Modal>
);
Expand Down

0 comments on commit d68a7dd

Please sign in to comment.