diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-11-21 16:10:20 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-21 18:17:47 +0100 |
| commit | c6212f927daf3c928f479afa052e4772216a2d8a (patch) | |
| tree | 6bb71d9cea03e110d10120ba4bf24e3a6f4ff7d0 /src/components/templates/layout | |
| parent | 70b4f633a6fbedb58c8b9134ac64ede854d489de (diff) | |
refactor(components): replace items prop in Navbar component
* replace `items` prop with `children` prop: it is more readable this
way,
* handle navbar item state inside NavbarItem component: it avoid using
three differents states and their methods to do exactly the same thing
* remove useAutofocus hook since we can't use it anymore
* add `onActivation` and `activationHandlerDelay` prop to NavbarItem
component to be able to focus the search input only when the item is
activated (it replicates the functioning of useAutofocus hook)
* replace `ref` type in SearchForm component: it does not make sense to
use an input ref for a form. Instead I use useImperativeHandle to
provide different a focus method to the given ref.
Diffstat (limited to 'src/components/templates/layout')
| -rw-r--r-- | src/components/templates/layout/layout.tsx | 125 |
1 files changed, 49 insertions, 76 deletions
diff --git a/src/components/templates/layout/layout.tsx b/src/components/templates/layout/layout.tsx index 953b0db..ce7f1fa 100644 --- a/src/components/templates/layout/layout.tsx +++ b/src/components/templates/layout/layout.tsx @@ -16,12 +16,7 @@ import type { Person, SearchAction, WebSite, WithContext } from 'schema-dts'; import type { NextPageWithLayoutOptions } from '../../../types'; import { CONFIG } from '../../../utils/config'; import { ROUTES } from '../../../utils/constants'; -import { - useAutofocus, - useBoolean, - useOnRouteChange, - useScrollPosition, -} from '../../../utils/hooks'; +import { useOnRouteChange, useScrollPosition } from '../../../utils/hooks'; import { ButtonLink, Footer, @@ -45,8 +40,10 @@ import { MainNav, SearchForm, SettingsForm, - type NavbarItems, type SearchFormSubmit, + NavbarItem, + type SearchFormRef, + type NavbarItemActivationHandler, } from '../../organisms'; import styles from './layout.module.scss'; @@ -174,21 +171,6 @@ export const Layout: FC<LayoutProps> = ({ children, isHome }) => { }, ]; - const { - deactivate: deactivateMainNav, - state: isMainNavOpen, - toggle: toggleMainNav, - } = useBoolean(false); - const { - deactivate: deactivateSearch, - state: isSearchOpen, - toggle: toggleSearch, - } = useBoolean(false); - const { - deactivate: deactivateSettings, - state: isSettingsOpen, - toggle: toggleSettings, - } = useBoolean(false); const labels = { mainNavItem: intl.formatMessage({ defaultMessage: 'Open menu', @@ -231,10 +213,13 @@ export const Layout: FC<LayoutProps> = ({ children, isHome }) => { e.preventDefault(); }, []); - const searchInputRef = useAutofocus<HTMLInputElement>({ - condition: () => isSearchOpen, - delay: 360, - }); + const searchFormRef = useRef<SearchFormRef>(null); + const giveFocusToSearchInput: NavbarItemActivationHandler = useCallback( + (isActive) => { + if (isActive) searchFormRef.current?.focus(); + }, + [] + ); const searchSubmitHandler: SearchFormSubmit = useCallback( ({ query }) => { if (!query) @@ -256,55 +241,6 @@ export const Layout: FC<LayoutProps> = ({ children, isHome }) => { [intl, router] ); - useOnRouteChange(deactivateSearch); - - const navbarItems: NavbarItems = [ - { - contents: <MainNav aria-label={labels.mainNavModal} items={mainNav} />, - icon: 'hamburger', - id: 'main-nav', - isActive: isMainNavOpen, - label: labels.mainNavItem, - modalVisibleFrom: 'md', - onDeactivate: deactivateMainNav, - onToggle: toggleMainNav, - }, - { - contents: ( - <SearchForm - className={styles.search} - isLabelHidden - onSubmit={searchSubmitHandler} - ref={searchInputRef} - /> - ), - icon: 'magnifying-glass', - id: 'search', - isActive: isSearchOpen, - label: labels.searchItem, - onDeactivate: deactivateSearch, - onToggle: toggleSearch, - modalHeading: labels.searchModal, - }, - { - contents: ( - <SettingsForm - aria-label={labels.settingsForm} - className={styles.settings} - onSubmit={settingsSubmitHandler} - /> - ), - icon: 'cog', - id: 'settings', - isActive: isSettingsOpen, - label: labels.settingsItem, - onDeactivate: deactivateSettings, - onToggle: toggleSettings, - modalHeading: labels.settingsModal, - showIconOnModal: true, - }, - ]; - const legalNoticeLabel = intl.formatMessage({ defaultMessage: 'Legal notice', description: 'Layout: Legal notice label', @@ -436,7 +372,44 @@ export const Layout: FC<LayoutProps> = ({ children, isHome }) => { } url="/" /> - <Navbar items={navbarItems} /> + <Navbar> + <NavbarItem + icon="hamburger" + id="main-nav" + label={labels.mainNavItem} + modalVisibleFrom="md" + > + <MainNav aria-label={labels.mainNavModal} items={mainNav} /> + </NavbarItem> + <NavbarItem + activationHandlerDelay={350} + icon="magnifying-glass" + id="search" + label={labels.searchItem} + modalHeading={labels.searchModal} + onActivation={giveFocusToSearchInput} + > + <SearchForm + className={styles.search} + isLabelHidden + onSubmit={searchSubmitHandler} + ref={searchFormRef} + /> + </NavbarItem> + <NavbarItem + icon="cog" + id="settings" + label={labels.settingsItem} + modalHeading={labels.settingsModal} + showIconOnModal + > + <SettingsForm + aria-label={labels.settingsForm} + className={styles.settings} + onSubmit={settingsSubmitHandler} + /> + </NavbarItem> + </Navbar> </div> </Header> <Main id="main" className={styles.main}> |
