From 352047fd967758bbeb2ee2187b317aeff39d67f0 Mon Sep 17 00:00:00 2001 From: Matej Lubej Date: Wed, 6 Mar 2024 22:31:31 +0100 Subject: [PATCH 1/2] Add Alert component - add matching icons - support error, success, loading, insufficient-balance types --- .../src/components/Alert/index.module.css | 93 +++++++++++++++++++ frontend/src/components/Alert/index.tsx | 60 ++++++++++++ frontend/src/components/Card/index.tsx | 8 +- frontend/src/components/Icon/index.tsx | 10 +- frontend/src/components/MascotCard/index.tsx | 2 +- .../src/components/icons/CheckCircleIcon.tsx | 11 +++ .../src/components/icons/PiggyBankIcon.tsx | 11 +++ frontend/src/components/icons/SpinnerIcon.tsx | 11 +++ .../components/icons/WarningCircleIcon.tsx | 11 +++ frontend/src/index.css | 12 +++ frontend/src/pages/HomePage/index.tsx | 28 ++++++ 11 files changed, 253 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/Alert/index.module.css create mode 100644 frontend/src/components/Alert/index.tsx create mode 100644 frontend/src/components/icons/CheckCircleIcon.tsx create mode 100644 frontend/src/components/icons/PiggyBankIcon.tsx create mode 100644 frontend/src/components/icons/SpinnerIcon.tsx create mode 100644 frontend/src/components/icons/WarningCircleIcon.tsx diff --git a/frontend/src/components/Alert/index.module.css b/frontend/src/components/Alert/index.module.css new file mode 100644 index 0000000..e259113 --- /dev/null +++ b/frontend/src/components/Alert/index.module.css @@ -0,0 +1,93 @@ +.alert { + min-height: 688px; + text-align: center; + + h2 { + color: var(--palatinate-blue); + margin-top: 6rem; + margin-bottom: 1rem; + } + + p { + max-width: 335px; + font-size: 14px; + font-weight: 400; + line-height: 120%; + letter-spacing: 0; + margin: 0 auto; + margin-bottom: 2.375rem; + } + + .icon { + margin: 0 auto; + margin-bottom: 1.125rem; + } + + .actions { + &:empty { + display: none; + } + + span { + font-size: 22px; + font-weight: 500; + line-height: 150%; + letter-spacing: -0.03em; + color: var(--palatinate-blue); + } + } +} + +.alertError { + svg { + color: var(--mystic); + } +} + +.alertSuccess { + svg { + color: var(--green-sheen); + } +} + +@keyframes rotating { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +.alertLoading { + .icon { + display: flex; + justify-content: center; + align-items: center; + width: 106px; + height: 106px; + border-radius: 50%; + background: linear-gradient(302.43deg, var(--medium-blue) -18.46%, var(--azure) 93.84%); + } + + svg { + color: var(--white); + animation: rotating 3s linear infinite; + } +} + +.alertInsufficientBalance { + .icon { + display: flex; + justify-content: center; + align-items: center; + width: 106px; + height: 106px; + border-radius: 50%; + background: linear-gradient(282.09deg, var(--mystic) 6.24%, var(--rose-red) 102.94%); + } + + svg { + color: var(--white); + } +} diff --git a/frontend/src/components/Alert/index.tsx b/frontend/src/components/Alert/index.tsx new file mode 100644 index 0000000..97c1be6 --- /dev/null +++ b/frontend/src/components/Alert/index.tsx @@ -0,0 +1,60 @@ +import { FC, PropsWithChildren, ReactElement } from 'react' +import classes from './index.module.css' +import { Card } from '../Card' +import { WarningCircleIcon } from '../icons/WarningCircleIcon.tsx' +import { CheckCircleIcon } from '../icons/CheckCircleIcon.tsx' +import { SpinnerIcon } from '../icons/SpinnerIcon.tsx' +import { PiggyBankSvgIcon } from '../icons/PiggyBankIcon.tsx' + +type AlertType = 'error' | 'success' | 'loading' | 'insufficient-balance' + +interface AlertTypeValues { + header: string + icon: ReactElement +} + +const alertTypeValuesMap: Record = { + error: { + header: 'Something went wrong', + icon: , + }, + success: { + header: 'Vote cast', + icon: , + }, + loading: { + header: 'Casting your vote', + icon: , + }, + 'insufficient-balance': { + header: 'Insufficient balance', + icon: , + }, +} + +const alertTypeClassMap: Record = { + error: classes.alertError, + success: classes.alertSuccess, + loading: classes.alertLoading, + 'insufficient-balance': classes.alertInsufficientBalance, +} + +interface Props extends PropsWithChildren { + type: AlertType + actions?: ReactElement +} + +export const Alert: FC = ({ children, type, actions }) => { + const { header, icon } = alertTypeValuesMap[type] + + return ( + +
+

{header}

+

{children}

+
{icon}
+
{actions}
+
+
+ ) +} diff --git a/frontend/src/components/Card/index.tsx b/frontend/src/components/Card/index.tsx index dba52ae..c140480 100644 --- a/frontend/src/components/Card/index.tsx +++ b/frontend/src/components/Card/index.tsx @@ -1,6 +1,10 @@ import { FC, PropsWithChildren } from 'react' import classes from './index.module.css' -export const Card: FC = ({ children }) => { - return
{children}
+interface Props extends PropsWithChildren { + className?: string +} + +export const Card: FC = ({ children, className }) => { + return
{children}
} diff --git a/frontend/src/components/Icon/index.tsx b/frontend/src/components/Icon/index.tsx index 9e56490..a4053d0 100644 --- a/frontend/src/components/Icon/index.tsx +++ b/frontend/src/components/Icon/index.tsx @@ -1,6 +1,6 @@ import { cloneElement, FC, ReactElement, SVGProps } from 'react' -type IconSize = 'medium' +type IconSize = 'medium' | 'large' | 'xlarge' interface Props { children: ReactElement @@ -12,6 +12,14 @@ const sizeMap: Record>> = { width: 30, height: 30, }, + large: { + width: 64, + height: 64, + }, + xlarge: { + width: 100, + height: 100, + }, } export const Icon: FC = ({ children, size = 'medium' }) => { diff --git a/frontend/src/components/MascotCard/index.tsx b/frontend/src/components/MascotCard/index.tsx index b9a022e..025cc19 100644 --- a/frontend/src/components/MascotCard/index.tsx +++ b/frontend/src/components/MascotCard/index.tsx @@ -12,7 +12,7 @@ export const MascotCard: FC = ({ image, title, description, actions }) => return (
{image} -

{title}

+

{title}

{description}

{actions}
diff --git a/frontend/src/components/icons/CheckCircleIcon.tsx b/frontend/src/components/icons/CheckCircleIcon.tsx new file mode 100644 index 0000000..6fabeca --- /dev/null +++ b/frontend/src/components/icons/CheckCircleIcon.tsx @@ -0,0 +1,11 @@ +/// + +import { FC } from 'react' +import CheckCircleSvg from '@phosphor-icons/core/assets/fill/check-circle-fill.svg?react' +import { Icon } from '../Icon' + +export const CheckCircleIcon: FC = () => ( + + + +) diff --git a/frontend/src/components/icons/PiggyBankIcon.tsx b/frontend/src/components/icons/PiggyBankIcon.tsx new file mode 100644 index 0000000..a39ad2b --- /dev/null +++ b/frontend/src/components/icons/PiggyBankIcon.tsx @@ -0,0 +1,11 @@ +/// + +import { FC } from 'react' +import PiggyBankSvg from '@phosphor-icons/core/assets/regular/piggy-bank.svg?react' +import { Icon } from '../Icon' + +export const PiggyBankSvgIcon: FC = () => ( + + + +) diff --git a/frontend/src/components/icons/SpinnerIcon.tsx b/frontend/src/components/icons/SpinnerIcon.tsx new file mode 100644 index 0000000..8a69700 --- /dev/null +++ b/frontend/src/components/icons/SpinnerIcon.tsx @@ -0,0 +1,11 @@ +/// + +import { FC } from 'react' +import SpinnerSvg from '@phosphor-icons/core/assets/regular/spinner.svg?react' +import { Icon } from '../Icon' + +export const SpinnerIcon: FC = () => ( + + + +) diff --git a/frontend/src/components/icons/WarningCircleIcon.tsx b/frontend/src/components/icons/WarningCircleIcon.tsx new file mode 100644 index 0000000..9ab0251 --- /dev/null +++ b/frontend/src/components/icons/WarningCircleIcon.tsx @@ -0,0 +1,11 @@ +/// + +import { FC } from 'react' +import WarningCircleSvg from '@phosphor-icons/core/assets/fill/warning-circle-fill.svg?react' +import { Icon } from '../Icon' + +export const WarningCircleIcon: FC = () => ( + + + +) diff --git a/frontend/src/index.css b/frontend/src/index.css index 83522d6..1ae230c 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -4,6 +4,11 @@ --bright-gray: #eae6f0; --dark-gunmetal: #242629; --navy-blue: #000062; + --mystic: #d44c7d; + --green-sheen: #66bfa0; + --azure: #008cff; + --rose-red: #cc1e5c; + --medium-blue: #0d00d2; } *, @@ -47,6 +52,13 @@ h1 { } h2 { + font-size: 30px; + font-weight: 500; + line-height: 140%; + letter-spacing: -0.03em; +} + +h3 { font-size: 26px; font-weight: 500; line-height: 130%; diff --git a/frontend/src/pages/HomePage/index.tsx b/frontend/src/pages/HomePage/index.tsx index 52361e8..e4a17d2 100644 --- a/frontend/src/pages/HomePage/index.tsx +++ b/frontend/src/pages/HomePage/index.tsx @@ -4,10 +4,38 @@ import { Button } from '../../components/Button' import { Card } from '../../components/Card' import classes from './index.module.css' import { MascotCard } from '../../components/MascotCard' +import { Alert } from '../../components/Alert' export const HomePage: FC = () => { return (
+ + Please note there is a 100 ROSE threshold in order to cast your vote. + +
+
+ Submitting vote...}> + Once you confirm this vote you will not be able to cancel it. + +
+
+ + Your vote has successfully submitted. +
+ Thank you for your participation. + + } + /> +
+
+ + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod Ipsum + +
+

Select your preferred mascot option. Once you confirm this vote you will not be able to cancel it. From 073b000bc9bb97982fd103194ec30e0f965e41e7 Mon Sep 17 00:00:00 2001 From: Matej Lubej Date: Thu, 7 Mar 2024 11:05:22 +0100 Subject: [PATCH 2/2] Add StringUtils clsx --- frontend/src/components/Button/index.tsx | 11 ++++++----- frontend/src/components/Card/index.tsx | 3 ++- frontend/src/utils/string.utils.ts | 7 +++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Button/index.tsx b/frontend/src/components/Button/index.tsx index dce3b50..b5d3f88 100644 --- a/frontend/src/components/Button/index.tsx +++ b/frontend/src/components/Button/index.tsx @@ -1,5 +1,6 @@ import classes from './index.module.css' import { FC, MouseEventHandler, PropsWithChildren } from 'react' +import { StringUtils } from '../../utils/string.utils.ts' type ButtonSize = 'small' | 'medium' type ButtonColor = 'primary' | 'secondary' @@ -43,15 +44,15 @@ export const Button: FC = ({ type, }) => (