diff options
Diffstat (limited to 'src/components/organisms/toolbar')
| -rw-r--r-- | src/components/organisms/toolbar/index.ts | 3 | ||||
| -rw-r--r-- | src/components/organisms/toolbar/main-nav.stories.tsx | 34 | ||||
| -rw-r--r-- | src/components/organisms/toolbar/main-nav.test.tsx | 37 | ||||
| -rw-r--r-- | src/components/organisms/toolbar/main-nav.tsx | 54 | ||||
| -rw-r--r-- | src/components/organisms/toolbar/toolbar.tsx | 28 |
5 files changed, 75 insertions, 81 deletions
diff --git a/src/components/organisms/toolbar/index.ts b/src/components/organisms/toolbar/index.ts index 9433412..316a52a 100644 --- a/src/components/organisms/toolbar/index.ts +++ b/src/components/organisms/toolbar/index.ts @@ -1,4 +1 @@ -export * from './main-nav'; -export * from './search'; -export * from './settings'; export * from './toolbar'; diff --git a/src/components/organisms/toolbar/main-nav.stories.tsx b/src/components/organisms/toolbar/main-nav.stories.tsx index 57485d3..d79addf 100644 --- a/src/components/organisms/toolbar/main-nav.stories.tsx +++ b/src/components/organisms/toolbar/main-nav.stories.tsx @@ -1,13 +1,13 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { useState } from 'react'; -import { MainNav } from './main-nav'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import { useCallback, useState } from 'react'; +import { MainNavItem } from './main-nav'; /** - * MainNav - Storybook Meta + * MainNavItem - Storybook Meta */ export default { - title: 'Organisms/Toolbar/MainNav', - component: MainNav, + title: 'Organisms/Toolbar/MainNavItem', + component: MainNavItem, argTypes: { className: { control: { @@ -54,28 +54,24 @@ export default { }, }, }, -} as ComponentMeta<typeof MainNav>; +} as ComponentMeta<typeof MainNavItem>; -const Template: ComponentStory<typeof MainNav> = ({ +const Template: ComponentStory<typeof MainNavItem> = ({ isActive = false, setIsActive: _setIsActive, ...args }) => { const [isOpen, setIsOpen] = useState<boolean>(isActive); - return ( - <MainNav - isActive={isOpen} - setIsActive={() => { - setIsOpen(!isOpen); - }} - {...args} - /> - ); + const toggle = useCallback(() => { + setIsOpen((prevState) => !prevState); + }, []); + + return <MainNavItem isActive={isOpen} setIsActive={toggle} {...args} />; }; /** - * MainNav Stories - Inactive + * MainNavItem Stories - Inactive */ export const Inactive = Template.bind({}); Inactive.args = { @@ -87,7 +83,7 @@ Inactive.args = { }; /** - * MainNav Stories - Active + * MainNavItem Stories - Active */ export const Active = Template.bind({}); Active.args = { diff --git a/src/components/organisms/toolbar/main-nav.test.tsx b/src/components/organisms/toolbar/main-nav.test.tsx index 054a14e..177e692 100644 --- a/src/components/organisms/toolbar/main-nav.test.tsx +++ b/src/components/organisms/toolbar/main-nav.test.tsx @@ -1,6 +1,10 @@ import { describe, expect, it } from '@jest/globals'; -import { render, screen } from '../../../../tests/utils'; -import { MainNav } from './main-nav'; +import { render, screen as rtlScreen } from '../../../../tests/utils'; +import { MainNavItem } from './main-nav'; + +const doNothing = () => { + // do nothing +}; const items = [ { id: 'home', label: 'Home', href: '/' }, @@ -8,27 +12,34 @@ const items = [ { id: 'contact', label: 'Contact', href: '/contact' }, ]; -describe('MainNav', () => { +describe('MainNavItem', () => { it('renders a checkbox to open main nav', () => { - render(<MainNav items={items} isActive={false} setIsActive={() => null} />); - expect(screen.getByRole('checkbox')).toHaveAccessibleName('Open menu'); + render( + <MainNavItem items={items} isActive={false} setIsActive={doNothing} /> + ); + expect(rtlScreen.getByRole('checkbox')).toHaveAccessibleName('Open menu'); }); it('renders a checkbox to close main nav', () => { - render(<MainNav items={items} isActive={true} setIsActive={() => null} />); - expect(screen.getByRole('checkbox')).toHaveAccessibleName('Close menu'); + render( + <MainNavItem items={items} isActive={true} setIsActive={doNothing} /> + ); + expect(rtlScreen.getByRole('checkbox')).toHaveAccessibleName('Close menu'); }); it('renders the correct number of items', () => { - render(<MainNav items={items} isActive={true} setIsActive={() => null} />); - expect(screen.getAllByRole('listitem')).toHaveLength(items.length); + render( + <MainNavItem items={items} isActive={true} setIsActive={doNothing} /> + ); + expect(rtlScreen.getAllByRole('listitem')).toHaveLength(items.length); }); it('renders some links with the right label', () => { - render(<MainNav items={items} isActive={true} setIsActive={() => null} />); - expect(screen.getByRole('link', { name: items[0].label })).toHaveAttribute( - 'href', - items[0].href + render( + <MainNavItem items={items} isActive={true} setIsActive={doNothing} /> ); + expect( + rtlScreen.getByRole('link', { name: items[0].label }) + ).toHaveAttribute('href', items[0].href); }); }); diff --git a/src/components/organisms/toolbar/main-nav.tsx b/src/components/organisms/toolbar/main-nav.tsx index a5a105e..ee799f5 100644 --- a/src/components/organisms/toolbar/main-nav.tsx +++ b/src/components/organisms/toolbar/main-nav.tsx @@ -1,28 +1,11 @@ -import { - forwardRef, - type ReactNode, - type ForwardRefRenderFunction, -} from 'react'; +import { forwardRef, type ForwardRefRenderFunction } from 'react'; import { useIntl } from 'react-intl'; -import { - BooleanField, - type BooleanFieldProps, - Icon, - Label, - Nav, -} from '../../atoms'; -import { NavList, NavItem, NavLink } from '../../molecules'; +import { BooleanField, type BooleanFieldProps, Icon, Label } from '../../atoms'; +import { type MainNavItem as Item, MainNav } from '../nav'; import mainNavStyles from './main-nav.module.scss'; import sharedStyles from './toolbar-items.module.scss'; -export type MainNavItem = { - id: string; - href: string; - label: string; - logo?: ReactNode; -}; - -export type MainNavProps = { +export type MainNavItemProps = { /** * Set additional classnames to the nav element. */ @@ -34,17 +17,17 @@ export type MainNavProps = { /** * The main nav items. */ - items: MainNavItem[]; + items: Item[]; /** * A callback function to handle button state. */ setIsActive: BooleanFieldProps['onChange']; }; -const MainNavWithRef: ForwardRefRenderFunction<HTMLDivElement, MainNavProps> = ( - { className = '', isActive = false, items, setIsActive }, - ref -) => { +const MainNavItemWithRef: ForwardRefRenderFunction< + HTMLDivElement, + MainNavItemProps +> = ({ className = '', isActive = false, items, setIsActive }, ref) => { const intl = useIntl(); const label = isActive ? intl.formatMessage({ @@ -76,24 +59,17 @@ const MainNavWithRef: ForwardRefRenderFunction<HTMLDivElement, MainNavProps> = ( > <Icon shape="hamburger" /> </Label> - <Nav + <MainNav className={`${sharedStyles.modal} ${mainNavStyles.modal} ${className}`} - > - <NavList isInline spacing="2xs"> - {items.map(({ id, ...link }) => ( - <NavItem key={id}> - <NavLink {...link} isStack variant="main" /> - </NavItem> - ))} - </NavList> - </Nav> + items={items} + /> </div> ); }; /** - * MainNav component + * MainNavItem component * - * Render the main navigation. + * Render the main navigation as toolbar item. */ -export const MainNav = forwardRef(MainNavWithRef); +export const MainNavItem = forwardRef(MainNavItemWithRef); diff --git a/src/components/organisms/toolbar/toolbar.tsx b/src/components/organisms/toolbar/toolbar.tsx index 94c9d95..999a29a 100644 --- a/src/components/organisms/toolbar/toolbar.tsx +++ b/src/components/organisms/toolbar/toolbar.tsx @@ -1,6 +1,7 @@ -import { FC, useState } from 'react'; +/* eslint-disable max-statements */ +import { type FC, useState, useCallback } from 'react'; import { useOnClickOutside, useRouteChange } from '../../../utils/hooks'; -import { MainNav, type MainNavProps } from './main-nav'; +import { MainNavItem, type MainNavItemProps } from './main-nav'; import { Search, type SearchProps } from './search'; import { Settings, type SettingsProps } from './settings'; import styles from './toolbar.module.scss'; @@ -14,7 +15,7 @@ export type ToolbarProps = Pick<SearchProps, 'searchPage'> & /** * The main nav items. */ - nav: MainNavProps['items']; + nav: MainNavItemProps['items']; }; /** @@ -43,23 +44,36 @@ export const Toolbar: FC<ToolbarProps> = ({ () => isSettingsOpened && setIsSettingsOpened(false) ); + const toggleMainNav = useCallback( + () => setIsNavOpened((prevState) => !prevState), + [] + ); + const toggleSearch = useCallback( + () => setIsSearchOpened((prevState) => !prevState), + [] + ); + const toggleSettings = useCallback( + () => setIsSettingsOpened((prevState) => !prevState), + [] + ); + useRouteChange(() => setIsSearchOpened(false)); return ( <div className={`${styles.wrapper} ${className}`}> - <MainNav + <MainNavItem className={styles.modal} isActive={isNavOpened} items={nav} ref={mainNavRef} - setIsActive={() => setIsNavOpened(!isNavOpened)} + setIsActive={toggleMainNav} /> <Search className={`${styles.modal} ${styles['modal--search']}`} isActive={isSearchOpened} ref={searchRef} searchPage={searchPage} - setIsActive={() => setIsSearchOpened(!isSearchOpened)} + setIsActive={toggleSearch} /> <Settings ackeeStorageKey={ackeeStorageKey} @@ -67,7 +81,7 @@ export const Toolbar: FC<ToolbarProps> = ({ isActive={isSettingsOpened} motionStorageKey={motionStorageKey} ref={settingsRef} - setIsActive={() => setIsSettingsOpened(!isSettingsOpened)} + setIsActive={toggleSettings} /> </div> ); |
