Skip to content

Commit

Permalink
feat(modal): add modal animation
Browse files Browse the repository at this point in the history
  • Loading branch information
glrodasz committed Feb 13, 2022
1 parent a1a8e14 commit e49a5a4
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 40 deletions.
9 changes: 8 additions & 1 deletion atoms/Button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import styles from './Button.module.css'
import { options } from './constants'
import withStyles from '../../hocs/withStyles'

import isEmpty from '../../utils/isEmpty'
import isObject from '../../utils/isObject'

export const handleClick = ({ onClick }) => (event) => {
onClick(event)
}
Expand All @@ -29,7 +32,11 @@ export const Button = ({
>
{addons && addons.prepend}

<Heading color={type === 'primary' ? 'inverted' : 'primary'}>
<Heading
color={type === 'primary' ? 'inverted' : 'primary'}
isCentered
isInline={isObject(addons) && !isEmpty(addons)}
>
{children}
</Heading>

Expand Down
13 changes: 10 additions & 3 deletions atoms/Heading/Heading.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,24 @@ import styles from './Heading.module.css'
import { options } from './constants'
import withStyles from '../../hocs/withStyles'

export const Heading = ({ children, getStyles }) => {
export const Heading = ({ children, isCentered, isInline, getStyles }) => {
return (
<header className={getStyles('heading', ['color', 'size', 'weight'])}>
<h1
className={getStyles('heading', ['color', 'size', 'weight'], {
'is-centered': isCentered,
'is-inline': isInline,
})}
>
{children}
</header>
</h1>
)
}

Heading.propTypes = {
children: PropTypes.string.isRequired,
getStyles: PropTypes.func.isRequired,
isInline: PropTypes.bool,
isCentered: PropTypes.bool,
color: PropTypes.oneOf(options.colors),
size: PropTypes.oneOf(options.sizes),
weight: PropTypes.oneOf(options.weights),
Expand Down
12 changes: 10 additions & 2 deletions atoms/Heading/Heading.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.heading {
display: flex;
align-items: center;
width: 100%;
font-family: var(--font-family-sans);
line-height: var(--line-height-tight);
}
Expand Down Expand Up @@ -52,3 +51,12 @@
.weight-bold {
font-weight: var(--font-weight-bold);
}

.is-centered {
text-align: center;
}

.is-inline {
display: inline-block;
max-width: max-content;
}
12 changes: 12 additions & 0 deletions atoms/Heading/Heading.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ export default {

export const Default = Template.bind({})

export const Inline = Template.bind({})
Inline.args = {
isInline: true,
}

export const Centered = Template.bind({})
Centered.args = {
isCentered: true,
children:
'Lose consequence night studies Wolves should wizards destruction burglar? All right, then. Keep your secrets.',
}

export const Colors = ListTemplate.bind({})
Colors.args = { items: options.colors.map((color) => ({ color })) }

Expand Down
17 changes: 17 additions & 0 deletions atoms/Icon/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,23 @@ export const iconsMap = {
</>
),
},
cross: {
viewBox: '0 0 28 28',
svg: (
<>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M1.65702 27.6578L0.343018 26.3418L26.343 0.341797L27.657 1.6578L1.65702 27.6578Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M26.343 27.6578L0.343018 1.6578L1.65702 0.341797L27.657 26.3418L26.343 27.6578Z"
/>
</>
),
},
}

export const options = {
Expand Down
72 changes: 48 additions & 24 deletions atoms/Modal/Modal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useState } from 'react'
import PropTypes from 'prop-types'

import styles from './Modal.module.css'
Expand All @@ -8,8 +8,18 @@ import Icon from '../Icon'
import Container from '../../layout/Container'
import isEmpty from '../../utils/isEmpty'

const handleClose = ({ onClose }) => () => {
onClose()
import useMedia from '../../hook/useMedia'

// Sync with ./Modal.module.css#L13-L17
const FADE_OUT_ANIMATION_TIME = 400

const createHandlerClick = () => (event) => {
event?.stopPropagation()
}

const createHandlerClose = ({ onClose, setOnFadeOut }) => () => {
setOnFadeOut(true)
setTimeout(onClose, FADE_OUT_ANIMATION_TIME)
}

const handleSecondaryAction = ({ onSecondaryAction }) => () => {
Expand All @@ -21,35 +31,49 @@ export const Modal = ({
secondaryAction,
children,
getStyles,
type,
isPlayground,
}) => {
const isDesktop = useMedia(['(min-width: 992px)'], [true])
const [onFadeOut, setOnFadeOut] = useState(false)

const handleClose = createHandlerClose({ onClose, setOnFadeOut })

return (
<div
className={getStyles('modal', ['type'], {
className={getStyles('backdrop', {
'is-playground': isPlayground,
'on-fade-out': onFadeOut,
})}
onClick={handleClose}
>
<div className={getStyles('heading')}>
{!!onClose && (
<Icon
color="inverted"
name="angleLeft"
background="muted"
onClick={handleClose({ onClose })}
/>
)}
{secondaryAction && !isEmpty(secondaryAction) && (
<Icon
color="inverted"
name={secondaryAction?.icon}
background="muted"
onClick={handleSecondaryAction({
onSecondaryAction: secondaryAction?.handler,
})}
/>
)}
<div
className={getStyles('modal', ['type'])}
onClick={createHandlerClick()}
>
<div className={getStyles('heading')}>
{!!onClose && (
<Icon
color={isDesktop && type === 'secondary' ? 'primary' : 'inverted'}
name={isDesktop ? 'cross' : 'angleLeft'}
background={isDesktop ? 'transparent' : 'muted'}
onClick={handleClose}
size={isDesktop ? 'lg' : 'md'}
/>
)}
{secondaryAction && !isEmpty(secondaryAction) && (
<Icon
color="inverted"
name={secondaryAction?.icon}
background="muted"
onClick={handleSecondaryAction({
onSecondaryAction: secondaryAction?.handler,
})}
/>
)}
</div>
<Container>{children}</Container>
</div>
<Container>{children}</Container>
</div>
)
}
Expand Down
60 changes: 54 additions & 6 deletions atoms/Modal/Modal.module.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
.modal {
.backdrop {
position: fixed;
z-index: var(--z-index-50);
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
animation: fadeInModal 0.2s ease-in forwards;
background: var(--modal-backdrop-color);
inset: 0;
}

.backdrop.on-fade-out {
animation: fadeOutModal 0.2s ease-in forwards;
}

.modal {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
padding: 16px 32px;
animation: fadeInModal 0.4s ease-in forwards;
opacity: 0;
}

.backdrop.on-fade-out .modal {
animation: fadeOutModal 0.4s ease-in forwards;
}

.heading {
Expand All @@ -18,7 +35,6 @@
.is-playground {
position: relative;
width: calc(50% - 15px);
height: 400px;
border: var(--border-width-thick) dashed var(--color-primary);
}

Expand All @@ -29,3 +45,35 @@
.type-secondary {
background-color: var(--background-color-primary);
}

@media (min-width: 992px) {
.modal {
max-width: var(--modal-desktop-max-width);
height: var(--modal-desktop-height);
border-radius: var(--border-radius-sm);
}

.heading {
flex-direction: row-reverse;
}
}

@keyframes fadeInModal {
from {
opacity: 0;
}

to {
opacity: 1;
}
}

@keyframes fadeOutModal {
from {
opacity: 1;
}

to {
opacity: 0;
}
}
7 changes: 5 additions & 2 deletions atoms/Paragraph/Paragraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export const Paragraph = ({
isStriked,
isInline,
isMonospace,
isCentered,
}) => {
return (
<div
<p
className={getStyles(
className,
'paragraph',
Expand All @@ -23,11 +24,12 @@ export const Paragraph = ({
'is-striked': isStriked,
'is-inline': isInline,
'is-monospace': isMonospace,
'is-centered': isCentered,
}
)}
>
{children}
</div>
</p>
)
}

Expand All @@ -40,6 +42,7 @@ Paragraph.propTypes = {
className: PropTypes.string,
isStriked: PropTypes.bool,
isInline: PropTypes.bool,
isCentered: PropTypes.bool,
isMonospace: PropTypes.bool,
}

Expand Down
4 changes: 4 additions & 0 deletions atoms/Paragraph/Paragraph.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@
.is-monospace {
font-family: var(--font-family-mono);
}

.is-centered {
text-align: center;
}
7 changes: 7 additions & 0 deletions atoms/Paragraph/Paragraph.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ Striked.args = { isStriked: true }
export const Inline = Template.bind({})
Inline.args = { isInline: true, children: 'Swords are no more.' }

export const Centered = Template.bind({})
Centered.args = {
isCentered: true,
children:
'Lose consequence night studies Wolves should wizards destruction burglar? All right, then. Keep your secrets.',
}

export const Monospace = Template.bind({})
Monospace.args = { isMonospace: true }

Expand Down
4 changes: 4 additions & 0 deletions atoms/Picture/Picture.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.picture {
user-select: none;
}

.picture img {
display: block;
width: 100%;
Expand Down
22 changes: 22 additions & 0 deletions hook/useMedia.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useEffect, useState } from 'react'

const useMedia = (queries, values, defaultValue) => {
const mediaQueryLists = queries.map((q) => window.matchMedia(q))
const getValue = () => {
const index = mediaQueryLists.findIndex((mql) => mql.matches)
return typeof values[index] !== 'undefined' ? values[index] : defaultValue
}

const [value, setValue] = useState(getValue)

useEffect(() => {
const handler = () => setValue(getValue)
mediaQueryLists.forEach((mql) => mql.addListener(handler))

return () => mediaQueryLists.forEach((mql) => mql.removeListener(handler))
}, [])

return value
}

export default useMedia
2 changes: 1 addition & 1 deletion layout/CenteredContent/CenteredContent.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
height: 100%;
flex: auto;
flex-direction: column;
align-items: stretch;
align-items: center;
justify-content: center;
}

Expand Down
Loading

0 comments on commit e49a5a4

Please sign in to comment.