New Empty States (#3465)
New empty states --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -0,0 +1,86 @@
|
||||
import { useEffect } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion, useMotionValue, useTransform } from 'framer-motion';
|
||||
|
||||
import {
|
||||
Background,
|
||||
MovingImage,
|
||||
} from '@/ui/layout/animated-placeholder/constants/AnimatedImages';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
interface StyledImageProps {
|
||||
type: string;
|
||||
}
|
||||
|
||||
const StyledBackgroundImage = styled.img<StyledImageProps>`
|
||||
max-height: ${({ type }) =>
|
||||
type === 'error500' || type === 'error404' ? '245px' : '160px'};
|
||||
max-width: ${({ type }) =>
|
||||
type === 'error500' || type === 'error404' ? '245px' : '160px'};
|
||||
`;
|
||||
|
||||
const StyledMovingImage = styled(motion.img)<StyledImageProps>`
|
||||
position: absolute;
|
||||
max-width: ${({ type }) =>
|
||||
type === 'error500' || type === 'error404' ? '185px' : '130px'};
|
||||
max-height: ${({ type }) =>
|
||||
type === 'error500' || type === 'error404' ? '185px' : '130px'};
|
||||
z-index: 2;
|
||||
`;
|
||||
|
||||
interface AnimatedPlaceholderProps {
|
||||
type: keyof typeof Background | keyof typeof MovingImage;
|
||||
}
|
||||
|
||||
const AnimatedPlaceholder = ({ type }: AnimatedPlaceholderProps) => {
|
||||
const x = useMotionValue(window.innerWidth / 2);
|
||||
const y = useMotionValue(window.innerHeight / 2);
|
||||
|
||||
const translateX = useTransform(x, [0, window.innerWidth], [-2, 2]);
|
||||
const translateY = useTransform(y, [0, window.innerHeight], [-2, 2]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleMove = (event: MouseEvent | TouchEvent) => {
|
||||
const clientX =
|
||||
'touches' in event ? event.touches[0].clientX : event.clientX;
|
||||
const clientY =
|
||||
'touches' in event ? event.touches[0].clientY : event.clientY;
|
||||
|
||||
x.set(clientX);
|
||||
y.set(clientY);
|
||||
};
|
||||
|
||||
window.addEventListener('mousemove', handleMove);
|
||||
window.addEventListener('touchmove', handleMove);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('mousemove', handleMove);
|
||||
window.removeEventListener('touchmove', handleMove);
|
||||
};
|
||||
}, [x, y]);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledBackgroundImage
|
||||
src={Background[type]}
|
||||
alt="Background"
|
||||
type={type}
|
||||
/>
|
||||
<StyledMovingImage
|
||||
src={MovingImage[type]}
|
||||
alt="Moving"
|
||||
style={{ translateX, translateY }}
|
||||
transition={{ type: 'spring', stiffness: 100, damping: 10 }}
|
||||
type={type}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnimatedPlaceholder;
|
||||
@ -0,0 +1,40 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const StyledEmptyContainer = styled.div`
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(6)};
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
margin: ${({ theme }) => theme.spacing(16)} 0px;
|
||||
`;
|
||||
|
||||
export const StyledEmptyTextContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(3)};
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const StyledEmptyTitle = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
font-size: ${({ theme }) => theme.font.size.lg};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.lg};
|
||||
`;
|
||||
|
||||
export const StyledEmptySubTitle = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.md};
|
||||
max-height: 2.4em;
|
||||
overflow: hidden;
|
||||
width: 50%;
|
||||
`;
|
||||
@ -0,0 +1,38 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const StyledErrorContainer = styled.div`
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(8)};
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
export const StyledErrorTextContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const StyledErrorTitle = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
font-size: ${({ theme }) => theme.font.size.xl};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.lg};
|
||||
`;
|
||||
|
||||
export const StyledErrorSubTitle = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
font-size: ${({ theme }) => theme.font.size.xs};
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.md};
|
||||
max-height: 2.4em;
|
||||
overflow: hidden;
|
||||
`;
|
||||
@ -0,0 +1,21 @@
|
||||
export const Background: Record<string, string> = {
|
||||
noFile: '/images/placeholders/background/no_file_bg.png',
|
||||
noNote: '/images/placeholders/background/no_note_bg.png',
|
||||
noRecord: '/images/placeholders/background/no_record_bg.png',
|
||||
noTask: '/images/placeholders/background/no_task_bg.png',
|
||||
errorIndex: '/images/placeholders/background/error_index_bg.png',
|
||||
emptyTimeline: '/images/placeholders/background/empty_timeline_bg.png',
|
||||
error404: '/images/placeholders/background/404_bg.png',
|
||||
error500: '/images/placeholders/background/500_bg.png',
|
||||
};
|
||||
|
||||
export const MovingImage: Record<string, string> = {
|
||||
noFile: '/images/placeholders/moving-image/no_file.png',
|
||||
noNote: '/images/placeholders/moving-image/no_note.png',
|
||||
noRecord: '/images/placeholders/moving-image/no_record.png',
|
||||
noTask: '/images/placeholders/moving-image/no_task.png',
|
||||
errorIndex: '/images/placeholders/moving-image/error_index.png',
|
||||
emptyTimeline: '/images/placeholders/moving-image/empty_timeline.png',
|
||||
error404: '/images/placeholders/moving-image/404.png',
|
||||
error500: '/images/placeholders/moving-image/500.png',
|
||||
};
|
||||
Reference in New Issue
Block a user