diff options
| -rw-r--r-- | src/components/atoms/icons/hamburger.module.scss | 57 | ||||
| -rw-r--r-- | src/components/atoms/icons/hamburger.stories.tsx | 25 | ||||
| -rw-r--r-- | src/components/atoms/icons/hamburger.test.tsx | 9 | ||||
| -rw-r--r-- | src/components/atoms/icons/hamburger.tsx | 20 |
4 files changed, 111 insertions, 0 deletions
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<typeof HamburgerIcon>; + +const Template: ComponentStory<typeof HamburgerIcon> = (args) => ( + <HamburgerIcon {...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(<Hamburger isActive={false} />); + 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<HamburgerProps> = ({ isActive }) => { + const stateClass = isActive ? `${styles['icon--active']}` : ''; + const iconClasses = `${styles.icon} ${stateClass}`; + + return <span className={iconClasses}></span>; +}; + +export default Hamburger; |
