From b214baab3e17d92f784b4f782863deafc5558ee4 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Wed, 18 May 2022 14:27:11 +0200 Subject: chore: close toolbar modals on click/focus outside --- src/components/organisms/toolbar/main-nav.tsx | 16 +++++++--------- src/components/organisms/toolbar/search.stories.tsx | 1 - src/components/organisms/toolbar/search.test.tsx | 5 ----- src/components/organisms/toolbar/search.tsx | 16 +++++++--------- src/components/organisms/toolbar/settings.stories.tsx | 8 -------- src/components/organisms/toolbar/settings.tsx | 16 +++++++--------- src/components/organisms/toolbar/toolbar.tsx | 18 ++++++++++++++++-- 7 files changed, 37 insertions(+), 43 deletions(-) (limited to 'src/components/organisms/toolbar') diff --git a/src/components/organisms/toolbar/main-nav.tsx b/src/components/organisms/toolbar/main-nav.tsx index 35e3fd6..d205112 100644 --- a/src/components/organisms/toolbar/main-nav.tsx +++ b/src/components/organisms/toolbar/main-nav.tsx @@ -5,7 +5,7 @@ import Nav, { type NavProps, type NavItem, } from '@components/molecules/nav/nav'; -import { FC } from 'react'; +import { forwardRef, ForwardRefRenderFunction } from 'react'; import { useIntl } from 'react-intl'; import mainNavStyles from './main-nav.module.scss'; import sharedStyles from './toolbar-items.module.scss'; @@ -34,12 +34,10 @@ export type MainNavProps = { * * Render the main navigation. */ -const MainNav: FC = ({ - className = '', - isActive, - items, - setIsActive, -}) => { +const MainNav: ForwardRefRenderFunction = ( + { className = '', isActive, items, setIsActive }, + ref +) => { const intl = useIntl(); const label = isActive ? intl.formatMessage({ @@ -54,7 +52,7 @@ const MainNav: FC = ({ }); return ( -
+
= ({ ); }; -export default MainNav; +export default forwardRef(MainNav); diff --git a/src/components/organisms/toolbar/search.stories.tsx b/src/components/organisms/toolbar/search.stories.tsx index c6063a0..6aaffde 100644 --- a/src/components/organisms/toolbar/search.stories.tsx +++ b/src/components/organisms/toolbar/search.stories.tsx @@ -1,6 +1,5 @@ import { ComponentMeta, ComponentStory } from '@storybook/react'; import { useState } from 'react'; -import { IntlProvider } from 'react-intl'; import Search from './search'; /** diff --git a/src/components/organisms/toolbar/search.test.tsx b/src/components/organisms/toolbar/search.test.tsx index a18b679..7c77eac 100644 --- a/src/components/organisms/toolbar/search.test.tsx +++ b/src/components/organisms/toolbar/search.test.tsx @@ -11,9 +11,4 @@ describe('Search', () => { render( null} />); expect(screen.getByRole('checkbox')).toHaveAccessibleName('Close search'); }); - - it('renders a search form', () => { - render( null} />); - expect(screen.getByRole('searchbox')).toBeInTheDocument(); - }); }); diff --git a/src/components/organisms/toolbar/search.tsx b/src/components/organisms/toolbar/search.tsx index a1471ef..5695348 100644 --- a/src/components/organisms/toolbar/search.tsx +++ b/src/components/organisms/toolbar/search.tsx @@ -1,7 +1,7 @@ import Checkbox, { type CheckboxProps } from '@components/atoms/forms/checkbox'; import Label from '@components/atoms/forms/label'; import MagnifyingGlass from '@components/atoms/icons/magnifying-glass'; -import { FC } from 'react'; +import { forwardRef, ForwardRefRenderFunction } from 'react'; import { useIntl } from 'react-intl'; import SearchModal, { type SearchModalProps } from '../modals/search-modal'; import searchStyles from './search.module.scss'; @@ -26,12 +26,10 @@ export type SearchProps = { setIsActive: CheckboxProps['setValue']; }; -const Search: FC = ({ - className = '', - isActive, - searchPage, - setIsActive, -}) => { +const Search: ForwardRefRenderFunction = ( + { className = '', isActive, searchPage, setIsActive }, + ref +) => { const intl = useIntl(); const label = isActive ? intl.formatMessage({ @@ -46,7 +44,7 @@ const Search: FC = ({ }); return ( -
+
= ({ ); }; -export default Search; +export default forwardRef(Search); diff --git a/src/components/organisms/toolbar/settings.stories.tsx b/src/components/organisms/toolbar/settings.stories.tsx index 1ec0897..aab4b9e 100644 --- a/src/components/organisms/toolbar/settings.stories.tsx +++ b/src/components/organisms/toolbar/settings.stories.tsx @@ -1,6 +1,5 @@ import { ComponentMeta, ComponentStory } from '@storybook/react'; import { useState } from 'react'; -import { IntlProvider } from 'react-intl'; import Settings from './settings'; /** @@ -57,13 +56,6 @@ export default { }, }, }, - decorators: [ - (Story) => ( - - - - ), - ], } as ComponentMeta; const Template: ComponentStory = ({ diff --git a/src/components/organisms/toolbar/settings.tsx b/src/components/organisms/toolbar/settings.tsx index 3b10226..43d3190 100644 --- a/src/components/organisms/toolbar/settings.tsx +++ b/src/components/organisms/toolbar/settings.tsx @@ -1,7 +1,7 @@ import Checkbox, { type CheckboxProps } from '@components/atoms/forms/checkbox'; import Label from '@components/atoms/forms/label'; import Cog from '@components/atoms/icons/cog'; -import { FC } from 'react'; +import { FC, forwardRef, ForwardRefRenderFunction } from 'react'; import { useIntl } from 'react-intl'; import SettingsModal, { type SettingsModalProps, @@ -28,12 +28,10 @@ export type SettingsProps = { tooltipClassName?: SettingsModalProps['tooltipClassName']; }; -const Settings: FC = ({ - className = '', - isActive, - setIsActive, - tooltipClassName = '', -}) => { +const Settings: ForwardRefRenderFunction = ( + { className = '', isActive, setIsActive, tooltipClassName = '' }, + ref +) => { const intl = useIntl(); const label = isActive ? intl.formatMessage({ @@ -48,7 +46,7 @@ const Settings: FC = ({ }); return ( -
+
= ({ ); }; -export default Settings; +export default forwardRef(Settings); diff --git a/src/components/organisms/toolbar/toolbar.tsx b/src/components/organisms/toolbar/toolbar.tsx index 6593055..e4188fe 100644 --- a/src/components/organisms/toolbar/toolbar.tsx +++ b/src/components/organisms/toolbar/toolbar.tsx @@ -1,4 +1,5 @@ -import { FC, useState } from 'react'; +import useClickOutside from '@utils/hooks/use-click-outside'; +import { FC, useRef, useState } from 'react'; import MainNav, { type MainNavProps } from '../toolbar/main-nav'; import Search, { type SearchProps } from '../toolbar/search'; import Settings from '../toolbar/settings'; @@ -22,8 +23,18 @@ export type ToolbarProps = Pick & { */ const Toolbar: FC = ({ className = '', nav, searchPage }) => { const [isNavOpened, setIsNavOpened] = useState(false); - const [isSettingsOpened, setIsSettingsOpened] = useState(false); const [isSearchOpened, setIsSearchOpened] = useState(false); + const [isSettingsOpened, setIsSettingsOpened] = useState(false); + const mainNavRef = useRef(null); + const searchRef = useRef(null); + const settingsRef = useRef(null); + + useClickOutside(mainNavRef, () => isNavOpened && setIsNavOpened(false)); + useClickOutside(searchRef, () => isSearchOpened && setIsSearchOpened(false)); + useClickOutside( + settingsRef, + () => isSettingsOpened && setIsSettingsOpened(false) + ); return (
@@ -32,18 +43,21 @@ const Toolbar: FC = ({ className = '', nav, searchPage }) => { isActive={isNavOpened} setIsActive={setIsNavOpened} className={styles.modal} + ref={mainNavRef} />
); -- cgit v1.2.3