1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

refactor: styled component in header (#2808)

This commit is contained in:
Mateusz Kwasniewski 2023-01-03 14:52:10 +01:00 committed by GitHub
parent 88d649d239
commit cc1512cd44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 155 additions and 153 deletions

View File

@ -4,6 +4,6 @@ export const FooterTitle = styled('h2')(({ theme }) => ({
all: 'unset',
display: 'block',
margin: theme.spacing(2, 0),
fontSize: '1rem',
fontSize: theme.fontSizes.bodySize,
fontWeight: theme.fontWeight.bold,
}));

View File

@ -1,89 +0,0 @@
import { makeStyles } from 'tss-react/mui';
export const useStyles = makeStyles()(theme => ({
header: {
backgroundColor: theme.palette.headerBackground,
padding: '0.5rem',
boxShadow: 'none',
position: 'relative',
zIndex: 300,
},
links: {
display: 'flex',
justifyContent: 'center',
marginLeft: '1.5rem',
'& a': {
textDecoration: 'none',
color: 'inherit',
marginRight: '1.5rem',
display: 'flex',
alignItems: 'center',
},
},
container: {
display: 'flex',
alignItems: 'center',
maxWidth: 1280,
[theme.breakpoints.down('md')]: {
padding: '0',
},
},
nav: {
display: 'flex',
alignItems: 'center',
flexGrow: 1,
},
drawerButton: {
color: '#000',
},
advancedNavButton: {
border: 'none',
background: 'transparent',
height: '100%',
display: 'flex',
fontSize: '1rem',
fontFamily: theme.typography.fontFamily,
alignItems: 'center',
color: 'inherit',
cursor: 'pointer',
},
headerTitle: {
fontSize: '1.4rem',
},
userContainer: {
marginLeft: 'auto',
display: 'flex',
alignItems: 'center',
},
logoOnly: {
width: '60px',
},
logo: {
width: '150px',
},
popover: {
top: '25px',
},
menuItem: {
minWidth: '150px',
},
menuItemBox: {
width: '12.5px',
height: '12.5px',
display: 'block',
backgroundColor: theme.palette.primary.main,
marginRight: '1rem',
borderRadius: '2px',
},
navMenuLink: {
textDecoration: 'none',
alignItems: 'center',
display: 'flex',
},
icon: {
color: theme.palette.grey[700],
},
wideButton: {
borderRadius: 100,
},
}));

View File

@ -9,6 +9,8 @@ import {
IconButton,
Tooltip,
Switch,
styled,
Theme,
} from '@mui/material';
import MenuIcon from '@mui/icons-material/Menu';
import SettingsIcon from '@mui/icons-material/Settings';
@ -20,7 +22,7 @@ import { ReactComponent as UnleashLogoWhite } from 'assets/img/logoWithWhiteText
import { DrawerMenu } from './DrawerMenu/DrawerMenu';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useThemeStyles } from 'themes/themeStyles';
import { flexRow, focusable, useThemeStyles } from 'themes/themeStyles';
import { ADMIN } from 'component/providers/AccessProvider/permissions';
import { IPermission } from 'interfaces/user';
import { NavigationMenu } from './NavigationMenu/NavigationMenu';
@ -28,13 +30,82 @@ import { getRoutes } from 'component/menu/routes';
import { KeyboardArrowDown } from '@mui/icons-material';
import { filterByConfig } from 'component/common/util';
import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions';
import { useStyles } from './Header.styles';
import classNames from 'classnames';
import { useId } from 'hooks/useId';
import { IRoute } from 'interfaces/route';
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
import { useThemeMode } from 'hooks/useThemeMode';
const StyledHeader = styled(AppBar)(({ theme }) => ({
backgroundColor: theme.palette.headerBackground,
padding: theme.spacing(1),
boxShadow: 'none',
position: 'relative',
zIndex: 300,
}));
const StyledContainer = styled(Container)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
maxWidth: 1280,
[theme.breakpoints.down('md')]: {
padding: '0',
},
}));
const StyledUserContainer = styled('div')({
marginLeft: 'auto',
display: 'flex',
alignItems: 'center',
});
const StyledNav = styled('nav')({
display: 'flex',
alignItems: 'center',
flexGrow: 1,
});
const StyledUnleashLogoWhite = styled(UnleashLogoWhite)({ width: '150px' });
const StyledUnleashLogo = styled(UnleashLogo)({ width: '150px' });
const StyledLinks = styled('div')(({ theme }) => ({
display: 'flex',
justifyContent: 'center',
marginLeft: theme.spacing(3),
'& a': {
textDecoration: 'none',
color: 'inherit',
marginRight: theme.spacing(3),
display: 'flex',
alignItems: 'center',
},
}));
const StyledAdvancedNavButton = styled('button')(({ theme }) => ({
border: 'none',
background: 'transparent',
height: '100%',
display: 'flex',
fontSize: theme.fontSizes.bodySize,
fontFamily: theme.typography.fontFamily,
alignItems: 'center',
color: 'inherit',
cursor: 'pointer',
}));
const styledIconProps = (theme: Theme) => ({
color: theme.palette.neutral.main,
});
const StyledLink = styled(Link)(({ theme }) => ({
...focusable(theme),
}));
const StyledIconButton = styled(IconButton)(({ theme }) => ({
...focusable(theme),
borderRadius: 100,
}));
const Header: VFC = () => {
const { onSetThemeMode, themeMode } = useThemeMode();
const theme = useTheme();
@ -47,8 +118,6 @@ const Header: VFC = () => {
const { permissions } = useAuthPermissions();
const { uiConfig, isOss } = useUiConfig();
const smallScreen = useMediaQuery(theme.breakpoints.down('md'));
const { classes: styles } = useStyles();
const { classes: themeStyles } = useThemeStyles();
const [openDrawer, setOpenDrawer] = useState(false);
const toggleDrawer = () => setOpenDrawer(prev => !prev);
@ -85,11 +154,13 @@ const Header: VFC = () => {
if (smallScreen) {
return (
<AppBar className={styles.header} position="static">
<Container className={styles.container}>
<StyledHeader position="static">
<StyledContainer>
<Tooltip title="Menu" arrow>
<IconButton
className={styles.drawerButton}
sx={theme => ({
color: theme.palette.text.tertiaryContrast,
})}
onClick={toggleDrawer}
aria-controls="header-drawer"
aria-expanded={openDrawer}
@ -107,63 +178,40 @@ const Header: VFC = () => {
admin={admin}
routes={filteredMainRoutes}
/>
<div className={styles.userContainer}>
<StyledUserContainer>
<UserProfile />
</div>
</Container>
</AppBar>
</StyledUserContainer>
</StyledContainer>
</StyledHeader>
);
}
return (
<AppBar className={styles.header} position="static">
<Container className={styles.container}>
<Link
to="/"
className={classNames(
themeStyles.flexRow,
themeStyles.focusable
)}
aria-label="Home"
>
<StyledHeader position="static">
<StyledContainer>
<StyledLink to="/" sx={flexRow} aria-label="Home">
<ThemeMode
darkmode={
<UnleashLogoWhite
className={styles.logo}
aria-label="Unleash logo"
/>
<StyledUnleashLogoWhite aria-label="Unleash logo" />
}
lightmode={
<UnleashLogo
className={styles.logo}
aria-label="Unleash logo"
/>
<StyledUnleashLogo aria-label="Unleash logo" />
}
/>
</Link>
<nav className={styles.nav}>
<div className={styles.links}>
<Link to="/projects" className={themeStyles.focusable}>
Projects
</Link>
<Link to="/features" className={themeStyles.focusable}>
Feature toggles
</Link>
<Link
to="/playground"
className={themeStyles.focusable}
>
Playground
</Link>
<button
className={styles.advancedNavButton}
</StyledLink>
<StyledNav>
<StyledLinks>
<StyledLink to="/projects">Projects</StyledLink>
<StyledLink to="/features">Feature toggles</StyledLink>
<StyledLink to="/playground">Playground</StyledLink>
<StyledAdvancedNavButton
onClick={e => setConfigRef(e.currentTarget)}
aria-controls={configRef ? configId : undefined}
aria-expanded={Boolean(configRef)}
>
Configure
<KeyboardArrowDown className={styles.icon} />
</button>
<KeyboardArrowDown sx={styledIconProps} />
</StyledAdvancedNavButton>
<NavigationMenu
id={configId}
options={filteredMainRoutes.mainNavRoutes}
@ -171,8 +219,8 @@ const Header: VFC = () => {
handleClose={onConfigureClose}
style={{ top: 10 }}
/>
</div>
<div className={styles.userContainer}>
</StyledLinks>
<StyledUserContainer>
<ConditionallyRender
condition={Boolean(
uiConfig.flags.ENABLE_DARK_MODE_SUPPORT
@ -196,7 +244,7 @@ const Header: VFC = () => {
rel="noopener noreferrer"
size="large"
disableRipple
className={themeStyles.focusable}
sx={focusable}
>
<MenuBookIcon />
</IconButton>
@ -205,14 +253,10 @@ const Header: VFC = () => {
condition={admin}
show={
<Tooltip title="Settings" arrow>
<IconButton
<StyledIconButton
onClick={e =>
setAdminRef(e.currentTarget)
}
className={classNames(
styles.wideButton,
themeStyles.focusable
)}
aria-controls={
adminRef ? adminId : undefined
}
@ -222,9 +266,9 @@ const Header: VFC = () => {
>
<SettingsIcon />
<KeyboardArrowDown
className={styles.icon}
sx={styledIconProps}
/>
</IconButton>
</StyledIconButton>
</Tooltip>
}
/>
@ -236,10 +280,10 @@ const Header: VFC = () => {
style={{ top: 5, left: -100 }}
/>{' '}
<UserProfile />
</div>
</nav>
</Container>
</AppBar>
</StyledUserContainer>
</StyledNav>
</StyledContainer>
</StyledHeader>
);
};

View File

@ -1,5 +1,25 @@
import { makeStyles } from 'tss-react/mui';
import { Theme } from '@mui/material';
export const focusable = (theme: Theme) => ({
'&:focus-visible': {
outline: 0,
outlineStyle: 'solid',
outlineWidth: 2,
outlineOffset: 2,
outlineColor: theme.palette.primary.main,
},
});
export const flexRow = {
display: 'flex',
alignItems: 'center',
};
/**
* Please extract styles below into MUI fragments as shown above
* @deprecated
*/
export const useThemeStyles = makeStyles()(theme => ({
focusable: {
'&:focus-visible': {

View File

@ -14,3 +14,30 @@ In the codebase, we need to have a uniform way of performing style updates.
We have decided to move away from using makeStyles as it's currently deprecated from @material/ui, and kept alive with an
external interop package to maintain compatability with the latest version. The preferred path forward is to use styled components which is
supported natively in @material/ui and sparingly use the sx prop available on all mui components.
### Consequences: code sharing
With makeStyles it was common to reuse CSS fragments via library utilities.
In the styled components approach we use themeable functions and object literals
```ts
import { Theme } from '@mui/material';
export const focusable = (theme: Theme) => ({
color: theme.palette.primary.main,
});
export const flexRow = {
display: 'flex',
alignItems: 'center',
};
```
Usage:
```ts
const StyledLink = styled(Link)(({ theme }) => ({
...focusable(theme),
}));
<IconButton sx={focusable}/>
```