From cc1512cd4410a08312700b9088687438e06797ad Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Tue, 3 Jan 2023 14:52:10 +0100 Subject: [PATCH] refactor: styled component in header (#2808) --- .../src/component/menu/Footer/FooterTitle.tsx | 2 +- .../component/menu/Header/Header.styles.ts | 89 --------- frontend/src/component/menu/Header/Header.tsx | 170 +++++++++++------- frontend/src/themes/themeStyles.ts | 20 +++ .../front-end/preferred-styling-method.md | 27 +++ 5 files changed, 155 insertions(+), 153 deletions(-) delete mode 100644 frontend/src/component/menu/Header/Header.styles.ts diff --git a/frontend/src/component/menu/Footer/FooterTitle.tsx b/frontend/src/component/menu/Footer/FooterTitle.tsx index b15e427097..707f8c6a7b 100644 --- a/frontend/src/component/menu/Footer/FooterTitle.tsx +++ b/frontend/src/component/menu/Footer/FooterTitle.tsx @@ -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, })); diff --git a/frontend/src/component/menu/Header/Header.styles.ts b/frontend/src/component/menu/Header/Header.styles.ts deleted file mode 100644 index 5c04ad56e1..0000000000 --- a/frontend/src/component/menu/Header/Header.styles.ts +++ /dev/null @@ -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, - }, -})); diff --git a/frontend/src/component/menu/Header/Header.tsx b/frontend/src/component/menu/Header/Header.tsx index a41744c3da..5bebc93ee5 100644 --- a/frontend/src/component/menu/Header/Header.tsx +++ b/frontend/src/component/menu/Header/Header.tsx @@ -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 ( - - + + ({ + 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} /> -
+ -
-
-
+ + + ); } return ( - - - + + + + } lightmode={ - + } /> - - - - + + + + ); }; diff --git a/frontend/src/themes/themeStyles.ts b/frontend/src/themes/themeStyles.ts index 58d11aa2b3..753d9f174b 100644 --- a/frontend/src/themes/themeStyles.ts +++ b/frontend/src/themes/themeStyles.ts @@ -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': { diff --git a/website/docs/contributing/ADRs/front-end/preferred-styling-method.md b/website/docs/contributing/ADRs/front-end/preferred-styling-method.md index 9478fb704d..d0cefa27d3 100644 --- a/website/docs/contributing/ADRs/front-end/preferred-styling-method.md +++ b/website/docs/contributing/ADRs/front-end/preferred-styling-method.md @@ -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), +})); + + +```