Skip to content

Commit

Permalink
fixup! Feat(web-react): Introduce Navigation #DS-1524
Browse files Browse the repository at this point in the history
  • Loading branch information
curdaj committed Dec 11, 2024
1 parent 4ef4c74 commit 78b7b37
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 9 deletions.
14 changes: 7 additions & 7 deletions packages/web-react/src/components/Navigation/NavigationLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import classNames from 'classnames';
import React, { ElementType, forwardRef } from 'react';
import { useStyleProps } from '../../hooks';
import { PolymorphicRef, SpiritNavigationLinkProps } from '../../types';
import { useNavigationLinkProps } from './useNavigationLinkProps';
import { useNavigationLinkStyleProps } from './useNavigationLinkStyleProps';

const defaultProps: Partial<SpiritNavigationLinkProps> = {
Expand All @@ -17,19 +18,18 @@ const _NavigationLink = <E extends ElementType = 'a'>(
ref: PolymorphicRef<E>,
): JSX.Element => {
const propsWithDefaults = { ...defaultProps, ...props };
const {
elementType: ElementTag = defaultProps.elementType as ElementType,
children,
...restProps
} = propsWithDefaults;
const { elementType = defaultProps.elementType as ElementType, children, ...restProps } = propsWithDefaults;
const ElementTag = propsWithDefaults.isDisabled ? 'span' : elementType;

const { navigationLinkProps } = useNavigationLinkProps(propsWithDefaults);
const { classProps, props: modifiedProps } = useNavigationLinkStyleProps(restProps);
const { styleProps, props: otherProps } = useStyleProps(modifiedProps);

return (
<ElementTag
{...otherProps}
{...styleProps}
href={restProps.href}
{...navigationLinkProps}
className={classNames(classProps, styleProps.className)}
ref={ref}
>
Expand All @@ -38,6 +38,6 @@ const _NavigationLink = <E extends ElementType = 'a'>(
);
};

const NavigationLink = forwardRef<HTMLAnchorElement, SpiritNavigationLinkProps<ElementType>>(_NavigationLink);
const NavigationLink = forwardRef<HTMLElement, SpiritNavigationLinkProps<ElementType>>(_NavigationLink);

export default NavigationLink;
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@ describe('NavigationLink', () => {
);

expect(screen.getByRole('link')).toHaveClass('NavigationLink NavigationLink--selected');
expect(screen.getByRole('link')).toHaveAttribute('aria-current', 'page');
});

it('should have disabled classname', () => {
it('should have disabled classname and correct elementType', () => {
render(
<NavigationLink href="/" isDisabled>
Content
</NavigationLink>,
);

expect(screen.getByRole('link')).toHaveClass('NavigationLink NavigationLink--disabled');
expect(screen.getByText('Content')).toHaveClass('NavigationLink NavigationLink--disabled');
expect(screen.getByText('Content')).toContainHTML('span');
expect(screen.queryByRole('link')).not.toBeInTheDocument();
});

it('should render children', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { renderHook } from '@testing-library/react';
import { SpiritNavigationLinkProps } from '../../../types';
import { useNavigationLinkProps } from '../useNavigationLinkProps';

describe('useNavigationLinkProps', () => {
it('should return defaults props', () => {
const props: SpiritNavigationLinkProps = {
href: '/',
target: '_blank',
isSelected: false,
isDisabled: false,
ariaLabel: 'label',
};
const { result } = renderHook(() => useNavigationLinkProps(props));

expect(result.current).toStrictEqual({
navigationLinkProps: {
'aria-current': undefined,
'aria-label': 'label',
href: '/',
rel: undefined,
target: '_blank',
},
});
});

it('should return defaults if element is different from anchor', () => {
const props: SpiritNavigationLinkProps<'span'> = {
elementType: 'span',
href: '/',
target: '_blank',
isSelected: false,
isDisabled: false,
ariaLabel: 'label',
};
const { result } = renderHook(() => useNavigationLinkProps(props));

expect(result.current).toStrictEqual({
navigationLinkProps: {
'aria-current': undefined,
'aria-label': 'label',
href: undefined,
rel: undefined,
target: undefined,
},
});
});

it('should return for isDisabled', () => {
const props: SpiritNavigationLinkProps = {
href: '/',
target: '_blank',
isSelected: false,
isDisabled: true,
ariaLabel: 'label',
};
const { result } = renderHook(() => useNavigationLinkProps(props));

expect(result.current).toStrictEqual({
navigationLinkProps: {
'aria-current': undefined,
'aria-label': 'label',
href: undefined,
rel: undefined,
target: undefined,
},
});
});

it('should return for isSelected', () => {
const props: SpiritNavigationLinkProps = {
href: '/',
target: '_blank',
isSelected: true,
isDisabled: false,
ariaLabel: 'label',
};
const { result } = renderHook(() => useNavigationLinkProps(props));

expect(result.current).toStrictEqual({
navigationLinkProps: {
'aria-current': 'page',
'aria-label': 'label',
href: '/',
rel: undefined,
target: '_blank',
},
});
});

it('should return for elementType', () => {
const props: SpiritNavigationLinkProps<'div'> = {
elementType: 'div',
href: '/',
target: '_blank',
isSelected: false,
isDisabled: false,
ariaLabel: 'label',
};
const { result } = renderHook(() => useNavigationLinkProps(props));

expect(result.current).toStrictEqual({
navigationLinkProps: {
'aria-current': undefined,
'aria-label': 'label',
href: undefined,
rel: undefined,
target: undefined,
},
});
});
});
1 change: 1 addition & 0 deletions packages/web-react/src/components/Navigation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export { default as Navigation } from './Navigation';
export { default as NavigationItem } from './NavigationItem';
export { default as NavigationLink } from './NavigationLink';
export * from './useNavigationStyleProps';
export * from './useNavigationLinkProps';
export * from './useNavigationLinkStyleProps';
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ElementType } from 'react';
import { SpiritNavigationLinkProps } from '../../types';

export type UseNavigationLinkProps<E extends ElementType = 'a'> = Partial<SpiritNavigationLinkProps<E>>;
export type UseNavigationLinkReturn<E extends ElementType = 'a'> = {
navigationLinkProps: UseNavigationLinkProps<E>;
};

export const useNavigationLinkProps = <E extends ElementType = 'a'>(
props: UseNavigationLinkProps<E>,
): UseNavigationLinkReturn<E> => {
const { elementType = 'a', isDisabled, isSelected, href, target, rel, ariaLabel } = props;

const additionalProps: Partial<SpiritNavigationLinkProps> = {
href: elementType === 'a' && !isDisabled ? href : undefined,
target: elementType === 'a' && !isDisabled ? target : undefined,
rel: elementType === 'a' ? rel : undefined,
};

return {
navigationLinkProps: {
...additionalProps,
'aria-label': ariaLabel || undefined,
'aria-current': isSelected ? 'page' : undefined,
},
};
};

0 comments on commit 78b7b37

Please sign in to comment.