Skip to content

Commit

Permalink
feat: add authorization modal and multi step component (#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
meelrossi committed May 11, 2023
1 parent 409c909 commit 5296ae2
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 1 deletion.
41 changes: 41 additions & 0 deletions src/components/AuthorizationModal/AuthorizationModal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.authorization-modal {
padding: 45px 32px;
width: 100%;
max-width: 580px;
}

.authorization-modal .header {
font-weight: 700;
font-size: 32px;
line-height: 32px;
margin-bottom: 48px;
margin-top: 0;
}

.authorization-modal .contract-name {
color: var(--primary);
}

.close-button {
position: absolute;
top: 16px;
right: 16px;
}

.authorization-modal .ui.button.close-button::before {
content: url(../../assets/close.svg);
width: 16px;
height: 16px;
}

.authorization-modal .authorization-error {
display: flex;
align-items: center;
gap: 10px;
}

.authorization-modal .authorization-error::before {
content: url(../../assets/close.svg);
width: 16px;
height: 16px;
}
31 changes: 31 additions & 0 deletions src/components/AuthorizationModal/AuthorizationModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react'
import { Button } from '../Button/Button'
import { Modal } from '../Modal/Modal'
import { MultiStep } from '../MultiStep'
import { Props } from './AuthorizationModal.types'
import './AuthorizationModal.css'

export function AuthorizationModal({
currentStep,
header,
steps,
onClose
}: Props) {
return (
<Modal
open
className="authorization-modal"
onClose={onClose}
data-testid="authorization-modal"
>
<Button
basic
aria-label={close}
className="close-button"
onClick={onClose}
/>
<h1 className="header">{header}</h1>
<MultiStep currentStep={currentStep} steps={steps} />
</Modal>
)
}
29 changes: 29 additions & 0 deletions src/components/AuthorizationModal/AuthorizationModal.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Step } from '../MultiStep/MultiStep.types'

export enum AuthorizationStepStatus {
LOADING_INFO = 'loading_info',
PENDING = 'pending',
WAITING = 'waiting',
PROCESSING = 'processing',
ALLOWANCE_AMOUNT_ERROR = 'allowance_amount_error',
ERROR = 'error',
DONE = 'done'
}

export enum AuthorizationStepAction {
REVOKE = 'revoke',
GRANT = 'grant',
CONFIRM = 'confirm'
}

export type AuthorizationStep = Step & {
status: AuthorizationStepStatus
actionType: AuthorizationStepAction
}

export type Props = {
currentStep: number
header: string
steps: AuthorizationStep[]
onClose: () => void
}
2 changes: 2 additions & 0 deletions src/components/AuthorizationModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './AuthorizationModal'
export * from './AuthorizationModal.types'
83 changes: 83 additions & 0 deletions src/components/MultiStep/MultiStep.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
.ui-multi-step {
display: flex;
flex-direction: column;
gap: 40px;
}

.ui-multi-step .step-container {
display: grid;
grid-template-columns: 24px 1fr;
gap: 10px;
}

.ui-multi-step .step-container.disabled {
opacity: 0.5;
}

.ui-multi-step .step-position {
border: 1px solid var(--text);
border-radius: 50%;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}

.ui-multi-step .step-info {
display: flex;
flex-direction: column;
gap: 16px;
}

.ui-multi-step .step-title {
margin: 0;
font-weight: 400;
font-size: 16px;
line-height: 26px;
}

.ui-multi-step .step-description {
margin: 0;
font-weight: 400;
font-size: 13px;
line-height: 24px;
}

.ui-multi-step .step-action {
max-width: 230px;
width: 100%;
}

.ui-multi-step .step-action-container {
display: flex;
gap: 10px;
margin-top: 10px;
font-size: 13px;
align-items: center;
}

.ui-multi-step .disabled .step-action:disabled {
background: rgba(115, 110, 125, 0.5);
opacity: 1 !important; /** This is to override opacity: 0.45!important for buttons. The opacity will be given by upper component **/
}

.ui-multi-step .step-message .ui.loader {
position: relative;
top: 12px;
left: 10px;
}

.ui-multi-step .check-icon {
color: var(--primary);
}

.ui-multi-step .step-message {
display: flex;
gap: 10px;
font-size: 13px;
height: 44px;
align-items: center;
margin-top: 10px;
position: relative;
}
60 changes: 60 additions & 0 deletions src/components/MultiStep/MultiStep.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react'
import classNames from 'classnames'
import Icon from 'semantic-ui-react/dist/commonjs/elements/Icon'
import { Button } from '../Button/Button'
import { Loader } from '../Loader/Loader'
import { Props } from './MultiStep.types'
import './MultiStep.css'

export function MultiStep({ steps, currentStep }: Props): JSX.Element {
return (
<div className="ui-multi-step" data-testid="multi-step">
{steps.map((step, index) => {
const showAction =
step.action && currentStep <= index && !step.isLoading
const isDisabled = index > currentStep
return (
<div
key={`step-${index}`}
data-testid={step.testId || `step-${index}`}
className={classNames('step-container', {
disabled: isDisabled
})}
>
<div>
<span className="step-position">{index + 1}</span>
</div>
<div className="step-info">
<p className="step-title">{step.title}</p>
{step.description ? (
<p className="step-description">{step.description}</p>
) : null}
{showAction ? (
<div className="step-action-container">
<Button
primary
onClick={step.onActionClick}
className="step-action"
disabled={isDisabled}
>
{step.action}
</Button>
{step.message ? <span>{step.message}</span> : null}
</div>
) : (
<div className="step-message">
{step.isLoading ? (
<Loader size="small" active data-testid="step-loader" />
) : (
<Icon className="check-icon" name="check" />
)}
{step.message ? <span>{step.message}</span> : null}
</div>
)}
</div>
</div>
)
})}
</div>
)
}
15 changes: 15 additions & 0 deletions src/components/MultiStep/MultiStep.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export type Step = {
title: string
description?: string
isLoading?: boolean
message?: string | JSX.Element
action?: string
actionDescription?: string
testId?: string
onActionClick: () => void
}

export type Props = {
steps: Step[]
currentStep: number
}
1 change: 1 addition & 0 deletions src/components/MultiStep/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './MultiStep'
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ export * from './components/Box'
export * from './components/RangeField'
export * from './components/SliderField/SliderField'
export * from './components/BarChart/BarChart'

export * from './components/MultiStep/MultiStep'
export * from './components/AuthorizationModal'
// Semantic components
/* eslint-disable no-restricted-imports */
export * from 'semantic-ui-react'
Expand Down

0 comments on commit 5296ae2

Please sign in to comment.