Refactor: Move inline styles to styled components

This commit is contained in:
sahil-tgs 2024-07-17 00:00:36 +05:30
parent d61d4f4e11
commit 2f3a353a7e
6 changed files with 561 additions and 502 deletions

View File

@ -18,18 +18,6 @@ import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContex
const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter; const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter;
const MainContent = styled(Box)(({ theme }) => ({
marginTop: '100px',
marginBottom: '80px',
padding: theme.spacing(2),
overflowY: 'auto',
overflowX: 'hidden',
height: 'calc(100vh - 180px)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}));
const Main: React.FC = () => { const Main: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { settings, page, slideDirection, setOpen, windowSize } = const { settings, page, slideDirection, setOpen, windowSize } =
@ -130,4 +118,19 @@ const Main: React.FC = () => {
); );
}; };
// Styled components
const MainContent = styled(Box)(({ theme }) => ({
marginTop: '100px',
marginBottom: '80px',
padding: theme.spacing(2),
overflowY: 'auto',
overflowX: 'hidden',
height: 'calc(100vh - 180px)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}));
export default Main; export default Main;

View File

@ -5,9 +5,9 @@ import {
BottomNavigation, BottomNavigation,
BottomNavigationAction, BottomNavigationAction,
Paper, Paper,
styled,
useTheme, useTheme,
useMediaQuery, useMediaQuery,
styled,
} from '@mui/material'; } from '@mui/material';
import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined'; import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined';
import StorefrontOutlinedIcon from '@mui/icons-material/StorefrontOutlined'; import StorefrontOutlinedIcon from '@mui/icons-material/StorefrontOutlined';
@ -20,24 +20,6 @@ import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageCon
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext'; import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
import { type Page, isPage } from '.'; import { type Page, isPage } from '.';
const StyledBottomNavigation = styled(BottomNavigation)(({ theme }) => ({
width: '100%',
maxWidth: '100%',
padding: theme.spacing(0.5, 0),
borderRadius: 'inherit',
}));
const StyledBottomNavigationAction = styled(BottomNavigationAction)(({ theme }) => ({
minWidth: 'auto',
padding: theme.spacing(0.5, 0),
'& .MuiBottomNavigationAction-label': {
fontSize: '0.75rem',
},
'& .MuiSvgIcon-root': {
fontSize: '1.5rem',
},
}));
const NavBar = (): JSX.Element => { const NavBar = (): JSX.Element => {
const { t } = useTranslation(); const { t } = useTranslation();
const theme = useTheme(); const theme = useTheme();
@ -103,35 +85,7 @@ const NavBar = (): JSX.Element => {
}, [page, setOpen]); }, [page, setOpen]);
return ( return (
<Paper <StyledPaper elevation={isMobile ? 0 : 3} $isMobile={isMobile}>
sx={{
position: 'fixed',
bottom: 0,
left: 0,
right: 0,
zIndex: 1000,
...(isMobile
? {
boxShadow: 'none',
backgroundColor: theme.palette.background.paper,
borderTop: `2px solid black`,
borderRadius: '0',
}
: {
bottom: theme.spacing(2),
left: '50%',
transform: 'translateX(-50%)',
width: '95%',
maxWidth: 600,
borderRadius: '8px',
boxShadow: '8px 8px 0px 0px rgba(0,0,0,1)',
border: `2px solid black`,
backgroundColor: theme.palette.background.paper,
overflow: 'hidden',
}),
}}
elevation={isMobile ? 0 : 3}
>
<StyledBottomNavigation value={value} onChange={changePage} showLabels> <StyledBottomNavigation value={value} onChange={changePage} showLabels>
<StyledBottomNavigationAction <StyledBottomNavigationAction
label={t('Robot')} label={t('Robot')}
@ -160,8 +114,54 @@ const NavBar = (): JSX.Element => {
icon={<SettingsOutlinedIcon />} icon={<SettingsOutlinedIcon />}
/> />
</StyledBottomNavigation> </StyledBottomNavigation>
</Paper> </StyledPaper>
); );
}; };
// Styled components
const StyledPaper = styled(Paper)<{ $isMobile: boolean }>(({ theme, $isMobile }) => ({
position: 'fixed',
bottom: 0,
left: 0,
right: 0,
zIndex: 1000,
...($isMobile
? {
boxShadow: 'none',
backgroundColor: theme.palette.background.paper,
borderTop: `2px solid black`,
borderRadius: '0',
}
: {
bottom: theme.spacing(2),
left: '50%',
transform: 'translateX(-50%)',
width: '95%',
maxWidth: 600,
borderRadius: '8px',
boxShadow: '8px 8px 0px 0px rgba(0,0,0,1)',
border: `2px solid black`,
backgroundColor: theme.palette.background.paper,
overflow: 'hidden',
}),
}));
const StyledBottomNavigation = styled(BottomNavigation)(({ theme }) => ({
width: '100%',
maxWidth: '100%',
padding: theme.spacing(0.5, 0),
borderRadius: 'inherit',
}));
const StyledBottomNavigationAction = styled(BottomNavigationAction)(({ theme }) => ({
minWidth: 'auto',
padding: theme.spacing(0.5, 0),
'& .MuiBottomNavigationAction-label': {
fontSize: '0.75rem',
},
'& .MuiSvgIcon-root': {
fontSize: '1.5rem',
},
}));
export default NavBar; export default NavBar;

View File

@ -37,91 +37,12 @@ import { genBase62Token } from '../../utils';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext'; import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext'; import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
const StyledPaper = styled(Paper)(({ theme }) => ({ interface OnboardingProps {
backgroundColor: theme.palette.background.paper, setView: (view: string) => void;
boxShadow: '8px 8px 0px 0px rgba(0, 0, 0, 0.2)', inputToken: string;
borderRadius: '16px', setInputToken: (token: string) => void;
border: '2px solid #000', badToken: boolean;
padding: theme.spacing(2), getGenerateRobot: (token: string) => void;
color: theme.palette.text.primary,
width: '100%',
maxWidth: '500px',
margin: '0 auto',
}));
const StyledButton = styled(Button)(({ theme }) => ({
justifyContent: 'center',
textAlign: 'center',
padding: theme.spacing(1),
borderRadius: '8px',
border: '2px solid #000',
boxShadow: '4px 4px 0px 0px rgba(0, 0, 0, 0.2)',
textTransform: 'none',
fontWeight: 'bold',
width: '100%',
'&:hover': {
boxShadow: '6px 6px 0px 0px rgba(0, 0, 0, 0.3)',
},
}));
const StyledStepConnector = styled(StepConnector)(({ theme }) => ({
[`&.${stepConnectorClasses.alternativeLabel}`]: {
top: 22,
left: 'calc(-50% + 20px)',
right: 'calc(50% + 20px)',
},
[`&.${stepConnectorClasses.active}`]: {
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.primary.main,
},
},
[`&.${stepConnectorClasses.completed}`]: {
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.primary.main,
},
},
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.mode === 'dark' ? theme.palette.grey[800] : '#eaeaf0',
borderTopWidth: 3,
borderRadius: 1,
},
}));
const StyledStepIconRoot = styled('div')<{ ownerState: { active?: boolean; completed?: boolean } }>(
({ theme, ownerState }) => ({
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.grey[700] : '#ccc',
zIndex: 1,
color: '#fff',
width: 44,
height: 44,
display: 'flex',
borderRadius: '50%',
justifyContent: 'center',
alignItems: 'center',
...(ownerState.active && {
backgroundColor: theme.palette.primary.main,
boxShadow: '0 4px 10px 0 rgba(0,0,0,.25)',
}),
...(ownerState.completed && {
backgroundColor: theme.palette.primary.main,
}),
}),
);
function StyledStepIcon(props: StepIconProps) {
const { active, completed, className } = props;
const icons: { [index: string]: React.ReactElement } = {
1: <Casino />,
2: <SmartToy />,
3: <Storefront />,
};
return (
<StyledStepIconRoot ownerState={{ active, completed }} className={className}>
{icons[String(props.icon)]}
</StyledStepIconRoot>
);
} }
const Onboarding = ({ const Onboarding = ({
@ -161,17 +82,7 @@ const Onboarding = ({
]; ];
return ( return (
<Box <OnboardingContainer>
sx={{
mt: 3,
mb: 3,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
px: 2,
width: '100%',
}}
>
<Stepper <Stepper
alternativeLabel={!isMobile} alternativeLabel={!isMobile}
orientation={isMobile ? 'horizontal' : 'horizontal'} orientation={isMobile ? 'horizontal' : 'horizontal'}
@ -274,18 +185,13 @@ const Onboarding = ({
</Typography> </Typography>
{!slot?.hashId && <LinearProgress sx={{ mb: 2 }} />} {!slot?.hashId && <LinearProgress sx={{ mb: 2 }} />}
<Box display='flex' justifyContent='center' sx={{ mb: 2 }}> <Box display='flex' justifyContent='center' sx={{ mb: 2 }}>
<RobotAvatarContainer>
<RobotAvatar <RobotAvatar
hashId={slot?.hashId ?? ''} hashId={slot?.hashId ?? ''}
smooth={true} smooth={true}
style={{ width: '150px', height: '150px' }}
placeholderType='generating' placeholderType='generating'
imageStyle={{
border: '2px solid #555',
borderRadius: '50%',
boxShadow: '0 4px 10px rgba(0,0,0,0.3)',
}}
tooltipPosition='top'
/> />
</RobotAvatarContainer>
</Box> </Box>
{slot?.nickname && ( {slot?.nickname && (
<> <>
@ -293,11 +199,11 @@ const Onboarding = ({
{t('Hi! My name is')} {t('Hi! My name is')}
</Typography> </Typography>
<Typography variant='h6' align='center' sx={{ mt: 1, mb: 2 }}> <Typography variant='h6' align='center' sx={{ mt: 1, mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <NicknameContainer>
<SmartToy sx={{ color: '#fcba03', fontSize: '1.2em', mr: 1 }} /> <SmartToy sx={{ color: '#fcba03', fontSize: '1.2em', mr: 1 }} />
<strong>{slot.nickname}</strong> <strong>{slot.nickname}</strong>
<SmartToy sx={{ color: '#fcba03', fontSize: '1.2em', ml: 1 }} /> <SmartToy sx={{ color: '#fcba03', fontSize: '1.2em', ml: 1 }} />
</Box> </NicknameContainer>
</Typography> </Typography>
</> </>
)} )}
@ -315,7 +221,6 @@ const Onboarding = ({
</Box> </Box>
</> </>
)} )}
{step === '3' && ( {step === '3' && (
<> <>
<Typography variant='h6' gutterBottom align='center'> <Typography variant='h6' gutterBottom align='center'>
@ -382,8 +287,122 @@ const Onboarding = ({
</> </>
)} )}
</StyledPaper> </StyledPaper>
</Box> </OnboardingContainer>
); );
}; };
// Styled components
const StyledPaper = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
boxShadow: '8px 8px 0px 0px rgba(0, 0, 0, 0.2)',
borderRadius: '16px',
border: '2px solid #000',
padding: theme.spacing(2),
color: theme.palette.text.primary,
width: '100%',
maxWidth: '500px',
margin: '0 auto',
}));
const StyledButton = styled(Button)(({ theme }) => ({
justifyContent: 'center',
textAlign: 'center',
padding: theme.spacing(1),
borderRadius: '8px',
border: '2px solid #000',
boxShadow: '4px 4px 0px 0px rgba(0, 0, 0, 0.2)',
textTransform: 'none',
fontWeight: 'bold',
width: '100%',
'&:hover': {
boxShadow: '6px 6px 0px 0px rgba(0, 0, 0, 0.3)',
},
}));
const OnboardingContainer = styled(Box)(({ theme }) => ({
marginTop: theme.spacing(3),
marginBottom: theme.spacing(3),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
width: '100%',
}));
const RobotAvatarContainer = styled(Box)(({ theme }) => ({
width: '150px',
height: '150px',
border: '2px solid #555',
borderRadius: '50%',
boxShadow: '0 4px 10px rgba(0,0,0,0.3)',
}));
const NicknameContainer = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}));
const StyledStepConnector = styled(StepConnector)(({ theme }) => ({
[`&.${stepConnectorClasses.alternativeLabel}`]: {
top: 22,
left: 'calc(-50% + 20px)',
right: 'calc(50% + 20px)',
},
[`&.${stepConnectorClasses.active}`]: {
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.primary.main,
},
},
[`&.${stepConnectorClasses.completed}`]: {
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.primary.main,
},
},
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.mode === 'dark' ? theme.palette.grey[800] : '#eaeaf0',
borderTopWidth: 3,
borderRadius: 1,
},
}));
const StyledStepIconRoot = styled('div')<{ ownerState: { active?: boolean; completed?: boolean } }>(
({ theme, ownerState }) => ({
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.grey[700] : '#ccc',
zIndex: 1,
color: '#fff',
width: 44,
height: 44,
display: 'flex',
borderRadius: '50%',
justifyContent: 'center',
alignItems: 'center',
...(ownerState.active && {
backgroundColor: theme.palette.primary.main,
boxShadow: '0 4px 10px 0 rgba(0,0,0,.25)',
}),
...(ownerState.completed && {
backgroundColor: theme.palette.primary.main,
}),
}),
);
function StyledStepIcon(props: StepIconProps) {
const { active, completed, className } = props;
const icons: { [index: string]: React.ReactElement } = {
1: <Casino />,
2: <SmartToy />,
3: <Storefront />,
};
return (
<StyledStepIconRoot ownerState={{ active, completed }} className={className}>
{icons[String(props.icon)]}
</StyledStepIconRoot>
);
}
export default Onboarding; export default Onboarding;

View File

@ -27,140 +27,67 @@ const Welcome = ({ setView, getGenerateRobot, width }: WelcomeProps): JSX.Elemen
shadow: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', shadow: theme.palette.mode === 'dark' ? '#ffffff' : '#000000',
}; };
const StyledButton = styled(Button)(({ theme }) => ({
justifyContent: 'space-between',
textAlign: 'left',
padding: theme.spacing(2),
height: '100%',
borderRadius: 0,
border: `2px solid ${theme.palette.mode === 'dark' ? '#ffffff' : '#000000'}`,
boxShadow: `8px 8px 0px 0px ${COLORS.shadow}`,
'&:not(:last-child)': {
borderBottom: 'none',
},
'&:hover': {
boxShadow: `12px 12px 0px 0px ${COLORS.shadow}`,
},
}));
return ( return (
<Box <WelcomeContainer>
sx={{ <LogoSection colors={COLORS}>
width: '100%',
maxWidth: 800,
mx: 'auto',
display: 'flex',
flexDirection: { xs: 'column', md: 'row' },
mb: 8,
}}
>
<Box
sx={{
flexGrow: 1,
flexBasis: 0,
bgcolor: COLORS.background,
border: `2px solid ${COLORS.textPrimary}`,
borderRight: 'none',
borderRadius: { xs: '8px 8px 0 0', md: '8px 0 0 8px' },
boxShadow: `8px 8px 0px 0px ${COLORS.shadow}`,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
p: 4,
}}
>
<svg width={0} height={0}> <svg width={0} height={0}>
<linearGradient id='linearColors' x1={1} y1={0} x2={1} y2={1}> <linearGradient id='linearColors' x1={1} y1={0} x2={1} y2={1}>
<stop offset={0} stopColor={theme.palette.primary.main} /> <stop offset={0} stopColor={theme.palette.primary.main} />
<stop offset={1} stopColor={theme.palette.secondary.main} /> <stop offset={1} stopColor={theme.palette.secondary.main} />
</linearGradient> </linearGradient>
</svg> </svg>
<Box sx={{ width: '80%', maxWidth: '400px', height: 'auto' }}> <LogoBox>
<RoboSatsTextIcon <StyledRoboSatsTextIcon />
sx={{ </LogoBox>
fill: 'url(#linearColors)',
width: '100%',
height: 'auto',
}}
/>
</Box>
<Typography variant='subtitle1' sx={{ fontSize: '1rem', mt: 2, textAlign: 'center' }}> <Typography variant='subtitle1' sx={{ fontSize: '1rem', mt: 2, textAlign: 'center' }}>
A Simple and Private Lightning P2P Exchange A Simple and Private Lightning P2P Exchange
</Typography> </Typography>
</Box> </LogoSection>
<Box <ButtonsSection>
sx={{
flexGrow: 1,
flexBasis: 0,
display: 'flex',
flexDirection: 'column',
bgcolor: 'transparent',
}}
>
<StyledButton <StyledButton
fullWidth fullWidth
variant='contained' variant='contained'
sx={{ $buttonColor={BUTTON_COLORS.primary}
bgcolor: BUTTON_COLORS.primary, $textColor={BUTTON_COLORS.text}
color: BUTTON_COLORS.text, $shadowColor={COLORS.shadow}
borderRadius: { xs: '0', md: '0 8px 0 0' }, $borderRadius={{ xs: '0', md: '0 8px 0 0' }}
'&:hover': {
backgroundColor: BUTTON_COLORS.primary,
boxShadow: `12px 12px 0px 0px ${COLORS.shadow}`,
},
}}
endIcon={<ArrowForwardIcon />} endIcon={<ArrowForwardIcon />}
onClick={() => { onClick={() => setView('onboarding')}
setView('onboarding');
}}
> >
<Box> <ButtonContent>
<Typography variant='body2'>Create a new robot and</Typography> <Typography variant='body2'>Create a new robot and</Typography>
<Typography variant='body2'>learn to use RoboSats.</Typography> <Typography variant='body2'>learn to use RoboSats.</Typography>
<Typography variant='h6' sx={{ mt: 1, fontWeight: 'bold' }}> <Typography variant='h6' sx={{ mt: 1, fontWeight: 'bold' }}>
Start Start
</Typography> </Typography>
</Box> </ButtonContent>
</StyledButton> </StyledButton>
<StyledButton <StyledButton
fullWidth fullWidth
variant='contained' variant='contained'
sx={{ $buttonColor={BUTTON_COLORS.secondary}
bgcolor: BUTTON_COLORS.secondary, $textColor={BUTTON_COLORS.text}
color: BUTTON_COLORS.text, $shadowColor={COLORS.shadow}
borderRadius: { xs: '0', md: '0' }, $borderRadius={{ xs: '0', md: '0' }}
'&:hover': {
backgroundColor: BUTTON_COLORS.secondary,
boxShadow: `12px 12px 0px 0px ${COLORS.shadow}`,
},
}}
endIcon={<ArrowForwardIcon />} endIcon={<ArrowForwardIcon />}
onClick={() => { onClick={() => setView('recovery')}
setView('recovery');
}}
> >
<Box> <ButtonContent>
<Typography variant='body2'>Recover an existing</Typography> <Typography variant='body2'>Recover an existing</Typography>
<Typography variant='body2'>Robot using your token.</Typography> <Typography variant='body2'>Robot using your token.</Typography>
<Typography variant='h6' sx={{ mt: 1, fontWeight: 'bold' }}> <Typography variant='h6' sx={{ mt: 1, fontWeight: 'bold' }}>
Recover Recover
</Typography> </Typography>
</Box> </ButtonContent>
</StyledButton> </StyledButton>
<StyledButton <StyledButton
fullWidth fullWidth
variant='contained' variant='contained'
sx={{ $buttonColor={COLORS.background}
bgcolor: COLORS.background, $textColor={BUTTON_COLORS.primary}
color: BUTTON_COLORS.primary, $shadowColor={COLORS.shadow}
borderRadius: { xs: '0 0 8px 8px', md: '0 0 8px 0' }, $borderRadius={{ xs: '0 0 8px 8px', md: '0 0 8px 0' }}
'&:hover': { sx={{ justifyContent: 'flex-start' }}
backgroundColor: COLORS.background,
boxShadow: `12px 12px 0px 0px ${COLORS.shadow}`,
},
justifyContent: 'flex-start',
}}
onClick={() => { onClick={() => {
setView('profile'); setView('profile');
getGenerateRobot(genBase62Token(36)); getGenerateRobot(genBase62Token(36));
@ -170,9 +97,93 @@ const Welcome = ({ setView, getGenerateRobot, width }: WelcomeProps): JSX.Elemen
Fast Generate Robot Fast Generate Robot
</Typography> </Typography>
</StyledButton> </StyledButton>
</Box> </ButtonsSection>
</Box> </WelcomeContainer>
); );
}; };
// Styled components
const WelcomeContainer = styled(Box)(({ theme }) => ({
width: '100%',
maxWidth: 800,
margin: '0 auto',
display: 'flex',
flexDirection: 'column',
marginBottom: theme.spacing(8),
[theme.breakpoints.up('md')]: {
flexDirection: 'row',
},
}));
const LogoSection = styled(Box)<{ colors: typeof COLORS }>(({ theme, colors }) => ({
flexGrow: 1,
flexBasis: 0,
backgroundColor: colors.background,
border: `2px solid ${colors.textPrimary}`,
borderRight: 'none',
borderRadius: '8px 8px 0 0',
boxShadow: `8px 8px 0px 0px ${colors.shadow}`,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
padding: theme.spacing(4),
[theme.breakpoints.up('md')]: {
borderRadius: '8px 0 0 8px',
},
}));
const LogoBox = styled(Box)({
width: '80%',
maxWidth: '400px',
height: 'auto',
});
const StyledRoboSatsTextIcon = styled(RoboSatsTextIcon)({
fill: 'url(#linearColors)',
width: '100%',
height: 'auto',
});
const ButtonsSection = styled(Box)(({ theme }) => ({
flexGrow: 1,
flexBasis: 0,
display: 'flex',
flexDirection: 'column',
backgroundColor: 'transparent',
}));
const StyledButton = styled(Button)<{
$buttonColor: string;
$textColor: string;
$shadowColor: string;
$borderRadius: { xs: string; md: string };
}>(({ theme, $buttonColor, $textColor, $shadowColor, $borderRadius }) => ({
justifyContent: 'space-between',
textAlign: 'left',
padding: theme.spacing(2),
height: '100%',
borderRadius: 0,
border: `2px solid ${theme.palette.mode === 'dark' ? '#ffffff' : '#000000'}`,
boxShadow: `8px 8px 0px 0px ${$shadowColor}`,
'&:not(:last-child)': {
borderBottom: 'none',
},
'&:hover': {
backgroundColor: $buttonColor,
boxShadow: `12px 12px 0px 0px ${$shadowColor}`,
},
backgroundColor: $buttonColor,
color: $textColor,
borderRadius: $borderRadius.xs,
[theme.breakpoints.up('md')]: {
borderRadius: $borderRadius.md,
},
}));
const ButtonContent = styled(Box)({
display: 'flex',
flexDirection: 'column',
});
export default Welcome; export default Welcome;

View File

@ -9,6 +9,7 @@ import {
Typography, Typography,
useTheme, useTheme,
AlertTitle, AlertTitle,
styled,
} from '@mui/material'; } from '@mui/material';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
@ -85,12 +86,7 @@ const RobotPage = (): JSX.Element => {
if (settings.useProxy && !(window.NativeRobosats === undefined) && !(torStatus === 'ON')) { if (settings.useProxy && !(window.NativeRobosats === undefined) && !(torStatus === 'ON')) {
return ( return (
<Box <StyledConnectingBox>
sx={{
width: '100vw',
height: 'auto',
}}
>
<Grid container direction='column' alignItems='center' spacing={1} padding={2}> <Grid container direction='column' alignItems='center' spacing={1} padding={2}>
<Grid item> <Grid item>
<Typography align='center' variant='h6'> <Typography align='center' variant='h6'>
@ -105,8 +101,8 @@ const RobotPage = (): JSX.Element => {
<stop offset={1} stopColor={theme.palette.secondary.main} /> <stop offset={1} stopColor={theme.palette.secondary.main} />
</linearGradient> </linearGradient>
</svg> </svg>
<CircularProgress thickness={3} style={{ width: '11.2em', height: '11.2em' }} /> <CircularProgress thickness={3} sx={{ width: '11.2em', height: '11.2em' }} />
<Box sx={{ position: 'fixed', top: '4.6em' }}> <StyledTorIconBox>
<TorIcon <TorIcon
sx={{ sx={{
fill: 'url(#linearColors)', fill: 'url(#linearColors)',
@ -116,7 +112,7 @@ const RobotPage = (): JSX.Element => {
left: '0.7em', left: '0.7em',
}} }}
/> />
</Box> </StyledTorIconBox>
</Box> </Box>
</Grid> </Grid>
<Grid item> <Grid item>
@ -128,23 +124,73 @@ const RobotPage = (): JSX.Element => {
</Alert> </Alert>
</Grid> </Grid>
</Grid> </Grid>
</Box> </StyledConnectingBox>
); );
} else { } else {
return ( return (
<Box <StyledMainBox>
sx={{ <StyledPaper>
{view === 'welcome' && (
<Welcome setView={setView} getGenerateRobot={getGenerateRobot} width={1200} />
)}
{view === 'onboarding' && (
<Onboarding
setView={setView}
badToken={badToken}
inputToken={inputToken}
setInputToken={setInputToken}
getGenerateRobot={getGenerateRobot}
/>
)}
{view === 'profile' && (
<RobotProfile
setView={setView}
logoutRobot={logoutRobot}
width={1200}
inputToken={inputToken}
setInputToken={setInputToken}
getGenerateRobot={getGenerateRobot}
/>
)}
{view === 'recovery' && (
<Recovery
setView={setView}
badToken={badToken}
inputToken={inputToken}
setInputToken={setInputToken}
getRecoverRobot={getGenerateRobot}
/>
)}
</StyledPaper>
</StyledMainBox>
);
}
};
// Styled components
const StyledConnectingBox = styled(Box)({
width: '100vw',
height: 'auto',
});
const StyledTorIconBox = styled(Box)({
position: 'fixed',
top: '4.6em',
});
const StyledMainBox = styled(Box)({
width: '100vw', width: '100vw',
height: 'auto', height: 'auto',
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
padding: '2em', padding: '2em',
}} });
>
<Paper const StyledPaper = styled(Paper)(({ theme }) => ({
elevation={0}
sx={{
width: '80vw', width: '80vw',
maxWidth: '1200px', maxWidth: '1200px',
maxHeight: '85vh', maxHeight: '85vh',
@ -154,46 +200,6 @@ const RobotPage = (): JSX.Element => {
border: 'none', border: 'none',
boxShadow: 'none', boxShadow: 'none',
padding: '1em', padding: '1em',
}} }));
>
{view === 'welcome' ? (
<Welcome setView={setView} getGenerateRobot={getGenerateRobot} width={1200} />
) : null}
{view === 'onboarding' ? (
<Onboarding
setView={setView}
badToken={badToken}
inputToken={inputToken}
setInputToken={setInputToken}
getGenerateRobot={getGenerateRobot}
/>
) : null}
{view === 'profile' ? (
<RobotProfile
setView={setView}
logoutRobot={logoutRobot}
width={1200}
inputToken={inputToken}
setInputToken={setInputToken}
getGenerateRobot={getGenerateRobot}
/>
) : null}
{view === 'recovery' ? (
<Recovery
setView={setView}
badToken={badToken}
inputToken={inputToken}
setInputToken={setInputToken}
getRecoverRobot={getGenerateRobot}
/>
) : null}
</Paper>
</Box>
);
}
};
export default RobotPage; export default RobotPage;

View File

@ -23,30 +23,166 @@ import RobotAvatar from '../../components/RobotAvatar';
import { RoboSatsTextIcon } from '../../components/Icons'; import { RoboSatsTextIcon } from '../../components/Icons';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
const TopNavBar = (): JSX.Element => {
const theme = useTheme();
const { t } = useTranslation();
const { setOpen, open } = useContext<UseAppStoreType>(AppContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [drawerOpen, setDrawerOpen] = useState(false);
const slot = garage.getSlot();
const navItems = [
{ label: 'Robosats Info', key: 'info' },
{ label: 'Learn Robosats', key: 'learn' },
{ label: 'Community', key: 'community' },
{ label: 'Exchange Summary', key: 'exchange' },
];
const toggleDrawer = (open: boolean) => () => {
setDrawerOpen(open);
};
const handleLogoClick = () => {
setOpen({ ...closeAll, client: !open.client });
};
return (
<>
<StyledAppBar
position='fixed'
elevation={drawerOpen ? 0 : 3}
$isMobile={isMobile}
$drawerOpen={drawerOpen}
>
<StyledToolbar>
<svg width={0} height={0}>
<linearGradient id='linearColors' x1={1} y1={0} x2={1} y2={1}>
<stop offset={0} stopColor={theme.palette.primary.main} />
<stop offset={1} stopColor={theme.palette.secondary.main} />
</linearGradient>
</svg>
{isMobile ? (
<>
<IconButton edge='start' aria-label='menu' onClick={toggleDrawer(true)}>
{drawerOpen ? (
<StyledIcon as={CloseIcon} $isDark={theme.palette.mode === 'dark'} />
) : (
<StyledIcon as={MenuIcon} $isDark={theme.palette.mode === 'dark'} />
)}
</IconButton>
<MobileToolbarContent>
<IconButton
edge='end'
onClick={() => {
setOpen({ ...closeAll, profile: !open.profile });
}}
style={{ visibility: slot?.hashId ? 'visible' : 'hidden' }}
>
{slot?.hashId ? (
<StyledRobotAvatar
avatarClass={
theme.palette.mode === 'dark' ? 'navBarAvatarDark' : 'navBarAvatar'
}
hashId={slot?.hashId}
/>
) : (
<StyledAccountIcon />
)}
</IconButton>
</MobileToolbarContent>
<StyledDrawer
anchor='left'
open={drawerOpen}
onClose={toggleDrawer(false)}
BackdropProps={{ invisible: true }}
>
<List>
<StyledLogoListItem button onClick={handleLogoClick}>
<StyledDrawerRoboSatsTextIcon />
</StyledLogoListItem>
<Divider />
{navItems.map((item) => (
<StyledListItem
button
key={item.key}
onClick={() => setOpen({ ...closeAll, [item.key]: !open[item.key] })}
>
<ListItemText primary={t(item.label)} />
</StyledListItem>
))}
</List>
</StyledDrawer>
</>
) : (
<>
<StyledDesktopRoboSatsTextIcon onClick={handleLogoClick} />
<CenterBox>
{navItems.map((item) => (
<CenterButton
key={item.key}
onClick={() => setOpen({ ...closeAll, [item.key]: !open[item.key] })}
>
{t(item.label)}
</CenterButton>
))}
</CenterBox>
<IconButton
edge='end'
onClick={() => {
setOpen({ ...closeAll, profile: !open.profile });
}}
style={{ visibility: slot?.hashId ? 'visible' : 'hidden' }}
>
{slot?.hashId ? (
<StyledRobotAvatar
avatarClass={
theme.palette.mode === 'dark' ? 'navBarAvatarDark' : 'navBarAvatar'
}
hashId={slot?.hashId}
/>
) : (
<StyledAccountIcon />
)}
</IconButton>
</>
)}
</StyledToolbar>
</StyledAppBar>
</>
);
};
// Styled components
const NAVBAR_HEIGHT = '64px'; const NAVBAR_HEIGHT = '64px';
const StyledAppBar = styled(AppBar)(({ theme, isMobile, drawerOpen }) => ({ const StyledAppBar = styled(AppBar)<{ $isMobile: boolean; $drawerOpen: boolean }>(
({ theme, $isMobile, $drawerOpen }) => ({
height: NAVBAR_HEIGHT, height: NAVBAR_HEIGHT,
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
boxShadow: isMobile ? 'none' : '8px 8px 0px 0px rgba(0,0,0,1)', boxShadow: $isMobile ? 'none' : '8px 8px 0px 0px rgba(0,0,0,1)',
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
borderBottom: isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '', borderBottom: $isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
border: !isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '', border: !$isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
borderRadius: isMobile ? '0' : '1vw', borderRadius: $isMobile ? '0' : '1vw',
padding: isMobile ? '0' : '1vh', padding: $isMobile ? '0' : '1vh',
top: isMobile ? 0 : theme.spacing(2), top: $isMobile ? 0 : theme.spacing(2),
left: '50%', left: '50%',
transform: 'translateX(-50%)', transform: 'translateX(-50%)',
width: isMobile ? '100%' : 'calc(100% - 64px)', width: $isMobile ? '100%' : 'calc(100% - 64px)',
position: 'fixed', position: 'fixed',
zIndex: 1100, zIndex: 1100,
...(drawerOpen && ...($drawerOpen &&
isMobile && { $isMobile && {
background: 'none', background: 'none',
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
}), }),
})); })
);
const StyledToolbar = styled(Toolbar)(({ theme }) => ({ const StyledToolbar = styled(Toolbar)(({ theme }) => ({
display: 'flex', display: 'flex',
@ -81,170 +217,54 @@ const MobileToolbarContent = styled(Box)(({ theme }) => ({
marginLeft: theme.spacing(2), marginLeft: theme.spacing(2),
})); }));
const TopNavBar = (): JSX.Element => { const StyledIcon = styled('svg')<{ $isDark: boolean }>(({ $isDark }) => ({
const theme = useTheme(); color: $isDark ? '#fff' : '#000',
const { t } = useTranslation(); }));
const { setOpen, open } = useContext<UseAppStoreType>(AppContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [drawerOpen, setDrawerOpen] = useState(false); const StyledRobotAvatar = styled(RobotAvatar)({
width: '2.5em',
height: '2.5em',
});
const slot = garage.getSlot(); const StyledAccountIcon = styled(AccountCircleIcon)({
fontSize: '1.5em',
});
const navItems = [ const StyledDrawer = styled(Drawer)(({ theme }) => ({
{ label: 'Robosats Info', key: 'info' }, '& .MuiDrawer-paper': {
{ label: 'Learn Robosats', key: 'learn' },
{ label: 'Community', key: 'community' },
{ label: 'Exchange Summary', key: 'exchange' },
];
const toggleDrawer = (open: boolean) => () => {
setDrawerOpen(open);
};
const handleLogoClick = () => {
setOpen({ ...closeAll, client: !open.client });
};
return (
<>
<StyledAppBar
position='fixed'
elevation={drawerOpen ? 0 : 3}
isMobile={isMobile}
drawerOpen={drawerOpen}
>
<StyledToolbar>
<svg width={0} height={0}>
<linearGradient id='linearColors' x1={1} y1={0} x2={1} y2={1}>
<stop offset={0} stopColor={theme.palette.primary.main} />
<stop offset={1} stopColor={theme.palette.secondary.main} />
</linearGradient>
</svg>
{isMobile ? (
<>
<IconButton edge='start' aria-label='menu' onClick={toggleDrawer(true)}>
{drawerOpen ? (
<CloseIcon style={{ color: theme.palette.mode === 'dark' ? '#fff' : '#000' }} />
) : (
<MenuIcon style={{ color: theme.palette.mode === 'dark' ? '#fff' : '#000' }} />
)}
</IconButton>
<MobileToolbarContent>
<IconButton
edge='end'
onClick={() => {
setOpen({ ...closeAll, profile: !open.profile });
}}
style={{ visibility: slot?.hashId ? 'visible' : 'hidden' }}
>
{slot?.hashId ? (
<RobotAvatar
style={{ width: '2.5em', height: '2.5em' }}
avatarClass={
theme.palette.mode === 'dark' ? 'navBarAvatarDark' : 'navBarAvatar'
}
hashId={slot?.hashId}
/>
) : (
<AccountCircleIcon style={{ fontSize: '1.5em' }} />
)}
</IconButton>
</MobileToolbarContent>
<Drawer
anchor='left'
open={drawerOpen}
onClose={toggleDrawer(false)}
BackdropProps={{ invisible: true }}
PaperProps={{
style: {
marginTop: NAVBAR_HEIGHT, marginTop: NAVBAR_HEIGHT,
borderLeft: '2px solid black', borderLeft: '2px solid black',
borderRight: '2px solid black', borderRight: '2px solid black',
borderBottom: '2px solid black', borderBottom: '2px solid black',
width: '100%',
maxWidth: '300px',
}, },
}} }));
>
<List> const StyledListItem = styled(ListItem)(({ theme }) => ({
<ListItem borderBottom: `1px solid ${theme.palette.divider}`,
button padding: theme.spacing(2),
onClick={handleLogoClick} }));
sx={{ borderBottom: '1px solid black' }}
> const StyledLogoListItem = styled(ListItem)(({ theme }) => ({
<RoboSatsTextIcon borderBottom: `1px solid ${theme.palette.divider}`,
sx={{ padding: theme.spacing(2),
justifyContent: 'center',
}));
const StyledDesktopRoboSatsTextIcon = styled(RoboSatsTextIcon)(({ theme }) => ({
height: '1.5em',
width: 'auto',
cursor: 'pointer',
marginLeft: theme.spacing(-1),
fill: 'url(#linearColors)',
}));
const StyledDrawerRoboSatsTextIcon = styled(RoboSatsTextIcon)(({ theme }) => ({
height: '2em', height: '2em',
width: 'auto', width: 'auto',
cursor: 'pointer', cursor: 'pointer',
fill: 'url(#linearColors)', fill: 'url(#linearColors)',
}} }));
/>
</ListItem>
<Divider />
{navItems.map((item) => (
<ListItem
button
key={item.key}
onClick={() => setOpen({ ...closeAll, [item.key]: !open[item.key] })}
sx={{
borderBottom: `1px solid ${theme.palette.divider}`,
padding: theme.spacing(2),
}}
>
<ListItemText primary={t(item.label)} />
</ListItem>
))}
</List>
</Drawer>
</>
) : (
<>
<RoboSatsTextIcon
sx={{
height: '1.5em',
width: 'auto',
cursor: 'pointer',
marginLeft: -2,
fill: 'url(#linearColors)',
}}
onClick={handleLogoClick}
/>
<CenterBox>
{navItems.map((item) => (
<CenterButton
key={item.key}
onClick={() => setOpen({ ...closeAll, [item.key]: !open[item.key] })}
>
{t(item.label)}
</CenterButton>
))}
</CenterBox>
<IconButton
edge='end'
onClick={() => {
setOpen({ ...closeAll, profile: !open.profile });
}}
style={{ visibility: slot?.hashId ? 'visible' : 'hidden' }}
>
{slot?.hashId ? (
<RobotAvatar
style={{ width: '2.5em', height: '2.5em' }}
avatarClass={
theme.palette.mode === 'dark' ? 'navBarAvatarDark' : 'navBarAvatar'
}
hashId={slot?.hashId}
/>
) : (
<AccountCircleIcon style={{ fontSize: '1.5em' }} />
)}
</IconButton>
</>
)}
</StyledToolbar>
</StyledAppBar>
</>
);
};
export default TopNavBar; export default TopNavBar;