diff options
Diffstat (limited to 'src/components/atoms')
| -rw-r--r-- | src/components/atoms/links/link.module.scss | 37 | ||||
| -rw-r--r-- | src/components/atoms/links/link.stories.tsx | 66 | ||||
| -rw-r--r-- | src/components/atoms/links/link.test.tsx | 9 | ||||
| -rw-r--r-- | src/components/atoms/links/link.tsx | 41 | 
4 files changed, 153 insertions, 0 deletions
| diff --git a/src/components/atoms/links/link.module.scss b/src/components/atoms/links/link.module.scss new file mode 100644 index 0000000..e7ead86 --- /dev/null +++ b/src/components/atoms/links/link.module.scss @@ -0,0 +1,37 @@ +@use "@styles/abstracts/functions" as fun; +@use "@styles/abstracts/variables" as var; + +.link { +  &[hreflang] { +    &::after { +      display: inline-block; +      content: "\0000a0["attr(hreflang) "]"; +      font-size: var(--font-size-sm); +    } +  } + +  &--external { +    &::after { +      display: inline-block; +      content: "\0000a0"url(fun.encode-svg('<svg width="13" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path fill="#{var.$light-theme_blue}" d="M100 0 59.543 5.887l20.8 6.523-51.134 51.134 7.249 7.248L87.59 19.66l6.522 20.798z"/><path fill="#{var.$light-theme_blue}" d="M4 10a4 4 0 0 0-4 4v82a4 4 0 0 0 4 4h82a4 4 0 0 0 4-4V62.314h-8V92H8V18h29.686v-8z"/></svg>')); +    } + +    &:focus:not(:active)::after { +      content: "\0000a0"url(fun.encode-svg('<svg width="13" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path fill="#{var.$light-theme_white}" d="M100 0 59.543 5.887l20.8 6.523-51.134 51.134 7.249 7.248L87.59 19.66l6.522 20.798z"/><path fill="#{var.$light-theme_white}" d="M4 10a4 4 0 0 0-4 4v82a4 4 0 0 0 4 4h82a4 4 0 0 0 4-4V62.314h-8V92H8V18h29.686v-8z"/></svg>')); +    } + +    &[hreflang] { +      &::after { +        content: "\0000a0["attr(hreflang) "]\0000a0"url(fun.encode-svg( +            '<svg width="13" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path fill="#{var.$light-theme_blue}" d="M100 0 59.543 5.887l20.8 6.523-51.134 51.134 7.249 7.248L87.59 19.66l6.522 20.798z"/><path fill="#{var.$light-theme_blue}" d="M4 10a4 4 0 0 0-4 4v82a4 4 0 0 0 4 4h82a4 4 0 0 0 4-4V62.314h-8V92H8V18h29.686v-8z"/></svg>' +          )); +      } + +      &:focus:not(:active)::after { +        content: "\0000a0["attr(hreflang) "]\0000a0"url(fun.encode-svg( +            '<svg width="13" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path fill="#{var.$light-theme_white}" d="M100 0 59.543 5.887l20.8 6.523-51.134 51.134 7.249 7.248L87.59 19.66l6.522 20.798z"/><path fill="#{var.$light-theme_white}" d="M4 10a4 4 0 0 0-4 4v82a4 4 0 0 0 4 4h82a4 4 0 0 0 4-4V62.314h-8V92H8V18h29.686v-8z"/></svg>' +          )); +      } +    } +  } +} diff --git a/src/components/atoms/links/link.stories.tsx b/src/components/atoms/links/link.stories.tsx new file mode 100644 index 0000000..e5a8b0a --- /dev/null +++ b/src/components/atoms/links/link.stories.tsx @@ -0,0 +1,66 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import LinkComponent from './link'; + +export default { +  title: 'Atoms/Links', +  component: LinkComponent, +  argTypes: { +    children: { +      control: { +        type: 'text', +      }, +      description: 'The link body.', +      type: { +        name: 'string', +        required: true, +      }, +    }, +    external: { +      control: { +        type: 'boolean', +      }, +      table: { +        category: 'Options', +      }, +      description: 'Determine if the link is external of the current website.', +      type: { +        name: 'boolean', +        required: false, +      }, +    }, +    href: { +      control: { +        type: 'text', +      }, +      description: 'The link target.', +      type: { +        name: 'string', +        required: true, +      }, +    }, +    lang: { +      control: { +        type: 'text', +      }, +      table: { +        category: 'Options', +      }, +      description: 'The target language as code language.', +      type: { +        name: 'string', +        required: false, +      }, +    }, +  }, +} as ComponentMeta<typeof LinkComponent>; + +const Template: ComponentStory<typeof LinkComponent> = (args) => ( +  <LinkComponent {...args} /> +); + +export const Link = Template.bind({}); +Link.args = { +  children: 'A link', +  href: '#', +  external: false, +}; diff --git a/src/components/atoms/links/link.test.tsx b/src/components/atoms/links/link.test.tsx new file mode 100644 index 0000000..54e2414 --- /dev/null +++ b/src/components/atoms/links/link.test.tsx @@ -0,0 +1,9 @@ +import { render, screen } from '@test-utils'; +import Link from './link'; + +describe('Link', () => { +  it('render a link', () => { +    render(<Link href="#">A link</Link>); +    expect(screen.getByRole('link')).toHaveTextContent('A link'); +  }); +}); diff --git a/src/components/atoms/links/link.tsx b/src/components/atoms/links/link.tsx new file mode 100644 index 0000000..0a69c33 --- /dev/null +++ b/src/components/atoms/links/link.tsx @@ -0,0 +1,41 @@ +import NextLink from 'next/link'; +import { FC } from 'react'; +import styles from './link.module.scss'; + +type LinkProps = { +  /** +   * True if it is an external link. Default: false. +   */ +  external?: boolean; +  /** +   * The link target. +   */ +  href: string; +  /** +   * The link target code language. +   */ +  lang?: string; +}; + +/** + * Link Component + * + * Render a link. + */ +const Link: FC<LinkProps> = ({ children, href, lang, external = false }) => { +  return external ? ( +    <a +      href={href} +      hrefLang={lang} +      className={`${styles.link} ${styles['link--external']}`} +    > +      {children} +    </a> +  ) : ( +    <NextLink href={href}> +      <a className={styles.link}>{children}</a> +    </NextLink> +  ); +}; + +export default Link; | 
