Refactor: Move inline styles to styled components

This commit is contained in:
sahil-tgs 2024-07-17 00:00:36 +05:30 committed by Reckless_Satoshi
parent e8d53c9bf9
commit 6fc5f906dc
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 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 { t } = useTranslation();
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;

View File

@ -5,9 +5,9 @@ import {
BottomNavigation,
BottomNavigationAction,
Paper,
styled,
useTheme,
useMediaQuery,
styled,
} from '@mui/material';
import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined';
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 { 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 { t } = useTranslation();
const theme = useTheme();
@ -103,35 +85,7 @@ const NavBar = (): JSX.Element => {
}, [page, setOpen]);
return (
<Paper
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}
>
<StyledPaper elevation={isMobile ? 0 : 3} $isMobile={isMobile}>
<StyledBottomNavigation value={value} onChange={changePage} showLabels>
<StyledBottomNavigationAction
label={t('Robot')}
@ -160,8 +114,54 @@ const NavBar = (): JSX.Element => {
icon={<SettingsOutlinedIcon />}
/>
</StyledBottomNavigation>
</Paper>
</StyledPaper>
);
};
export default NavBar;
// 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;

View File

@ -37,91 +37,12 @@ import { genBase62Token } from '../../utils';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
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 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>
);
interface OnboardingProps {
setView: (view: string) => void;
inputToken: string;
setInputToken: (token: string) => void;
badToken: boolean;
getGenerateRobot: (token: string) => void;
}
const Onboarding = ({
@ -161,17 +82,7 @@ const Onboarding = ({
];
return (
<Box
sx={{
mt: 3,
mb: 3,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
px: 2,
width: '100%',
}}
>
<OnboardingContainer>
<Stepper
alternativeLabel={!isMobile}
orientation={isMobile ? 'horizontal' : 'horizontal'}
@ -274,18 +185,13 @@ const Onboarding = ({
</Typography>
{!slot?.hashId && <LinearProgress sx={{ mb: 2 }} />}
<Box display='flex' justifyContent='center' sx={{ mb: 2 }}>
<RobotAvatar
hashId={slot?.hashId ?? ''}
smooth={true}
style={{ width: '150px', height: '150px' }}
placeholderType='generating'
imageStyle={{
border: '2px solid #555',
borderRadius: '50%',
boxShadow: '0 4px 10px rgba(0,0,0,0.3)',
}}
tooltipPosition='top'
/>
<RobotAvatarContainer>
<RobotAvatar
hashId={slot?.hashId ?? ''}
smooth={true}
placeholderType='generating'
/>
</RobotAvatarContainer>
</Box>
{slot?.nickname && (
<>
@ -293,11 +199,11 @@ const Onboarding = ({
{t('Hi! My name is')}
</Typography>
<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 }} />
<strong>{slot.nickname}</strong>
<SmartToy sx={{ color: '#fcba03', fontSize: '1.2em', ml: 1 }} />
</Box>
</NicknameContainer>
</Typography>
</>
)}
@ -315,7 +221,6 @@ const Onboarding = ({
</Box>
</>
)}
{step === '3' && (
<>
<Typography variant='h6' gutterBottom align='center'>
@ -382,8 +287,122 @@ const Onboarding = ({
</>
)}
</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;

View File

@ -27,140 +27,67 @@ const Welcome = ({ setView, getGenerateRobot, width }: WelcomeProps): JSX.Elemen
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 (
<Box
sx={{
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,
}}
>
<WelcomeContainer>
<LogoSection colors={COLORS}>
<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>
<Box sx={{ width: '80%', maxWidth: '400px', height: 'auto' }}>
<RoboSatsTextIcon
sx={{
fill: 'url(#linearColors)',
width: '100%',
height: 'auto',
}}
/>
</Box>
<LogoBox>
<StyledRoboSatsTextIcon />
</LogoBox>
<Typography variant='subtitle1' sx={{ fontSize: '1rem', mt: 2, textAlign: 'center' }}>
A Simple and Private Lightning P2P Exchange
</Typography>
</Box>
<Box
sx={{
flexGrow: 1,
flexBasis: 0,
display: 'flex',
flexDirection: 'column',
bgcolor: 'transparent',
}}
>
</LogoSection>
<ButtonsSection>
<StyledButton
fullWidth
variant='contained'
sx={{
bgcolor: BUTTON_COLORS.primary,
color: BUTTON_COLORS.text,
borderRadius: { xs: '0', md: '0 8px 0 0' },
'&:hover': {
backgroundColor: BUTTON_COLORS.primary,
boxShadow: `12px 12px 0px 0px ${COLORS.shadow}`,
},
}}
$buttonColor={BUTTON_COLORS.primary}
$textColor={BUTTON_COLORS.text}
$shadowColor={COLORS.shadow}
$borderRadius={{ xs: '0', md: '0 8px 0 0' }}
endIcon={<ArrowForwardIcon />}
onClick={() => {
setView('onboarding');
}}
onClick={() => setView('onboarding')}
>
<Box>
<ButtonContent>
<Typography variant='body2'>Create a new robot and</Typography>
<Typography variant='body2'>learn to use RoboSats.</Typography>
<Typography variant='h6' sx={{ mt: 1, fontWeight: 'bold' }}>
Start
</Typography>
</Box>
</ButtonContent>
</StyledButton>
<StyledButton
fullWidth
variant='contained'
sx={{
bgcolor: BUTTON_COLORS.secondary,
color: BUTTON_COLORS.text,
borderRadius: { xs: '0', md: '0' },
'&:hover': {
backgroundColor: BUTTON_COLORS.secondary,
boxShadow: `12px 12px 0px 0px ${COLORS.shadow}`,
},
}}
$buttonColor={BUTTON_COLORS.secondary}
$textColor={BUTTON_COLORS.text}
$shadowColor={COLORS.shadow}
$borderRadius={{ xs: '0', md: '0' }}
endIcon={<ArrowForwardIcon />}
onClick={() => {
setView('recovery');
}}
onClick={() => setView('recovery')}
>
<Box>
<ButtonContent>
<Typography variant='body2'>Recover an existing</Typography>
<Typography variant='body2'>Robot using your token.</Typography>
<Typography variant='h6' sx={{ mt: 1, fontWeight: 'bold' }}>
Recover
</Typography>
</Box>
</ButtonContent>
</StyledButton>
<StyledButton
fullWidth
variant='contained'
sx={{
bgcolor: COLORS.background,
color: BUTTON_COLORS.primary,
borderRadius: { xs: '0 0 8px 8px', md: '0 0 8px 0' },
'&:hover': {
backgroundColor: COLORS.background,
boxShadow: `12px 12px 0px 0px ${COLORS.shadow}`,
},
justifyContent: 'flex-start',
}}
$buttonColor={COLORS.background}
$textColor={BUTTON_COLORS.primary}
$shadowColor={COLORS.shadow}
$borderRadius={{ xs: '0 0 8px 8px', md: '0 0 8px 0' }}
sx={{ justifyContent: 'flex-start' }}
onClick={() => {
setView('profile');
getGenerateRobot(genBase62Token(36));
@ -170,9 +97,93 @@ const Welcome = ({ setView, getGenerateRobot, width }: WelcomeProps): JSX.Elemen
Fast Generate Robot
</Typography>
</StyledButton>
</Box>
</Box>
</ButtonsSection>
</WelcomeContainer>
);
};
export default Welcome;
// 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;

View File

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

View File

@ -23,30 +23,166 @@ import RobotAvatar from '../../components/RobotAvatar';
import { RoboSatsTextIcon } from '../../components/Icons';
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 StyledAppBar = styled(AppBar)(({ theme, isMobile, drawerOpen }) => ({
height: NAVBAR_HEIGHT,
display: 'flex',
justifyContent: 'center',
boxShadow: isMobile ? 'none' : '8px 8px 0px 0px rgba(0,0,0,1)',
backgroundColor: theme.palette.background.paper,
borderBottom: isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
border: !isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
borderRadius: isMobile ? '0' : '1vw',
padding: isMobile ? '0' : '1vh',
top: isMobile ? 0 : theme.spacing(2),
left: '50%',
transform: 'translateX(-50%)',
width: isMobile ? '100%' : 'calc(100% - 64px)',
position: 'fixed',
zIndex: 1100,
...(drawerOpen &&
isMobile && {
background: 'none',
backgroundColor: theme.palette.background.paper,
}),
}));
const StyledAppBar = styled(AppBar)<{ $isMobile: boolean; $drawerOpen: boolean }>(
({ theme, $isMobile, $drawerOpen }) => ({
height: NAVBAR_HEIGHT,
display: 'flex',
justifyContent: 'center',
boxShadow: $isMobile ? 'none' : '8px 8px 0px 0px rgba(0,0,0,1)',
backgroundColor: theme.palette.background.paper,
borderBottom: $isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
border: !$isMobile ? `2px solid ${theme.palette.mode === 'dark' ? '#fff' : '#000'}` : '',
borderRadius: $isMobile ? '0' : '1vw',
padding: $isMobile ? '0' : '1vh',
top: $isMobile ? 0 : theme.spacing(2),
left: '50%',
transform: 'translateX(-50%)',
width: $isMobile ? '100%' : 'calc(100% - 64px)',
position: 'fixed',
zIndex: 1100,
...($drawerOpen &&
$isMobile && {
background: 'none',
backgroundColor: theme.palette.background.paper,
}),
})
);
const StyledToolbar = styled(Toolbar)(({ theme }) => ({
display: 'flex',
@ -81,170 +217,54 @@ const MobileToolbarContent = styled(Box)(({ theme }) => ({
marginLeft: theme.spacing(2),
}));
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 StyledIcon = styled('svg')<{ $isDark: boolean }>(({ $isDark }) => ({
color: $isDark ? '#fff' : '#000',
}));
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 = [
{ label: 'Robosats Info', key: 'info' },
{ label: 'Learn Robosats', key: 'learn' },
{ label: 'Community', key: 'community' },
{ label: 'Exchange Summary', key: 'exchange' },
];
const StyledDrawer = styled(Drawer)(({ theme }) => ({
'& .MuiDrawer-paper': {
marginTop: NAVBAR_HEIGHT,
borderLeft: '2px solid black',
borderRight: '2px solid black',
borderBottom: '2px solid black',
width: '100%',
maxWidth: '300px',
},
}));
const toggleDrawer = (open: boolean) => () => {
setDrawerOpen(open);
};
const StyledListItem = styled(ListItem)(({ theme }) => ({
borderBottom: `1px solid ${theme.palette.divider}`,
padding: theme.spacing(2),
}));
const handleLogoClick = () => {
setOpen({ ...closeAll, client: !open.client });
};
const StyledLogoListItem = styled(ListItem)(({ theme }) => ({
borderBottom: `1px solid ${theme.palette.divider}`,
padding: theme.spacing(2),
justifyContent: 'center',
}));
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,
borderLeft: '2px solid black',
borderRight: '2px solid black',
borderBottom: '2px solid black',
},
}}
>
<List>
<ListItem
button
onClick={handleLogoClick}
sx={{ borderBottom: '1px solid black' }}
>
<RoboSatsTextIcon
sx={{
height: '2em',
width: 'auto',
cursor: 'pointer',
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>
</>
);
};
const StyledDesktopRoboSatsTextIcon = styled(RoboSatsTextIcon)(({ theme }) => ({
height: '1.5em',
width: 'auto',
cursor: 'pointer',
marginLeft: theme.spacing(-1),
fill: 'url(#linearColors)',
}));
export default TopNavBar;
const StyledDrawerRoboSatsTextIcon = styled(RoboSatsTextIcon)(({ theme }) => ({
height: '2em',
width: 'auto',
cursor: 'pointer',
fill: 'url(#linearColors)',
}));
export default TopNavBar;