diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-04-11 18:50:20 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-04-11 18:50:20 +0200 |
| commit | a7adae1a2376082841053c91508b1c23dc951b74 (patch) | |
| tree | 07ef9ae47b00f2ce2cf9432f3300974171071bb3 /src/components/atoms/layout | |
| parent | 6a898c510f5c9b5469f639472970d1fefe9766ca (diff) | |
chore: add a Copyright component
Diffstat (limited to 'src/components/atoms/layout')
| -rw-r--r-- | src/components/atoms/layout/copyright.module.scss | 32 | ||||
| -rw-r--r-- | src/components/atoms/layout/copyright.stories.tsx | 55 | ||||
| -rw-r--r-- | src/components/atoms/layout/copyright.test.tsx | 32 | ||||
| -rw-r--r-- | src/components/atoms/layout/copyright.tsx | 59 |
4 files changed, 178 insertions, 0 deletions
diff --git a/src/components/atoms/layout/copyright.module.scss b/src/components/atoms/layout/copyright.module.scss new file mode 100644 index 0000000..a0e5347 --- /dev/null +++ b/src/components/atoms/layout/copyright.module.scss @@ -0,0 +1,32 @@ +@use "@styles/abstracts/functions" as fun; +@use "@styles/abstracts/mixins" as mix; + +.wrapper { + --icon-size: #{fun.convert-px(70)}; + + display: flex; + flex-flow: row wrap; + align-items: center; + place-content: center; + gap: var(--spacing-2xs); + margin: 0; + font-family: var(--font-family-secondary); + font-size: var(--font-size-md); + text-align: center; + + @include mix.media("screen") { + @include mix.dimensions("sm") { + text-align: left; + } + } +} + +.owner { + flex: 1 0 100%; + + @include mix.media("screen") { + @include mix.dimensions("sm") { + flex: initial; + } + } +} diff --git a/src/components/atoms/layout/copyright.stories.tsx b/src/components/atoms/layout/copyright.stories.tsx new file mode 100644 index 0000000..3b315fa --- /dev/null +++ b/src/components/atoms/layout/copyright.stories.tsx @@ -0,0 +1,55 @@ +import CCBySA from '@components/atoms/icons/cc-by-sa'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { IntlProvider } from 'react-intl'; +import CopyrightComponent from './copyright'; + +export default { + title: 'Atoms/Layout', + component: CopyrightComponent, + argTypes: { + dates: { + description: 'The copyright dates.', + type: { + name: 'object', + required: true, + value: {}, + }, + }, + icon: { + control: { + type: null, + }, + description: 'The copyright icon.', + type: { + name: 'string', + required: true, + }, + }, + owner: { + control: { + type: 'text', + }, + description: 'The copyright owner', + type: { + name: 'string', + required: true, + }, + }, + }, +} as ComponentMeta<typeof CopyrightComponent>; + +const Template: ComponentStory<typeof CopyrightComponent> = (args) => ( + <IntlProvider locale="en"> + <CopyrightComponent {...args} /> + </IntlProvider> +); + +export const Copyright = Template.bind({}); +Copyright.args = { + dates: { + start: '2012', + end: '2022', + }, + icon: <CCBySA />, + owner: 'Your name', +}; diff --git a/src/components/atoms/layout/copyright.test.tsx b/src/components/atoms/layout/copyright.test.tsx new file mode 100644 index 0000000..6bfe612 --- /dev/null +++ b/src/components/atoms/layout/copyright.test.tsx @@ -0,0 +1,32 @@ +import CCBySA from '@components/atoms/icons/cc-by-sa'; +import { render, screen } from '@test-utils'; +import Copyright from './copyright'; + +const dates = { + start: '2012', + end: '2022', +}; +const icon = <CCBySA />; +const owner = 'Your name'; + +describe('Copyright', () => { + it('renders the copyright owner', () => { + render(<Copyright dates={dates} icon={icon} owner={owner} />); + expect(screen.getByText(owner)).toBeInTheDocument(); + }); + + it('renders the copyright start date', () => { + render(<Copyright dates={dates} icon={icon} owner={owner} />); + expect(screen.getByText(dates.start)).toBeInTheDocument(); + }); + + it('renders the copyright end date', () => { + render(<Copyright dates={dates} icon={icon} owner={owner} />); + expect(screen.getByText(dates.end)).toBeInTheDocument(); + }); + + it('renders the copyright icon', () => { + render(<Copyright dates={dates} icon={icon} owner={owner} />); + expect(screen.getByTitle('CC BY SA')).toBeInTheDocument(); + }); +}); diff --git a/src/components/atoms/layout/copyright.tsx b/src/components/atoms/layout/copyright.tsx new file mode 100644 index 0000000..76252ee --- /dev/null +++ b/src/components/atoms/layout/copyright.tsx @@ -0,0 +1,59 @@ +import { ReactNode, VFC } from 'react'; +import styles from './copyright.module.scss'; + +export type CopyrightDates = { + /** + * The copyright start year. + */ + start: string; + /** + * The copyright end year. + */ + end?: string; +}; + +export type CopyrightProps = { + /** + * The copyright owner. + */ + owner: string; + /** + * The copyright dates. + */ + dates: CopyrightDates; + /** + * The copyright icon. + */ + icon: ReactNode; +}; + +/** + * Copyright component + * + * Renders a copyright information (owner, dates, license icon). + */ +const Copyright: VFC<CopyrightProps> = ({ owner, dates, icon }) => { + const getFormattedDate = (date: string) => { + const datetime = new Date(date).toISOString(); + + return <time dateTime={datetime}>{date}</time>; + }; + + return ( + <div className={styles.wrapper}> + <span className={styles.owner}>{owner}</span> + {icon} + {getFormattedDate(dates.start)} + {dates.end ? ( + <> + <span>-</span> + {getFormattedDate(dates.end)} + </> + ) : ( + '' + )} + </div> + ); +}; + +export default Copyright; |
