diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-10-19 19:30:54 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:14:41 +0100 |
| commit | c3cde71e60ae22d17c1d162f678f592915ac5398 (patch) | |
| tree | 770856e0876b8c613a21fa79199d6d40609d73e6 /src | |
| parent | 94448fa278ab352a741ff13f22d6104869571144 (diff) | |
refactor(components): rewrite NavLink component
* handle style variants to avoid declaring the styles in consumers
Diffstat (limited to 'src')
6 files changed, 190 insertions, 73 deletions
diff --git a/src/components/molecules/nav/nav-link/nav-link.module.scss b/src/components/molecules/nav/nav-link/nav-link.module.scss index 8a7d371..ac20c73 100644 --- a/src/components/molecules/nav/nav-link/nav-link.module.scss +++ b/src/components/molecules/nav/nav-link/nav-link.module.scss @@ -2,60 +2,97 @@ @use "../../../../styles/abstracts/placeholders"; .link { - --draw-border-thickness: #{fun.convert-px(4)}; - --draw-border-color1: var(--color-primary-light); - --draw-border-color2: var(--color-primary-lighter); - - display: flex; - flex-flow: row wrap; - place-items: center; - place-content: center; - row-gap: var(--spacing-2xs); - min-width: var(--link-min-width, fun.convert-px(80)); - padding: var(--spacing-xs) var(--spacing-xs) var(--spacing-2xs); - background: none; - border-radius: 8%; - font-size: var(--font-size-sm); - font-variant: small-caps; - font-weight: 600; - text-align: center; - text-decoration: none; + &--block, + &--main, + &--regular#{&}--stack { + display: flex; + place-items: center; + place-content: center; + row-gap: var(--spacing-2xs); + } - &--inline { - width: fit-content; + &--block { + padding: var(--spacing-2xs) var(--spacing-xs); + font-weight: 500; + text-decoration: underline solid transparent 0; - .logo { - margin-right: var(--spacing-xs); + &:hover, + &:focus { + background: var(--color-bg-secondary); } - } - &--stack { - .logo { - flex: 0 0 100%; - display: flex; - place-content: center; + &:focus { + color: var(--color-primary); + text-decoration-color: var(--color-primary-light); + text-decoration-thickness: 0.25ex; } - } - &:hover, - &:focus { - @extend %draw-borders; + &:active { + background: var(--color-bg-tertiary); + text-decoration-color: transparent; + text-decoration-thickness: 0; + } } - &:hover { - color: var(--color-primary-light); + &--main { + --draw-border-thickness: #{fun.convert-px(4)}; + --draw-border-color1: var(--color-primary-light); + --draw-border-color2: var(--color-primary-lighter); + + min-width: var(--link-min-width, fun.convert-px(82)); + padding: var(--spacing-xs); + background: none; + border-radius: 8%; + font-size: var(--font-size-sm); + font-variant: small-caps; + font-weight: 600; + line-height: initial; + text-align: center; + text-decoration: none; + + &:hover, + &:focus { + @extend %draw-borders; + } + + &:hover { + color: var(--color-primary-light); + } + + &:focus { + color: var(--color-primary-light); + } + + &:active { + --draw-border-color1: var(--color-primary-dark); + --draw-border-color2: var(--color-primary-light); + + color: var(--color-primary-dark); + + @extend %draw-borders; + } } - &:focus { - color: var(--color-primary-light); + &--inline { + .logo { + margin-right: var(--spacing-xs); + } } - &:active { - --draw-border-color1: var(--color-primary-dark); - --draw-border-color2: var(--color-primary-light); + &--inline#{&}--regular { + .logo { + display: inline-block; + vertical-align: middle; + } + } - color: var(--color-primary-dark); + &--stack { + flex-flow: column wrap; - @extend %draw-borders; + .logo { + flex: 0 0 100%; + display: flex; + place-content: center; + } } } diff --git a/src/components/molecules/nav/nav-link/nav-link.stories.tsx b/src/components/molecules/nav/nav-link/nav-link.stories.tsx index 4e8400f..b0ad76a 100644 --- a/src/components/molecules/nav/nav-link/nav-link.stories.tsx +++ b/src/components/molecules/nav/nav-link/nav-link.stories.tsx @@ -49,31 +49,100 @@ const Template: ComponentStory<typeof NavLinkComponent> = (args) => ( ); /** - * NavLink Stories - Default + * NavLink Stories - Regular */ -export const Default = Template.bind({}); -Default.args = { +export const Regular = Template.bind({}); +Regular.args = { href: '#', label: 'A nav link', }; /** - * NavLink Stories - StackWithLogo + * NavLink Stories - RegularInlineWithLogo */ -export const StackWithLogo = Template.bind({}); -StackWithLogo.args = { +export const RegularInlineWithLogo = Template.bind({}); +RegularInlineWithLogo.args = { href: '#example', + isStack: false, label: 'A nav link', logo: <Icon aria-hidden shape="home" />, }; /** - * NavLink Stories - InlineWithLogo + * NavLink Stories - RegularStackWithLogo */ -export const InlineWithLogo = Template.bind({}); -InlineWithLogo.args = { +export const RegularStackWithLogo = Template.bind({}); +RegularStackWithLogo.args = { href: '#example', - isInline: true, + isStack: true, label: 'A nav link', logo: <Icon aria-hidden shape="home" />, }; + +/** + * NavLink Stories - Block + */ +export const Block = Template.bind({}); +Block.args = { + href: '#', + label: 'A nav link', + variant: 'block', +}; + +/** + * NavLink Stories - BlockInlineWithLogo + */ +export const BlockInlineWithLogo = Template.bind({}); +BlockInlineWithLogo.args = { + href: '#example', + isStack: false, + label: 'A nav link', + logo: <Icon aria-hidden shape="home" />, + variant: 'block', +}; + +/** + * NavLink Stories - BlockStackWithLogo + */ +export const BlockStackWithLogo = Template.bind({}); +BlockStackWithLogo.args = { + href: '#example', + isStack: true, + label: 'A nav link', + logo: <Icon aria-hidden shape="home" />, + variant: 'block', +}; + +/** + * NavLink Stories - Main + */ +export const Main = Template.bind({}); +Main.args = { + href: '#', + label: 'A nav link', + variant: 'main', +}; + +/** + * NavLink Stories - MainInlineWithLogo + */ +export const MainInlineWithLogo = Template.bind({}); +MainInlineWithLogo.args = { + href: '#example', + isStack: false, + label: 'A nav link', + logo: <Icon aria-hidden shape="home" />, + variant: 'main', +}; + +/** + * NavLink Stories - MainStackWithLogo + */ +export const MainStackWithLogo = Template.bind({}); +MainStackWithLogo.args = { + href: '#example', + isStack: true, + label: 'A nav link', + logo: <Icon aria-hidden shape="home" />, + variant: 'main', +}; diff --git a/src/components/molecules/nav/nav-link/nav-link.test.tsx b/src/components/molecules/nav/nav-link/nav-link.test.tsx index aa9b557..e4c2d57 100644 --- a/src/components/molecules/nav/nav-link/nav-link.test.tsx +++ b/src/components/molecules/nav/nav-link/nav-link.test.tsx @@ -15,14 +15,14 @@ describe('NavLink', () => { ); }); - it('can render a nav link with inlined contents', () => { + it('can render a nav link with stacked contents', () => { const label = 'eius'; const target = '#harum'; - render(<NavLink href={target} isInline label={label} />); + render(<NavLink href={target} isStack label={label} />); expect(rtlScreen.getByRole('link', { name: label })).toHaveClass( - 'link--inline' + 'link--stack' ); }); }); diff --git a/src/components/molecules/nav/nav-link/nav-link.tsx b/src/components/molecules/nav/nav-link/nav-link.tsx index f9fc529..c2b0f5f 100644 --- a/src/components/molecules/nav/nav-link/nav-link.tsx +++ b/src/components/molecules/nav/nav-link/nav-link.tsx @@ -8,33 +8,55 @@ import styles from './nav-link.module.scss'; export type NavLinkProps = Omit<LinkProps, 'children' | 'disableTransition'> & { /** - * Should the logo and label be inlined? + * Should the logo be above the label? * * @default false */ - isInline?: boolean; + isStack?: boolean; /** * The link label. */ - label: string; + label: ReactNode; /** * The link logo. */ logo?: ReactNode; + /** + * The link variant. + * + * @default 'regular' + */ + variant?: 'block' | 'main' | 'regular'; }; const NavLinkWithRef: ForwardRefRenderFunction< HTMLAnchorElement, NavLinkProps -> = ({ className = '', isInline = false, label, logo, ...props }, ref) => { +> = ( + { + className = '', + isStack = false, + label, + logo, + variant = 'regular', + ...props + }, + ref +) => { const linkClass = [ styles.link, - styles[isInline ? 'link--inline' : 'link--stack'], + styles[`link--${variant}`], + styles[isStack ? 'link--stack' : 'link--inline'], className, ].join(' '); return ( - <Link {...props} className={linkClass} disableTransition ref={ref}> + <Link + {...props} + className={linkClass} + disableTransition={variant === 'main'} + ref={ref} + > {logo ? <span className={styles.logo}>{logo}</span> : null} {label} </Link> diff --git a/src/components/molecules/nav/nav-list.module.scss b/src/components/molecules/nav/nav-list.module.scss index 316638e..ff99581 100644 --- a/src/components/molecules/nav/nav-list.module.scss +++ b/src/components/molecules/nav/nav-list.module.scss @@ -1,14 +1,4 @@ .nav { - &--main { - width: fit-content; - } - - &--main & { - &__item { - flex: 1; - } - } - &--footer & { &__item:not(:first-child) { &::before { diff --git a/src/components/molecules/nav/nav-list.tsx b/src/components/molecules/nav/nav-list.tsx index b3c7138..a6acdcf 100644 --- a/src/components/molecules/nav/nav-list.tsx +++ b/src/components/molecules/nav/nav-list.tsx @@ -49,8 +49,7 @@ export const NavList: FC<NavListProps> = ({ listClassName = '', ...props }) => { - const kindClass = `nav--${kind}`; - const navClass = `${styles.nav} ${styles[kindClass]} ${className}`; + const navClass = [styles[`nav--${kind}`], className].join(' '); /** * Get the nav items. @@ -60,7 +59,7 @@ export const NavList: FC<NavListProps> = ({ items.map(({ id, href, label, logo }) => ( <ListItem key={id} className={styles.nav__item}> {kind === 'main' ? ( - <NavLink href={href} label={label} logo={logo} /> + <NavLink href={href} label={label} logo={logo} variant="main" /> ) : ( <Link href={href}>{label}</Link> )} |
