From 53677c794aafd55fc649cf7663f47cbeaeddc5d0 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 31 Mar 2022 22:53:16 +0200 Subject: chore: add an Arrow icon component --- src/components/atoms/icons/arrow.module.scss | 16 +++++ src/components/atoms/icons/arrow.stories.tsx | 29 +++++++++ src/components/atoms/icons/arrow.test.tsx | 9 +++ src/components/atoms/icons/arrow.tsx | 97 ++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 src/components/atoms/icons/arrow.module.scss create mode 100644 src/components/atoms/icons/arrow.stories.tsx create mode 100644 src/components/atoms/icons/arrow.test.tsx create mode 100644 src/components/atoms/icons/arrow.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/arrow.module.scss b/src/components/atoms/icons/arrow.module.scss new file mode 100644 index 0000000..76e6aea --- /dev/null +++ b/src/components/atoms/icons/arrow.module.scss @@ -0,0 +1,16 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + fill: var(--color-primary); + transition: all 0.25s ease-in-out 0s; + + &--left, + &--right { + width: var(--icon-size, #{fun.convert-px(30)}); + } + + &--bottom, + &--top { + height: var(--icon-size, #{fun.convert-px(30)}); + } +} diff --git a/src/components/atoms/icons/arrow.stories.tsx b/src/components/atoms/icons/arrow.stories.tsx new file mode 100644 index 0000000..52b5126 --- /dev/null +++ b/src/components/atoms/icons/arrow.stories.tsx @@ -0,0 +1,29 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import ArrowIcon from './arrow'; + +export default { + title: 'Atoms/Icons', + component: ArrowIcon, + argTypes: { + direction: { + control: { + type: 'select', + }, + description: 'An arrow icon.', + options: ['bottom', 'left', 'right', 'top'], + table: { + defaultValue: { summary: 'right' }, + }, + type: { + name: 'string', + required: false, + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Arrow = Template.bind({}); diff --git a/src/components/atoms/icons/arrow.test.tsx b/src/components/atoms/icons/arrow.test.tsx new file mode 100644 index 0000000..01813ce --- /dev/null +++ b/src/components/atoms/icons/arrow.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Arrow from './arrow'; + +describe('Arrow', () => { + it('renders an arrow icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/arrow.tsx b/src/components/atoms/icons/arrow.tsx new file mode 100644 index 0000000..f50d117 --- /dev/null +++ b/src/components/atoms/icons/arrow.tsx @@ -0,0 +1,97 @@ +import { FC } from 'react'; +import styles from './arrow.module.scss'; + +type ArrowDirection = 'top' | 'right' | 'bottom' | 'left'; + +type ArrowProps = { + /** + * The arrow direction. Default: right. + */ + direction?: ArrowDirection; +}; + +/** + * Arrow component + * + * Render a svg arrow icon. + */ +const Arrow: FC = ({ direction = 'right' }) => { + const directionClass = styles[`icon--${direction}`]; + const classes = `${styles.icon} ${directionClass}`; + + if (direction === 'top') { + return ( + + + + + ); + } + + if (direction === 'bottom') { + return ( + + + + + ); + } + + if (direction === 'left') { + return ( + + + + + ); + } + + return ( + + + + + ); +}; + +export default Arrow; -- cgit v1.2.3 From da9f0895bddd9385c1026715ac1b5e63594932eb Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 31 Mar 2022 23:00:41 +0200 Subject: chore: add a Sun icon component --- src/components/atoms/icons/sun.module.scss | 8 ++++++++ src/components/atoms/icons/sun.stories.tsx | 13 +++++++++++++ src/components/atoms/icons/sun.test.tsx | 9 +++++++++ src/components/atoms/icons/sun.tsx | 29 +++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 src/components/atoms/icons/sun.module.scss create mode 100644 src/components/atoms/icons/sun.stories.tsx create mode 100644 src/components/atoms/icons/sun.test.tsx create mode 100644 src/components/atoms/icons/sun.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/sun.module.scss b/src/components/atoms/icons/sun.module.scss new file mode 100644 index 0000000..5682aa3 --- /dev/null +++ b/src/components/atoms/icons/sun.module.scss @@ -0,0 +1,8 @@ +@use "@styles/abstracts/functions" as fun; + +.sun { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 4; + width: var(--icon-size, #{fun.convert-px(25)}); +} diff --git a/src/components/atoms/icons/sun.stories.tsx b/src/components/atoms/icons/sun.stories.tsx new file mode 100644 index 0000000..613b59e --- /dev/null +++ b/src/components/atoms/icons/sun.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import SunIcon from './sun'; + +export default { + title: 'Atoms/Icons', + component: SunIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Sun = Template.bind({}); diff --git a/src/components/atoms/icons/sun.test.tsx b/src/components/atoms/icons/sun.test.tsx new file mode 100644 index 0000000..21661a9 --- /dev/null +++ b/src/components/atoms/icons/sun.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Sun from './sun'; + +describe('Sun', () => { + it('renders a sun icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/sun.tsx b/src/components/atoms/icons/sun.tsx new file mode 100644 index 0000000..6caad9c --- /dev/null +++ b/src/components/atoms/icons/sun.tsx @@ -0,0 +1,29 @@ +import { FC } from 'react'; +import styles from './sun.module.scss'; + +type SunProps = { + /** + * The SVG title. + */ + title?: string; +}; + +/** + * Sun component. + * + * Render a svg sun icon. + */ +const Sun: FC = ({ title }) => { + return ( + + {title !== 'undefined' && {title}} + + + ); +}; + +export default Sun; -- cgit v1.2.3 From 82b70a23bc8fabedc8333f5063a858f7e90f253f Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 31 Mar 2022 23:04:39 +0200 Subject: chore: add a Moon icon component --- src/components/atoms/icons/moon.module.scss | 8 ++++++++ src/components/atoms/icons/moon.stories.tsx | 13 +++++++++++++ src/components/atoms/icons/moon.test.tsx | 9 +++++++++ src/components/atoms/icons/moon.tsx | 21 +++++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 src/components/atoms/icons/moon.module.scss create mode 100644 src/components/atoms/icons/moon.stories.tsx create mode 100644 src/components/atoms/icons/moon.test.tsx create mode 100644 src/components/atoms/icons/moon.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/moon.module.scss b/src/components/atoms/icons/moon.module.scss new file mode 100644 index 0000000..e0b53d6 --- /dev/null +++ b/src/components/atoms/icons/moon.module.scss @@ -0,0 +1,8 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 4; + width: var(--icon-size, #{fun.convert-px(25)}); +} diff --git a/src/components/atoms/icons/moon.stories.tsx b/src/components/atoms/icons/moon.stories.tsx new file mode 100644 index 0000000..393744b --- /dev/null +++ b/src/components/atoms/icons/moon.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import MoonIcon from './moon'; + +export default { + title: 'Atoms/Icons', + component: MoonIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Moon = Template.bind({}); diff --git a/src/components/atoms/icons/moon.test.tsx b/src/components/atoms/icons/moon.test.tsx new file mode 100644 index 0000000..1c96303 --- /dev/null +++ b/src/components/atoms/icons/moon.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Moon from './moon'; + +describe('Moon', () => { + it('renders a moon icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/moon.tsx b/src/components/atoms/icons/moon.tsx new file mode 100644 index 0000000..82b0ef6 --- /dev/null +++ b/src/components/atoms/icons/moon.tsx @@ -0,0 +1,21 @@ +import { FC } from 'react'; +import styles from './moon.module.scss'; + +type MoonProps = { + title?: string; +}; + +const Moon: FC = ({ title }) => { + return ( + + {title !== 'undefined' && {title}} + + + ); +}; + +export default Moon; -- cgit v1.2.3 From 9627efaf47db699ae379fda4db3abd77c55fe8f1 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 31 Mar 2022 23:13:53 +0200 Subject: chore: add a Home icon component --- src/components/atoms/icons/home.module.scss | 41 ++++++++++++++++++++++++ src/components/atoms/icons/home.stories.tsx | 13 ++++++++ src/components/atoms/icons/home.test.tsx | 9 ++++++ src/components/atoms/icons/home.tsx | 48 +++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+) create mode 100644 src/components/atoms/icons/home.module.scss create mode 100644 src/components/atoms/icons/home.stories.tsx create mode 100644 src/components/atoms/icons/home.test.tsx create mode 100644 src/components/atoms/icons/home.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/home.module.scss b/src/components/atoms/icons/home.module.scss new file mode 100644 index 0000000..48dcc6c --- /dev/null +++ b/src/components/atoms/icons/home.module.scss @@ -0,0 +1,41 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); +} + +.wall { + fill: var(--color-bg); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.indoor { + fill: var(--color-shadow-dark); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.door { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.roof { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.chimney { + fill: var(--color-bg); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.lines { + fill: var(--color-primary-darker); + stroke-width: 4; +} diff --git a/src/components/atoms/icons/home.stories.tsx b/src/components/atoms/icons/home.stories.tsx new file mode 100644 index 0000000..59eb477 --- /dev/null +++ b/src/components/atoms/icons/home.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import HomeIcon from './home'; + +export default { + title: 'Atoms/Icons', + component: HomeIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Home = Template.bind({}); diff --git a/src/components/atoms/icons/home.test.tsx b/src/components/atoms/icons/home.test.tsx new file mode 100644 index 0000000..a08a3cf --- /dev/null +++ b/src/components/atoms/icons/home.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Home from './home'; + +describe('Home', () => { + it('renders a home icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/home.tsx b/src/components/atoms/icons/home.tsx new file mode 100644 index 0000000..90d3a14 --- /dev/null +++ b/src/components/atoms/icons/home.tsx @@ -0,0 +1,48 @@ +import { FC } from 'react'; +import styles from './home.module.scss'; + +/** + * Home component. + * + * Render a home svg icon. + */ +const Home: FC = () => { + return ( + + + + + + + + + + ); +}; + +export default Home; -- cgit v1.2.3 From 60c284c7ad7383313886c5f4716589cb6c180693 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 31 Mar 2022 23:19:53 +0200 Subject: chore: add a posts stack svg icon component --- src/components/atoms/icons/posts-stack.module.scss | 22 +++++++ src/components/atoms/icons/posts-stack.stories.tsx | 13 +++++ src/components/atoms/icons/posts-stack.test.tsx | 9 +++ src/components/atoms/icons/posts-stack.tsx | 68 ++++++++++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 src/components/atoms/icons/posts-stack.module.scss create mode 100644 src/components/atoms/icons/posts-stack.stories.tsx create mode 100644 src/components/atoms/icons/posts-stack.test.tsx create mode 100644 src/components/atoms/icons/posts-stack.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/posts-stack.module.scss b/src/components/atoms/icons/posts-stack.module.scss new file mode 100644 index 0000000..a22d265 --- /dev/null +++ b/src/components/atoms/icons/posts-stack.module.scss @@ -0,0 +1,22 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); +} + +.lines { + fill: var(--color-fg); + stroke-width: 4; +} + +.picture { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); +} + +.background { + fill: var(--color-bg); + stroke: var(--color-primary-darker); + stroke-width: 4; +} diff --git a/src/components/atoms/icons/posts-stack.stories.tsx b/src/components/atoms/icons/posts-stack.stories.tsx new file mode 100644 index 0000000..e2206c2 --- /dev/null +++ b/src/components/atoms/icons/posts-stack.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import PostsStackIcon from './posts-stack'; + +export default { + title: 'Atoms/Icons', + component: PostsStackIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const PostsStack = Template.bind({}); diff --git a/src/components/atoms/icons/posts-stack.test.tsx b/src/components/atoms/icons/posts-stack.test.tsx new file mode 100644 index 0000000..8f44fa9 --- /dev/null +++ b/src/components/atoms/icons/posts-stack.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import PostsStack from './posts-stack'; + +describe('PostsStack', () => { + it('renders a posts stack icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/posts-stack.tsx b/src/components/atoms/icons/posts-stack.tsx new file mode 100644 index 0000000..22069ac --- /dev/null +++ b/src/components/atoms/icons/posts-stack.tsx @@ -0,0 +1,68 @@ +import { FC } from 'react'; +import styles from './posts-stack.module.scss'; + +/** + * Posts stack component. + * + * Render a posts stack svg icon. + */ +const PostsStack: FC = () => { + return ( + + + + + + + + + + + + + + + ); +}; + +export default PostsStack; -- cgit v1.2.3 From 3951a875a5c7619196239ce5f288f832d2f51224 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 31 Mar 2022 23:29:17 +0200 Subject: chore: add a CC BY SA svg icon component --- src/components/atoms/icons/cc-by-sa.module.scss | 7 +++++ src/components/atoms/icons/cc-by-sa.stories.tsx | 16 +++++++++++ src/components/atoms/icons/cc-by-sa.test.tsx | 9 ++++++ src/components/atoms/icons/cc-by-sa.tsx | 38 +++++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 src/components/atoms/icons/cc-by-sa.module.scss create mode 100644 src/components/atoms/icons/cc-by-sa.stories.tsx create mode 100644 src/components/atoms/icons/cc-by-sa.test.tsx create mode 100644 src/components/atoms/icons/cc-by-sa.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/cc-by-sa.module.scss b/src/components/atoms/icons/cc-by-sa.module.scss new file mode 100644 index 0000000..e1b2100 --- /dev/null +++ b/src/components/atoms/icons/cc-by-sa.module.scss @@ -0,0 +1,7 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(60)}); + fill: var(--color-fg); +} diff --git a/src/components/atoms/icons/cc-by-sa.stories.tsx b/src/components/atoms/icons/cc-by-sa.stories.tsx new file mode 100644 index 0000000..42a93c9 --- /dev/null +++ b/src/components/atoms/icons/cc-by-sa.stories.tsx @@ -0,0 +1,16 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { IntlProvider } from 'react-intl'; +import CCBySAIcon from './cc-by-sa'; + +export default { + title: 'Atoms/Icons', + component: CCBySAIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + + + +); + +export const CCBySA = Template.bind({}); diff --git a/src/components/atoms/icons/cc-by-sa.test.tsx b/src/components/atoms/icons/cc-by-sa.test.tsx new file mode 100644 index 0000000..03d54f7 --- /dev/null +++ b/src/components/atoms/icons/cc-by-sa.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import CCBySA from './cc-by-sa'; + +describe('CCBySA', () => { + it('renders a CC BY SA icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/cc-by-sa.tsx b/src/components/atoms/icons/cc-by-sa.tsx new file mode 100644 index 0000000..adc8b79 --- /dev/null +++ b/src/components/atoms/icons/cc-by-sa.tsx @@ -0,0 +1,38 @@ +import { FC } from 'react'; +import { useIntl } from 'react-intl'; +import styles from './cc-by-sa.module.scss'; + +/** + * CCBySA component + * + * Render a CC BY SA svg icon. + */ +const CCBySA: FC = () => { + const intl = useIntl(); + + return ( + + + {intl.formatMessage({ + defaultMessage: 'CC BY SA', + description: 'CCBySA: icon title', + id: 'cl7YNU', + })} + + + + + + + + + + + ); +}; + +export default CCBySA; -- cgit v1.2.3 From 9811d3d2777dcca9b74d15ce4f6126fb90b579bb Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 11:23:30 +0200 Subject: chore: add a Close icon component --- src/components/atoms/icons/close.module.scss | 12 ++++++++++++ src/components/atoms/icons/close.stories.tsx | 13 +++++++++++++ src/components/atoms/icons/close.test.tsx | 9 +++++++++ src/components/atoms/icons/close.tsx | 28 ++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 src/components/atoms/icons/close.module.scss create mode 100644 src/components/atoms/icons/close.stories.tsx create mode 100644 src/components/atoms/icons/close.test.tsx create mode 100644 src/components/atoms/icons/close.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/close.module.scss b/src/components/atoms/icons/close.module.scss new file mode 100644 index 0000000..4a5d18d --- /dev/null +++ b/src/components/atoms/icons/close.module.scss @@ -0,0 +1,12 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); +} + +.line { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 3; +} diff --git a/src/components/atoms/icons/close.stories.tsx b/src/components/atoms/icons/close.stories.tsx new file mode 100644 index 0000000..265df7a --- /dev/null +++ b/src/components/atoms/icons/close.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import CloseIcon from './close'; + +export default { + title: 'Atoms/Icons', + component: CloseIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Close = Template.bind({}); diff --git a/src/components/atoms/icons/close.test.tsx b/src/components/atoms/icons/close.test.tsx new file mode 100644 index 0000000..0357bec --- /dev/null +++ b/src/components/atoms/icons/close.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Close from './close'; + +describe('Close', () => { + it('renders a Close icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/close.tsx b/src/components/atoms/icons/close.tsx new file mode 100644 index 0000000..80d904e --- /dev/null +++ b/src/components/atoms/icons/close.tsx @@ -0,0 +1,28 @@ +import { FC } from 'react'; +import styles from './close.module.scss'; + +/** + * Close component + * + * Render a close svg icon. + */ +const Close: FC = () => { + return ( + + + + + ); +}; + +export default Close; -- cgit v1.2.3 From c1b6d057ba810705789e02e45f32ad29ce383954 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 11:25:56 +0200 Subject: chore: add a Cog icon component --- src/components/atoms/icons/cog.module.scss | 9 +++++++++ src/components/atoms/icons/cog.stories.tsx | 13 +++++++++++++ src/components/atoms/icons/cog.test.tsx | 9 +++++++++ src/components/atoms/icons/cog.tsx | 22 ++++++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 src/components/atoms/icons/cog.module.scss create mode 100644 src/components/atoms/icons/cog.stories.tsx create mode 100644 src/components/atoms/icons/cog.test.tsx create mode 100644 src/components/atoms/icons/cog.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/cog.module.scss b/src/components/atoms/icons/cog.module.scss new file mode 100644 index 0000000..8c48fcc --- /dev/null +++ b/src/components/atoms/icons/cog.module.scss @@ -0,0 +1,9 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 4; +} diff --git a/src/components/atoms/icons/cog.stories.tsx b/src/components/atoms/icons/cog.stories.tsx new file mode 100644 index 0000000..3b16ffc --- /dev/null +++ b/src/components/atoms/icons/cog.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import CogIcon from './cog'; + +export default { + title: 'Atoms/Icons', + component: CogIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Cog = Template.bind({}); diff --git a/src/components/atoms/icons/cog.test.tsx b/src/components/atoms/icons/cog.test.tsx new file mode 100644 index 0000000..89090fa --- /dev/null +++ b/src/components/atoms/icons/cog.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Cog from './cog'; + +describe('Cog', () => { + it('renders a Cog icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/cog.tsx b/src/components/atoms/icons/cog.tsx new file mode 100644 index 0000000..bed19ce --- /dev/null +++ b/src/components/atoms/icons/cog.tsx @@ -0,0 +1,22 @@ +import { FC } from 'react'; +import styles from './cog.module.scss'; + +/** + * Cog component + * + * Render a cog svg icon. + */ +const Cog: FC = () => { + return ( + + + + + ); +}; + +export default Cog; -- cgit v1.2.3 From 58005ad6ca761309eb8a92d2489030a7b1bad523 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 11:39:37 +0200 Subject: chore: add a Hamburger icon component --- src/components/atoms/icons/hamburger.module.scss | 57 ++++++++++++++++++++++++ src/components/atoms/icons/hamburger.stories.tsx | 25 +++++++++++ src/components/atoms/icons/hamburger.test.tsx | 9 ++++ src/components/atoms/icons/hamburger.tsx | 20 +++++++++ 4 files changed, 111 insertions(+) create mode 100644 src/components/atoms/icons/hamburger.module.scss create mode 100644 src/components/atoms/icons/hamburger.stories.tsx create mode 100644 src/components/atoms/icons/hamburger.test.tsx create mode 100644 src/components/atoms/icons/hamburger.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/hamburger.module.scss b/src/components/atoms/icons/hamburger.module.scss new file mode 100644 index 0000000..09e7e30 --- /dev/null +++ b/src/components/atoms/icons/hamburger.module.scss @@ -0,0 +1,57 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(50)}); + height: var(--icon-size, #{fun.convert-px(50)}); + position: relative; + + &, + &::before, + &::after { + display: block; + height: fun.convert-px(7); + background: var(--color-primary-lighter); + background-image: linear-gradient( + to right, + var(--color-primary-light) 0%, + var(--color-primary-lighter) 100% + ); + border: fun.convert-px(1) solid var(--color-primary-darker); + border-radius: fun.convert-px(3); + transition: all 0.25s ease-in-out 0s, transform 0.4s ease-in 0s; + } + + &::before, + &::after { + content: ""; + position: absolute; + left: fun.convert-px(-1); + right: fun.convert-px(-1); + } + + &::before { + bottom: fun.convert-px(15); + } + + &::after { + top: fun.convert-px(15); + } + + &--active { + background: transparent; + border: transparent; + + &::before { + bottom: 0; + transform-origin: 50% 50%; + transform: rotate(45deg); + } + + &::after { + top: 0; + transform-origin: 50% 50%; + transform: rotate(-45deg); + } + } +} diff --git a/src/components/atoms/icons/hamburger.stories.tsx b/src/components/atoms/icons/hamburger.stories.tsx new file mode 100644 index 0000000..c145daf --- /dev/null +++ b/src/components/atoms/icons/hamburger.stories.tsx @@ -0,0 +1,25 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import HamburgerIcon from './hamburger'; + +export default { + title: 'Atoms/Icons', + component: HamburgerIcon, + argTypes: { + isActive: { + control: { + type: 'boolean', + }, + description: 'Transform hamburger into a cross when state is active.', + type: { + name: 'boolean', + required: true, + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Hamburger = Template.bind({}); diff --git a/src/components/atoms/icons/hamburger.test.tsx b/src/components/atoms/icons/hamburger.test.tsx new file mode 100644 index 0000000..f8a3c04 --- /dev/null +++ b/src/components/atoms/icons/hamburger.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Hamburger from './hamburger'; + +describe('Hamburger', () => { + it('renders a Hamburger icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/hamburger.tsx b/src/components/atoms/icons/hamburger.tsx new file mode 100644 index 0000000..f081bf7 --- /dev/null +++ b/src/components/atoms/icons/hamburger.tsx @@ -0,0 +1,20 @@ +import { FC } from 'react'; +import styles from './hamburger.module.scss'; + +type HamburgerProps = { + isActive: boolean; +}; + +/** + * Hamburger component + * + * Render a Hamburger icon. + */ +const Hamburger: FC = ({ isActive }) => { + const stateClass = isActive ? `${styles['icon--active']}` : ''; + const iconClasses = `${styles.icon} ${stateClass}`; + + return ; +}; + +export default Hamburger; -- cgit v1.2.3 From 769c124ff54960ac9db4f9028b095c1385cd3961 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 11:43:38 +0200 Subject: chore: add a computer screen icon component --- .../atoms/icons/computer-screen.module.scss | 39 ++++++++++++ .../atoms/icons/computer-screen.stories.tsx | 13 ++++ .../atoms/icons/computer-screen.test.tsx | 9 +++ src/components/atoms/icons/computer-screen.tsx | 72 ++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 src/components/atoms/icons/computer-screen.module.scss create mode 100644 src/components/atoms/icons/computer-screen.stories.tsx create mode 100644 src/components/atoms/icons/computer-screen.test.tsx create mode 100644 src/components/atoms/icons/computer-screen.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/computer-screen.module.scss b/src/components/atoms/icons/computer-screen.module.scss new file mode 100644 index 0000000..6c8f701 --- /dev/null +++ b/src/components/atoms/icons/computer-screen.module.scss @@ -0,0 +1,39 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); +} + +.root, +.separator, +.cursor, +.line, +.text { + fill: var(--color-fg); +} + +.stand { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-dark); + + &--top { + stroke-width: 3; + } + + &--bottom { + stroke-width: 2; + } +} + +.screen { + fill: var(--color-bg); + stroke: var(--color-primary-dark); + stroke-width: 3; +} + +.contour { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-dark); + stroke-width: 3; +} diff --git a/src/components/atoms/icons/computer-screen.stories.tsx b/src/components/atoms/icons/computer-screen.stories.tsx new file mode 100644 index 0000000..317b4b6 --- /dev/null +++ b/src/components/atoms/icons/computer-screen.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import ComputerScreenIcon from './computer-screen'; + +export default { + title: 'Atoms/Icons', + component: ComputerScreenIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const ComputerScreen = Template.bind({}); diff --git a/src/components/atoms/icons/computer-screen.test.tsx b/src/components/atoms/icons/computer-screen.test.tsx new file mode 100644 index 0000000..c0e53e0 --- /dev/null +++ b/src/components/atoms/icons/computer-screen.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import ComputerScreen from './computer-screen'; + +describe('ComputerScreen', () => { + it('renders a computer screen icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/computer-screen.tsx b/src/components/atoms/icons/computer-screen.tsx new file mode 100644 index 0000000..c9c869d --- /dev/null +++ b/src/components/atoms/icons/computer-screen.tsx @@ -0,0 +1,72 @@ +import { FC } from 'react'; +import styles from './computer-screen.module.scss'; + +/** + * ComputerScreen component + * + * Render a computer screen svg icon. + */ +const ComputerScreen: FC = () => { + return ( + + + + + + + + + + + + + + + + ); +}; + +export default ComputerScreen; -- cgit v1.2.3 From 9b31e81c8d45eaf0dc6971655dc08b0d0a1cbe56 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 11:46:31 +0200 Subject: chore: add an envelop svg icon component --- src/components/atoms/icons/envelop.module.scss | 28 ++++++++++++ src/components/atoms/icons/envelop.stories.tsx | 13 ++++++ src/components/atoms/icons/envelop.test.tsx | 9 ++++ src/components/atoms/icons/envelop.tsx | 60 ++++++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 src/components/atoms/icons/envelop.module.scss create mode 100644 src/components/atoms/icons/envelop.stories.tsx create mode 100644 src/components/atoms/icons/envelop.test.tsx create mode 100644 src/components/atoms/icons/envelop.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/envelop.module.scss b/src/components/atoms/icons/envelop.module.scss new file mode 100644 index 0000000..202900b --- /dev/null +++ b/src/components/atoms/icons/envelop.module.scss @@ -0,0 +1,28 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); +} + +.envelop { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.lines { + fill: var(--color-fg); +} + +.background { + fill: var(--color-shadow-dark); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.paper { + fill: var(--color-bg); + stroke: var(--color-primary-darker); + stroke-width: 4; +} diff --git a/src/components/atoms/icons/envelop.stories.tsx b/src/components/atoms/icons/envelop.stories.tsx new file mode 100644 index 0000000..9577431 --- /dev/null +++ b/src/components/atoms/icons/envelop.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import EnvelopIcon from './envelop'; + +export default { + title: 'Atoms/Icons', + component: EnvelopIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Envelop = Template.bind({}); diff --git a/src/components/atoms/icons/envelop.test.tsx b/src/components/atoms/icons/envelop.test.tsx new file mode 100644 index 0000000..072dc85 --- /dev/null +++ b/src/components/atoms/icons/envelop.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Envelop from './envelop'; + +describe('Envelop', () => { + it('renders an envelop icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/envelop.tsx b/src/components/atoms/icons/envelop.tsx new file mode 100644 index 0000000..a846a45 --- /dev/null +++ b/src/components/atoms/icons/envelop.tsx @@ -0,0 +1,60 @@ +import { FC } from 'react'; +import styles from './envelop.module.scss'; + +/** + * Envelop Component + * + * Render an envelop svg icon. + */ +const Envelop: FC = () => { + return ( + + + + + + + + + + + + + ); +}; + +export default Envelop; -- cgit v1.2.3 From 3dba396791b37c4ae4dbdaf8e553ed636bc2ecc8 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 11:49:59 +0200 Subject: chore: add a magnifying glass icon component --- .../atoms/icons/magnifying-glass.module.scss | 30 ++++++++++++++++++ .../atoms/icons/magnifying-glass.stories.tsx | 13 ++++++++ .../atoms/icons/magnifying-glass.test.tsx | 9 ++++++ src/components/atoms/icons/magnifying-glass.tsx | 36 ++++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 src/components/atoms/icons/magnifying-glass.module.scss create mode 100644 src/components/atoms/icons/magnifying-glass.stories.tsx create mode 100644 src/components/atoms/icons/magnifying-glass.test.tsx create mode 100644 src/components/atoms/icons/magnifying-glass.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/magnifying-glass.module.scss b/src/components/atoms/icons/magnifying-glass.module.scss new file mode 100644 index 0000000..dca76fb --- /dev/null +++ b/src/components/atoms/icons/magnifying-glass.module.scss @@ -0,0 +1,30 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); +} + +.big-handle { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 3; +} + +.glass { + fill: var(--color-bg-opacity); + stroke: var(--color-primary-darker); + stroke-width: 2; +} + +.upright { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 3; +} + +.small-handle { + fill: var(--color-primary); + stroke: var(--color-primary-darker); + stroke-width: 2; +} diff --git a/src/components/atoms/icons/magnifying-glass.stories.tsx b/src/components/atoms/icons/magnifying-glass.stories.tsx new file mode 100644 index 0000000..69c5b50 --- /dev/null +++ b/src/components/atoms/icons/magnifying-glass.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import MagnifyingGlassIcon from './magnifying-glass'; + +export default { + title: 'Atoms/Icons', + component: MagnifyingGlassIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const MagnifyingGlass = Template.bind({}); diff --git a/src/components/atoms/icons/magnifying-glass.test.tsx b/src/components/atoms/icons/magnifying-glass.test.tsx new file mode 100644 index 0000000..8e788f7 --- /dev/null +++ b/src/components/atoms/icons/magnifying-glass.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import MagnifyingGlass from './magnifying-glass'; + +describe('MagnifyingGlass', () => { + it('renders a magnifying glass icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/magnifying-glass.tsx b/src/components/atoms/icons/magnifying-glass.tsx new file mode 100644 index 0000000..547dd00 --- /dev/null +++ b/src/components/atoms/icons/magnifying-glass.tsx @@ -0,0 +1,36 @@ +import { FC } from 'react'; +import styles from './magnifying-glass.module.scss'; + +/** + * MagnifyingGlass component + * + * Render a magnifying glass svg icon. + */ +const MagnifyingGlass: FC = () => { + return ( + + + + + + + ); +}; + +export default MagnifyingGlass; -- cgit v1.2.3 From 65da7e1ddaea17cb1391ce2bde5f4345acd7b4ad Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Apr 2022 11:53:23 +0200 Subject: chore: add a career icon component --- src/components/atoms/icons/career.module.scss | 53 ++++++++++++++++++++++ src/components/atoms/icons/career.stories.tsx | 13 ++++++ src/components/atoms/icons/career.test.tsx | 9 ++++ src/components/atoms/icons/career.tsx | 64 +++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 src/components/atoms/icons/career.module.scss create mode 100644 src/components/atoms/icons/career.stories.tsx create mode 100644 src/components/atoms/icons/career.test.tsx create mode 100644 src/components/atoms/icons/career.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/career.module.scss b/src/components/atoms/icons/career.module.scss new file mode 100644 index 0000000..c5d65eb --- /dev/null +++ b/src/components/atoms/icons/career.module.scss @@ -0,0 +1,53 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: block; + width: var(--icon-size, #{fun.convert-px(40)}); +} + +.lock { + fill: var(--color-bg); + stroke: var(--color-primary-darker); + stroke-width: 3; +} + +.lines { + fill: var(--color-fg); + stroke-width: 4; +} + +.seal-top { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 2; +} + +.seal-bottom { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 2; +} + +.diploma { + fill: var(--color-bg); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.top { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 4; +} + +.handle { + fill: var(--color-primary-lighter); + stroke: var(--color-primary-darker); + stroke-width: 3; +} + +.bottom { + fill: var(--color-primary); + stroke: var(--color-primary-darker); + stroke-width: 4; +} diff --git a/src/components/atoms/icons/career.stories.tsx b/src/components/atoms/icons/career.stories.tsx new file mode 100644 index 0000000..2c1d93a --- /dev/null +++ b/src/components/atoms/icons/career.stories.tsx @@ -0,0 +1,13 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import CareerIcon from './career'; + +export default { + title: 'Atoms/Icons', + component: CareerIcon, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Career = Template.bind({}); diff --git a/src/components/atoms/icons/career.test.tsx b/src/components/atoms/icons/career.test.tsx new file mode 100644 index 0000000..62ffc14 --- /dev/null +++ b/src/components/atoms/icons/career.test.tsx @@ -0,0 +1,9 @@ +import { render } from '@test-utils'; +import Career from './career'; + +describe('Career', () => { + it('renders a Career icon', () => { + const { container } = render(); + expect(container).toBeDefined(); + }); +}); diff --git a/src/components/atoms/icons/career.tsx b/src/components/atoms/icons/career.tsx new file mode 100644 index 0000000..aecab1e --- /dev/null +++ b/src/components/atoms/icons/career.tsx @@ -0,0 +1,64 @@ +import { FC } from 'react'; +import styles from './career.module.scss'; + +/** + * Career Component + * + * Render a career svg icon. + */ +const Career: FC = () => { + return ( + + + + + + + + + + + + + + ); +}; + +export default Career; -- cgit v1.2.3 From e8bac61a7f0be6c60624b00e06ab8d00efc932f8 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 4 Apr 2022 18:46:05 +0200 Subject: chore: add a PlusMinus icon component --- src/components/atoms/icons/plus-minus.module.scss | 39 ++++++++++++ src/components/atoms/icons/plus-minus.stories.tsx | 73 +++++++++++++++++++++++ src/components/atoms/icons/plus-minus.test.tsx | 16 +++++ src/components/atoms/icons/plus-minus.tsx | 45 ++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 src/components/atoms/icons/plus-minus.module.scss create mode 100644 src/components/atoms/icons/plus-minus.stories.tsx create mode 100644 src/components/atoms/icons/plus-minus.test.tsx create mode 100644 src/components/atoms/icons/plus-minus.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/plus-minus.module.scss b/src/components/atoms/icons/plus-minus.module.scss new file mode 100644 index 0000000..c54db33 --- /dev/null +++ b/src/components/atoms/icons/plus-minus.module.scss @@ -0,0 +1,39 @@ +@use "@styles/abstracts/functions" as fun; + +.icon { + display: flex; + place-content: center; + place-items: center; + width: var(--icon-size, #{fun.convert-px(30)}); + height: var(--icon-size, #{fun.convert-px(30)}); + position: relative; + background: var(--color-bg); + border: fun.convert-px(1) solid var(--color-primary); + border-radius: fun.convert-px(3); + color: var(--color-primary); + + &::before, + &::after { + content: ""; + position: absolute; + background: var(--color-primary); + transition: transform 0.4s ease-out 0s; + } + + &::after { + height: fun.convert-px(3); + width: 60%; + } + + &::before { + height: 60%; + width: fun.convert-px(3); + transform: scaleY(1); + } + + &--minus { + &::before { + transform: scaleY(0); + } + } +} diff --git a/src/components/atoms/icons/plus-minus.stories.tsx b/src/components/atoms/icons/plus-minus.stories.tsx new file mode 100644 index 0000000..1b5086a --- /dev/null +++ b/src/components/atoms/icons/plus-minus.stories.tsx @@ -0,0 +1,73 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import PlusMinusIcon from './plus-minus'; + +export default { + title: 'Atoms/Icons', + component: PlusMinusIcon, + args: { + ariaHidden: true, + }, + argTypes: { + additionalClasses: { + control: { + type: 'text', + }, + description: 'Set additional classes.', + table: { + category: 'Options', + }, + type: { + name: 'string', + required: false, + }, + }, + ariaHidden: { + control: { + type: 'boolean', + }, + description: 'Should be hidden for accessibility.', + table: { + category: 'Options', + defaultValue: { summary: true }, + }, + type: { + name: 'boolean', + required: false, + }, + }, + ariaLabel: { + control: { + type: 'text', + }, + description: 'An accessible name.', + table: { + category: 'Options', + }, + type: { + name: 'string', + required: false, + }, + }, + state: { + control: { + type: 'radio', + options: ['plus', 'minus'], + }, + description: 'Which state should be displayed.', + type: { + name: 'enum', + required: true, + value: ['plus', 'minus'], + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const PlusMinus = Template.bind({}); +PlusMinus.args = { + state: 'plus', +}; diff --git a/src/components/atoms/icons/plus-minus.test.tsx b/src/components/atoms/icons/plus-minus.test.tsx new file mode 100644 index 0000000..96c2ad0 --- /dev/null +++ b/src/components/atoms/icons/plus-minus.test.tsx @@ -0,0 +1,16 @@ +import { render, screen } from '@test-utils'; +import PlusMinus from './plus-minus'; + +describe('PlusMinus', () => { + it('renders a plus icon', () => { + render(); + expect(screen.getByLabelText('Plus icon')).toHaveClass('icon--plus'); + }); + + it('renders a minus icon', () => { + render( + + ); + expect(screen.getByLabelText('Minus icon')).toHaveClass('icon--minus'); + }); +}); diff --git a/src/components/atoms/icons/plus-minus.tsx b/src/components/atoms/icons/plus-minus.tsx new file mode 100644 index 0000000..1a6f7b0 --- /dev/null +++ b/src/components/atoms/icons/plus-minus.tsx @@ -0,0 +1,45 @@ +import { FC } from 'react'; +import styles from './plus-minus.module.scss'; + +type PlusMinusProps = { + /** + * Adds additional classes. + */ + additionalClasses?: string; + /** + * An accessible name. + */ + ariaLabel?: string; + /** + * Should be hidden for accessibility. Default: true. + */ + ariaHidden?: boolean; + /** + * Which state should be displayed. + */ + state: 'plus' | 'minus'; +}; + +/** + * PlusMinus component + * + * Render a plus or a minus icon. + */ +const PlusMinus: FC = ({ + additionalClasses, + ariaHidden = true, + ariaLabel, + state, +}) => { + const stateClass = `icon--${state}`; + + return ( +
+ ); +}; + +export default PlusMinus; -- cgit v1.2.3 From 47e12259d512e476326e83929efebf036b57f7c1 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Wed, 6 Apr 2022 18:40:17 +0200 Subject: chore: add a Modal component --- src/components/atoms/headings/heading.stories.tsx | 13 +++++ src/components/atoms/headings/heading.tsx | 6 +-- src/components/atoms/icons/cog.module.scss | 1 - .../atoms/icons/magnifying-glass.module.scss | 1 - src/components/molecules/layout/modal.module.scss | 21 ++++++++ src/components/molecules/layout/modal.stories.tsx | 57 ++++++++++++++++++++++ src/components/molecules/layout/modal.test.tsx | 9 ++++ src/components/molecules/layout/modal.tsx | 48 ++++++++++++++++++ 8 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 src/components/molecules/layout/modal.module.scss create mode 100644 src/components/molecules/layout/modal.stories.tsx create mode 100644 src/components/molecules/layout/modal.test.tsx create mode 100644 src/components/molecules/layout/modal.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/headings/heading.stories.tsx b/src/components/atoms/headings/heading.stories.tsx index 0b286fe..cea3532 100644 --- a/src/components/atoms/headings/heading.stories.tsx +++ b/src/components/atoms/headings/heading.stories.tsx @@ -9,6 +9,19 @@ export default { withMargin: true, }, argTypes: { + additionalClasses: { + control: { + type: 'text', + }, + description: 'Set additional classes.', + table: { + category: 'Options', + }, + type: { + name: 'string', + required: false, + }, + }, children: { description: 'Heading body.', type: { diff --git a/src/components/atoms/headings/heading.tsx b/src/components/atoms/headings/heading.tsx index 77580cc..136571d 100644 --- a/src/components/atoms/headings/heading.tsx +++ b/src/components/atoms/headings/heading.tsx @@ -1,7 +1,7 @@ import { FC } from 'react'; import styles from './heading.module.scss'; -type HeadingProps = { +export type HeadingProps = { /** * Adds additional classes. */ @@ -33,12 +33,12 @@ const Heading: FC = ({ withMargin = true, }) => { const TitleTag = isFake ? `p` : (`h${level}` as keyof JSX.IntrinsicElements); - const variantClass = withMargin ? 'heading--margin' : 'heading--regular'; const levelClass = `heading--${level}`; + const marginClass = withMargin ? 'heading--margin' : 'heading--regular'; return ( {children} diff --git a/src/components/atoms/icons/cog.module.scss b/src/components/atoms/icons/cog.module.scss index 8c48fcc..5201598 100644 --- a/src/components/atoms/icons/cog.module.scss +++ b/src/components/atoms/icons/cog.module.scss @@ -1,7 +1,6 @@ @use "@styles/abstracts/functions" as fun; .icon { - display: block; width: var(--icon-size, #{fun.convert-px(40)}); fill: var(--color-primary-lighter); stroke: var(--color-primary-darker); diff --git a/src/components/atoms/icons/magnifying-glass.module.scss b/src/components/atoms/icons/magnifying-glass.module.scss index dca76fb..d14bec5 100644 --- a/src/components/atoms/icons/magnifying-glass.module.scss +++ b/src/components/atoms/icons/magnifying-glass.module.scss @@ -1,7 +1,6 @@ @use "@styles/abstracts/functions" as fun; .icon { - display: block; width: var(--icon-size, #{fun.convert-px(40)}); } diff --git a/src/components/molecules/layout/modal.module.scss b/src/components/molecules/layout/modal.module.scss new file mode 100644 index 0000000..2fff562 --- /dev/null +++ b/src/components/molecules/layout/modal.module.scss @@ -0,0 +1,21 @@ +@use "@styles/abstracts/functions" as fun; + +.wrapper { + padding: var(--spacing-md); + background: var(--color-bg-secondary); + border: fun.convert-px(4) solid; + border-image: radial-gradient( + ellipse at top, + var(--color-primary-lighter) 20%, + var(--color-primary) 100% + ) + 1; + box-shadow: fun.convert-px(2) fun.convert-px(-2) fun.convert-px(3) + fun.convert-px(-1) var(--color-shadow-dark); +} + +.icon { + --icon-size: #{fun.convert-px(30)}; + + margin-right: var(--spacing-2xs); +} diff --git a/src/components/molecules/layout/modal.stories.tsx b/src/components/molecules/layout/modal.stories.tsx new file mode 100644 index 0000000..396e89e --- /dev/null +++ b/src/components/molecules/layout/modal.stories.tsx @@ -0,0 +1,57 @@ +import Cog from '@components/atoms/icons/cog'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import ModalComponent from './modal'; + +export default { + title: 'Molecules/Layout', + component: ModalComponent, + argTypes: { + children: { + control: { + type: 'text', + }, + description: 'The modal body.', + type: { + name: 'string', + required: true, + }, + }, + icon: { + control: { + type: 'select', + }, + description: 'The title icon.', + options: ['', 'cogs', 'search'], + table: { + category: 'Options', + }, + type: { + name: 'string', + required: false, + }, + }, + title: { + control: { + type: 'text', + }, + description: 'The modal title.', + table: { + category: 'Options', + }, + type: { + name: 'string', + required: false, + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Modal = Template.bind({}); +Modal.args = { + children: + 'Inventore natus dignissimos aut illum modi asperiores. Et voluptatibus delectus.', +}; diff --git a/src/components/molecules/layout/modal.test.tsx b/src/components/molecules/layout/modal.test.tsx new file mode 100644 index 0000000..14fb224 --- /dev/null +++ b/src/components/molecules/layout/modal.test.tsx @@ -0,0 +1,9 @@ +import { render, screen } from '@test-utils'; +import Modal from './modal'; + +describe('Modal', () => { + it('renders a title', () => { + render(); + expect(screen.getByText('A custom title')).toBeInTheDocument(); + }); +}); diff --git a/src/components/molecules/layout/modal.tsx b/src/components/molecules/layout/modal.tsx new file mode 100644 index 0000000..4dc3b0a --- /dev/null +++ b/src/components/molecules/layout/modal.tsx @@ -0,0 +1,48 @@ +import Heading from '@components/atoms/headings/heading'; +import dynamic from 'next/dynamic'; +import { FC, ReactNode } from 'react'; +import styles from './modal.module.scss'; + +export type Icons = 'cogs' | 'search'; + +export type ModalProps = { + icon?: Icons; + title?: string; +}; + +const CogIcon = dynamic(() => import('@components/atoms/icons/cog')); +const SearchIcon = dynamic( + () => import('@components/atoms/icons/magnifying-glass') +); + +/** + * Modal component + * + * Render a modal component with an optional title and icon. + */ +const Modal: FC = ({ children, icon, title }) => { + const getIcon = (id: Icons) => { + switch (id) { + case 'cogs': + return ; + case 'search': + return ; + default: + return <>; + } + }; + + return ( +
+ {title && ( + + {icon && {getIcon(icon)}} + {title} + + )} + {children} +
+ ); +}; + +export default Modal; -- cgit v1.2.3 From 5c75a302c2203cb3ebf31233121026b4775662cf Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 8 Apr 2022 19:32:58 +0200 Subject: chore(icons): accept a classname as prop --- src/components/atoms/icons/arrow.stories.tsx | 19 ++++++++++-- src/components/atoms/icons/arrow.test.tsx | 4 +-- src/components/atoms/icons/arrow.tsx | 16 ++++++---- src/components/atoms/icons/career.stories.tsx | 15 +++++++++ src/components/atoms/icons/career.tsx | 13 ++++++-- src/components/atoms/icons/cc-by-sa.stories.tsx | 15 +++++++++ src/components/atoms/icons/cc-by-sa.test.tsx | 6 ++-- src/components/atoms/icons/cc-by-sa.tsx | 13 ++++++-- src/components/atoms/icons/close.stories.tsx | 15 +++++++++ src/components/atoms/icons/close.tsx | 13 ++++++-- src/components/atoms/icons/cog.stories.tsx | 15 +++++++++ src/components/atoms/icons/cog.tsx | 13 ++++++-- .../atoms/icons/computer-screen.stories.tsx | 15 +++++++++ src/components/atoms/icons/computer-screen.tsx | 13 ++++++-- src/components/atoms/icons/envelop.stories.tsx | 15 +++++++++ src/components/atoms/icons/envelop.tsx | 13 ++++++-- src/components/atoms/icons/hamburger.stories.tsx | 13 ++++++++ src/components/atoms/icons/hamburger.tsx | 11 +++++-- src/components/atoms/icons/home.stories.tsx | 15 +++++++++ src/components/atoms/icons/home.tsx | 13 ++++++-- .../atoms/icons/magnifying-glass.stories.tsx | 15 +++++++++ src/components/atoms/icons/magnifying-glass.tsx | 13 ++++++-- src/components/atoms/icons/moon.stories.tsx | 28 +++++++++++++++++ src/components/atoms/icons/moon.tsx | 13 ++++++-- src/components/atoms/icons/plus-minus.stories.tsx | 36 ++-------------------- src/components/atoms/icons/plus-minus.test.tsx | 15 +++------ src/components/atoms/icons/plus-minus.tsx | 24 +++------------ src/components/atoms/icons/posts-stack.stories.tsx | 15 +++++++++ src/components/atoms/icons/posts-stack.tsx | 13 ++++++-- src/components/atoms/icons/sun.stories.tsx | 28 +++++++++++++++++ src/components/atoms/icons/sun.tsx | 10 ++++-- 31 files changed, 363 insertions(+), 112 deletions(-) (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/arrow.stories.tsx b/src/components/atoms/icons/arrow.stories.tsx index 52b5126..96ce1d8 100644 --- a/src/components/atoms/icons/arrow.stories.tsx +++ b/src/components/atoms/icons/arrow.stories.tsx @@ -5,15 +5,25 @@ export default { title: 'Atoms/Icons', component: ArrowIcon, argTypes: { + className: { + control: { + type: 'text', + }, + description: 'Set additional classnames.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, direction: { control: { type: 'select', }, description: 'An arrow icon.', options: ['bottom', 'left', 'right', 'top'], - table: { - defaultValue: { summary: 'right' }, - }, type: { name: 'string', required: false, @@ -27,3 +37,6 @@ const Template: ComponentStory = (args) => ( ); export const Arrow = Template.bind({}); +Arrow.args = { + direction: 'right', +}; diff --git a/src/components/atoms/icons/arrow.test.tsx b/src/components/atoms/icons/arrow.test.tsx index 01813ce..502dcc1 100644 --- a/src/components/atoms/icons/arrow.test.tsx +++ b/src/components/atoms/icons/arrow.test.tsx @@ -2,8 +2,8 @@ import { render } from '@test-utils'; import Arrow from './arrow'; describe('Arrow', () => { - it('renders an arrow icon', () => { - const { container } = render(); + it('renders an arrow icon oriented to the right', () => { + const { container } = render(); expect(container).toBeDefined(); }); }); diff --git a/src/components/atoms/icons/arrow.tsx b/src/components/atoms/icons/arrow.tsx index f50d117..5f3c460 100644 --- a/src/components/atoms/icons/arrow.tsx +++ b/src/components/atoms/icons/arrow.tsx @@ -1,13 +1,17 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './arrow.module.scss'; -type ArrowDirection = 'top' | 'right' | 'bottom' | 'left'; +export type ArrowDirection = 'top' | 'right' | 'bottom' | 'left'; -type ArrowProps = { +export type ArrowProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; /** * The arrow direction. Default: right. */ - direction?: ArrowDirection; + direction: ArrowDirection; }; /** @@ -15,9 +19,9 @@ type ArrowProps = { * * Render a svg arrow icon. */ -const Arrow: FC = ({ direction = 'right' }) => { +const Arrow: VFC = ({ className = '', direction }) => { const directionClass = styles[`icon--${direction}`]; - const classes = `${styles.icon} ${directionClass}`; + const classes = `${styles.icon} ${directionClass} ${className}`; if (direction === 'top') { return ( diff --git a/src/components/atoms/icons/career.stories.tsx b/src/components/atoms/icons/career.stories.tsx index 2c1d93a..8575cb9 100644 --- a/src/components/atoms/icons/career.stories.tsx +++ b/src/components/atoms/icons/career.stories.tsx @@ -4,6 +4,21 @@ import CareerIcon from './career'; export default { title: 'Atoms/Icons', component: CareerIcon, + argTypes: { + className: { + control: { + type: 'text', + }, + description: 'Set additional classnames.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, + }, } as ComponentMeta; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/career.tsx b/src/components/atoms/icons/career.tsx index aecab1e..28edcc7 100644 --- a/src/components/atoms/icons/career.tsx +++ b/src/components/atoms/icons/career.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './career.module.scss'; +export type CareerProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * Career Component * * Render a career svg icon. */ -const Career: FC = () => { +const Career: VFC = ({ className = '' }) => { return ( ; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/cc-by-sa.test.tsx b/src/components/atoms/icons/cc-by-sa.test.tsx index 03d54f7..adb03e4 100644 --- a/src/components/atoms/icons/cc-by-sa.test.tsx +++ b/src/components/atoms/icons/cc-by-sa.test.tsx @@ -1,9 +1,9 @@ -import { render } from '@test-utils'; +import { render, screen } from '@test-utils'; import CCBySA from './cc-by-sa'; describe('CCBySA', () => { it('renders a CC BY SA icon', () => { - const { container } = render(); - expect(container).toBeDefined(); + render(); + expect(screen.getByTitle('CC BY SA')).toBeInTheDocument(); }); }); diff --git a/src/components/atoms/icons/cc-by-sa.tsx b/src/components/atoms/icons/cc-by-sa.tsx index adc8b79..552504e 100644 --- a/src/components/atoms/icons/cc-by-sa.tsx +++ b/src/components/atoms/icons/cc-by-sa.tsx @@ -1,18 +1,25 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import { useIntl } from 'react-intl'; import styles from './cc-by-sa.module.scss'; +export type CCBySAProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * CCBySA component * * Render a CC BY SA svg icon. */ -const CCBySA: FC = () => { +const CCBySA: VFC = ({ className = '' }) => { const intl = useIntl(); return ( diff --git a/src/components/atoms/icons/close.stories.tsx b/src/components/atoms/icons/close.stories.tsx index 265df7a..b1d88cd 100644 --- a/src/components/atoms/icons/close.stories.tsx +++ b/src/components/atoms/icons/close.stories.tsx @@ -4,6 +4,21 @@ import CloseIcon from './close'; export default { title: 'Atoms/Icons', component: CloseIcon, + argTypes: { + className: { + control: { + type: 'text', + }, + description: 'Set additional classnames.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, + }, } as ComponentMeta; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/close.tsx b/src/components/atoms/icons/close.tsx index 80d904e..eb9ce7c 100644 --- a/src/components/atoms/icons/close.tsx +++ b/src/components/atoms/icons/close.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './close.module.scss'; +export type CloseProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * Close component * * Render a close svg icon. */ -const Close: FC = () => { +const Close: VFC = ({ className = '' }) => { return ( ; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/cog.tsx b/src/components/atoms/icons/cog.tsx index bed19ce..df6d54d 100644 --- a/src/components/atoms/icons/cog.tsx +++ b/src/components/atoms/icons/cog.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './cog.module.scss'; +export type CogProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * Cog component * * Render a cog svg icon. */ -const Cog: FC = () => { +const Cog: VFC = ({ className = '' }) => { return ( diff --git a/src/components/atoms/icons/computer-screen.stories.tsx b/src/components/atoms/icons/computer-screen.stories.tsx index 317b4b6..46e3ad4 100644 --- a/src/components/atoms/icons/computer-screen.stories.tsx +++ b/src/components/atoms/icons/computer-screen.stories.tsx @@ -4,6 +4,21 @@ import ComputerScreenIcon from './computer-screen'; export default { title: 'Atoms/Icons', component: ComputerScreenIcon, + argTypes: { + className: { + control: { + type: 'text', + }, + description: 'Set additional classnames.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, + }, } as ComponentMeta; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/computer-screen.tsx b/src/components/atoms/icons/computer-screen.tsx index c9c869d..310836f 100644 --- a/src/components/atoms/icons/computer-screen.tsx +++ b/src/components/atoms/icons/computer-screen.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './computer-screen.module.scss'; +export type ComputerScreenProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * ComputerScreen component * * Render a computer screen svg icon. */ -const ComputerScreen: FC = () => { +const ComputerScreen: VFC = ({ className = '' }) => { return ( ; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/envelop.tsx b/src/components/atoms/icons/envelop.tsx index a846a45..7b50d1d 100644 --- a/src/components/atoms/icons/envelop.tsx +++ b/src/components/atoms/icons/envelop.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './envelop.module.scss'; +export type EnvelopProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * Envelop Component * * Render an envelop svg icon. */ -const Envelop: FC = () => { +const Envelop: VFC = ({ className = '' }) => { return ( = ({ isActive }) => { +const Hamburger: FC = ({ className = '', isActive }) => { const stateClass = isActive ? `${styles['icon--active']}` : ''; - const iconClasses = `${styles.icon} ${stateClass}`; + const iconClasses = `${styles.icon} ${stateClass} ${className}`; return ; }; diff --git a/src/components/atoms/icons/home.stories.tsx b/src/components/atoms/icons/home.stories.tsx index 59eb477..b1c995c 100644 --- a/src/components/atoms/icons/home.stories.tsx +++ b/src/components/atoms/icons/home.stories.tsx @@ -4,6 +4,21 @@ import HomeIcon from './home'; export default { title: 'Atoms/Icons', component: HomeIcon, + argTypes: { + className: { + control: { + type: 'text', + }, + description: 'Set additional classnames.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, + }, } as ComponentMeta; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/home.tsx b/src/components/atoms/icons/home.tsx index 90d3a14..71bbc4a 100644 --- a/src/components/atoms/icons/home.tsx +++ b/src/components/atoms/icons/home.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './home.module.scss'; +export type HomeProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * Home component. * * Render a home svg icon. */ -const Home: FC = () => { +const Home: VFC = ({ className = '' }) => { return ( ; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/magnifying-glass.tsx b/src/components/atoms/icons/magnifying-glass.tsx index 547dd00..445ef10 100644 --- a/src/components/atoms/icons/magnifying-glass.tsx +++ b/src/components/atoms/icons/magnifying-glass.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './magnifying-glass.module.scss'; +export type MagnifyingGlassProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * MagnifyingGlass component * * Render a magnifying glass svg icon. */ -const MagnifyingGlass: FC = () => { +const MagnifyingGlass: VFC = ({ className = '' }) => { return ( ; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/moon.tsx b/src/components/atoms/icons/moon.tsx index 82b0ef6..4f52319 100644 --- a/src/components/atoms/icons/moon.tsx +++ b/src/components/atoms/icons/moon.tsx @@ -1,14 +1,21 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './moon.module.scss'; type MoonProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; + /** + * The SVG title. + */ title?: string; }; -const Moon: FC = ({ title }) => { +const Moon: VFC = ({ className = '', title }) => { return ( diff --git a/src/components/atoms/icons/plus-minus.stories.tsx b/src/components/atoms/icons/plus-minus.stories.tsx index 1b5086a..ffa28f2 100644 --- a/src/components/atoms/icons/plus-minus.stories.tsx +++ b/src/components/atoms/icons/plus-minus.stories.tsx @@ -4,44 +4,14 @@ import PlusMinusIcon from './plus-minus'; export default { title: 'Atoms/Icons', component: PlusMinusIcon, - args: { - ariaHidden: true, - }, argTypes: { - additionalClasses: { - control: { - type: 'text', - }, - description: 'Set additional classes.', - table: { - category: 'Options', - }, - type: { - name: 'string', - required: false, - }, - }, - ariaHidden: { - control: { - type: 'boolean', - }, - description: 'Should be hidden for accessibility.', - table: { - category: 'Options', - defaultValue: { summary: true }, - }, - type: { - name: 'boolean', - required: false, - }, - }, - ariaLabel: { + className: { control: { type: 'text', }, - description: 'An accessible name.', + description: 'Set additional classnames.', table: { - category: 'Options', + category: 'Styles', }, type: { name: 'string', diff --git a/src/components/atoms/icons/plus-minus.test.tsx b/src/components/atoms/icons/plus-minus.test.tsx index 96c2ad0..6903c7a 100644 --- a/src/components/atoms/icons/plus-minus.test.tsx +++ b/src/components/atoms/icons/plus-minus.test.tsx @@ -1,16 +1,9 @@ -import { render, screen } from '@test-utils'; +import { render } from '@test-utils'; import PlusMinus from './plus-minus'; describe('PlusMinus', () => { - it('renders a plus icon', () => { - render(); - expect(screen.getByLabelText('Plus icon')).toHaveClass('icon--plus'); - }); - - it('renders a minus icon', () => { - render( - - ); - expect(screen.getByLabelText('Minus icon')).toHaveClass('icon--minus'); + it('renders a plus/minus icon', () => { + const { container } = render(); + expect(container).toBeDefined(); }); }); diff --git a/src/components/atoms/icons/plus-minus.tsx b/src/components/atoms/icons/plus-minus.tsx index 1a6f7b0..78aa14a 100644 --- a/src/components/atoms/icons/plus-minus.tsx +++ b/src/components/atoms/icons/plus-minus.tsx @@ -3,17 +3,9 @@ import styles from './plus-minus.module.scss'; type PlusMinusProps = { /** - * Adds additional classes. + * Set additional classnames to the icon. */ - additionalClasses?: string; - /** - * An accessible name. - */ - ariaLabel?: string; - /** - * Should be hidden for accessibility. Default: true. - */ - ariaHidden?: boolean; + className?: string; /** * Which state should be displayed. */ @@ -25,19 +17,13 @@ type PlusMinusProps = { * * Render a plus or a minus icon. */ -const PlusMinus: FC = ({ - additionalClasses, - ariaHidden = true, - ariaLabel, - state, -}) => { +const PlusMinus: FC = ({ className, state }) => { const stateClass = `icon--${state}`; return (
); }; diff --git a/src/components/atoms/icons/posts-stack.stories.tsx b/src/components/atoms/icons/posts-stack.stories.tsx index e2206c2..46bb39f 100644 --- a/src/components/atoms/icons/posts-stack.stories.tsx +++ b/src/components/atoms/icons/posts-stack.stories.tsx @@ -4,6 +4,21 @@ import PostsStackIcon from './posts-stack'; export default { title: 'Atoms/Icons', component: PostsStackIcon, + argTypes: { + className: { + control: { + type: 'text', + }, + description: 'Set additional classnames.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, + }, } as ComponentMeta; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/posts-stack.tsx b/src/components/atoms/icons/posts-stack.tsx index 22069ac..1998d25 100644 --- a/src/components/atoms/icons/posts-stack.tsx +++ b/src/components/atoms/icons/posts-stack.tsx @@ -1,17 +1,24 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './posts-stack.module.scss'; +export type PostsStackProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; +}; + /** * Posts stack component. * * Render a posts stack svg icon. */ -const PostsStack: FC = () => { +const PostsStack: VFC = ({ className = '' }) => { return ( ; const Template: ComponentStory = (args) => ( diff --git a/src/components/atoms/icons/sun.tsx b/src/components/atoms/icons/sun.tsx index 6caad9c..fa9d922 100644 --- a/src/components/atoms/icons/sun.tsx +++ b/src/components/atoms/icons/sun.tsx @@ -1,7 +1,11 @@ -import { FC } from 'react'; +import { VFC } from 'react'; import styles from './sun.module.scss'; type SunProps = { + /** + * Set additional classnames to the icon. + */ + className?: string; /** * The SVG title. */ @@ -13,10 +17,10 @@ type SunProps = { * * Render a svg sun icon. */ -const Sun: FC = ({ title }) => { +const Sun: VFC = ({ className = '', title }) => { return ( -- cgit v1.2.3 From ff3a251e75fafce7d95177010401483127973313 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Tue, 12 Apr 2022 15:48:47 +0200 Subject: chore: add a MainNavButton component I also move the active state from the hamburger to this pseudo-button. It makes more sense that the button handles the icon shape. --- src/components/atoms/icons/hamburger.module.scss | 33 +++------ src/components/atoms/icons/hamburger.stories.tsx | 15 ++-- src/components/atoms/icons/hamburger.test.tsx | 2 +- src/components/atoms/icons/hamburger.tsx | 21 +++--- .../molecules/buttons/main-nav-button.module.scss | 37 ++++++++++ .../molecules/buttons/main-nav-button.stories.tsx | 80 ++++++++++++++++++++++ .../molecules/buttons/main-nav-button.test.tsx | 11 +++ .../molecules/buttons/main-nav-button.tsx | 75 ++++++++++++++++++++ 8 files changed, 235 insertions(+), 39 deletions(-) create mode 100644 src/components/molecules/buttons/main-nav-button.module.scss create mode 100644 src/components/molecules/buttons/main-nav-button.stories.tsx create mode 100644 src/components/molecules/buttons/main-nav-button.test.tsx create mode 100644 src/components/molecules/buttons/main-nav-button.tsx (limited to 'src/components/atoms/icons') diff --git a/src/components/atoms/icons/hamburger.module.scss b/src/components/atoms/icons/hamburger.module.scss index 09e7e30..4fba4df 100644 --- a/src/components/atoms/icons/hamburger.module.scss +++ b/src/components/atoms/icons/hamburger.module.scss @@ -1,16 +1,21 @@ @use "@styles/abstracts/functions" as fun; -.icon { - display: block; +.wrapper { + display: flex; + align-items: center; width: var(--icon-size, #{fun.convert-px(50)}); height: var(--icon-size, #{fun.convert-px(50)}); position: relative; +} +.icon { &, &::before, &::after { display: block; height: fun.convert-px(7); + width: 100%; + position: absolute; background: var(--color-primary-lighter); background-image: linear-gradient( to right, @@ -25,33 +30,13 @@ &::before, &::after { content: ""; - position: absolute; - left: fun.convert-px(-1); - right: fun.convert-px(-1); } &::before { - bottom: fun.convert-px(15); + top: fun.convert-px(-15); } &::after { - top: fun.convert-px(15); - } - - &--active { - background: transparent; - border: transparent; - - &::before { - bottom: 0; - transform-origin: 50% 50%; - transform: rotate(45deg); - } - - &::after { - top: 0; - transform-origin: 50% 50%; - transform: rotate(-45deg); - } + bottom: fun.convert-px(-15); } } diff --git a/src/components/atoms/icons/hamburger.stories.tsx b/src/components/atoms/icons/hamburger.stories.tsx index 062d3ee..c753e69 100644 --- a/src/components/atoms/icons/hamburger.stories.tsx +++ b/src/components/atoms/icons/hamburger.stories.tsx @@ -9,7 +9,7 @@ export default { control: { type: 'text', }, - description: 'Set additional classnames.', + description: 'Set additional classnames to the icon wrapper.', table: { category: 'Styles', }, @@ -18,14 +18,17 @@ export default { required: false, }, }, - isActive: { + iconClassName: { control: { - type: 'boolean', + type: 'text', + }, + description: 'Set additional classnames to the icon.', + table: { + category: 'Styles', }, - description: 'Transform hamburger into a cross when state is active.', type: { - name: 'boolean', - required: true, + name: 'string', + required: false, }, }, }, diff --git a/src/components/atoms/icons/hamburger.test.tsx b/src/components/atoms/icons/hamburger.test.tsx index f8a3c04..7173a23 100644 --- a/src/components/atoms/icons/hamburger.test.tsx +++ b/src/components/atoms/icons/hamburger.test.tsx @@ -3,7 +3,7 @@ import Hamburger from './hamburger'; describe('Hamburger', () => { it('renders a Hamburger icon', () => { - const { container } = render(); + const { container } = render(); expect(container).toBeDefined(); }); }); diff --git a/src/components/atoms/icons/hamburger.tsx b/src/components/atoms/icons/hamburger.tsx index 6716b26..7e7c2c9 100644 --- a/src/components/atoms/icons/hamburger.tsx +++ b/src/components/atoms/icons/hamburger.tsx @@ -3,13 +3,14 @@ import styles from './hamburger.module.scss'; type HamburgerProps = { /** - * Set additional classnames to the icon. + * Set additional classnames to the icon wrapper. */ className?: string; + /** - * Transform hamburger to a close icon when active. + * Set additional classnames to the icon. */ - isActive: boolean; + iconClassName?: string; }; /** @@ -17,11 +18,15 @@ type HamburgerProps = { * * Render a Hamburger icon. */ -const Hamburger: FC = ({ className = '', isActive }) => { - const stateClass = isActive ? `${styles['icon--active']}` : ''; - const iconClasses = `${styles.icon} ${stateClass} ${className}`; - - return ; +const Hamburger: FC = ({ + className = '', + iconClassName = '', +}) => { + return ( + + + + ); }; export default Hamburger; diff --git a/src/components/molecules/buttons/main-nav-button.module.scss b/src/components/molecules/buttons/main-nav-button.module.scss new file mode 100644 index 0000000..bc1ed19 --- /dev/null +++ b/src/components/molecules/buttons/main-nav-button.module.scss @@ -0,0 +1,37 @@ +@use "@styles/abstracts/functions" as fun; + +.checkbox { + position: absolute; + top: calc(#{fun.convert-px(50)} / 2); + left: calc(#{fun.convert-px(50)} / 2); + opacity: 0; + cursor: pointer; +} + +.label { + display: block; + cursor: pointer; + + .icon { + &__wrapper { + --icon-size: #{fun.convert-px(50)}; + } + + &--active { + background: transparent; + border: transparent; + + &::before { + top: 0; + transform-origin: 50% 50%; + transform: rotate(-45deg); + } + + &::after { + bottom: 0; + transform-origin: 50% 50%; + transform: rotate(45deg); + } + } + } +} diff --git a/src/components/molecules/buttons/main-nav-button.stories.tsx b/src/components/molecules/buttons/main-nav-button.stories.tsx new file mode 100644 index 0000000..39e495c --- /dev/null +++ b/src/components/molecules/buttons/main-nav-button.stories.tsx @@ -0,0 +1,80 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { useState } from 'react'; +import { IntlProvider } from 'react-intl'; +import MainNavButtonComponent from './main-nav-button'; + +export default { + title: 'Molecules/Buttons', + component: MainNavButtonComponent, + argTypes: { + checkboxClassName: { + control: { + type: 'text', + }, + description: 'Set additional classnames to the checkbox.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, + isActive: { + control: { + type: null, + }, + description: 'The button state.', + type: { + name: 'boolean', + required: true, + }, + }, + labelClassName: { + control: { + type: 'text', + }, + description: 'Set additional classnames to the label.', + table: { + category: 'Styles', + }, + type: { + name: 'string', + required: false, + }, + }, + setIsActive: { + control: { + type: null, + }, + description: 'A callback function to set the button state.', + type: { + name: 'function', + required: true, + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = ({ + isActive, + setIsActive: _setIsActive, + ...args +}) => { + const [isChecked, setIsChecked] = useState(isActive); + + return ( + + + + ); +}; + +export const MainNavButton = Template.bind({}); +MainNavButton.args = { + isActive: false, +}; diff --git a/src/components/molecules/buttons/main-nav-button.test.tsx b/src/components/molecules/buttons/main-nav-button.test.tsx new file mode 100644 index 0000000..e757305 --- /dev/null +++ b/src/components/molecules/buttons/main-nav-button.test.tsx @@ -0,0 +1,11 @@ +import { render, screen } from '@test-utils'; +import MainNavButton from './main-nav-button'; + +describe('MainNavButton', () => { + it('renders a checkbox', () => { + render( null} />); + expect( + screen.getByRole('checkbox', { name: 'Open menu' }) + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/molecules/buttons/main-nav-button.tsx b/src/components/molecules/buttons/main-nav-button.tsx new file mode 100644 index 0000000..59407db --- /dev/null +++ b/src/components/molecules/buttons/main-nav-button.tsx @@ -0,0 +1,75 @@ +import Checkbox, { CheckboxProps } from '@components/atoms/forms/checkbox'; +import Label from '@components/atoms/forms/label'; +import Hamburger from '@components/atoms/icons/hamburger'; +import { VFC } from 'react'; +import { useIntl } from 'react-intl'; +import styles from './main-nav-button.module.scss'; + +export type MainNavButtonProps = { + /** + * Set additional classnames to the checkbox. + */ + checkboxClassName?: string; + /** + * The button state. + */ + isActive: CheckboxProps['value']; + /** + * Set additional classnames to the label. + */ + labelClassName?: string; + /** + * A callback function to handle button state. + */ + setIsActive: CheckboxProps['setValue']; +}; + +/** + * MainNavButton component + * + * Render a hamburger icon or a close icon depending on state. + */ +const MainNavButton: VFC = ({ + checkboxClassName = '', + isActive, + labelClassName = '', + setIsActive, +}) => { + const intl = useIntl(); + const label = isActive + ? intl.formatMessage({ + defaultMessage: 'Close menu', + id: 'wT7YZb', + description: 'MainNavButton: close menu label', + }) + : intl.formatMessage({ + defaultMessage: 'Open menu', + id: 'P7j8ZZ', + description: 'MainNavButton: open menu label', + }); + const hamburgerModifier = isActive ? 'icon--active' : ''; + + return ( + <> + + + + ); +}; + +export default MainNavButton; -- cgit v1.2.3 From 5a6e4eea16047083e2de0e91a1b3ed9be8d6eb68 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Sat, 16 Apr 2022 16:08:49 +0200 Subject: refactor: support React 18 I replaced the deprecated VFC type with FC type and made all children explicits. Formatjs is still not compatible with React 18 so I need to skip type checking when comitting. There are some type errors because of IntlProvider in Storybook stories. --- jest.setup.js | 1 + src/components/atoms/buttons/button-link.tsx | 6 +- src/components/atoms/buttons/button.tsx | 6 +- src/components/atoms/forms/checkbox.tsx | 4 +- src/components/atoms/forms/field.tsx | 4 +- src/components/atoms/forms/form.test.tsx | 6 +- src/components/atoms/forms/form.tsx | 6 +- src/components/atoms/forms/label.tsx | 6 +- src/components/atoms/forms/select.tsx | 4 +- src/components/atoms/headings/heading.tsx | 6 +- src/components/atoms/icons/arrow.tsx | 4 +- src/components/atoms/icons/career.tsx | 4 +- src/components/atoms/icons/cc-by-sa.tsx | 4 +- src/components/atoms/icons/close.tsx | 4 +- src/components/atoms/icons/cog.tsx | 4 +- src/components/atoms/icons/computer-screen.tsx | 4 +- src/components/atoms/icons/envelop.tsx | 4 +- src/components/atoms/icons/hamburger.tsx | 2 +- src/components/atoms/icons/home.tsx | 4 +- src/components/atoms/icons/magnifying-glass.tsx | 4 +- src/components/atoms/icons/moon.tsx | 6 +- src/components/atoms/icons/plus-minus.tsx | 2 +- src/components/atoms/icons/posts-stack.tsx | 4 +- src/components/atoms/icons/sun.tsx | 6 +- src/components/atoms/images/logo.tsx | 6 +- src/components/atoms/layout/copyright.tsx | 4 +- src/components/atoms/layout/main.tsx | 6 +- src/components/atoms/layout/no-script.tsx | 4 +- src/components/atoms/layout/notice.tsx | 4 +- src/components/atoms/layout/section.tsx | 4 +- src/components/atoms/links/link.module.scss | 20 ++++-- src/components/atoms/links/link.tsx | 6 +- src/components/atoms/links/nav-link.tsx | 4 +- src/components/atoms/links/sharing-link.tsx | 4 +- src/components/atoms/links/social-link.tsx | 4 +- src/components/atoms/lists/description-list.tsx | 4 +- src/components/atoms/lists/list.tsx | 4 +- src/components/atoms/loaders/progress-bar.tsx | 4 +- src/components/atoms/loaders/spinner.tsx | 4 +- src/components/molecules/buttons/back-to-top.tsx | 14 ++-- .../molecules/buttons/heading-button.tsx | 4 +- src/components/molecules/buttons/help-button.tsx | 6 +- .../molecules/forms/ackee-select.test.tsx | 16 +++-- src/components/molecules/forms/ackee-select.tsx | 6 +- src/components/molecules/forms/labelled-field.tsx | 4 +- src/components/molecules/forms/labelled-select.tsx | 15 +++-- src/components/molecules/forms/motion-toggle.tsx | 8 +-- .../molecules/forms/prism-theme-toggle.tsx | 8 +-- .../molecules/forms/select-with-tooltip.tsx | 10 +-- src/components/molecules/forms/theme-toggle.tsx | 8 +-- src/components/molecules/forms/toggle.tsx | 18 ++--- .../molecules/images/responsive-image.tsx | 10 +-- src/components/molecules/layout/branding.tsx | 12 ++-- src/components/molecules/layout/card.tsx | 8 +-- src/components/molecules/layout/flipping-logo.tsx | 10 +-- src/components/molecules/layout/meta.tsx | 4 +- src/components/molecules/layout/widget.tsx | 10 ++- src/components/molecules/modals/modal.test.tsx | 13 +++- src/components/molecules/modals/modal.tsx | 14 ++-- src/components/molecules/modals/tooltip.tsx | 4 +- src/components/molecules/nav/breadcrumb.tsx | 4 +- src/components/molecules/nav/nav.tsx | 4 +- .../organisms/forms/comment-form.stories.tsx | 1 - src/components/organisms/forms/comment-form.tsx | 4 +- src/components/organisms/forms/contact-form.tsx | 4 +- src/components/organisms/forms/search-form.tsx | 11 +++- src/components/organisms/layout/cards-list.tsx | 4 +- src/components/organisms/layout/footer.tsx | 13 ++-- src/components/organisms/layout/overview.tsx | 4 +- .../organisms/layout/summary.stories.tsx | 2 +- src/components/organisms/layout/summary.test.tsx | 2 +- src/components/organisms/layout/summary.tsx | 77 +++++++++++++--------- src/components/organisms/modals/search-modal.tsx | 8 +-- src/components/organisms/modals/settings-modal.tsx | 14 ++-- src/components/organisms/toolbar/main-nav.tsx | 18 +++-- src/components/organisms/toolbar/search.tsx | 16 ++--- src/components/organisms/toolbar/settings.tsx | 14 ++-- src/components/organisms/toolbar/toolbar.tsx | 4 +- src/components/organisms/widgets/image-widget.tsx | 34 ++++------ .../organisms/widgets/links-list-widget.tsx | 9 ++- src/components/organisms/widgets/sharing.tsx | 6 +- 81 files changed, 353 insertions(+), 289 deletions(-) (limited to 'src/components/atoms/icons') diff --git a/jest.setup.js b/jest.setup.js index 5c5ecbc..d50c988 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -2,3 +2,4 @@ import '@testing-library/jest-dom/extend-expect'; import './__tests__/jest/__mocks__/matchMedia.mock'; jest.mock('next/dist/client/router', () => require('next-router-mock')); +jest.mock('next/dynamic', () => () => 'dynamic-import'); diff --git a/src/components/atoms/buttons/button-link.tsx b/src/components/atoms/buttons/button-link.tsx index 77a7f7b..906fa76 100644 --- a/src/components/atoms/buttons/button-link.tsx +++ b/src/components/atoms/buttons/button-link.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import { FC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './buttons.module.scss'; export type ButtonLinkProps = { @@ -7,6 +7,10 @@ export type ButtonLinkProps = { * ButtonLink accessible label. */ 'aria-label'?: string; + /** + * The button link body. + */ + children: ReactNode; /** * Set additional classnames to the button link. */ diff --git a/src/components/atoms/buttons/button.tsx b/src/components/atoms/buttons/button.tsx index 545c5c5..a6eef8b 100644 --- a/src/components/atoms/buttons/button.tsx +++ b/src/components/atoms/buttons/button.tsx @@ -1,7 +1,11 @@ -import { FC, MouseEventHandler } from 'react'; +import { FC, MouseEventHandler, ReactNode } from 'react'; import styles from './buttons.module.scss'; export type ButtonProps = { + /** + * The button body. + */ + children: ReactNode; /** * Set additional classnames to the button wrapper. */ diff --git a/src/components/atoms/forms/checkbox.tsx b/src/components/atoms/forms/checkbox.tsx index 8babcc8..aec97f0 100644 --- a/src/components/atoms/forms/checkbox.tsx +++ b/src/components/atoms/forms/checkbox.tsx @@ -1,4 +1,4 @@ -import { SetStateAction, VFC } from 'react'; +import { FC, SetStateAction } from 'react'; export type CheckboxProps = { /** @@ -32,7 +32,7 @@ export type CheckboxProps = { * * Render a checkbox type input. */ -const Checkbox: VFC = ({ value, setValue, ...props }) => { +const Checkbox: FC = ({ value, setValue, ...props }) => { return ( = ({ +const Field: FC = ({ className = '', setValue, type, diff --git a/src/components/atoms/forms/form.test.tsx b/src/components/atoms/forms/form.test.tsx index 9cd3c58..8b534f1 100644 --- a/src/components/atoms/forms/form.test.tsx +++ b/src/components/atoms/forms/form.test.tsx @@ -3,7 +3,11 @@ import Form from './form'; describe('Form', () => { it('renders a form', () => { - render(
null}>
); + render( +
null}> + Fields +
+ ); expect(screen.getByRole('form', { name: 'Jest form' })).toBeInTheDocument(); }); }); diff --git a/src/components/atoms/forms/form.tsx b/src/components/atoms/forms/form.tsx index 8e80930..ef8dce4 100644 --- a/src/components/atoms/forms/form.tsx +++ b/src/components/atoms/forms/form.tsx @@ -1,4 +1,4 @@ -import { Children, FC, FormEvent, Fragment } from 'react'; +import { Children, FC, FormEvent, Fragment, ReactNode } from 'react'; import styles from './forms.module.scss'; export type FormProps = { @@ -10,6 +10,10 @@ export type FormProps = { * One or more ids that refers to the form name. */ 'aria-labelledby'?: string; + /** + * The form body. + */ + children: ReactNode; /** * Set additional classnames to the form wrapper. */ diff --git a/src/components/atoms/forms/label.tsx b/src/components/atoms/forms/label.tsx index 8d57ee2..ce4c70f 100644 --- a/src/components/atoms/forms/label.tsx +++ b/src/components/atoms/forms/label.tsx @@ -1,7 +1,11 @@ -import { FC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './label.module.scss'; export type LabelProps = { + /** + * The label body. + */ + children: ReactNode; /** * Add classnames to the label. */ diff --git a/src/components/atoms/forms/select.tsx b/src/components/atoms/forms/select.tsx index 25e86e0..dbe9b37 100644 --- a/src/components/atoms/forms/select.tsx +++ b/src/components/atoms/forms/select.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, SetStateAction, VFC } from 'react'; +import { ChangeEvent, FC, SetStateAction } from 'react'; import styles from './forms.module.scss'; export type SelectOptions = { @@ -60,7 +60,7 @@ export type SelectProps = { * * Render a HTML select element. */ -const Select: VFC = ({ +const Select: FC = ({ className = '', options, setValue, diff --git a/src/components/atoms/headings/heading.tsx b/src/components/atoms/headings/heading.tsx index 4703b5d..c5bf4ca 100644 --- a/src/components/atoms/headings/heading.tsx +++ b/src/components/atoms/headings/heading.tsx @@ -1,9 +1,13 @@ -import { FC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './heading.module.scss'; export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6; export type HeadingProps = { + /** + * The heading body. + */ + children: ReactNode; /** * Set additional classnames. */ diff --git a/src/components/atoms/icons/arrow.tsx b/src/components/atoms/icons/arrow.tsx index 5f3c460..2962530 100644 --- a/src/components/atoms/icons/arrow.tsx +++ b/src/components/atoms/icons/arrow.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './arrow.module.scss'; export type ArrowDirection = 'top' | 'right' | 'bottom' | 'left'; @@ -19,7 +19,7 @@ export type ArrowProps = { * * Render a svg arrow icon. */ -const Arrow: VFC = ({ className = '', direction }) => { +const Arrow: FC = ({ className = '', direction }) => { const directionClass = styles[`icon--${direction}`]; const classes = `${styles.icon} ${directionClass} ${className}`; diff --git a/src/components/atoms/icons/career.tsx b/src/components/atoms/icons/career.tsx index 28edcc7..f28d399 100644 --- a/src/components/atoms/icons/career.tsx +++ b/src/components/atoms/icons/career.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './career.module.scss'; export type CareerProps = { @@ -13,7 +13,7 @@ export type CareerProps = { * * Render a career svg icon. */ -const Career: VFC = ({ className = '' }) => { +const Career: FC = ({ className = '' }) => { return ( = ({ className = '' }) => { +const CCBySA: FC = ({ className = '' }) => { const intl = useIntl(); return ( diff --git a/src/components/atoms/icons/close.tsx b/src/components/atoms/icons/close.tsx index eb9ce7c..3e0adb5 100644 --- a/src/components/atoms/icons/close.tsx +++ b/src/components/atoms/icons/close.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './close.module.scss'; export type CloseProps = { @@ -13,7 +13,7 @@ export type CloseProps = { * * Render a close svg icon. */ -const Close: VFC = ({ className = '' }) => { +const Close: FC = ({ className = '' }) => { return ( = ({ className = '' }) => { +const Cog: FC = ({ className = '' }) => { return ( = ({ className = '' }) => { +const ComputerScreen: FC = ({ className = '' }) => { return ( = ({ className = '' }) => { +const Envelop: FC = ({ className = '' }) => { return ( = ({ className = '' }) => { +const Home: FC = ({ className = '' }) => { return ( = ({ className = '' }) => { +const MagnifyingGlass: FC = ({ className = '' }) => { return ( = ({ className = '', title }) => { +const Moon: FC = ({ className = '', title }) => { return ( = ({ className = '' }) => { +const PostsStack: FC = ({ className = '' }) => { return ( = ({ className = '', title }) => { +const Sun: FC = ({ className = '', title }) => { return ( = ({ title }) => { +const Logo: FC = ({ title }) => { return ( = ({ owner, dates, icon }) => { +const Copyright: FC = ({ owner, dates, icon }) => { const getFormattedDate = (date: string) => { const datetime = new Date(date).toISOString(); diff --git a/src/components/atoms/layout/main.tsx b/src/components/atoms/layout/main.tsx index 4549328..d92a5c7 100644 --- a/src/components/atoms/layout/main.tsx +++ b/src/components/atoms/layout/main.tsx @@ -1,6 +1,10 @@ -import { FC } from 'react'; +import { FC, ReactNode } from 'react'; export type MainProps = { + /** + * The main body. + */ + children: ReactNode; /** * Set additional classnames to the main element. */ diff --git a/src/components/atoms/layout/no-script.tsx b/src/components/atoms/layout/no-script.tsx index 6358cf8..a503e0c 100644 --- a/src/components/atoms/layout/no-script.tsx +++ b/src/components/atoms/layout/no-script.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './no-script.module.scss'; export type NoScriptProps = { @@ -12,7 +12,7 @@ export type NoScriptProps = { position?: 'initial' | 'top'; }; -const NoScript: VFC = ({ message, position = 'initial' }) => { +const NoScript: FC = ({ message, position = 'initial' }) => { const positionClass = styles[`noscript--${position}`]; return
{message}
; diff --git a/src/components/atoms/layout/notice.tsx b/src/components/atoms/layout/notice.tsx index b6e09c5..115bd9c 100644 --- a/src/components/atoms/layout/notice.tsx +++ b/src/components/atoms/layout/notice.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './notice.module.scss'; export type NoticeKind = 'error' | 'info' | 'success' | 'warning'; @@ -19,7 +19,7 @@ export type NoticeProps = { * * Render a colored message depending on notice kind. */ -const Notice: VFC = ({ kind, message }) => { +const Notice: FC = ({ kind, message }) => { const kindClass = `wrapper--${kind}`; return ( diff --git a/src/components/atoms/layout/section.tsx b/src/components/atoms/layout/section.tsx index f1bbb34..cb727ff 100644 --- a/src/components/atoms/layout/section.tsx +++ b/src/components/atoms/layout/section.tsx @@ -1,4 +1,4 @@ -import { ReactNode, VFC } from 'react'; +import { FC, ReactNode } from 'react'; import Heading from '../headings/heading'; import styles from './section.module.scss'; @@ -32,7 +32,7 @@ export type SectionProps = { * * Render a section element. */ -const Section: VFC = ({ +const Section: FC = ({ className = '', content, title, diff --git a/src/components/atoms/links/link.module.scss b/src/components/atoms/links/link.module.scss index e7ead86..d23667a 100644 --- a/src/components/atoms/links/link.module.scss +++ b/src/components/atoms/links/link.module.scss @@ -5,7 +5,9 @@ &[hreflang] { &::after { display: inline-block; - content: "\0000a0["attr(hreflang) "]"; + /* Prettier is removing spacing between content parts. */ + /* prettier-ignore */ + content: "\0000a0[" attr(hreflang) "]"; font-size: var(--font-size-sm); } } @@ -13,22 +15,30 @@ &--external { &::after { display: inline-block; - content: "\0000a0"url(fun.encode-svg('')); + /* Prettier is removing spacing between content parts. */ + /* prettier-ignore */ + content: "\0000a0" url(fun.encode-svg('')); } &:focus:not(:active)::after { - content: "\0000a0"url(fun.encode-svg('')); + /* Prettier is removing spacing between content parts. */ + /* prettier-ignore */ + content: "\0000a0" url(fun.encode-svg('')); } &[hreflang] { &::after { - content: "\0000a0["attr(hreflang) "]\0000a0"url(fun.encode-svg( + /* Prettier is removing spacing between content parts. */ + /* prettier-ignore */ + content: "\0000a0[" attr(hreflang) "]\0000a0" url(fun.encode-svg( '' )); } &:focus:not(:active)::after { - content: "\0000a0["attr(hreflang) "]\0000a0"url(fun.encode-svg( + /* Prettier is removing spacing between content parts. */ + /* prettier-ignore */ + content: "\0000a0[" attr(hreflang) "]\0000a0" url(fun.encode-svg( '' )); } diff --git a/src/components/atoms/links/link.tsx b/src/components/atoms/links/link.tsx index 87f11fc..674c07b 100644 --- a/src/components/atoms/links/link.tsx +++ b/src/components/atoms/links/link.tsx @@ -1,8 +1,12 @@ import NextLink from 'next/link'; -import { FC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './link.module.scss'; export type LinkProps = { + /** + * The link body. + */ + children: ReactNode; /** * Set additional classnames to the link. */ diff --git a/src/components/atoms/links/nav-link.tsx b/src/components/atoms/links/nav-link.tsx index 25c0e7d..7c6fede 100644 --- a/src/components/atoms/links/nav-link.tsx +++ b/src/components/atoms/links/nav-link.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import { VFC, ReactNode } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './nav-link.module.scss'; export type NavLinkProps = { @@ -22,7 +22,7 @@ export type NavLinkProps = { * * Render a navigation link. */ -const NavLink: VFC = ({ href, label, logo }) => { +const NavLink: FC = ({ href, label, logo }) => { return ( diff --git a/src/components/atoms/links/sharing-link.tsx b/src/components/atoms/links/sharing-link.tsx index 3cd2dd1..ca53ef9 100644 --- a/src/components/atoms/links/sharing-link.tsx +++ b/src/components/atoms/links/sharing-link.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './sharing-link.module.scss'; @@ -26,7 +26,7 @@ export type SharingLinkProps = { * * Render a sharing link. */ -const SharingLink: VFC = ({ medium, url }) => { +const SharingLink: FC = ({ medium, url }) => { const intl = useIntl(); const text = intl.formatMessage( { diff --git a/src/components/atoms/links/social-link.tsx b/src/components/atoms/links/social-link.tsx index 8c7c790..464bc60 100644 --- a/src/components/atoms/links/social-link.tsx +++ b/src/components/atoms/links/social-link.tsx @@ -2,7 +2,7 @@ import GithubIcon from '@assets/images/social-media/github.svg'; import GitlabIcon from '@assets/images/social-media/gitlab.svg'; import LinkedInIcon from '@assets/images/social-media/linkedin.svg'; import TwitterIcon from '@assets/images/social-media/twitter.svg'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './social-link.module.scss'; export type SocialWebsite = 'Github' | 'Gitlab' | 'LinkedIn' | 'Twitter'; @@ -23,7 +23,7 @@ export type SocialLinkProps = { * * Render a social icon link. */ -const SocialLink: VFC = ({ name, url }) => { +const SocialLink: FC = ({ name, url }) => { /** * Retrieve a social link icon by id. * @param {string} id - The social website id. diff --git a/src/components/atoms/lists/description-list.tsx b/src/components/atoms/lists/description-list.tsx index 0a92465..a60a6a1 100644 --- a/src/components/atoms/lists/description-list.tsx +++ b/src/components/atoms/lists/description-list.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './description-list.module.scss'; export type DescriptionListItem = { @@ -52,7 +52,7 @@ export type DescriptionListProps = { * * Render a description list. */ -const DescriptionList: VFC = ({ +const DescriptionList: FC = ({ className = '', descriptionClassName = '', groupClassName = '', diff --git a/src/components/atoms/lists/list.tsx b/src/components/atoms/lists/list.tsx index d100a31..6726802 100644 --- a/src/components/atoms/lists/list.tsx +++ b/src/components/atoms/lists/list.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './list.module.scss'; export type ListItem = { @@ -44,7 +44,7 @@ export type ListProps = { * * Render either an ordered or an unordered list. */ -const List: VFC = ({ +const List: FC = ({ className = '', items, itemsClassName = '', diff --git a/src/components/atoms/loaders/progress-bar.tsx b/src/components/atoms/loaders/progress-bar.tsx index 1b1ff06..9bac847 100644 --- a/src/components/atoms/loaders/progress-bar.tsx +++ b/src/components/atoms/loaders/progress-bar.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './progress-bar.module.scss'; export type ProgressBarProps = { @@ -29,7 +29,7 @@ export type ProgressBarProps = { * * Render a progress bar. */ -const ProgressBar: VFC = ({ +const ProgressBar: FC = ({ current, info, min, diff --git a/src/components/atoms/loaders/spinner.tsx b/src/components/atoms/loaders/spinner.tsx index bff0f25..6655141 100644 --- a/src/components/atoms/loaders/spinner.tsx +++ b/src/components/atoms/loaders/spinner.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './spinner.module.scss'; @@ -14,7 +14,7 @@ export type SpinnerProps = { * * Render a loading message with animation. */ -const Spinner: VFC = ({ message }) => { +const Spinner: FC = ({ message }) => { const intl = useIntl(); return ( diff --git a/src/components/molecules/buttons/back-to-top.tsx b/src/components/molecules/buttons/back-to-top.tsx index 8a52231..bd1925a 100644 --- a/src/components/molecules/buttons/back-to-top.tsx +++ b/src/components/molecules/buttons/back-to-top.tsx @@ -1,18 +1,16 @@ -import ButtonLink from '@components/atoms/buttons/button-link'; +import ButtonLink, { + type ButtonLinkProps, +} from '@components/atoms/buttons/button-link'; import Arrow from '@components/atoms/icons/arrow'; -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './back-to-top.module.scss'; -export type BackToTopProps = { +export type BackToTopProps = Pick & { /** * Set additional classnames to the button wrapper. */ className?: string; - /** - * An element id (without hashtag) to use as anchor. - */ - target: string; }; /** @@ -20,7 +18,7 @@ export type BackToTopProps = { * * Render a back to top link. */ -const BackToTop: VFC = ({ className = '', target }) => { +const BackToTop: FC = ({ className = '', target }) => { const intl = useIntl(); const linkName = intl.formatMessage({ defaultMessage: 'Back to top', diff --git a/src/components/molecules/buttons/heading-button.tsx b/src/components/molecules/buttons/heading-button.tsx index fc79749..0ed9a76 100644 --- a/src/components/molecules/buttons/heading-button.tsx +++ b/src/components/molecules/buttons/heading-button.tsx @@ -1,6 +1,6 @@ import Heading, { type HeadingProps } from '@components/atoms/headings/heading'; import PlusMinus from '@components/atoms/icons/plus-minus'; -import { SetStateAction, VFC } from 'react'; +import { FC, SetStateAction } from 'react'; import { useIntl } from 'react-intl'; import styles from './heading-button.module.scss'; @@ -28,7 +28,7 @@ export type HeadingButtonProps = Pick & { * * Render a button as accordion title to toggle body. */ -const HeadingButton: VFC = ({ +const HeadingButton: FC = ({ className = '', expanded, level, diff --git a/src/components/molecules/buttons/help-button.tsx b/src/components/molecules/buttons/help-button.tsx index aeb84ec..f19322f 100644 --- a/src/components/molecules/buttons/help-button.tsx +++ b/src/components/molecules/buttons/help-button.tsx @@ -1,5 +1,5 @@ -import Button, { ButtonProps } from '@components/atoms/buttons/button'; -import { VFC } from 'react'; +import Button, { type ButtonProps } from '@components/atoms/buttons/button'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './help-button.module.scss'; @@ -15,7 +15,7 @@ export type HelpButtonProps = Pick & { * * Render a button with an interrogation mark icon. */ -const HelpButton: VFC = ({ className = '', onClick }) => { +const HelpButton: FC = ({ className = '', onClick }) => { const intl = useIntl(); const text = intl.formatMessage({ defaultMessage: 'Help', diff --git a/src/components/molecules/forms/ackee-select.test.tsx b/src/components/molecules/forms/ackee-select.test.tsx index e1e6b2d..ec27922 100644 --- a/src/components/molecules/forms/ackee-select.test.tsx +++ b/src/components/molecules/forms/ackee-select.test.tsx @@ -1,5 +1,5 @@ -import userEvent from '@testing-library/user-event'; -import { render, screen } from '@test-utils'; +import user from '@testing-library/user-event'; +import { act, render, screen } from '@test-utils'; import AckeeSelect from './ackee-select'; describe('Select', () => { @@ -9,13 +9,15 @@ describe('Select', () => { expect(screen.queryByRole('combobox')).not.toHaveValue('partial'); }); - it('should correctly change value when user choose another option', () => { + it('should correctly change value when user choose another option', async () => { render(); - userEvent.selectOptions( - screen.getByRole('combobox'), - screen.getByRole('option', { name: 'Partial' }) - ); + await act(async () => { + await user.selectOptions( + screen.getByRole('combobox'), + screen.getByRole('option', { name: 'Partial' }) + ); + }); expect(screen.getByRole('combobox')).toHaveValue('partial'); expect(screen.queryByRole('combobox')).not.toHaveValue('full'); diff --git a/src/components/molecules/forms/ackee-select.tsx b/src/components/molecules/forms/ackee-select.tsx index 4a8410c..101e5b5 100644 --- a/src/components/molecules/forms/ackee-select.tsx +++ b/src/components/molecules/forms/ackee-select.tsx @@ -1,8 +1,8 @@ import { SelectOptions } from '@components/atoms/forms/select'; -import { Dispatch, SetStateAction, useState, VFC } from 'react'; +import { Dispatch, FC, SetStateAction, useState } from 'react'; import { useIntl } from 'react-intl'; import SelectWithTooltip, { - SelectWithTooltipProps, + type SelectWithTooltipProps, } from './select-with-tooltip'; export type AckeeOptions = 'full' | 'partial'; @@ -22,7 +22,7 @@ export type AckeeSelectProps = Pick< * * Render a select to set Ackee settings. */ -const AckeeSelect: VFC = ({ initialValue, ...props }) => { +const AckeeSelect: FC = ({ initialValue, ...props }) => { const intl = useIntl(); const [value, setValue] = useState(initialValue); diff --git a/src/components/molecules/forms/labelled-field.tsx b/src/components/molecules/forms/labelled-field.tsx index 08d0126..ecc9255 100644 --- a/src/components/molecules/forms/labelled-field.tsx +++ b/src/components/molecules/forms/labelled-field.tsx @@ -1,6 +1,6 @@ import Field, { type FieldProps } from '@components/atoms/forms/field'; import Label from '@components/atoms/forms/label'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './labelled-field.module.scss'; export type LabelledFieldProps = FieldProps & { @@ -23,7 +23,7 @@ export type LabelledFieldProps = FieldProps & { * * Render a field tied to a label. */ -const LabelledField: VFC = ({ +const LabelledField: FC = ({ hideLabel = false, id, label, diff --git a/src/components/molecules/forms/labelled-select.tsx b/src/components/molecules/forms/labelled-select.tsx index 7d4237a..23057d0 100644 --- a/src/components/molecules/forms/labelled-select.tsx +++ b/src/components/molecules/forms/labelled-select.tsx @@ -1,6 +1,6 @@ -import Label, { LabelProps } from '@components/atoms/forms/label'; +import Label, { type LabelProps } from '@components/atoms/forms/label'; import Select, { type SelectProps } from '@components/atoms/forms/select'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './labelled-select.module.scss'; export type LabelledSelectProps = Omit< @@ -14,7 +14,7 @@ export type LabelledSelectProps = Omit< /** * Set additional classnames to the label. */ - labelClassName?: string; + labelClassName?: LabelProps['className']; /** * The label position. Default: top. */ @@ -26,10 +26,15 @@ export type LabelledSelectProps = Omit< /** * Set additional classnames to the select field. */ - selectClassName?: string; + selectClassName?: SelectProps['className']; }; -const LabelledSelect: VFC = ({ +/** + * LabelledSelect component + * + * Render a select with a label. + */ +const LabelledSelect: FC = ({ id, label, labelClassName = '', diff --git a/src/components/molecules/forms/motion-toggle.tsx b/src/components/molecules/forms/motion-toggle.tsx index 9f30b42..24b54ae 100644 --- a/src/components/molecules/forms/motion-toggle.tsx +++ b/src/components/molecules/forms/motion-toggle.tsx @@ -1,8 +1,8 @@ import Toggle, { - ToggleChoices, - ToggleProps, + type ToggleChoices, + type ToggleProps, } from '@components/molecules/forms/toggle'; -import { useState, VFC } from 'react'; +import { FC, useState } from 'react'; import { useIntl } from 'react-intl'; export type MotionToggleProps = Pick; @@ -12,7 +12,7 @@ export type MotionToggleProps = Pick; * * Render a Toggle component to set reduce motion. */ -const MotionToggle: VFC = ({ value, ...props }) => { +const MotionToggle: FC = ({ value, ...props }) => { const intl = useIntl(); const [isDeactivated, setIsDeactivated] = useState(value); const reduceMotionLabel = intl.formatMessage({ diff --git a/src/components/molecules/forms/prism-theme-toggle.tsx b/src/components/molecules/forms/prism-theme-toggle.tsx index daee6bd..0b9c447 100644 --- a/src/components/molecules/forms/prism-theme-toggle.tsx +++ b/src/components/molecules/forms/prism-theme-toggle.tsx @@ -1,10 +1,10 @@ import Moon from '@components/atoms/icons/moon'; import Sun from '@components/atoms/icons/sun'; import Toggle, { - ToggleChoices, - ToggleProps, + type ToggleChoices, + type ToggleProps, } from '@components/molecules/forms/toggle'; -import { useState, VFC } from 'react'; +import { FC, useState } from 'react'; import { useIntl } from 'react-intl'; export type PrismThemeToggleProps = Pick< @@ -17,7 +17,7 @@ export type PrismThemeToggleProps = Pick< * * Render a Toggle component to set code blocks theme. */ -const PrismThemeToggle: VFC = ({ value, ...props }) => { +const PrismThemeToggle: FC = ({ value, ...props }) => { const intl = useIntl(); const [isDarkTheme, setIsDarkTheme] = useState(value); const themeLabel = intl.formatMessage({ diff --git a/src/components/molecules/forms/select-with-tooltip.tsx b/src/components/molecules/forms/select-with-tooltip.tsx index f537e1e..cf7b041 100644 --- a/src/components/molecules/forms/select-with-tooltip.tsx +++ b/src/components/molecules/forms/select-with-tooltip.tsx @@ -1,4 +1,4 @@ -import { useState, VFC } from 'react'; +import { FC, useState } from 'react'; import HelpButton from '../buttons/help-button'; import Tooltip, { type TooltipProps } from '../modals/tooltip'; import LabelledSelect, { type LabelledSelectProps } from './labelled-select'; @@ -9,14 +9,10 @@ export type SelectWithTooltipProps = Omit< 'labelPosition' > & Pick & { - /** - * The select label. - */ - label: string; /** * Set additional classnames to the tooltip wrapper. */ - tooltipClassName?: string; + tooltipClassName?: TooltipProps['className']; }; /** @@ -24,7 +20,7 @@ export type SelectWithTooltipProps = Omit< * * Render a select with a button to display a tooltip about options. */ -const SelectWithTooltip: VFC = ({ +const SelectWithTooltip: FC = ({ title, content, id, diff --git a/src/components/molecules/forms/theme-toggle.tsx b/src/components/molecules/forms/theme-toggle.tsx index eb56ce9..10c6c47 100644 --- a/src/components/molecules/forms/theme-toggle.tsx +++ b/src/components/molecules/forms/theme-toggle.tsx @@ -1,10 +1,10 @@ import Moon from '@components/atoms/icons/moon'; import Sun from '@components/atoms/icons/sun'; import Toggle, { - ToggleChoices, - ToggleProps, + type ToggleChoices, + type ToggleProps, } from '@components/molecules/forms/toggle'; -import { useState, VFC } from 'react'; +import { FC, useState } from 'react'; import { useIntl } from 'react-intl'; export type ThemeToggleProps = Pick; @@ -14,7 +14,7 @@ export type ThemeToggleProps = Pick; * * Render a Toggle component to set theme. */ -const ThemeToggle: VFC = ({ value, ...props }) => { +const ThemeToggle: FC = ({ value, ...props }) => { const intl = useIntl(); const [isDarkTheme, setIsDarkTheme] = useState(value); const themeLabel = intl.formatMessage({ diff --git a/src/components/molecules/forms/toggle.tsx b/src/components/molecules/forms/toggle.tsx index dff2d2d..288062d 100644 --- a/src/components/molecules/forms/toggle.tsx +++ b/src/components/molecules/forms/toggle.tsx @@ -1,6 +1,6 @@ -import Checkbox from '@components/atoms/forms/checkbox'; +import Checkbox, { type CheckboxProps } from '@components/atoms/forms/checkbox'; import Label, { type LabelProps } from '@components/atoms/forms/label'; -import { ReactNode, VFC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './toggle.module.scss'; export type ToggleChoices = { @@ -14,15 +14,11 @@ export type ToggleChoices = { right: ReactNode; }; -export type ToggleProps = { +export type ToggleProps = Pick & { /** * The toggle choices. */ choices: ToggleChoices; - /** - * The input id. - */ - id: string; /** * The toggle label. */ @@ -30,15 +26,11 @@ export type ToggleProps = { /** * Set additional classnames to the label. */ - labelClassName?: string; + labelClassName?: LabelProps['className']; /** * The label size. */ labelSize?: LabelProps['size']; - /** - * The input name. - */ - name: string; /** * The toggle value. True if checked. */ @@ -54,7 +46,7 @@ export type ToggleProps = { * * Render a toggle with a label and two choices. */ -const Toggle: VFC = ({ +const Toggle: FC = ({ choices, id, label, diff --git a/src/components/molecules/images/responsive-image.tsx b/src/components/molecules/images/responsive-image.tsx index 1d8787e..31cbcd1 100644 --- a/src/components/molecules/images/responsive-image.tsx +++ b/src/components/molecules/images/responsive-image.tsx @@ -1,6 +1,6 @@ -import Link from '@components/atoms/links/link'; -import Image, { ImageProps } from 'next/image'; -import { VFC } from 'react'; +import Link, { type LinkProps } from '@components/atoms/links/link'; +import Image, { type ImageProps } from 'next/image'; +import { FC } from 'react'; import styles from './responsive-image.module.scss'; export type ResponsiveImageProps = Omit< @@ -26,7 +26,7 @@ export type ResponsiveImageProps = Omit< /** * A link target. */ - target?: string; + target?: LinkProps['href']; /** * The image width. */ @@ -38,7 +38,7 @@ export type ResponsiveImageProps = Omit< * * Render a responsive image wrapped in a figure element. */ -const ResponsiveImage: VFC = ({ +const ResponsiveImage: FC = ({ alt, caption, className = '', diff --git a/src/components/molecules/layout/branding.tsx b/src/components/molecules/layout/branding.tsx index 9f564bf..9fe89e7 100644 --- a/src/components/molecules/layout/branding.tsx +++ b/src/components/molecules/layout/branding.tsx @@ -1,11 +1,11 @@ import Heading from '@components/atoms/headings/heading'; import Link from 'next/link'; -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './branding.module.scss'; -import FlippingLogo from './flipping-logo'; +import FlippingLogo, { type FlippingLogoProps } from './flipping-logo'; -type BrandingProps = { +export type BrandingProps = Pick & { /** * The Branding baseline. */ @@ -14,10 +14,6 @@ type BrandingProps = { * Use H1 if the current page is homepage. Default: false. */ isHome?: boolean; - /** - * A photography URL. - */ - photo: string; /** * The Branding title; */ @@ -33,7 +29,7 @@ type BrandingProps = { * * Render the branding logo, title and optional baseline. */ -const Branding: VFC = ({ +const Branding: FC = ({ baseline, isHome = false, photo, diff --git a/src/components/molecules/layout/card.tsx b/src/components/molecules/layout/card.tsx index 23a0e54..89f100e 100644 --- a/src/components/molecules/layout/card.tsx +++ b/src/components/molecules/layout/card.tsx @@ -1,11 +1,11 @@ import ButtonLink from '@components/atoms/buttons/button-link'; import Heading, { type HeadingLevel } from '@components/atoms/headings/heading'; import DescriptionList, { - DescriptionListItem, + type DescriptionListItem, } from '@components/atoms/lists/description-list'; -import { VFC } from 'react'; +import { FC } from 'react'; import ResponsiveImage, { - ResponsiveImageProps, + type ResponsiveImageProps, } from '../images/responsive-image'; import styles from './card.module.scss'; @@ -68,7 +68,7 @@ export type CardProps = { * * Render a link with minimal information about its content. */ -const Card: VFC = ({ +const Card: FC = ({ className = '', cover, coverFit = 'cover', diff --git a/src/components/molecules/layout/flipping-logo.tsx b/src/components/molecules/layout/flipping-logo.tsx index 6f7645f..4a216ef 100644 --- a/src/components/molecules/layout/flipping-logo.tsx +++ b/src/components/molecules/layout/flipping-logo.tsx @@ -1,9 +1,9 @@ -import Logo from '@components/atoms/images/logo'; +import Logo, { type LogoProps } from '@components/atoms/images/logo'; import Image from 'next/image'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './flipping-logo.module.scss'; -type FlippingLogoProps = { +export type FlippingLogoProps = { /** * Set additional classnames to the logo wrapper. */ @@ -15,7 +15,7 @@ type FlippingLogoProps = { /** * Logo image title. */ - logoTitle?: string; + logoTitle?: LogoProps['title']; /** * Photo url. */ @@ -27,7 +27,7 @@ type FlippingLogoProps = { * * Render a logo and a photo with a flipping effect. */ -const FlippingLogo: VFC = ({ +const FlippingLogo: FC = ({ className = '', altText, logoTitle, diff --git a/src/components/molecules/layout/meta.tsx b/src/components/molecules/layout/meta.tsx index 218ebd9..fcce473 100644 --- a/src/components/molecules/layout/meta.tsx +++ b/src/components/molecules/layout/meta.tsx @@ -2,7 +2,7 @@ import DescriptionList, { type DescriptionListProps, type DescriptionListItem, } from '@components/atoms/lists/description-list'; -import { ReactNode, VFC } from 'react'; +import { FC, ReactNode } from 'react'; export type MetaItem = { /** @@ -43,7 +43,7 @@ export type MetaProps = { * * Renders the page metadata. */ -const Meta: VFC = ({ data, ...props }) => { +const Meta: FC = ({ data, ...props }) => { /** * Transform the metadata to description list item format. * diff --git a/src/components/molecules/layout/widget.tsx b/src/components/molecules/layout/widget.tsx index c04362a..feb2add 100644 --- a/src/components/molecules/layout/widget.tsx +++ b/src/components/molecules/layout/widget.tsx @@ -1,11 +1,17 @@ -import { FC, useState } from 'react'; -import HeadingButton, { HeadingButtonProps } from '../buttons/heading-button'; +import { FC, ReactNode, useState } from 'react'; +import HeadingButton, { + type HeadingButtonProps, +} from '../buttons/heading-button'; import styles from './widget.module.scss'; export type WidgetProps = Pick< HeadingButtonProps, 'expanded' | 'level' | 'title' > & { + /** + * The widget body. + */ + children: ReactNode; /** * Set additional classnames to the widget wrapper. */ diff --git a/src/components/molecules/modals/modal.test.tsx b/src/components/molecules/modals/modal.test.tsx index 14fb224..9a0e237 100644 --- a/src/components/molecules/modals/modal.test.tsx +++ b/src/components/molecules/modals/modal.test.tsx @@ -1,9 +1,18 @@ import { render, screen } from '@test-utils'; import Modal from './modal'; +const title = 'A custom title'; +const children = + 'Labore ullam delectus sit modi quam dolores. Ratione id sint aliquid facilis ipsum. Unde necessitatibus provident minus.'; + describe('Modal', () => { it('renders a title', () => { - render(); - expect(screen.getByText('A custom title')).toBeInTheDocument(); + render({children}); + expect(screen.getByText(title)).toBeInTheDocument(); + }); + + it('renders the modal body', () => { + render({children}); + expect(screen.getByText(children)).toBeInTheDocument(); }); }); diff --git a/src/components/molecules/modals/modal.tsx b/src/components/molecules/modals/modal.tsx index 52ada57..58f5fa0 100644 --- a/src/components/molecules/modals/modal.tsx +++ b/src/components/molecules/modals/modal.tsx @@ -1,13 +1,17 @@ -import Heading from '@components/atoms/headings/heading'; -import { CogProps } from '@components/atoms/icons/cog'; -import { MagnifyingGlassProps } from '@components/atoms/icons/magnifying-glass'; +import Heading, { type HeadingProps } from '@components/atoms/headings/heading'; +import { type CogProps } from '@components/atoms/icons/cog'; +import { type MagnifyingGlassProps } from '@components/atoms/icons/magnifying-glass'; import dynamic from 'next/dynamic'; -import { FC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './modal.module.scss'; export type Icons = 'cogs' | 'search'; export type ModalProps = { + /** + * The modal body. + */ + children: ReactNode; /** * Set additional classnames. */ @@ -15,7 +19,7 @@ export type ModalProps = { /** * Set additional classnames to the heading. */ - headingClassName?: string; + headingClassName?: HeadingProps['className']; /** * A icon to illustrate the modal. */ diff --git a/src/components/molecules/modals/tooltip.tsx b/src/components/molecules/modals/tooltip.tsx index 73f36e7..80721f3 100644 --- a/src/components/molecules/modals/tooltip.tsx +++ b/src/components/molecules/modals/tooltip.tsx @@ -1,5 +1,5 @@ import List, { type ListItem } from '@components/atoms/lists/list'; -import { ReactNode, VFC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './tooltip.module.scss'; export type TooltipProps = { @@ -26,7 +26,7 @@ export type TooltipProps = { * * Render a tooltip modal. */ -const Tooltip: VFC = ({ +const Tooltip: FC = ({ className = '', content, icon, diff --git a/src/components/molecules/nav/breadcrumb.tsx b/src/components/molecules/nav/breadcrumb.tsx index 33af735..6dc86a0 100644 --- a/src/components/molecules/nav/breadcrumb.tsx +++ b/src/components/molecules/nav/breadcrumb.tsx @@ -1,7 +1,7 @@ import Link from '@components/atoms/links/link'; import { settings } from '@utils/config'; import Script from 'next/script'; -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import { BreadcrumbList, ListItem, WithContext } from 'schema-dts'; import styles from './breadcrumb.module.scss'; @@ -37,7 +37,7 @@ export type BreadcrumbProps = { * * Render a breadcrumb navigation. */ -const Breadcrumb: VFC = ({ items, ...props }) => { +const Breadcrumb: FC = ({ items, ...props }) => { const intl = useIntl(); /** diff --git a/src/components/molecules/nav/nav.tsx b/src/components/molecules/nav/nav.tsx index 6ef9158..2666ea2 100644 --- a/src/components/molecules/nav/nav.tsx +++ b/src/components/molecules/nav/nav.tsx @@ -1,6 +1,6 @@ import Link from '@components/atoms/links/link'; import NavLink from '@components/atoms/links/nav-link'; -import { ReactNode, VFC } from 'react'; +import { FC, ReactNode } from 'react'; import styles from './nav.module.scss'; export type NavItem = { @@ -46,7 +46,7 @@ export type NavProps = { * * Render the nav links. */ -const Nav: VFC = ({ +const Nav: FC = ({ className = '', items, kind, diff --git a/src/components/organisms/forms/comment-form.stories.tsx b/src/components/organisms/forms/comment-form.stories.tsx index 1ab7cf2..670176c 100644 --- a/src/components/organisms/forms/comment-form.stories.tsx +++ b/src/components/organisms/forms/comment-form.stories.tsx @@ -1,4 +1,3 @@ -import Notice from '@components/atoms/layout/notice'; import { ComponentMeta, ComponentStory } from '@storybook/react'; import { IntlProvider } from 'react-intl'; import CommentFormComponent from './comment-form'; diff --git a/src/components/organisms/forms/comment-form.tsx b/src/components/organisms/forms/comment-form.tsx index 6acbf94..d7cb0f5 100644 --- a/src/components/organisms/forms/comment-form.tsx +++ b/src/components/organisms/forms/comment-form.tsx @@ -3,7 +3,7 @@ import Form from '@components/atoms/forms/form'; import Heading, { type HeadingLevel } from '@components/atoms/headings/heading'; import Spinner from '@components/atoms/loaders/spinner'; import LabelledField from '@components/molecules/forms/labelled-field'; -import { ReactNode, useState, VFC } from 'react'; +import { FC, ReactNode, useState } from 'react'; import { useIntl } from 'react-intl'; import styles from './comment-form.module.scss'; @@ -31,7 +31,7 @@ export type CommentFormProps = { titleLevel?: HeadingLevel; }; -const CommentForm: VFC = ({ +const CommentForm: FC = ({ className = '', Notice, saveComment, diff --git a/src/components/organisms/forms/contact-form.tsx b/src/components/organisms/forms/contact-form.tsx index 994244a..4a6902b 100644 --- a/src/components/organisms/forms/contact-form.tsx +++ b/src/components/organisms/forms/contact-form.tsx @@ -2,7 +2,7 @@ import Button from '@components/atoms/buttons/button'; import Form from '@components/atoms/forms/form'; import Spinner from '@components/atoms/loaders/spinner'; import LabelledField from '@components/molecules/forms/labelled-field'; -import { ReactNode, useState, VFC } from 'react'; +import { FC, ReactNode, useState } from 'react'; import { useIntl } from 'react-intl'; import styles from './contact-form.module.scss'; @@ -27,7 +27,7 @@ export type ContactFormProps = { * * Render a contact form. */ -const ContactForm: VFC = ({ +const ContactForm: FC = ({ className = '', Notice, sendMail, diff --git a/src/components/organisms/forms/search-form.tsx b/src/components/organisms/forms/search-form.tsx index 351d93c..18b7c08 100644 --- a/src/components/organisms/forms/search-form.tsx +++ b/src/components/organisms/forms/search-form.tsx @@ -2,15 +2,20 @@ import Button from '@components/atoms/buttons/button'; import Form from '@components/atoms/forms/form'; import MagnifyingGlass from '@components/atoms/icons/magnifying-glass'; import LabelledField, { - LabelledFieldProps, + type LabelledFieldProps, } from '@components/molecules/forms/labelled-field'; -import { useState, VFC } from 'react'; +import { FC, useState } from 'react'; import { useIntl } from 'react-intl'; import styles from './search-form.module.scss'; export type SearchFormProps = Pick; -const SearchForm: VFC = ({ hideLabel }) => { +/** + * SearchForm component + * + * Render a search form. + */ +const SearchForm: FC = ({ hideLabel }) => { const intl = useIntl(); const fieldLabel = intl.formatMessage({ defaultMessage: 'Search for:', diff --git a/src/components/organisms/layout/cards-list.tsx b/src/components/organisms/layout/cards-list.tsx index a53df0d..33ffe23 100644 --- a/src/components/organisms/layout/cards-list.tsx +++ b/src/components/organisms/layout/cards-list.tsx @@ -3,7 +3,7 @@ import List, { type ListProps, } from '@components/atoms/lists/list'; import Card, { type CardProps } from '@components/molecules/layout/card'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './cards-list.module.scss'; export type CardsListItem = Omit< @@ -37,7 +37,7 @@ export type CardsListProps = { * * Return a list of Card components. */ -const CardsList: VFC = ({ +const CardsList: FC = ({ coverFit, items, kind = 'unordered', diff --git a/src/components/organisms/layout/footer.tsx b/src/components/organisms/layout/footer.tsx index c9cb067..15bfa24 100644 --- a/src/components/organisms/layout/footer.tsx +++ b/src/components/organisms/layout/footer.tsx @@ -1,7 +1,9 @@ -import Copyright, { CopyrightProps } from '@components/atoms/layout/copyright'; +import Copyright, { + type CopyrightProps, +} from '@components/atoms/layout/copyright'; import BackToTop from '@components/molecules/buttons/back-to-top'; import Nav, { type NavItem } from '@components/molecules/nav/nav'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './footer.module.scss'; export type FooterProps = { @@ -28,12 +30,7 @@ export type FooterProps = { * * Renders a footer with copyright and nav; */ -const Footer: VFC = ({ - className, - copyright, - navItems, - topId, -}) => { +const Footer: FC = ({ className, copyright, navItems, topId }) => { return (