@mui/material/styles#alpha JavaScript Examples

The following examples show how to use @mui/material/styles#alpha. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Header.jsx    From hr-atx58-fec-havarti with Mozilla Public License 2.0 6 votes vote down vote up
Search = styled('div')(({ theme }) => ({
  position: 'relative',
  borderRadius: theme.shape.borderRadius,
  backgroundColor: alpha(theme.palette.common.white, 0.15),
  '&:hover': {
    backgroundColor: alpha(theme.palette.common.white, 0.25),
  },
  marginLeft: 0,
  width: '100%',
  [theme.breakpoints.up('sm')]: {
    marginLeft: theme.spacing(1),
    width: 'auto',
  },
}))
Example #2
Source File: shadows.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
createCustomShadow = (color) => {
  const transparent = alpha(color, 0.24);

  return {
    z1: `0 1px 2px 0 ${transparent}`,
    z8: `0 8px 16px 0 ${transparent}`,
    z12: `0 0 2px 0 ${transparent}, 0 12px 24px 0 ${transparent}`,
    z16: `0 0 2px 0 ${transparent}, 0 16px 32px -4px ${transparent}`,
    z20: `0 0 2px 0 ${transparent}, 0 20px 40px -4px ${transparent}`,
    z24: `0 0 4px 0 ${transparent}, 0 24px 48px 0 ${transparent}`,
    primary: `0 8px 16px 0 ${alpha(palette.primary.main, 0.24)}`,
    secondary: `0 8px 16px 0 ${alpha(palette.secondary.main, 0.24)}`,
    info: `0 8px 16px 0 ${alpha(palette.info.main, 0.24)}`,
    success: `0 8px 16px 0 ${alpha(palette.success.main, 0.24)}`,
    warning: `0 8px 16px 0 ${alpha(palette.warning.main, 0.24)}`,
    error: `0 8px 16px 0 ${alpha(palette.error.main, 0.24)}`,
  };
}
Example #3
Source File: MenuPopover.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
ArrowStyle = styled('span')(({ theme }) => ({
  [theme.breakpoints.up('sm')]: {
    top: -7,
    zIndex: 1,
    width: 12,
    right: 20,
    height: 12,
    content: "''",
    position: 'absolute',
    borderRadius: '0 0 4px 0',
    transform: 'rotate(-135deg)',
    background: theme.palette.background.paper,
    borderRight: `solid 1px ${alpha(theme.palette.grey[500], 0.12)}`,
    borderBottom: `solid 1px ${alpha(theme.palette.grey[500], 0.12)}`,
  },
}))
Example #4
Source File: shadows.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
createShadow = (color) => {
  const transparent1 = alpha(color, 0.2);
  const transparent2 = alpha(color, 0.14);
  const transparent3 = alpha(color, 0.12);
  return [
    'none',
    `0px 2px 1px -1px ${transparent1},0px 1px 1px 0px ${transparent2},0px 1px 3px 0px ${transparent3}`,
    `0px 3px 1px -2px ${transparent1},0px 2px 2px 0px ${transparent2},0px 1px 5px 0px ${transparent3}`,
    `0px 3px 3px -2px ${transparent1},0px 3px 4px 0px ${transparent2},0px 1px 8px 0px ${transparent3}`,
    `0px 2px 4px -1px ${transparent1},0px 4px 5px 0px ${transparent2},0px 1px 10px 0px ${transparent3}`,
    `0px 3px 5px -1px ${transparent1},0px 5px 8px 0px ${transparent2},0px 1px 14px 0px ${transparent3}`,
    `0px 3px 5px -1px ${transparent1},0px 6px 10px 0px ${transparent2},0px 1px 18px 0px ${transparent3}`,
    `0px 4px 5px -2px ${transparent1},0px 7px 10px 1px ${transparent2},0px 2px 16px 1px ${transparent3}`,
    `0px 5px 5px -3px ${transparent1},0px 8px 10px 1px ${transparent2},0px 3px 14px 2px ${transparent3}`,
    `0px 5px 6px -3px ${transparent1},0px 9px 12px 1px ${transparent2},0px 3px 16px 2px ${transparent3}`,
    `0px 6px 6px -3px ${transparent1},0px 10px 14px 1px ${transparent2},0px 4px 18px 3px ${transparent3}`,
    `0px 6px 7px -4px ${transparent1},0px 11px 15px 1px ${transparent2},0px 4px 20px 3px ${transparent3}`,
    `0px 7px 8px -4px ${transparent1},0px 12px 17px 2px ${transparent2},0px 5px 22px 4px ${transparent3}`,
    `0px 7px 8px -4px ${transparent1},0px 13px 19px 2px ${transparent2},0px 5px 24px 4px ${transparent3}`,
    `0px 7px 9px -4px ${transparent1},0px 14px 21px 2px ${transparent2},0px 5px 26px 4px ${transparent3}`,
    `0px 8px 9px -5px ${transparent1},0px 15px 22px 2px ${transparent2},0px 6px 28px 5px ${transparent3}`,
    `0px 8px 10px -5px ${transparent1},0px 16px 24px 2px ${transparent2},0px 6px 30px 5px ${transparent3}`,
    `0px 8px 11px -5px ${transparent1},0px 17px 26px 2px ${transparent2},0px 6px 32px 5px ${transparent3}`,
    `0px 9px 11px -5px ${transparent1},0px 18px 28px 2px ${transparent2},0px 7px 34px 6px ${transparent3}`,
    `0px 9px 12px -6px ${transparent1},0px 19px 29px 2px ${transparent2},0px 7px 36px 6px ${transparent3}`,
    `0px 10px 13px -6px ${transparent1},0px 20px 31px 3px ${transparent2},0px 8px 38px 7px ${transparent3}`,
    `0px 10px 13px -6px ${transparent1},0px 21px 33px 3px ${transparent2},0px 8px 40px 7px ${transparent3}`,
    `0px 10px 14px -6px ${transparent1},0px 22px 35px 3px ${transparent2},0px 8px 42px 7px ${transparent3}`,
    `0px 11px 14px -7px ${transparent1},0px 23px 36px 3px ${transparent2},0px 9px 44px 8px ${transparent3}`,
    `0px 11px 15px -7px ${transparent1},0px 24px 38px 3px ${transparent2},0px 9px 46px 8px ${transparent3}`,
  ];
}
Example #5
Source File: Scrollbar.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
SimpleBarStyle = styled(SimpleBarReact)(({ theme }) => ({
  maxHeight: '100%',
  '& .simplebar-scrollbar': {
    '&:before': {
      backgroundColor: alpha(theme.palette.grey[600], 0.48),
    },
    '&.simplebar-visible:before': {
      opacity: 1,
    },
  },
  '& .simplebar-track.simplebar-vertical': {
    width: 10,
  },
  '& .simplebar-track.simplebar-horizontal .simplebar-scrollbar': {
    height: 6,
  },
  '& .simplebar-mask': {
    zIndex: 'inherit',
  },
}))
Example #6
Source File: palette.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
GREY = {
  0: '#FFFFFF',
  100: '#F9FAFB',
  200: '#F4F6F8',
  300: '#DFE3E8',
  400: '#C4CDD5',
  500: '#919EAB',
  600: '#637381',
  700: '#454F5B',
  800: '#212B36',
  900: '#161C24',
  500_8: alpha('#919EAB', 0.08),
  500_12: alpha('#919EAB', 0.12),
  500_16: alpha('#919EAB', 0.16),
  500_24: alpha('#919EAB', 0.24),
  500_32: alpha('#919EAB', 0.32),
  500_48: alpha('#919EAB', 0.48),
  500_56: alpha('#919EAB', 0.56),
  500_80: alpha('#919EAB', 0.8),
}
Example #7
Source File: Backdrop.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
// ----------------------------------------------------------------------

export default function Backdrop(theme) {
  const varLow = alpha(theme.palette.grey[900], 0.48);
  const varHigh = alpha(theme.palette.grey[900], 1);

  return {
    MuiBackdrop: {
      styleOverrides: {
        root: {
          background: [
            `rgb(22,28,36)`,
            `-moz-linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`,
            `-webkit-linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`,
            `linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`
          ],
          '&.MuiBackdrop-invisible': {
            background: 'transparent'
          }
        }
      }
    }
  };
}
Example #8
Source File: Searchbar.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
SearchbarStyle = styled('div')(({ theme }) => ({
  top: 0,
  left: 0,
  zIndex: 99,
  width: '100%',
  display: 'flex',
  position: 'absolute',
  alignItems: 'center',
  height: APPBAR_MOBILE,
  backdropFilter: 'blur(6px)',
  WebkitBackdropFilter: 'blur(6px)', // Fix on Mobile
  padding: theme.spacing(0, 3),
  boxShadow: theme.customShadows.z8,
  backgroundColor: `${alpha(theme.palette.background.default, 0.72)}`,
  [theme.breakpoints.up('md')]: {
    height: APPBAR_DESKTOP,
    padding: theme.spacing(0, 5),
  },
}))
Example #9
Source File: DashboardNavbar.js    From Django-REST-Framework-React-BoilerPlate with MIT License 6 votes vote down vote up
RootStyle = styled(AppBar)(({ theme }) => ({
  boxShadow: 'none',
  backdropFilter: 'blur(6px)',
  WebkitBackdropFilter: 'blur(6px)', // Fix on Mobile
  backgroundColor: alpha(theme.palette.background.default, 0.72),
  [theme.breakpoints.up('lg')]: {
    width: `calc(100% - ${DRAWER_WIDTH + 1}px)`,
  },
}))
Example #10
Source File: TopBarSearchField.js    From sampo-ui with MIT License 5 votes vote down vote up
render () {
    const { screenSize } = this.props
    const placeholder = screenSize === 'xs'
      ? intl.get('topBar.searchBarPlaceHolderShort')
      : intl.get('topBar.searchBarPlaceHolder')
    return (
      <Box
        sx={theme => ({
          position: 'relative',
          borderRadius: theme.shape.borderRadius,
          backgroundColor: alpha(theme.palette.common.white, 0.15),
          '&:hover': {
            backgroundColor: alpha(theme.palette.common.white, 0.25)
          },
          marginRight: theme.spacing(2),
          marginLeft: 0,
          width: '100%',
          [theme.breakpoints.up('sm')]: {
            marginLeft: theme.spacing(3),
            width: 'auto'
          }
        })}
      >
        <Box
          sx={theme => ({
            padding: theme.spacing(0, 2),
            height: '100%',
            position: 'absolute',
            pointerEvents: 'none',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center'
          })}
        >
          <SearchIcon />
        </Box>
        <InputBase
          placeholder={placeholder}
          inputProps={{ 'aria-label': 'search' }}
          onChange={this.handleChange}
          onKeyDown={this.handleOnKeyDown}
          sx={theme => ({
            color: 'inherit',
            '& .MuiInputBase-input': {
              padding: theme.spacing(1, 1, 1, 0),
              // vertical padding + font size from searchIcon
              paddingLeft: `calc(1em + ${theme.spacing(4)})`,
              transition: theme.transitions.create('width'),
              width: '100%',
              [theme.breakpoints.up('md')]: {
                width: '20ch'
              }
            }
          })}
        />
      </Box>
    )
  }
Example #11
Source File: ColorPreview.js    From Django-REST-Framework-React-BoilerPlate with MIT License 5 votes vote down vote up
IconStyle = styled('div')(({ theme }) => ({
  marginLeft: -4,
  borderRadius: '50%',
  width: theme.spacing(2),
  height: theme.spacing(2),
  border: `solid 2px ${theme.palette.background.paper}`,
  boxShadow: `inset -1px 1px 2px ${alpha(theme.palette.common.black, 0.24)}`,
}))
Example #12
Source File: BaseOptionChart.js    From Django-REST-Framework-React-BoilerPlate with MIT License 5 votes vote down vote up
// ----------------------------------------------------------------------

export function BaseOptionChartStyle() {
  const theme = useTheme();

  const background = {
    backdropFilter: 'blur(6px)',
    WebkitBackdropFilter: 'blur(6px)', // Fix on Mobile
    backgroundColor: alpha(theme.palette.background.default, 0.72)
  };

  return (
    <GlobalStyles
      styles={{
        '&.apexcharts-canvas': {
          // Tooltip
          '.apexcharts-xaxistooltip': {
            ...background,
            border: 0,
            boxShadow: theme.customShadows.z24,
            color: theme.palette.text.primary,
            borderRadius: Number(theme.shape.borderRadius) * 1.5,
            '&:before': { borderBottomColor: 'transparent' },
            '&:after': { borderBottomColor: alpha(theme.palette.background.default, 0.72) }
          },
          '.apexcharts-tooltip.apexcharts-theme-light': {
            ...background,
            border: 0,
            boxShadow: theme.customShadows.z24,
            borderRadius: Number(theme.shape.borderRadius) * 1.5,
            '& .apexcharts-tooltip-title': {
              border: 0,
              textAlign: 'center',
              fontWeight: theme.typography.fontWeightBold,
              backgroundColor: theme.palette.grey[500_16],
              color: theme.palette.text[theme.palette.mode === 'light' ? 'secondary' : 'primary']
            }
          },
          // Legend
          '.apexcharts-legend': {
            padding: 0
          },
          '.apexcharts-legend-series': {
            display: 'flex !important',
            alignItems: 'center'
          },
          '.apexcharts-legend-marker': {
            marginRight: 8
          },
          '.apexcharts-legend-text': {
            lineHeight: '18px',
            textTransform: 'capitalize'
          }
        }
      }}
    />
  );
}
Example #13
Source File: Label.js    From Django-REST-Framework-React-BoilerPlate with MIT License 5 votes vote down vote up
RootStyle = styled('span')(({ theme, ownerState }) => {
  const isLight = theme.palette.mode === 'light';
  const { color, variant } = ownerState;

  const styleFilled = (color) => ({
    color: theme.palette[color].contrastText,
    backgroundColor: theme.palette[color].main,
  });

  const styleOutlined = (color) => ({
    color: theme.palette[color].main,
    backgroundColor: 'transparent',
    border: `1px solid ${theme.palette[color].main}`,
  });

  const styleGhost = (color) => ({
    color: theme.palette[color][isLight ? 'dark' : 'light'],
    backgroundColor: alpha(theme.palette[color].main, 0.16),
  });

  return {
    height: 22,
    minWidth: 22,
    lineHeight: 0,
    borderRadius: 6,
    cursor: 'default',
    alignItems: 'center',
    whiteSpace: 'nowrap',
    display: 'inline-flex',
    justifyContent: 'center',
    padding: theme.spacing(0, 1),
    color: theme.palette.grey[800],
    fontSize: theme.typography.pxToRem(12),
    fontFamily: theme.typography.fontFamily,
    backgroundColor: theme.palette.grey[300],
    fontWeight: theme.typography.fontWeightBold,

    ...(color !== 'default'
      ? {
          ...(variant === 'filled' && { ...styleFilled(color) }),
          ...(variant === 'outlined' && { ...styleOutlined(color) }),
          ...(variant === 'ghost' && { ...styleGhost(color) }),
        }
      : {
          ...(variant === 'outlined' && {
            backgroundColor: 'transparent',
            color: theme.palette.text.primary,
            border: `1px solid ${theme.palette.grey[500_32]}`,
          }),
          ...(variant === 'ghost' && {
            color: isLight ? theme.palette.text.secondary : theme.palette.common.white,
            backgroundColor: theme.palette.grey[500_16],
          }),
        }),
  };
})
Example #14
Source File: AccountPopover.js    From Django-REST-Framework-React-BoilerPlate with MIT License 4 votes vote down vote up
// ----------------------------------------------------------------------

export default function AccountPopover() {
  const dispatch = useDispatch();
  const navigate = useNavigate();
  const anchorRef = useRef(null);

  const [open, setOpen] = useState(null);

  const handleOpen = (event) => {
    setOpen(event.currentTarget);
  };

  const handleClose = () => {
    setOpen(null);
  };

  const userLogin = useSelector((state) => state.userLogin);
  const { userInfo } = userLogin;

  useEffect(() => {
    if (!userInfo) {
      navigate('/login', { replace: true });
      dispatch({ type: LOGOUT });
    }
  }, [navigate, userInfo]);

  const logoutHandler = () => {
    dispatch(logout());
  };
  return (
    <>
      <IconButton
        ref={anchorRef}
        onClick={handleOpen}
        sx={{
          p: 0,
          ...(open && {
            '&:before': {
              zIndex: 1,
              content: "''",
              width: '100%',
              height: '100%',
              borderRadius: '50%',
              position: 'absolute',
              bgcolor: (theme) => alpha(theme.palette.grey[900], 0.8),
            },
          }),
        }}
      >
        <Avatar src={account.photoURL} alt="photoURL" />
      </IconButton>

      <MenuPopover
        open={Boolean(open)}
        anchorEl={open}
        onClose={handleClose}
        sx={{
          p: 0,
          mt: 1.5,
          ml: 0.75,
          '& .MuiMenuItem-root': {
            typography: 'body2',
            borderRadius: 0.75,
          },
        }}
      >
        <Box sx={{ my: 1.5, px: 2.5 }}>
          <Typography variant="subtitle2" noWrap>
            {userInfo ? <>{userInfo.name}</> : 'John Doe'}
          </Typography>
          <Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
            {userInfo ? <>{userInfo.email}</> : '[email protected]'}
          </Typography>
        </Box>

        <Divider sx={{ borderStyle: 'dashed' }} />

        <Stack sx={{ p: 1 }}>
          {MENU_OPTIONS.map((option) => (
            <MenuItem key={option.label} to={option.linkTo} component={RouterLink} onClick={handleClose}>
              {option.label}
            </MenuItem>
          ))}
        </Stack>

        <Divider sx={{ borderStyle: 'dashed' }} />

        <MenuItem onClick={logoutHandler} sx={{ m: 1 }}>
          Logout
        </MenuItem>
      </MenuPopover>
    </>
  );
}
Example #15
Source File: NavSection.js    From Django-REST-Framework-React-BoilerPlate with MIT License 4 votes vote down vote up
function NavItem({ item, active }) {
  const theme = useTheme();

  const isActiveRoot = active(item.path);

  const { title, path, icon, info, children } = item;

  const [open, setOpen] = useState(isActiveRoot);

  const handleOpen = () => {
    setOpen((prev) => !prev);
  };

  const activeRootStyle = {
    color: 'primary.main',
    fontWeight: 'fontWeightMedium',
    bgcolor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
  };

  const activeSubStyle = {
    color: 'text.primary',
    fontWeight: 'fontWeightMedium',
  };

  if (children) {
    return (
      <>
        <ListItemStyle
          onClick={handleOpen}
          sx={{
            ...(isActiveRoot && activeRootStyle),
          }}
        >
          <ListItemIconStyle>{icon && icon}</ListItemIconStyle>
          <ListItemText disableTypography primary={title} />
          {info && info}
          <Iconify
            icon={open ? 'eva:arrow-ios-downward-fill' : 'eva:arrow-ios-forward-fill'}
            sx={{ width: 16, height: 16, ml: 1 }}
          />
        </ListItemStyle>

        <Collapse in={open} timeout="auto" unmountOnExit>
          <List component="div" disablePadding>
            {children.map((item) => {
              const { title, path } = item;
              const isActiveSub = active(path);

              return (
                <ListItemStyle
                  key={title}
                  component={RouterLink}
                  to={path}
                  sx={{
                    ...(isActiveSub && activeSubStyle),
                  }}
                >
                  <ListItemIconStyle>
                    <Box
                      component="span"
                      sx={{
                        width: 4,
                        height: 4,
                        display: 'flex',
                        borderRadius: '50%',
                        alignItems: 'center',
                        justifyContent: 'center',
                        bgcolor: 'text.disabled',
                        transition: (theme) => theme.transitions.create('transform'),
                        ...(isActiveSub && {
                          transform: 'scale(2)',
                          bgcolor: 'primary.main',
                        }),
                      }}
                    />
                  </ListItemIconStyle>
                  <ListItemText disableTypography primary={title} />
                </ListItemStyle>
              );
            })}
          </List>
        </Collapse>
      </>
    );
  }

  return (
    <ListItemStyle
      component={RouterLink}
      to={path}
      sx={{
        ...(isActiveRoot && activeRootStyle),
      }}
    >
      <ListItemIconStyle>{icon && icon}</ListItemIconStyle>
      <ListItemText disableTypography primary={title} />
      {info && info}
    </ListItemStyle>
  );
}
Example #16
Source File: mac-title-bar.js    From neutron with Mozilla Public License 2.0 4 votes vote down vote up
FakeTitleBar = ({ themeColor }) => {
  const title = useSelector((state) => state.general.title);
  const searchEngine = useSelector((state) => state.preferences.searchEngine);
  const navigationBar = useSelector((state) => (window.process.platform === 'linux'
  && state.preferences.attachToMenubar
  && !state.preferences.sidebar)
  || state.preferences.navigationBar);
  const titleBarNavigationButtons = useSelector(
    (state) => state.preferences.titleBarNavigationButtons,
  );

  if (window.process.platform !== 'darwin') return null;

  const showNavigationButtons = titleBarNavigationButtons && !navigationBar && window.mode !== 'menubar';

  const appJson = getStaticGlobal('appJson');

  // Big Sur increases title bar height: https://github.com/microsoft/vscode/pull/110592 (28px)
  // older macOS versions use 22px
  // but we use 28px on all versions to fit the navigation buttons
  const titleBarHeight = isMacOs11() ? 28 : 22;

  return (
    <Box
      sx={[
        {
          background: (theme) => {
            if (themeColor != null) {
              return themeColors[themeColor][900];
            }
            return theme.palette.mode === 'dark' ? '#2a2b2c' : '#efefef';
          },
          borderBottom: '1px solid',
          borderBottomColor: 'divider',
          height: titleBarHeight,
          WebkitAppRegion: 'drag',
          WebkitUserSelect: 'none',
          textAlign: 'center',
          lineHeight: `${titleBarHeight}px`,
          fontSize: 13,
          color: (theme) => {
            if (themeColor != null) {
              return alpha(theme.palette.getContrastText(themeColors[themeColor][900]), 0.7);
            }
            return (theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.7)' : 'rgb(77, 77, 77)');
          },
          fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif',
          fontWeight: 500,
          px: 9,
          overflow: 'hidden',
          textOverflow: 'ellipsis',
          whiteSpace: 'nowrap',
        },
        showNavigationButtons && { px: 18.5 },
        window.mode === 'menubar' && { px: 1 },
      ]}
      onDoubleClick={() => {
        // feature: double click on title bar to expand #656
        // https://github.com/webcatalog/webcatalog-app/issues/656

        // User can choose title bar behavior from macOS System Preferences > Dock & Menu Bar
        const systemPref = systemPreferences.getUserDefault('AppleActionOnDoubleClick', 'string');

        switch (systemPref) {
          case 'Minimize': {
            const win = getCurrentWindow();
            win.minimize();
            break;
          }
          case 'Maximize': {
            const win = getCurrentWindow();
            if (win.isMaximized()) {
              win.unmaximize();
            } else {
              win.maximize();
            }
            break;
          }
          default: break;
        }
      }}
      onDragOver={(window.mode === 'main' || window.mode === 'menubar') ? (e) => {
        e.preventDefault();
      } : null}
      onDrop={(window.mode === 'main' || window.mode === 'menubar') ? (e) => {
        const text = e.dataTransfer.getData('URL') || e.dataTransfer.getData('text');
        if (text) {
          e.preventDefault();
          const processedUrl = getUrlFromText(text, searchEngine);
          requestLoadUrl(processedUrl);
        }
      } : null}
    >
      {(window.mode === 'main' || window.mode === 'menubar') && title ? title : appJson.name}

      {showNavigationButtons && (
        <Box
          sx={{
            position: 'absolute',
            top: -1,
            right: 1,
          }}
        >
          <NavigationButtons themeColor={themeColor} disableGutter={!isMacOs11()} />
        </Box>
      )}
    </Box>
  );
}
Example #17
Source File: navigation-bar.js    From neutron with Mozilla Public License 2.0 4 votes vote down vote up
NavigationBar = ({
  themeColor,
}) => {
  const dispatch = useDispatch();

  const activeWorkspaceId = useSelector((state) => state.workspaces.activeWorkspaceId);
  const address = useSelector((state) => state.general.address || '');
  const addressEdited = useSelector((state) => Boolean(state.general.addressEdited));
  const draggable = useSelector((state) => window.process.platform === 'darwin' && !state.preferences.titleBar);
  const hasTrafficLights = useSelector((state) => window.process.platform === 'darwin'
  && getStaticGlobal('windowButtons')
  && window.mode !== 'menubar'
  && !state.preferences.titleBar
  && !state.preferences.sidebar
  && !state.general.isFullScreen);
  const hasWorkspaces = useSelector((state) => Object.keys(state.workspaces.workspaces).length > 0);
  const muteApp = useSelector((state) => state.preferences.muteApp);
  const searchEngine = useSelector((state) => state.preferences.searchEngine);
  const shouldPauseNotifications = useSelector(
    (state) => state.notifications.pauseNotificationsInfo !== null,
  );
  const sidebar = useSelector((state) => state.preferences.sidebar);
  const sidebarSize = useSelector((state) => state.preferences.sidebarSize);

  const [addressInputClicked, setAddressInputClicked] = useState(false);
  const hasExpandedSidebar = sidebar && sidebarSize === 'expanded';
  const addressBarRef = useRef(null);

  useEffect(() => {
    ipcRenderer.removeAllListeners('focus-on-address-bar');
    ipcRenderer.on('focus-on-address-bar', () => {
      if (addressBarRef.current) {
        addressBarRef.current.focus();
        addressBarRef.current.select();
      }
    });
    return () => {
      ipcRenderer.removeAllListeners('focus-on-address-bar');
    };
  }, [addressBarRef]);

  return (
    <Box
      sx={[
        {
          width: 1,
          height: 36,
          bgcolor: (theme) => {
            if (themeColor != null) {
              return themeColors[themeColor][800];
            }
            return theme.palette.background.paper;
          },
          borderBottom: (theme) => `1px solid ${theme.palette.divider} `,
          display: 'flex',
          alignItems: 'center',
          px: 1,
          WebkitUserSelect: 'none',
        },
        draggable && { WebkitAppRegion: 'drag' },
        hasTrafficLights && { pl: 8.5 },
      ]}
    >
      <Box
        sx={[
          hasExpandedSidebar && {
            '@media (max-width:600px)': {
              display: 'none',
            },
          },
        ]}
      >
        <NavigationButtons themeColor={themeColor} />
      </Box>
      <Box
        sx={[
          {
            flex: 1,
            px: 6,
          },
          hasExpandedSidebar && {
            '@media (max-width:700px)': {
              display: 'none',
            },
          },
        ]}
      >
        <InputBase
          sx={[
            {
              width: 1,
              bgcolor: (theme) => {
                if (themeColor != null) {
                  return themeColors[themeColor][900];
                }
                return theme.palette.mode === 'dark' ? theme.palette.background.default : theme.palette.grey[200];
              },
              color: (theme) => {
                if (themeColor != null) {
                  return theme.palette.getContrastText(themeColors[themeColor][800]);
                }
                return theme.palette.text.primary;
              },
              borderRadius: 0.5,
              WebkitAppRegion: 'none',
              WebkitUserSelect: 'text',
            },
            {
              '& .MuiInputBase-input': {
                fontSize: '0.8em',
                px: 2,
                py: 0.625,
              },
            },
          ]}
          placeholder={`Search on ${searchEngines[searchEngine].name} or type a URL`}
          type="text"
          value={hasWorkspaces ? address : ''}
          disabled={!hasWorkspaces}
          inputProps={{
            spellCheck: false,
            ref: addressBarRef,
          }}
          endAdornment={addressEdited && address && hasWorkspaces && (
            <IconButton
              title="Go"
              aria-label="Go"
              sx={{ p: 4 }}
              onClick={() => {
                const processedUrl = getUrlFromText(address, searchEngine);
                dispatch(updateAddressBarInfo(processedUrl, false));
                requestLoadUrl(processedUrl);
              }}
              size="large"
            >
              <ArrowForwardIcon fontSize="small" />
            </IconButton>
          )}
          onChange={(e) => {
            dispatch(updateAddressBarInfo(e.target.value, true));
          }}
          onKeyDown={(e) => {
            if (e.key === 'Enter') {
              e.target.blur();
              const processedUrl = getUrlFromText(address, searchEngine);
              dispatch(updateAddressBarInfo(processedUrl, false));
              requestLoadUrl(processedUrl);
            }
          }}
          // https://stackoverflow.com/a/16659291
          onClick={(e) => {
            if (!addressInputClicked) {
              e.target.select();
              setAddressInputClicked(true);
            }
          }}
          onBlur={() => {
            setAddressInputClicked(false);
          }}
          onDrop={(e) => {
            const text = e.dataTransfer.getData('URL') || e.dataTransfer.getData('text');
            if (text) {
              e.preventDefault();
              const processedUrl = getUrlFromText(text, searchEngine);
              dispatch(updateAddressBarInfo(processedUrl, false));
              requestLoadUrl(processedUrl);
            }
          }}
        />
      </Box>
      <Box>
        <RatingButton
          sx={[
            {
              p: 6,
              WebkitAppRegion: 'no-drag',
              color: (theme) => {
                if (themeColor != null) {
                  return theme.palette.getContrastText(themeColors[themeColor][800]);
                }
                return theme.palette.text.secondary;
              },
            },
            {
              '& .Mui-disabled': {
                color: (theme) => {
                  if (themeColor != null) {
                    return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                  }
                  return theme.palette.text.disabled;
                },
              },
            },
          ]}
          iconSx={{ fontSize: 18 }}
        />
        {window.process.platform === 'darwin' && hasWorkspaces && (
          <IconButton
            title="Share"
            aria-label="Share"
            onClick={() => requestShowShareMenu()}
            sx={[
              {
                p: 0.725,
                WebkitAppRegion: 'no-drag',
                color: (theme) => {
                  if (themeColor != null) {
                    return theme.palette.getContrastText(themeColors[themeColor][800]);
                  }
                  return theme.palette.text.secondary;
                },
              },
              {
                '& .Mui-disabled': {
                  color: (theme) => {
                    if (themeColor != null) {
                      return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                    }
                    return theme.palette.text.disabled;
                  },
                },
              },
            ]}
            size="small"
          >
            <SvgIcon sx={{ fontSize: 18 }}>
              <path fill="currentColor" d="M12,1L8,5H11V14H13V5H16M18,23H6C4.89,23 4,22.1 4,21V9A2,2 0 0,1 6,7H9V9H6V21H18V9H15V7H18A2,2 0 0,1 20,9V21A2,2 0 0,1 18,23Z" />
            </SvgIcon>
          </IconButton>
        )}
        <IconButton
          title="Notifications"
          aria-label="Notifications"
          onClick={requestShowNotificationsWindow}
          sx={[
            {
              p: 0.725,
              WebkitAppRegion: 'no-drag',
              color: (theme) => {
                if (themeColor != null) {
                  return theme.palette.getContrastText(themeColors[themeColor][800]);
                }
                return theme.palette.text.secondary;
              },
            },
            {
              '& .Mui-disabled': {
                color: (theme) => {
                  if (themeColor != null) {
                    return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                  }
                  return theme.palette.text.disabled;
                },
              },
            },
          ]}
          size="large"
        >
          {shouldPauseNotifications
            ? <NotificationsPausedIcon sx={{ fontSize: 18 }} />
            : <NotificationsIcon sx={{ fontSize: 18 }} />}
        </IconButton>
        <IconButton
          title={muteApp ? 'Unmute' : 'Mute'}
          aria-label={muteApp ? 'Unmute' : 'Mute'}
          onClick={() => requestSetPreference('muteApp', !muteApp)}
          sx={[
            {
              p: 0.725,
              WebkitAppRegion: 'no-drag',
              color: (theme) => {
                if (themeColor != null) {
                  return theme.palette.getContrastText(themeColors[themeColor][800]);
                }
                return theme.palette.text.secondary;
              },
            },
            {
              '& .Mui-disabled': {
                color: (theme) => {
                  if (themeColor != null) {
                    return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                  }
                  return theme.palette.text.disabled;
                },
              },
            },
          ]}
          size="large"
        >
          {muteApp
            ? <VolumeOffIcon sx={{ fontSize: 18 }} />
            : <VolumeUpIcon sx={{ fontSize: 18 }} />}
        </IconButton>
        <IconButton
          title="Preferences"
          aria-label="Preferences"
          sx={[
            {
              p: 0.75,
              WebkitAppRegion: 'no-drag',
              color: (theme) => {
                if (themeColor != null) {
                  return theme.palette.getContrastText(themeColors[themeColor][800]);
                }
                return theme.palette.text.secondary;
              },
            },
            {
              '& .Mui-disabled': {
                color: (theme) => {
                  if (themeColor != null) {
                    return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                  }
                  return theme.palette.text.disabled;
                },
              },
            },
          ]}
          onClick={() => {
            if (isMenubarBrowser() && activeWorkspaceId) {
              requestShowWorkspacePreferencesWindow(activeWorkspaceId);
            } else {
              requestShowPreferencesWindow();
            }
          }}
          size="large"
        >
          <SettingsIcon sx={{ fontSize: 18 }} />
        </IconButton>
      </Box>
    </Box>
  );
}
Example #18
Source File: sidebar.js    From neutron with Mozilla Public License 2.0 4 votes vote down vote up
Sidebar = () => {
  const activeWorkspace = useSelector(
    (state) => state.workspaces.workspaces[state.workspaces.activeWorkspaceId],
  );
  const isFullScreen = useSelector((state) => state.general.isFullScreen);
  const isLoading = useSelector((state) => (
    activeWorkspace && state.workspaceMetas[activeWorkspace.id]
      ? Boolean(state.workspaceMetas[activeWorkspace.id].isLoading)
      : false));
  const navigationBar = useSelector((state) => (window.process.platform === 'linux'
  && state.preferences.attachToMenubar
  && !state.preferences.sidebar)
  || state.preferences.navigationBar);
  const shouldPauseNotifications = useSelector(
    (state) => state.notifications.pauseNotificationsInfo !== null,
  );
  const sidebarAddButton = useSelector((state) => state.preferences.sidebarAddButton);
  const sidebarSize = useSelector((state) => state.preferences.sidebarSize);
  const titleBar = useSelector((state) => state.preferences.titleBar);
  const muteApp = useSelector((state) => state.preferences.muteApp);
  const workspaces = useSelector((state) => state.workspaces.workspaces);
  const themeColor = useSelector((state) => (() => {
    if (state.preferences.themeColor === 'auto') {
      if (activeWorkspace && activeWorkspace.preferences && activeWorkspace.preferences.color) {
        return activeWorkspace.preferences.color;
      }
      return null;
    }
    return state.preferences.themeColor;
  })());

  const appJson = getStaticGlobal('appJson');
  const workspacesList = getWorkspacesAsList(workspaces);
  const showMacTitleBar = window.process.platform === 'darwin' && titleBar && !isFullScreen;
  const isSidebarExpanded = sidebarSize === 'expanded';
  const rtl = getStaticGlobal('rtlCoordination');

  // Big Sur increases title bar height: https://github.com/microsoft/vscode/pull/110592 (28px)
  // but following Electron@13, somehow the height is now also 22px on Big Sur
  const titleBarHeight = 22;

  return (
    <ScrollbarContainer
      sx={[
        {
          display: 'flex',
          height: 1,
          width: 68,
          bgcolor: (theme) => {
            if (themeColor != null) {
              return themeColors[themeColor][800];
            }
            return theme.palette.background.paper;
          },
          overflowX: 'hidden',
        },
        isSidebarExpanded && { width: 256 },
        rtl ? {
          borderLeft: '1px solid',
          borderLeftColor: 'divider',
        } : {
          borderRight: '1px solid',
          borderRightColor: 'divider',
        },
      ]}
    >
      <Box
        sx={{
          flex: 1,
          width: 1,
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          pb: 1,
          boxSizing: 'border-box',
        }}
      >
        {window.process.platform === 'darwin' && !isFullScreen && !showMacTitleBar && (
          <Box
            sx={[
              {
                width: 1,
                height: titleBarHeight + 4,
                WebkitAppRegion: 'drag',
                WebkitUserSelect: 'none',
              },
              navigationBar && { height: 36 },
            ]}
          />
        )}
        <Box
          sx={{
            flex: 1,
            width: 1,
            WebkitAppRegion: 'drag',
            WebkitUserSelect: 'none',
            pb: 5,
          }}
        >
          <SortableContainer
            distance={10}
            helperClass="grabbing"
            onSortEnd={({ oldIndex, newIndex }) => {
              if (oldIndex === newIndex) return;

              const newWorkspacesList = arrayMove(workspacesList, oldIndex, newIndex);
              const newWorkspaces = { ...workspaces };
              newWorkspacesList.forEach((workspace, i) => {
                newWorkspaces[workspace.id].order = i;
              });

              requestSetWorkspaces(newWorkspaces);
            }}
          >
            {workspacesList.map((workspace, i) => (
              <SortableItem key={`item-${workspace.id}`} index={i} value={{ index: i, workspace, themeColor }} />
            ))}
          </SortableContainer>
          {sidebarAddButton && (
            <WorkspaceSelector
              id="add"
              themeColor={themeColor}
              onClick={() => {
                if (!appJson.url) {
                  requestShowAddWorkspaceWindow();
                  return;
                }
                requestCreateWorkspace();
              }}
              onContextMenu={!appJson.url ? null : (e) => {
                e.preventDefault();
                const template = [
                  {
                    label: `Add ${appJson.name} ${getWorkspaceFriendlyName()}`,
                    click: () => requestCreateWorkspace(),
                  },
                  {
                    label: `Add Custom ${getWorkspaceFriendlyName()}`,
                    click: () => requestShowAddWorkspaceWindow(),
                  },
                ];

                const menu = Menu.buildFromTemplate(template);
                menu.popup({
                  window: getCurrentWindow(),
                });
              }}
            />
          )}
        </Box>
        {!navigationBar && (
        <Box
          sx={[
            {
              display: 'flex',
              flexDirection: 'column',
              width: 1,
            },
            isSidebarExpanded && {
              display: 'block',
              p: 1,
            },
          ]}
        >
          {!titleBar && isLoading && (
            <Box
              sx={{
                width: 1,
                display: 'flex',
                justifyContent: 'center',
                p: 1,
              }}
            >
              <CircularProgress
                size={20}
                sx={{
                  color: (theme) => {
                    if (themeColor != null) {
                      // eslint-disable-next-line max-len
                      return alpha(theme.palette.getContrastText(themeColors[themeColor][900]), 0.7);
                    }
                    return theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.7)' : 'rgb(77, 77, 77)';
                  },
                }}
              />
            </Box>
          )}
          <RatingButton
            sx={[
              {
                color: (theme) => {
                  if (themeColor != null) {
                    return theme.palette.getContrastText(themeColors[themeColor][800]);
                  }
                  return theme.palette.text.secondary;
                },
              },
              !isSidebarExpanded && {
                width: 1,
                borderRadius: 0,
              },
            ]}
            size="small"
          />
          {window.process.platform === 'darwin' && (
            <IconButton
              title="Share"
              aria-label="Share"
              onClick={() => requestShowShareMenu()}
              sx={[
                {
                  color: (theme) => {
                    if (themeColor != null) {
                      return theme.palette.getContrastText(themeColors[themeColor][800]);
                    }
                    return theme.palette.text.secondary;
                  },
                },
                !isSidebarExpanded && {
                  width: 1,
                  borderRadius: 0,
                },
                {
                  '& .Mui-disabled': {
                    color: (theme) => {
                      if (themeColor != null) {
                        return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                      }
                      return theme.palette.text.disabled;
                    },
                  },
                },
              ]}
              size="small"
              disabled={workspacesList.length < 1}
            >
              <SvgIcon>
                <path fill="currentColor" d="M12,1L8,5H11V14H13V5H16M18,23H6C4.89,23 4,22.1 4,21V9A2,2 0 0,1 6,7H9V9H6V21H18V9H15V7H18A2,2 0 0,1 20,9V21A2,2 0 0,1 18,23Z" />
              </SvgIcon>
            </IconButton>
          )}
          <IconButton
            title="Notifications"
            aria-label="Notifications"
            onClick={requestShowNotificationsWindow}
            sx={[
              {
                color: (theme) => {
                  if (themeColor != null) {
                    return theme.palette.getContrastText(themeColors[themeColor][800]);
                  }
                  return theme.palette.text.secondary;
                },
              },
              !isSidebarExpanded && {
                width: 1,
                borderRadius: 0,
              },
              {
                '& .Mui-disabled': {
                  color: (theme) => {
                    if (themeColor != null) {
                      return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                    }
                    return theme.palette.text.disabled;
                  },
                },
              },
            ]}
            size="small"
          >
            {shouldPauseNotifications ? <NotificationsPausedIcon /> : <NotificationsIcon />}
          </IconButton>
          <IconButton
            title={muteApp ? 'Unmute' : 'Mute'}
            aria-label={muteApp ? 'Unmute' : 'Mute'}
            onClick={() => requestSetPreference('muteApp', !muteApp)}
            sx={[
              {
                color: (theme) => {
                  if (themeColor != null) {
                    return theme.palette.getContrastText(themeColors[themeColor][800]);
                  }
                  return theme.palette.text.secondary;
                },
              },
              !isSidebarExpanded && {
                width: 1,
                borderRadius: 0,
              },
              {
                '& .Mui-disabled': {
                  color: (theme) => {
                    if (themeColor != null) {
                      return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                    }
                    return theme.palette.text.disabled;
                  },
                },
              },
            ]}
            size="small"
          >
            {muteApp ? <VolumeOffIcon /> : <VolumeUpIcon />}
          </IconButton>
          <IconButton
            title="Preferences"
            aria-label="Preferences"
            onClick={() => requestShowPreferencesWindow()}
            sx={[
              {

              },
              !isSidebarExpanded && {
                width: 1,
                borderRadius: 0,
              },
              {
                '& .Mui-disabled': {
                  color: (theme) => {
                    if (themeColor != null) {
                      return `${alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3)} !important`;
                    }
                    return theme.palette.text.disabled;
                  },
                },
              },
            ]}
            size="small"
          >
            <SettingsIcon />
          </IconButton>
        </Box>
        )}
      </Box>
    </ScrollbarContainer>
  );
}
Example #19
Source File: index.js    From neutron with Mozilla Public License 2.0 4 votes vote down vote up
NavigationBar = ({ disableGutter, themeColor }) => {
  const activeWorkspace = useSelector(
    (state) => state.workspaces.workspaces[state.workspaces.activeWorkspaceId],
  );
  const canGoBack = useSelector((state) => state.general.canGoBack);
  const canGoForward = useSelector((state) => state.general.canGoForward);
  const hasWorkspaces = useSelector((state) => Object.keys(state.workspaces.workspaces).length > 0);
  const isLoading = useSelector(
    (state) => (activeWorkspace && state.workspaceMetas[activeWorkspace.id]
      ? Boolean(state.workspaceMetas[activeWorkspace.id].isLoading) : false),
  );

  return (
    <>
      <IconButton
        title="Back"
        aria-label="Back"
        sx={[
          {
            p: 0.75,
            WebkitAppRegion: 'no-drag',
            color: (theme) => {
              if (themeColor != null) {
                return theme.palette.getContrastText(themeColors[themeColor][800]);
              }
              return theme.palette.text.secondary;
            },
          },
          disableGutter && { py: 0 },
        ]}
        disabled={!hasWorkspaces || !canGoBack}
        onClick={requestGoBack}
        size="large"
      >
        <ArrowBackIcon
          sx={[
            { fontSize: 18 },
            // has to apply it here
            // somehow, JSS is not applied correctly for IconButton disabled class
            (!hasWorkspaces || !canGoBack) && {
              color: (theme) => {
                if (themeColor != null) {
                  // eslint-disable-next-line max-len
                  return alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3);
                }
                return theme.palette.text.disabled;
              },
            },
          ]}
        />
      </IconButton>
      <IconButton
        title="Forward"
        aria-label="Forward"
        sx={[
          {
            p: 0.75,
            WebkitAppRegion: 'no-drag',
            color: (theme) => {
              if (themeColor != null) {
                return theme.palette.getContrastText(themeColors[themeColor][800]);
              }
              return theme.palette.text.secondary;
            },
          },
          disableGutter && { py: 0 },
        ]}
        disabled={!hasWorkspaces || !canGoForward}
        onClick={requestGoForward}
        size="large"
      >
        <ArrowForwardIcon
          sx={[
            { fontSize: 18 },
            // has to apply it here
            // somehow, JSS is not applied correctly for IconButton disabled class
            (!hasWorkspaces || !canGoBack) && {
              color: (theme) => {
                if (themeColor != null) {
                  // eslint-disable-next-line max-len
                  return alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3);
                }
                return theme.palette.text.disabled;
              },
            },
          ]}
        />
      </IconButton>
      <IconButton
        title="Reload"
        aria-label="Reload"
        sx={[
          {
            p: 0.75,
            WebkitAppRegion: 'no-drag',
            color: (theme) => {
              if (themeColor != null) {
                return theme.palette.getContrastText(themeColors[themeColor][800]);
              }
              return theme.palette.text.secondary;
            },
          },
          disableGutter && { py: 0 },
        ]}
        onClick={requestReload}
        disabled={!hasWorkspaces || isLoading}
        size="large"
      >
        {isLoading ? (
          <CircularProgress size={18} color="inherit" />
        ) : (
          <RefreshIcon
            sx={{
              fontSize: 18,
              // has to apply it here
              // somehow, JSS is not applied correctly for IconButton disabled class
              color: (theme) => {
                if (themeColor != null) {
                  // eslint-disable-next-line max-len
                  return alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3);
                }
                return theme.palette.text.disabled;
              },
            }}
          />
        )}
      </IconButton>
      <IconButton
        title="Home"
        aria-label="Home"
        sx={[
          {
            p: 0.75,
            WebkitAppRegion: 'no-drag',
            color: (theme) => {
              if (themeColor != null) {
                return theme.palette.getContrastText(themeColors[themeColor][800]);
              }
              return theme.palette.text.secondary;
            },
          },
          disableGutter && { py: 0 },
        ]}
        onClick={requestGoHome}
        disabled={!hasWorkspaces}
        size="large"
      >
        <HomeIcon
          sx={[
            { fontSize: 18 },
            // has to apply it here
            // somehow, JSS is not applied correctly for IconButton disabled class
            !hasWorkspaces && {
              color: (theme) => {
                if (themeColor != null) {
                  // eslint-disable-next-line max-len
                  return alpha(theme.palette.getContrastText(themeColors[themeColor][800]), 0.3);
                }
                return theme.palette.text.disabled;
              },
            },
          ]}
        />
      </IconButton>
    </>
  );
}
Example #20
Source File: index.js    From neutron with Mozilla Public License 2.0 4 votes vote down vote up
EnhancedAppBar = ({ title: _title }) => {
  const appJson = getStaticGlobal('appJson');

  const activeWorkspace = useSelector(
    (state) => state.workspaces.workspaces[state.workspaces.activeWorkspaceId],
  );
  const isMaximized = useSelector((state) => state.general.isMaximized);
  const title = useSelector((state) => _title || ((window.mode === 'main' || window.mode === 'menubar') && state.general.title ? state.general.title : appJson.name));
  const sidebar = useSelector((state) => state.preferences.sidebar);
  const sidebarSize = useSelector((state) => state.preferences.sidebarSize);
  const navigationBar = useSelector((state) => (window.process.platform === 'linux'
  && state.preferences.attachToMenubar
  && !state.preferences.sidebar)
  || state.preferences.navigationBar);
  const themeColor = useSelector((state) => {
    if (window.mode === 'main' || window.mode === 'menubar') {
      if (state.preferences.themeColor === 'auto') {
        if (activeWorkspace && activeWorkspace.preferences && activeWorkspace.preferences.color) {
          return activeWorkspace.preferences.color;
        }
        return null;
      }
      return state.preferences.themeColor;
    }
    return null;
  });

  const onDoubleClick = (e) => {
    // feature: double click on title bar to expand #656
    // https://github.com/webcatalog/webcatalog-app/issues/656
    // https://stackoverflow.com/questions/10554446/no-onclick-when-child-is-clicked
    if (e.target === e.currentTarget) {
      const win = getCurrentWindow();
      if (win.isMaximized()) {
        win.unmaximize();
      } else {
        win.maximize();
      }
    }
  };

  return (
    <AppBar
      position="static"
      sx={{
        // leave space for resizing cursor
        // https://github.com/electron/electron/issues/3022
        p: 0.125,
        background: (theme) => {
          if (themeColor != null) {
            return themeColors[themeColor][900];
          }
          return theme.palette.mode === 'dark' ? undefined : theme.palette.grey[300];
        },
        color: (theme) => {
          if (themeColor != null) {
            return alpha(theme.palette.getContrastText(themeColors[themeColor][900]), 0.7);
          }
          return theme.palette.text.secondary;
        },
      }}
      color="default"
      elevation={0}
    >
      <Toolbar
        variant="dense"
        sx={{
          minHeight: TOOLBAR_HEIGHT,
          height: TOOLBAR_HEIGHT,
          px: '0 !important',
          display: 'flex',
          WebkitAppRegion: 'drag',
          userSelect: 'none',
        }}
      >
        <Box
          sx={{
            // leave space for traffic light buttons
            pl: window.process.platform === 'darwin' && window.mode !== 'menubar' ? 64 : 0,
            boxSizing: 'border-box',
          }}
          onDoubleClick={onDoubleClick}
        >
          {(window.mode !== 'main' && window.mode !== 'menubar') ? null : (
            <IconButton
              size="small"
              color="inherit"
              aria-label="Menu"
              sx={[
                {
                  width: BUTTON_WIDTH,
                  borderRadius: 0,
                  height: TOOLBAR_HEIGHT,
                  '&:hover, &:focus': {
                    backgroundColor: () => {
                      if (window.process.platform === 'win32') return 'rgba(0, 0, 0, 0.04)';
                      return undefined;
                    },
                  },
                },
                sidebar && sidebarSize === 'compact' && {
                  ml: 1.125,
                  mr: 1.325,
                },
                sidebar && sidebarSize === 'expanded' && {
                  width: 36, // same as avatar img size
                  ml: 1,
                  mr: 0,
                },
                { WebkitAppRegion: 'no-drag' },
              ]}
              onClick={(e) => {
                e.stopPropagation();
                requestShowAppMenu(e.x, e.y);
              }}
              disableRipple
            >
              <MenuIcon fontSize="small" />
            </IconButton>
          )}
          {window.mode === 'main' && !navigationBar && (
            <NavigationButtons />
          )}
        </Box>
        <Box
          sx={{
            flex: 1,
            fontSize: '0.8rem',
            height: TOOLBAR_HEIGHT,
            lineHeight: `${TOOLBAR_HEIGHT}px`,
            color: 'inherit',
            whiteSpace: 'nowrap',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            px: 1,
          }}
          onDoubleClick={onDoubleClick}
        >
          {title}
        </Box>
        <Box
          sx={{
            textAlign: 'right',
            boxSizing: 'border-box',
          }}
          onDoubleClick={onDoubleClick}
        >
          {!getStaticGlobal('useSystemWindowButtons') && (
            <Box
              sx={{
                verticalAlign: 'middle',
                display: 'inline-block',
                height: TOOLBAR_HEIGHT,
                ml: 0,
              }}
            >
              <Button
                sx={{
                  minWidth: 46.5,
                  display: 'inline-block',
                  WebkitAppRegion: 'no-drag',
                  height: 1,
                  width: BUTTON_WIDTH,
                  background: 'none',
                  border: 'none',
                  outline: 'none',
                  p: 0,
                  m: 0,
                  '&:hover': {
                    bgcolor: () => {
                      if (themeColor != null) {
                        return themeColors[themeColor][800];
                      }
                      return (theme) => (theme.palette.mode === 'dark' ? theme.palette.common.black : theme.palette.grey[400]);
                    },
                  },
                }}
                type="button"
                tabIndex="-1" // normally, windows buttons is not navigable by keyboard
                aria-label="Minimize"
                onClick={(e) => {
                  e.stopPropagation();
                  const browserWindow = getCurrentWindow();
                  if (window.mode === 'menubar') {
                    browserWindow.hide();
                  } else {
                    browserWindow.minimize();
                  }
                }}
              >
                <Box
                  sx={{
                    height: 1,
                    width: 1,
                    maskSize: '23.1%',
                    backgroundColor: (theme) => {
                      if (themeColor != null) {
                        // eslint-disable-next-line max-len
                        return alpha(theme.palette.getContrastText(themeColors[themeColor][900]), 0.7);
                      }
                      return theme.palette.text.secondary;
                    },
                    cursor: 'pointer',
                    mask: "url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 4.399V5.5H0V4.399h11z' fill='%23000'/%3E%3C/svg%3E\") no-repeat 50% 50%",
                  }}
                />
              </Button>
              {window.mode === 'main' && (
                <Button
                  sx={{
                    minWidth: 46.5,
                    display: 'inline-block',
                    WebkitAppRegion: 'no-drag',
                    height: 1,
                    width: BUTTON_WIDTH,
                    background: 'none',
                    border: 'none',
                    outline: 'none',
                    p: 0,
                    m: 0,
                    '&:hover': {
                      bgcolor: () => {
                        if (themeColor != null) {
                          return themeColors[themeColor][800];
                        }
                        return (theme) => (theme.palette.mode === 'dark' ? theme.palette.common.black : theme.palette.grey[400]);
                      },
                    },
                  }}
                  type="button"
                  tabIndex="-1" // normally, windows buttons is not navigable by keyboard
                  aria-label={isMaximized ? 'Unmaximize' : 'Maximize'}
                  onClick={(e) => {
                    e.stopPropagation();
                    const browserWindow = getCurrentWindow();
                    if (browserWindow.isMaximized()) {
                      browserWindow.unmaximize();
                    } else {
                      browserWindow.maximize();
                    }
                  }}
                >
                  <Box
                    sx={[
                      {
                        height: 1,
                        width: 1,
                        maskSize: '23.1%',
                        bgcolor: (theme) => {
                          if (themeColor != null) {
                            // eslint-disable-next-line max-len
                            return alpha(theme.palette.getContrastText(themeColors[themeColor][900]), 0.7);
                          }
                          return theme.palette.text.secondary;
                        },
                        cursor: 'pointer',
                      },
                      isMaximized && {
                        mask: "url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 8.798H8.798V11H0V2.202h2.202V0H11v8.798zm-3.298-5.5h-6.6v6.6h6.6v-6.6zM9.9 1.1H3.298v1.101h5.5v5.5h1.1v-6.6z' fill='%23000'/%3E%3C/svg%3E\") no-repeat 50% 50%",
                      },
                      !isMaximized && {
                        mask: "url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 0v11H0V0h11zM9.899 1.101H1.1V9.9h8.8V1.1z' fill='%23000'/%3E%3C/svg%3E\") no-repeat 50% 50%",
                      },
                    ]}
                  />
                </Button>
              )}
              {window.mode !== 'menubar' && (
                <Button
                  sx={{
                    minWidth: 46.5,
                    display: 'inline-block',
                    WebkitAppRegion: 'no-drag',
                    height: 1,
                    width: BUTTON_WIDTH,
                    background: 'none',
                    border: 'none',
                    outline: 'none',
                    p: 0,
                    m: 0,
                    '&:hover': {
                      bgcolor: () => {
                        if (themeColor != null) {
                          return themeColors[themeColor][800];
                        }
                        return (theme) => (theme.palette.mode === 'dark' ? theme.palette.common.black : theme.palette.grey[400]);
                      },
                    },
                  }}
                  type="button"
                  tabIndex="-1" // normally, windows buttons is not navigable by keyboard
                  aria-label={isMaximized ? 'Unmaximize' : 'Maximize'}
                  onClick={(e) => {
                    e.stopPropagation();
                    const browserWindow = getCurrentWindow();
                    browserWindow.close();
                  }}
                >
                  <Box
                    sx={{
                      height: 1,
                      width: 1,
                      maskSize: '23.1%',
                      backgroundColor: (theme) => {
                        if (themeColor != null) {
                          // eslint-disable-next-line max-len
                          return alpha(theme.palette.getContrastText(themeColors[themeColor][900]), 0.7);
                        }
                        return theme.palette.text.secondary;
                      },
                      cursor: 'pointer',
                      mask: "url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.279 5.5L11 10.221l-.779.779L5.5 6.279.779 11 0 10.221 4.721 5.5 0 .779.779 0 5.5 4.721 10.221 0 11 .779 6.279 5.5z' fill='%23000'/%3E%3C/svg%3E\") no-repeat 50% 50%",
                    }}
                  />
                </Button>
              )}
            </Box>
          )}
        </Box>
      </Toolbar>
    </AppBar>
  );
}