feat: UI responsiveness on mint and AP flow (#245)

* wip: make mint flow responsive

* feat: add responsivness

* feat: add button connection

* refactor: remove iconSpacing from button for responsiveness

* styles: text ellipsis variation

* style: ellipsis on combobox
This commit is contained in:
Camila Sosa Morales 2023-04-28 12:16:24 -03:00 committed by GitHub
parent 0983e28755
commit f685d6800b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 174 additions and 169 deletions

View File

@ -2,6 +2,7 @@ import { styled } from '@/theme';
export abstract class CardStyles {
static readonly Container = styled('div', {
width: '$full',
backgroundColor: '$slate2',
borderRadius: '$xlh',
padding: '$7',

View File

@ -1,57 +1,23 @@
import React from 'react';
import { ButtonProps } from '.';
import {
StyledButtonContentFlex,
StyledButtonContentGrid,
} from './button-content.styles';
import { ButtonIcon } from './button-icon';
export type ButtonContentProps = Pick<
ButtonProps,
| 'leftIcon'
| 'rightIcon'
| 'topIcon'
| 'bottomIcon'
| 'children'
| 'iconSpacing'
'leftIcon' | 'rightIcon' | 'children'
>;
export const ButtonContent: React.FC<ButtonContentProps> = (props) => {
const {
leftIcon,
rightIcon,
topIcon,
bottomIcon,
children,
iconSpacing = '1h',
} = props;
const { leftIcon, rightIcon, children } = props;
const midNode = (
<>
{leftIcon && (
<ButtonIcon css={{ marginRight: `$${iconSpacing}` }}>
{leftIcon}
</ButtonIcon>
)}
{leftIcon && <ButtonIcon>{leftIcon}</ButtonIcon>}
{children}
{rightIcon && (
<ButtonIcon css={{ marginLeft: `$${iconSpacing}` }}>
{rightIcon}
</ButtonIcon>
)}
{rightIcon && <ButtonIcon>{rightIcon}</ButtonIcon>}
</>
);
if (!topIcon && !bottomIcon) {
return midNode;
}
return (
<StyledButtonContentGrid>
{topIcon && <ButtonIcon>{topIcon}</ButtonIcon>}
<StyledButtonContentFlex>{midNode}</StyledButtonContentFlex>
{bottomIcon && <ButtonIcon>{bottomIcon}</ButtonIcon>}
</StyledButtonContentGrid>
);
return midNode;
};

View File

@ -49,11 +49,6 @@ export interface ButtonProps extends StyledButtonProps {
* @type React.ReactElement
*/
bottomIcon?: React.ReactElement;
/**
* The space between the button icon and label.
* @type SystemProps["marginRight"]
*/
iconSpacing?: string;
/**
* Replace the spinner component when `isLoading` is set to `true`
* @type React.ReactElement

View File

@ -13,9 +13,6 @@ export const Button = forwardStyledRef<HTMLButtonElement, ButtonProps>(
spinnerPlacement = 'start',
spinner,
loadingText,
iconSpacing,
topIcon,
bottomIcon,
rightIcon,
leftIcon,
isFullWidth,
@ -26,9 +23,6 @@ export const Button = forwardStyledRef<HTMLButtonElement, ButtonProps>(
const contentProps = {
rightIcon,
leftIcon,
bottomIcon,
topIcon,
iconSpacing,
children,
};
@ -40,16 +34,12 @@ export const Button = forwardStyledRef<HTMLButtonElement, ButtonProps>(
data-loading={isLoading}
css={{
width: isFullWidth ? '100%' : undefined,
...(ownProps?.css || {}),
...ownProps?.css,
}}
{...ownProps}
>
{isLoading && spinnerPlacement === 'start' && (
<ButtonSpinner
label={loadingText}
placement={spinnerPlacement}
spacing={iconSpacing}
>
<ButtonSpinner label={loadingText} placement={spinnerPlacement}>
{spinner}
</ButtonSpinner>
)}
@ -65,11 +55,7 @@ export const Button = forwardStyledRef<HTMLButtonElement, ButtonProps>(
)}
{isLoading && spinnerPlacement === 'end' && (
<ButtonSpinner
label={loadingText}
placement={spinnerPlacement}
spacing={iconSpacing}
>
<ButtonSpinner label={loadingText} placement={spinnerPlacement}>
{spinner}
</ButtonSpinner>
)}

View File

@ -8,7 +8,6 @@ type OmittedProps =
| 'isFullWidth'
| 'rightIcon'
| 'loadingText'
| 'iconSpacing'
| 'spinnerPlacement';
type BaseButtonProps = Omit<ButtonProps, OmittedProps>;

View File

@ -62,7 +62,7 @@ export const ColorPicker: React.FC<ColorPickerProps> = ({
</Button>
<input
ref={inputColorRef}
className="absolute right-16"
className="absolute right-16 h-5"
type="color"
value={logoColor}
onChange={handleColorChange}

View File

@ -1,3 +1,13 @@
import { styled } from '@/theme';
export const Text = styled('span');
export const Text = styled('span', {
variants: {
ellipsis: {
true: {
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
},
},
},
});

View File

@ -6,12 +6,17 @@ type RowDataProps = {
leftIcon: React.ReactNode;
label: string;
rightComponent: React.ReactNode;
onClick?: () => void;
};
export const RowData = forwardStyledRef<HTMLDivElement, RowDataProps>(
({ leftIcon, label, rightComponent, ...props }, ref) => {
({ leftIcon, label, rightComponent, onClick, ...props }, ref) => {
const handleOnClick = (): void => {
if (onClick) onClick();
};
return (
<S.Container ref={ref} {...props}>
<S.Container ref={ref} {...props} onClick={handleOnClick}>
<S.Text.Container>
{leftIcon}
<S.Text.Label>{label}</S.Text.Label>

View File

@ -0,0 +1,26 @@
import { Flex } from '@/components';
import { styled } from '@/theme';
export const StepStyles = {
Container: styled(Flex, {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
width: '$full',
gap: '$6',
'@media (min-width: 768px)': {
flexDirection: 'row',
justifyContent: 'center',
},
'@media (min-width: 1024px)': {
gap: '$34',
},
}),
Indicator: styled(Flex, {
flexDirection: 'column',
justifyContent: 'center',
maxWidth: '$106',
}),
};

View File

@ -1,37 +1,6 @@
import { Flex, Stepper } from '@/components';
import { Stepper } from '@/components';
type StepperIndicatorContainerProps = {
children: React.ReactNode;
};
const StepperIndicatorContainer: React.FC<StepperIndicatorContainerProps> = ({
children,
}: StepperIndicatorContainerProps) => {
return (
<Flex
css={{
flexDirection: 'column',
justifyContent: 'center',
mr: '$34',
width: '$106',
}}
>
{children}
</Flex>
);
};
type MintStepContainerProps = {
children: React.ReactNode;
};
const Container: React.FC<MintStepContainerProps> = ({
children,
}: MintStepContainerProps) => (
<Flex css={{ flexDirection: 'row', justifyContent: 'center' }}>
{children}
</Flex>
);
import { StepStyles as S } from './step.styles';
type StepProps = {
children: React.ReactNode;
@ -40,12 +9,12 @@ type StepProps = {
export const Step: React.FC<StepProps> = ({ children, header }: StepProps) => {
return (
<Container>
<StepperIndicatorContainer>
<S.Container>
<S.Indicator>
<Stepper.Indicator />
<h2 className="text-4xl">{header}</h2>
</StepperIndicatorContainer>
</S.Indicator>
{children}
</Container>
</S.Container>
);
};

View File

@ -10,6 +10,7 @@ export const themeGlobals = globalCss({
fontFamily: 'Manrope',
fontSize: '16px',
'@media (max-width: 850px)': {
fontSize: '13px',
},

View File

@ -6,7 +6,7 @@ export const CreateAccessPointForm: React.FC = () => {
const { prevStep } = Stepper.useContext();
return (
<Card.Container css={{ width: '$107h' }}>
<Card.Container css={{ maxWidth: '$107h' }}>
<Card.Heading
title="Enter Domain"
leftIcon={

View File

@ -5,7 +5,7 @@ import { APRecordCardHeader } from './ap-record-header';
export const APRecordStep: React.FC = () => {
return (
<Card.Container css={{ width: '$107h' }}>
<Card.Container css={{ maxWidth: '$107h' }}>
<APRecordCardHeader />
<APRecordCardBody />
</Card.Container>

View File

@ -111,7 +111,7 @@ export const CreateAccessPointPreview: React.FC = () => {
}, [writeStatus, transactionStatus]);
return (
<Card.Container css={{ width: '$107h' }}>
<Card.Container css={{ maxWidth: '$107h' }}>
<Card.Heading
title="Review Details"
leftIcon={

View File

@ -6,7 +6,7 @@ import { AccessPointDataFragment } from './create-ap-preview';
export const CreateAccessPointSuccess: React.FC = () => {
const { nfa } = CreateAccessPoint.useContext();
return (
<Card.Container css={{ width: '$107h' }}>
<Card.Container css={{ maxWidth: '$107h' }}>
<Card.Heading
title="Hosting Successful"
leftIcon={

View File

@ -0,0 +1,34 @@
import { Button, ButtonProps } from '@/components';
import { forwardStyledRef } from '@/theme';
import { Icon, IconName } from '../../components/core/icon';
type ButtonConnectionProps = {
icon: IconName;
label: string;
} & Omit<ButtonProps, 'rightIcon' | 'leftIcon'>;
export const ButtonConnection = forwardStyledRef<
HTMLButtonElement,
ButtonConnectionProps
>(({ icon, label, ...props }, ref) => {
return (
<Button
ref={ref}
{...props}
size="lg"
variant="ghost"
css={{
backgroundColor: '$slate4',
color: '$slate12',
justifyContent: 'space-between',
py: '$2h',
}}
rightIcon={
<Icon name={icon} css={{ color: 'white', fontSize: '$4xl' }} />
}
>
{label}
</Button>
);
});

View File

@ -1,7 +1,7 @@
import { useCallback, useEffect } from 'react';
import { Button, Icon } from '@/components';
import { githubActions, useAppDispatch, useGithubStore } from '@/store';
import { ButtonConnection } from '@/views/mint/button-connection';
import { Mint } from '@/views/mint/mint.context';
export const GithubButton: React.FC = () => {
@ -18,22 +18,11 @@ export const GithubButton: React.FC = () => {
}, [setGithubStep, state]);
return (
<Button
iconSpacing="59"
size="lg"
variant="ghost"
css={{
backgroundColor: '$slate4',
color: '$slate12',
py: '$2h',
}}
<ButtonConnection
icon={'github'}
label={'GitHub'}
onClick={handleGithubLogin}
disabled={state === 'loading'}
rightIcon={
<Icon name="github" css={{ color: 'white', fontSize: '$4xl' }} />
}
>
GitHub
</Button>
/>
);
};

View File

@ -7,13 +7,18 @@ export const GithubConnect: React.FC = () => {
const { prevStep } = Stepper.useContext();
return (
<Card.Container>
<Card.Container css={{ maxWidth: '$107h' }}>
<MintCardHeader title="Connect GitHub" onClickBack={prevStep} />
<Card.Body>
<Grid css={{ rowGap: '$6' }}>
<GithubButton />
<Card.Text
css={{ height: '$46h', width: '$95', fontSize: '$md', px: '$12' }}
css={{
height: '$46h',
maxWidth: '$95',
fontSize: '$md',
px: '$12',
}}
>
<span>
After connecting your GitHub, your repositories will show here.

View File

@ -0,0 +1,13 @@
import { Text } from '@/components';
import { styled } from '@/theme';
export const TextStyles = styled(Text, {
maxWidth: '12.5rem',
'@media (min-width: 375px)': {
maxWidth: '17rem',
},
'@media (min-width: 425px)': {
maxWidth: '18rem',
},
});

View File

@ -10,6 +10,7 @@ import {
import { AppLog } from '@/utils';
import { Mint } from '@/views/mint/mint.context';
import { useMintFormContext } from '@/views/mint/nfa-step/form-step';
import { TextStyles } from './repo-branch-commit-fields.styles';
export const RepoBranchCommitFields: React.FC = () => {
const { queryLoading, branches } = useGithubStore();
@ -105,12 +106,16 @@ export const RepoBranchCommitFields: React.FC = () => {
{(selected) => (
<>
<Icon name="branch" />
{selected?.name || 'Select a branch'}
<TextStyles ellipsis>
{selected?.name || 'Select a branch'}
</TextStyles>
</>
)}
</Field>
<Options>{(item) => item.name}</Options>
<Options>
{(item) => <TextStyles ellipsis>{item.name}</TextStyles>}
</Options>
</>
)}
</Form.Combobox>

View File

@ -5,7 +5,7 @@ import { RepoConfigurationHeader } from './repo-configuration-header';
export const GithubRepoConfiguration: React.FC = () => {
return (
<Card.Container css={{ width: '$107h' }}>
<Card.Container css={{ minWidth: '17rem', maxWidth: '$107h' }}>
<RepoConfigurationHeader />
<RepoConfigurationBody />
</Card.Container>

View File

@ -81,9 +81,10 @@ export const GithubRepositoryConnection: React.FC = () => {
<S.Container>
<S.Row>
<UserOrgsCombobox />
<InputGroup css={{ flex: 1 }}>
<InputGroup>
<S.Group.Icon name="search" />
<InputGroupText
css={{ overflow: 'hidden' }}
placeholder="Search repo"
onChange={handleSearchChange}
/>

View File

@ -30,11 +30,11 @@ export const Repository: React.FC<RepositoryProps> = ({
leftIcon={<Icon name="github" />}
label={repository.name}
css={{ cursor: 'pointer', my: '$4' }}
onClick={handleSelectRepo}
rightComponent={
<Button
colorScheme="blue"
variant="outline"
onClick={handleSelectRepo}
css={{ py: '$1', height: '$5', borderRadius: '$md' }}
>
Use for NFA

View File

@ -1,6 +1,6 @@
import { useEffect } from 'react';
import { Avatar, Combobox, Icon } from '@/components';
import { Avatar, Combobox, Icon, Text } from '@/components';
import {
githubActions,
GithubClient,
@ -21,7 +21,9 @@ const renderSelected = (selected?: GithubClient.UserData): JSX.Element => (
) : (
<Icon name="github" css={{ fontSize: '$2xl' }} />
)}
{selected?.label || 'Select'}
<Text ellipsis css={{ maxWidth: '60%' }}>
{selected?.label || 'Select'}
</Text>
</>
);
@ -75,7 +77,7 @@ export const UserOrgsCombobox: React.FC = () => {
<Combobox
items={userAndOrganizations}
unattached
css={{ flex: 1, minWidth: '$44' }}
css={{ width: '$full', flexGrow: 1 }}
selected={[selectedUserOrg, handleUserOrgChange]}
queryKey="label"
>

View File

@ -0,0 +1,13 @@
import { Flex } from '@/components';
import { styled } from '@/theme';
export const MintStyles = {
Container: styled(Flex, {
height: '100%',
justifyContent: 'center',
'@media (min-width: 1024px)': {
flexDirection: 'row',
},
}),
};

View File

@ -1,25 +1,17 @@
import { Flex } from '@/components';
import { Mint as MintContext } from './mint.context';
import { MintStyles as MS } from './mint.styles';
import { MintStepper } from './mint-stepper';
import { MintFormProvider, useMintFormContextInit } from './nfa-step/form-step';
export const Mint: React.FC = () => {
const context = useMintFormContextInit();
return (
<Flex
css={{
height: '100%',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<MS.Container>
<MintContext.Provider>
<MintFormProvider value={context}>
<MintStepper />
</MintFormProvider>
</MintContext.Provider>
</Flex>
</MS.Container>
);
};

View File

@ -78,7 +78,7 @@ export const MintFormStep: React.FC = () => {
};
return (
<Card.Container css={{ width: '$107h' }}>
<Card.Container css={{ maxWidth: '$107h' }}>
<MintCardHeader title="NFA Details" onClickBack={handlePrevStep} />
<Card.Body>
<Grid

View File

@ -100,7 +100,7 @@ export const VerifyNFAStep: React.FC = () => {
};
return (
<Card.Container css={{ width: '$107h' }}>
<Card.Container css={{ maxWidth: '$107h' }}>
<MintCardHeader title="Verify NFA" onClickBack={prevStep} />
<Card.Body>
<Flex css={{ flexDirection: 'column', gap: '$6' }}>

View File

@ -43,7 +43,7 @@ export const NftCard: React.FC<NftCardProps> = ({
} = useMintFormContext();
return (
<Card.Container css={{ width: '$107h', p: '$0' }}>
<Card.Container css={{ maxWidth: '$107h', p: '$0' }}>
<NFAPreview
color={logoColor}
logo={appLogo}

View File

@ -1,6 +1,8 @@
import { ConnectKitButton } from 'connectkit';
import { Button, Icon, Stepper } from '@/components';
import { Button, Stepper } from '@/components';
import { ButtonConnection } from '../button-connection';
export const ConnectWalletButton: React.FC = () => {
const { nextStep } = Stepper.useContext();
@ -11,31 +13,17 @@ export const ConnectWalletButton: React.FC = () => {
if (isConnected && address) {
return (
<Button onClick={nextStep} css={{ color: '$slate12' }}>
Connected address: {truncatedAddress}. Continue
{truncatedAddress}. Continue
</Button>
);
} else {
return (
<Button
<ButtonConnection
icon={'ethereum'}
label={' Connect Wallet'}
disabled={isConnected}
iconSpacing="44"
size="lg"
variant="ghost"
css={{
backgroundColor: '$slate4',
color: '$slate12',
py: '$2h',
}}
onClick={show}
rightIcon={
<Icon
name="ethereum"
css={{ color: 'white', fontSize: '$4xl' }}
/>
}
>
Connect Wallet
</Button>
/>
);
}
}}

View File

@ -4,7 +4,7 @@ import { ConnectWalletButton } from './connect-wallet-button';
export const WalletStep: React.FC = () => {
return (
<Card.Container>
<Card.Container css={{ maxWidth: '$107h' }}>
<Card.Heading
title="Connect Wallet"
rightIcon={
@ -20,7 +20,12 @@ export const WalletStep: React.FC = () => {
<Grid css={{ rowGap: '$6' }}>
<ConnectWalletButton />
<Card.Text
css={{ height: '$46h', width: '$95', fontSize: '$md', px: '$12' }}
css={{
height: '$46h',
maxWidth: '$95',
fontSize: '$md',
px: '$12',
}}
>
<span>Connect with the wallet you want to mint & own the NFA.</span>
</Card.Text>