Skip to content

Commit

Permalink
Add new stepper
Browse files Browse the repository at this point in the history
  • Loading branch information
kattylucy committed Nov 11, 2024
1 parent 6b6c953 commit ad33ab4
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 98 deletions.
4 changes: 2 additions & 2 deletions centrifuge-app/src/components/LayoutBase/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ export const ContentWrapper = styled.div`
@media (min-width: ${({ theme }) => theme.breakpoints['M']}) and (max-width: ${({ theme }) =>
theme.breakpoints['L']}) {
margin-left: 7vw;
width: calc(100% - 7vw);
margin-left: 6vw;
width: calc(100% - 6vw);
margin-top: 10px;
}
Expand Down
33 changes: 21 additions & 12 deletions centrifuge-app/src/pages/IssuerCreatePool/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import {
Grid,
Select,
Shelf,
Step,
Stepper,
Text,
TextInput,
TextWithPlaceholder,
Thumbnail,
} from '@centrifuge/fabric'
import { createKeyMulti, sortAddresses } from '@polkadot/util-crypto'
Expand All @@ -33,11 +34,11 @@ import { Field, FieldProps, Form, FormikErrors, FormikProvider, setIn, useFormik
import * as React from 'react'
import { useNavigate } from 'react-router'
import { combineLatest, firstValueFrom, lastValueFrom, switchMap, tap } from 'rxjs'
import { useTheme } from 'styled-components'
import { useDebugFlags } from '../../components/DebugFlags'
import { PreimageHashDialog } from '../../components/Dialogs/PreimageHashDialog'
import { ShareMultisigDialog } from '../../components/Dialogs/ShareMultisigDialog'
import { FieldWithErrorMessage } from '../../components/FieldWithErrorMessage'
import { PageHeader } from '../../components/PageHeader'
import { PageSection } from '../../components/PageSection'
import { Tooltips } from '../../components/Tooltips'
import { config, isTestEnv } from '../../config'
Expand All @@ -50,7 +51,6 @@ import { useCreatePoolFee } from '../../utils/useCreatePoolFee'
import { usePoolCurrencies } from '../../utils/useCurrencies'
import { useFocusInvalidInput } from '../../utils/useFocusInvalidInput'
import { usePools } from '../../utils/usePools'
import { truncate } from '../../utils/web3'
import { AdminMultisigSection } from './AdminMultisig'
import { IssuerInput } from './IssuerInput'
import { PoolFeeSection } from './PoolFeeInput'
Expand Down Expand Up @@ -179,6 +179,9 @@ function PoolIcon({ icon, children }: { icon?: File | null; children: string })
}

function CreatePoolForm() {
const theme = useTheme()
const [activeStep, setActiveStep] = React.useState(1)

const address = useAddress('substrate')
const {
substrate: { addMultisig },
Expand Down Expand Up @@ -623,15 +626,21 @@ function CreatePoolForm() {
)}
<FormikProvider value={form}>
<Form ref={formRef} noValidate>
<PageHeader
icon={<PoolIcon icon={form.values.poolIcon}>{(form.values.poolName || 'New Pool')[0]}</PoolIcon>}
title={form.values.poolName || 'New Pool'}
subtitle={
<TextWithPlaceholder isLoading={waitingForStoredIssuer} width={15}>
by {form.values.issuerName || (address && truncate(address))}
</TextWithPlaceholder>
}
/>
<Box padding={3}>
<Text variant="heading2">New pool setup</Text>
</Box>
<Box
backgroundColor={theme.colors.backgroundSecondary}
padding="32px 208px"
borderTop={`1px solid ${theme.colors.borderPrimary}`}
borderBottom={`1px solid ${theme.colors.borderPrimary}`}
>
<Stepper activeStep={activeStep} setActiveStep={setActiveStep} direction="row">
<Step label="Pool structure" />
<Step label="Pool details" />
<Step label="Pool setup" />
</Stepper>
</Box>
<PageSection title="Details">
<Grid columns={[4]} equalColumns gap={2} rowGap={3}>
<Box gridColumn="span 2">
Expand Down
137 changes: 53 additions & 84 deletions fabric/src/components/Stepper/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react'
import styled from 'styled-components'
import styled, { useTheme } from 'styled-components'
import { Box } from '../Box'
import { Grid } from '../Grid'
import { Text } from '../Text'

type EnrichedStepProps = {
Expand All @@ -11,6 +10,7 @@ type EnrichedStepProps = {
count?: number
setActiveStep?: React.Dispatch<number> | null
maxStep?: number
direction?: 'row' | 'column'
}

type StepProps = {
Expand All @@ -22,110 +22,78 @@ type StepperProps = {
activeStep: number
setActiveStep: React.Dispatch<number> | null
children: React.ReactNode
direction?: 'row' | 'column'
}

const getStepColor = (isActive: boolean, empty: boolean) => {
if (isActive) {
return 'textPrimary'
}
if (empty) {
return 'borderPrimary'
}
return 'transparent'
}

const counterSize = 28
const spaceDefault = 30
const spaceActive = 80

const List = styled(Box)`
list-style: none;
counter-reset: step-counter;
`

const ListItem = styled(Grid)<{ isActive?: boolean; empty?: boolean; isFinal?: boolean }>`
--duration: 0.15s;
counter-increment: step-counter;
position: relative;
place-content: center;
place-items: center;
justify-items: start;
transition: margin-bottom var(--duration);
&::before {
content: counter(step-counter);
width: ${counterSize}px;
height: ${counterSize}px;
display: flex;
justify-content: center;
align-items: center;
background-color: ${({ empty, isActive, theme }) => (theme.colors as any)[getStepColor(!!isActive, !!empty)]};
border: 2px solid;
border-color: ${({ theme, isActive }) => (isActive ? theme.colors.textPrimary : theme.colors.borderPrimary)};
border-radius: 50%;
color: ${({ theme, isActive }) => (isActive ? theme.colors.backgroundPrimary : theme.colors.borderPrimary)};
transition: background-color var(--duration) linear, border-color var(--duration) linear,
color var(--duration) linear;
}
&::after {
content: '';
display: ${({ isFinal }) => (isFinal ? 'none' : 'block')};
position: absolute;
top: 100%;
left: ${counterSize * 0.5}px;
height: ${({ isActive, isFinal }) => (isActive && !isFinal ? spaceActive : spaceDefault)}px;
width: 2px;
background-color: ${({ theme, isActive }) => (isActive ? theme.colors.textPrimary : theme.colors.borderPrimary)};
transition: height var(--duration), background-color var(--duration) linear;
}
const ListItem = styled(Box)<{ isActive?: boolean; empty?: boolean; isFinal?: boolean }>`
display: flex;
flex-direction: row;
align-items: center;
`

const Hitearea = styled.button`
--offset: 10px;
position: absolute;
top: calc(var(--offset) * -1);
left: calc(var(--offset) * -1);
width: calc(100% + var(--offset) * 2);
height: calc(100% + var(--offset) * 2);
appearance: none;
background-color: transparent;
const Hitearea = styled.button<{ direction?: string }>`
border: none;
border-radius: ${({ theme }) => theme.radii.input}px;
background-color: transparent;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
`

&:focus-visible {
outline: ${({ theme }) => `2px solid ${theme.colors.accentPrimary}`};
}
const Number = styled(Text)<{ isActive?: boolean }>`
background-color: ${({ theme, isActive }) => (isActive ? theme.colors.textGold : 'transparent')};
border: ${({ theme, isActive }) =>
isActive ? `1px solid ${theme.colors.textGold}` : `1.73px solid ${theme.colors.textDisabled}`};
border-radius: 100%;
width: 32px;
height: 32px;
text-align: center;
padding-top: 8px;
font-weight: 500;
`

export const Step = (props: StepProps & EnrichedStepProps) => {
const { isActive, count, isFinal, activeStep, label, empty, setActiveStep, maxStep } = props
const isClickable = (count as number) + 1 < (activeStep as number) || (count as number) + 1 <= (maxStep as number)
const theme = useTheme()
const { isActive, count, isFinal, label, empty, setActiveStep, direction } = props

return (
<ListItem
forwardedAs="li"
gridTemplateColumns={`${counterSize}px 1fr`}
gap={2}
height={counterSize}
mb={isActive && !isFinal ? spaceActive : spaceDefault}
{...{ empty, isActive, isFinal }}
<Box
display="flex"
flexDirection={direction || 'column'}
alignItems={direction === 'row' ? 'flex-start' : 'center'}
>
<Text as="h3" fontSize={18} lineHeight={1.2}>
{label}
</Text>
{!empty && isClickable && setActiveStep && (
<ListItem forwardedAs="li">
<Hitearea
title={`Step ${(count as number) + 1}`}
direction={direction}
onClick={() => {
setActiveStep((count as number) + 1)
!empty && setActiveStep && setActiveStep((count as number) + 1)
}}
>
<Number variant="body3" isActive={isActive}>
{count ? count + 1 : 1}
</Number>
<Text as="h3" variant="heading4" style={{ marginTop: 8 }}>
{label}
</Text>
</Hitearea>
</ListItem>
{!isFinal && (
<Box
borderTop={direction === 'row' ? `3px dashed ${theme.colors.textDisabled}` : 'none'}
borderLeft={direction === 'column' ? `3px dashed ${theme.colors.textDisabled}` : 'none'}
width={direction === 'row' ? '140px' : 0}
height={direction === 'column' ? 80 : 0}
mt={direction === 'row' ? 2 : 3}
mb={direction === 'row' ? 0 : 3}
marginLeft={direction === 'row' ? '20px' : 0}
/>
)}
</ListItem>
</Box>
)
}

Expand Down Expand Up @@ -162,13 +130,14 @@ export const Stepper = (props: StepperProps) => {
count: index,
setActiveStep: props.setActiveStep,
maxStep: maxStep.current,
direction: props.direction,
})
}
return step
})

return (
<List as="ol" role="list">
<List as="ol" role="list" display="flex" flexDirection={props.direction || 'column'} justifyContent="space-evenly">
{stepItems}
</List>
)
Expand Down

0 comments on commit ad33ab4

Please sign in to comment.