From 40836e5707f9dce118d5a20777331953a3ccb308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kry=C5=A1p=C3=ADn?= Date: Wed, 8 Jan 2025 14:50:39 +0100 Subject: [PATCH] Feat(web-react): Introduce `NavigationItem` subcomponent #DS-1411 --- .../components/Navigation/NavigationItem.tsx | 14 ++++++++--- .../src/components/Navigation/README.md | 22 +++++++++++++++--- .../__tests__/NavigationItem.test.tsx | 17 ++++++++++++-- .../useNavigationItemStyleProps.test.ts | 18 +++++++++++++++ .../Navigation/useNavigationItemStyleProps.ts | 23 +++++++++++++++++++ .../Navigation/useNavigationStyleProps.ts | 2 +- packages/web-react/src/types/navigation.ts | 4 +++- 7 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 packages/web-react/src/components/Navigation/__tests__/useNavigationItemStyleProps.test.ts create mode 100644 packages/web-react/src/components/Navigation/useNavigationItemStyleProps.ts diff --git a/packages/web-react/src/components/Navigation/NavigationItem.tsx b/packages/web-react/src/components/Navigation/NavigationItem.tsx index bb32fff3ca..f59379fb43 100644 --- a/packages/web-react/src/components/Navigation/NavigationItem.tsx +++ b/packages/web-react/src/components/Navigation/NavigationItem.tsx @@ -1,16 +1,24 @@ 'use client'; +import classNames from 'classnames'; import React from 'react'; import { useStyleProps } from '../../hooks'; import { SpiritNavigationItemProps } from '../../types'; +import { useNavigationItemStyleProps } from './useNavigationItemStyleProps'; + +const defaultProps: Partial = { + isStretchingChildren: false, +}; const NavigationItem = (props: SpiritNavigationItemProps): JSX.Element => { - const { children, ...restProps } = props; + const propsWithDefaults = { ...defaultProps, ...props }; + const { children, ...restProps } = propsWithDefaults; - const { styleProps, props: otherProps } = useStyleProps(restProps); + const { classProps, props: modifiedProps } = useNavigationItemStyleProps(restProps); + const { styleProps, props: otherProps } = useStyleProps(modifiedProps); return ( -
  • +
  • {children}
  • ); diff --git a/packages/web-react/src/components/Navigation/README.md b/packages/web-react/src/components/Navigation/README.md index f9fcdcee67..3d0df96612 100644 --- a/packages/web-react/src/components/Navigation/README.md +++ b/packages/web-react/src/components/Navigation/README.md @@ -43,11 +43,27 @@ import { NavigationItem } from '@lmc-eu/spirit-web-react'; {/* Navigation actions go here */}; ``` +If the children are not `NavigationAction` components or the `NavigationItem` does not have the +`isStretchingChildren` class, it will centre its children vertically. + +```jsx + + Vertically centered Link + + + Stretched Link + + + Stretched NavigationAction + +``` + ### API -| Name | Type | Default | Required | Description | -| ---------- | ----------------------- | ------- | -------- | ----------------------------- | -| `children` | `string` \| `ReactNode` | `null` | ✓ | Content of the NavigationItem | +| Name | Type | Default | Required | Description | +| ---------------------- | ----------------------- | ------- | -------- | ---------------------------------------- | +| `children` | `string` \| `ReactNode` | `null` | ✓ | Content of the NavigationItem | +| `isStretchingChildren` | `boolean` | `false` | ✕ | Whether the children should be stretched | The components accept [additional attributes][readme-additional-attributes]. If you need more control over the styling of a component, you can use [style props][readme-style-props] diff --git a/packages/web-react/src/components/Navigation/__tests__/NavigationItem.test.tsx b/packages/web-react/src/components/Navigation/__tests__/NavigationItem.test.tsx index 2037bdb321..4757d284a1 100644 --- a/packages/web-react/src/components/Navigation/__tests__/NavigationItem.test.tsx +++ b/packages/web-react/src/components/Navigation/__tests__/NavigationItem.test.tsx @@ -1,15 +1,28 @@ import '@testing-library/jest-dom'; import { render, screen } from '@testing-library/react'; import React from 'react'; -import { restPropsTest } from '../../../../tests/providerTests/restPropsTest'; -import { stylePropsTest } from '../../../../tests/providerTests/stylePropsTest'; +import { classNamePrefixProviderTest, restPropsTest, stylePropsTest } from '@local/tests'; import NavigationItem from '../NavigationItem'; describe('NavigationItem', () => { + classNamePrefixProviderTest(NavigationItem, 'NavigationItem'); + stylePropsTest(NavigationItem); restPropsTest(NavigationItem, 'li'); + it('should have default classname', () => { + render(Content); + + expect(screen.getByRole('listitem')).toHaveClass('NavigationItem'); + }); + + it('should have stretchChildren classname', () => { + render(Content); + + expect(screen.getByRole('listitem')).toHaveClass('NavigationItem--stretchChildren'); + }); + it('should have correct role', () => { render(Content); diff --git a/packages/web-react/src/components/Navigation/__tests__/useNavigationItemStyleProps.test.ts b/packages/web-react/src/components/Navigation/__tests__/useNavigationItemStyleProps.test.ts new file mode 100644 index 0000000000..fef17f46cb --- /dev/null +++ b/packages/web-react/src/components/Navigation/__tests__/useNavigationItemStyleProps.test.ts @@ -0,0 +1,18 @@ +import { renderHook } from '@testing-library/react'; +import { useNavigationItemStyleProps } from '../useNavigationItemStyleProps'; + +describe('useNavigationItemStyleProps', () => { + it('should return defaults', () => { + const props = {}; + const { result } = renderHook(() => useNavigationItemStyleProps(props)); + + expect(result.current.classProps).toBe('NavigationItem'); + }); + + it('should return stretchChildren class', () => { + const props = { isStretchingChildren: true }; + const { result } = renderHook(() => useNavigationItemStyleProps(props)); + + expect(result.current.classProps).toBe('NavigationItem NavigationItem--stretchChildren'); + }); +}); diff --git a/packages/web-react/src/components/Navigation/useNavigationItemStyleProps.ts b/packages/web-react/src/components/Navigation/useNavigationItemStyleProps.ts new file mode 100644 index 0000000000..7a8afe157f --- /dev/null +++ b/packages/web-react/src/components/Navigation/useNavigationItemStyleProps.ts @@ -0,0 +1,23 @@ +import classNames from 'classnames'; +import { useClassNamePrefix } from '../../hooks'; +import { SpiritNavigationItemProps } from '../../types'; + +export interface NavigationItemStyles { + classProps: string; + props: SpiritNavigationItemProps; +} + +export const useNavigationItemStyleProps = (props: SpiritNavigationItemProps): NavigationItemStyles => { + const { isStretchingChildren, ...restProps } = props; + const itemClass = useClassNamePrefix('NavigationItem'); + const itemIsStretchingChildrenClass = `${itemClass}--stretchChildren`; + + const className = classNames(itemClass, { + [itemIsStretchingChildrenClass]: isStretchingChildren, + }); + + return { + classProps: className, + props: restProps, + }; +}; diff --git a/packages/web-react/src/components/Navigation/useNavigationStyleProps.ts b/packages/web-react/src/components/Navigation/useNavigationStyleProps.ts index 608f5492f7..cbdfcd1864 100644 --- a/packages/web-react/src/components/Navigation/useNavigationStyleProps.ts +++ b/packages/web-react/src/components/Navigation/useNavigationStyleProps.ts @@ -4,7 +4,7 @@ export interface NavigationStyles { classProps: string; } -export const useNavigationStyleProps = () => { +export const useNavigationStyleProps = (): NavigationStyles => { const navigationClass = useClassNamePrefix('Navigation'); return { diff --git a/packages/web-react/src/types/navigation.ts b/packages/web-react/src/types/navigation.ts index 8ddf9de085..c891f861de 100644 --- a/packages/web-react/src/types/navigation.ts +++ b/packages/web-react/src/types/navigation.ts @@ -29,7 +29,9 @@ export type NavigationActionProps = { elementType?: E; } & NavigationActionBaseProps; -export interface SpiritNavigationItemProps extends ChildrenProps, StyleProps {} +export interface SpiritNavigationItemProps extends ChildrenProps, StyleProps { + isStretchingChildren?: boolean; +} export type SpiritNavigationActionProps = NavigationActionProps & SpiritPolymorphicElementPropsWithRef>;