@mui/material#Toolbar TypeScript Examples
The following examples show how to use
@mui/material#Toolbar.
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: GridAppbar.tsx From frontend with MIT License | 6 votes |
export default function GridAppbar() {
const router = useRouter()
const { t } = useTranslation()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>{t('countries:headings.countries')}</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title={t('countries:tooltips.add') || ''}>
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => router.push(routes.admin.countries.create)}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #2
Source File: toast.tsx From NekoMaid with MIT License | 6 votes |
Snackbars: React.FC = () => {
const [, updateF] = useState<number>(0)
useEffect(() => {
update = updateF
return () => { update = undefined as any }
})
return <Box sx={{
position: 'fixed',
top: 12,
right: 44,
zIndex: theme => theme.zIndex.modal + 1,
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-end',
pointerEvents: 'none'
}}><Toolbar sx={{ padding: '0!important' }} />{Object.values(toasts).map(it => React.createElement(Snackbar, it))}</Box>
}
Example #3
Source File: InfoRequestBottomAppBar.tsx From frontend with MIT License | 6 votes |
export default function InfoRequestBottomAppBar() {
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>Всички заявки за контакт</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="Преглед">
<EventNoteIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Запази">
<SaveIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Принт">
<PrintIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Сподели">
<ShareIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Добави">
<AddIcon sx={addIconStyles} fontSize="large" />
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #4
Source File: PlayerList.tsx From NekoMaid with MIT License | 6 votes |
PlayerList: React.FC = () => {
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3}>
<Grid item lg={8} md={12} xl={9} xs={12}><Players /></Grid>
<Grid item lg={4} md={6} xl={3} xs={12}><PlayerActions /></Grid>
</Grid>
</Container>
</Box>
}
Example #5
Source File: GridAppbar.tsx From frontend with MIT License | 6 votes |
export default function GridAppbar() {
const router = useRouter()
const { t } = useTranslation('benefactor')
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>{t('benefactor')}</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title={t('cta.add') || ''}>
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => router.push(routes.admin.benefactor.add)}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #6
Source File: Config.tsx From NekoMaid with MIT License | 6 votes |
Config: React.FC = () => {
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3}>
{configs.map((it, i) => <Grid key={i} item lg={4} md={12} xl={6} xs={12}>
<Card>
<CardHeader title={it.title} />
<Divider />
<it.component />
</Card>
</Grid>)}
</Grid>
</Container>
</Box>
}
Example #7
Source File: GridAppbar.tsx From frontend with MIT License | 6 votes |
export default function GridAppbar() {
const router = useRouter()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>Всички градове</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="Добави">
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => {
router.push(routes.admin.cities.create)
}}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #8
Source File: client.tsx From mui-toolpad with MIT License | 6 votes |
function ConnectionParamsInput({ value, onChange }: ConnectionEditorProps<MoviesConnectionParams>) {
const { handleSubmit, register, formState, reset } = useForm({
defaultValues: withDefaults(value),
});
React.useEffect(() => reset(withDefaults(value)), [reset, value]);
const doSubmit = handleSubmit((connectionParams) => onChange(connectionParams));
return (
<Stack direction="column" gap={1}>
<Toolbar disableGutters>
<Button onClick={doSubmit} disabled={!formState.isDirty || !formState.isValid}>
Save
</Button>
</Toolbar>
<TextField
label="API key"
{...register('apiKey', { required: true })}
{...validation(formState, 'apiKey')}
/>
</Stack>
);
}
Example #9
Source File: GridAppbar.tsx From frontend with MIT License | 6 votes |
export default function GridAppbar() {
const router = useRouter()
const { t } = useTranslation()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>{t('documents:all')}</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title={t('documents:cta:add') || ''}>
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => router.push(routes.admin.documents.create)}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #10
Source File: app-bar.component.tsx From master-frontend-lemoncode with MIT License | 6 votes |
AppBarComponent: React.FunctionComponent = () => {
return (
<AppBar position="static">
<Toolbar variant="dense" className={classes.root}>
<img className={classes.logo} src={logo} />
</Toolbar>
</AppBar>
);
}
Example #11
Source File: Header.tsx From mojito_pdm with Creative Commons Attribution Share Alike 4.0 International | 6 votes |
Header: React.FC = () => {
const [colorMode, setColorMode] = useRecoilState(GlobalState.theme)
const {setVisible} = useVisibility()
const handleExit = async () => {
try {
await fetchNui("exit")
setVisible(false);
} catch (e) {
console.error(e)
}
}
const handleThemeswitch = () => {
colorMode === "light" ? setColorMode("dark") : setColorMode("light")
}
return (
<AppBar position="sticky">
<Toolbar sx={{backgroundColor: "primary.dark"}}>
<Typography sx={{flex: 1}}>
<img src={logo} height="100px" alt=""/>
</Typography>
<CategorySelect/>
<IconButton sx={{ml: 1}} onClick={handleThemeswitch} color="inherit">
{colorMode === 'dark' ? <Brightness7Icon/> : <Brightness4Icon/>}
</IconButton>
<IconButton sx={{ml: 1}} onClick={handleExit} color="inherit">
<CloseIcon/>
</IconButton>
</Toolbar>
</AppBar>
)
}
Example #12
Source File: GridAppbar.tsx From frontend with MIT License | 6 votes |
export default function GridAppbar() {
const router = useRouter()
const { t } = useTranslation()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>{t('vaults:all')}</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title={t('vaults:cta:add') || ''}>
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => router.push(routes.admin.vaults.create)}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #13
Source File: DetailFrame.tsx From airmessage-web with Apache License 2.0 | 6 votes |
DetailFrame = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
return (
<div className={styles.root} ref={ref}>
<Toolbar>
<Typography className={styles.title} variant="h6" noWrap>{props.title}</Typography>
{props.showCall && (
<IconButton
size="large"
onClick={props.onClickCall}>
<VideocamOutlined />
</IconButton>
)}
</Toolbar>
<SoftDivider />
{props.children}
</div>
);
})
Example #14
Source File: GridAppbar.tsx From frontend with MIT License | 6 votes |
export default function GridAppbar() {
const router = useRouter()
const { t } = useTranslation()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>{t('withdrawals:all')}</Typography>
</Box>
<Box sx={{ display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title={t('withdrawals:cta:add') || ''}>
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => router.push(routes.admin.withdrawals.create)}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #15
Source File: header.tsx From example with MIT License | 6 votes |
export function Header() {
return (
<AppBar position={"static"}>
<Container maxWidth={"xl"} disableGutters>
<Toolbar>
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
Rarible SDK Example
</Typography>
<ConnectionStatus/>
</Toolbar>
</Container>
</AppBar>
)
}
Example #16
Source File: GridAppbar.tsx From frontend with MIT License | 6 votes |
export default function GridAppbar() {
const router = useRouter()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>Всички разходи</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="Добави">
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => router.push(routes.admin.expenses.create)}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #17
Source File: EnhancedTableToolbar.tsx From yearn-watch-legacy with GNU Affero General Public License v3.0 | 6 votes |
EnhancedTableToolbar = (props: EnhancedTableToolbarProps) => {
const classes = useToolbarStyles();
return (
<Toolbar className={clsx(classes.root)}>
<Typography
className={classes.title}
variant="h6"
id="tableTitle"
component="div"
align="center"
>
{props.title}
</Typography>
</Toolbar>
);
}
Example #18
Source File: GridAppbar.tsx From frontend with MIT License | 5 votes |
export default function GridAppbar() {
const router = useRouter()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>Всички банкови сметки</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="Преглед">
<EventNoteIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Запази">
<SaveIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Принт">
<PrintIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Сподели">
<ShareIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Добави">
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => {
router.push(routes.admin.bankaccounts.add)
}}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #19
Source File: Profiler.tsx From NekoMaid with MIT License | 5 votes |
Profiler: React.FC = () => { const plugin = usePlugin() const theme = useTheme() const globalData = useGlobalData() const [tab, setTab] = useState(0) const [key, setTKey] = useState(0) const [status, setStatus] = useState(!!globalData.profilerStarted) useEffect(() => { const off = plugin.on('profiler:status', setStatus) return () => { off() } }, []) const transitionDuration = { enter: theme.transitions.duration.enteringScreen, exit: theme.transitions.duration.leavingScreen } const Elm = components[tab] const createFab = (onClick: any, children: any, show: boolean) => <Zoom in={show} timeout={transitionDuration} style={{ transitionDelay: (show ? transitionDuration.exit : 0) + 'ms' }} unmountOnExit > <Fab color='primary' sx={{ position: 'fixed', bottom: { xs: 16, sm: 40 }, right: { xs: 16, sm: 40 }, zIndex: 3 }} onClick={onClick} >{children}</Fab> </Zoom> return <Box sx={{ minHeight: status || !tab ? '100%' : undefined }}> <Toolbar /> <Paper square variant='outlined' sx={{ margin: '0 -1px', position: 'fixed', width: 'calc(100% + 1px)', zIndex: 3 }}> <Tabs value={tab} onChange={(_, it) => setTab(it)} variant='scrollable' scrollButtons='auto'> <Tab label={lang.profiler.summary} /> <Tab label='Timings' disabled={!globalData.hasTimings} /> <Tab label={lang.profiler.plugins} /> <Tab label={lang.profiler.carbageCollection} /> <Tab label={lang.profiler.entities} /> <Tab label={lang.profiler.heap} /> <Tab label={lang.profiler.threads} /> </Tabs> </Paper> <Tabs /> {tab < 4 && !status ? <Box sx={{ textAlign: 'center', marginTop: '40vh' }}>{lang.profiler.notStarted}</Box> : Elm && <Elm key={key} />} {createFab(() => plugin.emit('profiler:status', !status), status ? <Stop /> : <PlayArrow />, tab < 4)} {createFab(() => setTKey(key + 1), <Refresh />, tab >= 4)} </Box> }
Example #20
Source File: BitcoinStatusBar.tsx From sapio-studio with Mozilla Public License 2.0 | 5 votes |
export function BitcoinStatusBar(props: BitcoinStatusBarProps) {
const theme = useTheme();
const freq = useSelector(selectNodePollFreq);
const [balance, setBalance] = React.useState<number>(0);
const [blockchaininfo, setBlockchaininfo] = React.useState<any>(null);
React.useEffect(() => {
let next: ReturnType<typeof setTimeout> | null = null;
let mounted = true;
const periodic_update_stats = async () => {
next = null;
try {
const balance = await props.api.check_balance();
setBalance(balance);
} catch (err) {
console.error(err);
setBalance(0);
}
try {
const info = await props.api.blockchaininfo();
console.log(balance);
setBlockchaininfo(info);
} catch (err) {
console.error(err);
setBlockchaininfo(null);
}
if (mounted) {
let prefs = freq;
prefs = clamp(prefs ?? 0, 5, 5 * 60);
console.log('StatusBar', 'NEXT PERIODIC CHECK IN ', prefs);
next = setTimeout(periodic_update_stats, prefs * 1000);
}
};
let prefs = freq;
prefs = clamp(prefs ?? 0, 5, 5 * 60);
next = setTimeout(periodic_update_stats, prefs * 1000);
return () => {
mounted = false;
if (next !== null) clearTimeout(next);
};
}, []);
const network = blockchaininfo?.chain ?? 'disconnected';
const headers = blockchaininfo?.headers ?? '?';
const blocks = blockchaininfo?.headers ?? '?';
return (
<Paper
square={true}
sx={{
top: 'auto',
bottom: 0,
}}
className="BitcoinStatusBar Draggable"
style={{
background: theme.palette.background.default,
color: theme.palette.info.main,
}}
>
<Toolbar variant="dense">
<Typography variant="h6" color="inherit" component="div">
<div>chain: {network}</div>
</Typography>
<Typography variant="h6" color="inherit" component="div">
<div style={{ marginLeft: '0.5em' }}>
balance: {balance} BTC
</div>
</Typography>
<Typography variant="h6" color="inherit" component="div">
<div style={{ marginLeft: '0.5em' }}>
processed: {blocks}/{headers}
</div>
</Typography>
</Toolbar>
</Paper>
);
}
Example #21
Source File: Navbar.tsx From website with Apache License 2.0 | 5 votes |
StyledToolbar = styled(Toolbar)<{ scrollPos: number }>`
box-shadow: ${({ scrollPos }) => (scrollPos > 10 ? "initial" : "unset")};
`
Example #22
Source File: client.tsx From mui-toolpad with MIT License | 5 votes |
function ConnectionParamsInput({
value,
onChange,
}: ConnectionEditorProps<PostgresConnectionParams>) {
const { handleSubmit, register, formState, reset } = useForm({
defaultValues: withDefaults(value),
reValidateMode: 'onChange',
mode: 'all',
});
React.useEffect(() => reset(withDefaults(value)), [reset, value]);
const doSubmit = handleSubmit((connectionParams) => onChange(connectionParams));
return (
<Stack direction="column" gap={1}>
<Toolbar disableGutters>
<Button onClick={doSubmit} disabled={!formState.isDirty || !formState.isValid}>
Save
</Button>
</Toolbar>
<TextField
label="host"
{...register('host', { required: true })}
{...validation(formState, 'host')}
/>
<TextField
label="port"
{...register('port', { required: true })}
{...validation(formState, 'port')}
/>
<TextField
label="user"
{...register('user', { required: true })}
{...validation(formState, 'user')}
/>
<TextField
label="password"
type="password"
{...register('password', { required: true })}
{...validation(formState, 'password')}
/>
<TextField
label="database"
{...register('database', { required: true })}
{...validation(formState, 'database')}
/>
</Stack>
);
}
Example #23
Source File: GridAppbar.tsx From frontend with MIT License | 5 votes |
export default function GridAppbar() {
const router = useRouter()
return (
<Toolbar
sx={{
background: 'white',
borderTop: '1px solid lightgrey',
display: 'flex',
justifyContent: 'space-between',
height: '72px',
}}>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'start', pt: 1 }}>
<Typography>Всички координатори</Typography>
</Box>
<Box sx={{ height: '64px', display: 'flex', alignItems: 'flex-end', pb: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="Преглед">
<EventNoteIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Запази">
<SaveIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Принт">
<PrintIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Сподели">
<ShareIcon sx={iconStyles} fontSize="medium" color="action" />
</Tooltip>
<Tooltip title="Добави">
<AddIcon
sx={addIconStyles}
fontSize="large"
onClick={() => router.push(routes.admin.coordinators.add)}
/>
</Tooltip>
</Box>
</Box>
</Toolbar>
)
}
Example #24
Source File: MessageAttachmentImage.tsx From airmessage-web with Apache License 2.0 | 5 votes |
export default function MessageAttachmentImage(props: {data: ArrayBuffer | Blob, name: string, type: string, partProps: MessagePartProps, tapbacks?: TapbackItem[], stickers?: StickerItem[]}) {
const [imageURL, setImageURL] = useState<string | undefined>(undefined);
const [previewOpen, setPreviewOpen] = useState(false);
const theme = createTheme({
palette: {
mode: "dark",
messageIncoming: undefined,
messageOutgoing: undefined,
messageOutgoingTextMessage: undefined
}
});
useEffect(() => {
//Creating a new image URL
const imageURL = URL.createObjectURL(props.data instanceof Blob ? props.data : new Blob([props.data], {type: props.type}));
//Setting the image URL
setImageURL(imageURL);
//Cleaning up the URL
return () => URL.revokeObjectURL(imageURL);
}, [props.data, props.type, setImageURL]);
function downloadFile(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
//So that we don't dismiss the backdrop
event.stopPropagation();
if(!imageURL) return;
downloadURL(imageURL, props.type, props.name);
}
//All of the styles, without the border radius
const buttonStyle: Partial<MessagePartProps> = {...props.partProps};
delete buttonStyle["borderRadius"];
return (
<React.Fragment>
<ThemeProvider theme={theme}>
<Backdrop className={stylesImage.lightboxBackdrop} open={previewOpen} onClick={() => setPreviewOpen(false)}>
<Toolbar className={stylesImage.lightboxToolbar}>
<IconButton edge="start">
<ArrowBack />
</IconButton>
<Typography variant="h6" color="textPrimary" style={{flexGrow: 1}}>{props.name}</Typography>
<Tooltip title="Save">
<IconButton onClick={downloadFile}>
<SaveAlt />
</IconButton>
</Tooltip>
</Toolbar>
<div className={stylesImage.lightboxContainer}>
<div style={{width: "100%", height: "100%", backgroundImage: `url("${imageURL}")`, backgroundPosition: "center", backgroundRepeat: "no-repeat", backgroundSize: "contain"}} />
</div>
</Backdrop>
</ThemeProvider>
<DecorativeMessageBubble element={ButtonBase} className={styles.contentBubble} style={props.partProps} onClick={() => setPreviewOpen(true)} tapbacks={props.tapbacks} stickers={props.stickers}>
<img src={imageURL} style={{borderRadius: props.partProps.borderRadius}} alt="" />
</DecorativeMessageBubble>
{/*<ButtonBase className={styles.contentBubble} style={props.partProps} onClick={() => setPreviewOpen(true)}>*/}
{/* <img src={imageURL} style={{borderRadius: props.partProps.borderRadius}} alt="" />*/}
{/*</ButtonBase>*/}
</React.Fragment>
);
}
Example #25
Source File: Header.tsx From genshin-optimizer with MIT License | 5 votes |
function MobileHeader({ anchor, currentTab }) {
const [mobileOpen, setMobileOpen] = useState(false);
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
const { t } = useTranslation("ui")
return <>
<AppBar position="fixed" sx={{ bgcolor: "#343a40" }} elevation={0} >
<Drawer
anchor="right"
variant="temporary"
open={mobileOpen}
onClose={handleDrawerToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
<List>
<ListItemButton key="home" component={RouterLink} to={'/'} selected={currentTab === ""} disabled={currentTab === ""} onClick={handleDrawerToggle} >
<ListItemText>{t("pageTitle")}</ListItemText>
</ListItemButton >
{content.map(({ i18Key, value, to, svg }) =>
<ListItemButton key={value} component={RouterLink} to={to} selected={currentTab === value} disabled={currentTab === value} onClick={handleDrawerToggle} >
<ListItemIcon><FontAwesomeIcon icon={svg} /></ListItemIcon>
<ListItemText>{t(i18Key)}</ListItemText>
</ListItemButton >)}
</List>
<Divider />
<List>
{links.map(({ i18Key, href, svg, label }) =>
<ListItemButton key={label} component="a" href={href} target="_blank" onClick={e => ReactGA.outboundLink({ label }, () => { })} >
<ListItemIcon><FontAwesomeIcon icon={svg} /></ListItemIcon>
<ListItemText>{t(i18Key)}</ListItemText>
</ListItemButton >)}
</List>
</Drawer>
<Toolbar>
<Button variant="text" sx={{ color: "white" }} component={RouterLink} to="/">
<Typography variant="h6" noWrap component="div">
<Trans t={t} i18nKey="pageTitle">Genshin Optimizer</Trans>
</Typography>
</Button>
<Box flexGrow={1} />
<IconButton
color="inherit"
aria-label="open drawer"
edge="end"
onClick={handleDrawerToggle}
>
<MenuIcon />
</IconButton>
</Toolbar>
</AppBar>
{/* add a blank toolbar to keep space and provide a scroll anchor */}
<Toolbar id={anchor} />
</>
}
Example #26
Source File: AppNavBar.tsx From frontend with MIT License | 4 votes |
export default function AppNavBar({ navMenuToggle }: AppBarDeckProps) {
const { locale } = useRouter()
const { status } = useSession()
const shrink = useScrollTrigger()
return (
<AppBar
position="fixed"
className={clsx({ shrink })}
sx={(theme) => ({
overflow: 'hidden',
transition: 'height .5s, background-color .5s ease 0s',
height: theme.spacing(14),
lineHeight: theme.spacing(14),
[theme.breakpoints.down('md')]: {
height: theme.spacing(10),
},
'&.shrink': {
height: theme.spacing(10),
lineHeight: theme.spacing(10),
backgroundColor: 'hsla(0,0%,100%,0.85)',
backdropFilter: 'saturate(180%) blur(5px)',
},
backgroundColor: theme.palette.common.white,
})}>
<Toolbar
sx={{
height: '100%',
display: 'flex',
justifyContent: 'space-between',
}}>
<Link href={routes.index} passHref>
<ButtonBase
component="a"
className={clsx({ shrink })}
sx={(theme) => ({
transition: 'height .5s',
height: theme.spacing(7.5),
minWidth: theme.spacing(15),
marginLeft: theme.spacing(5),
[theme.breakpoints.up('lg')]: {
marginLeft: theme.spacing(10),
},
[theme.breakpoints.down('md')]: {
marginLeft: 0,
width: '100%',
height: '50%',
},
'&.shrink': {
height: '50%',
},
'& > svg': {
display: 'block',
height: '100%',
},
})}>
<PodkrepiLogo locale={locale} variant="adaptive" />
</ButtonBase>
</Link>
<Hidden mdDown>
<Grid
container
wrap="nowrap"
direction="row"
justifyContent="flex-end"
sx={(theme) => ({
marginLeft: theme.spacing(2),
marginRight: theme.spacing(5),
[theme.breakpoints.up('lg')]: {
marginRight: theme.spacing(10),
},
})}>
<Grid item>
<MainNavMenu>
{status === 'authenticated' ? <PrivateMenu /> : <PublicMenu />}
<Grid item>
<LocaleButton />
</Grid>
</MainNavMenu>
</Grid>
</Grid>
</Hidden>
<Hidden mdUp>
<IconButton
size="small"
edge="end"
onClick={navMenuToggle}
aria-labelledby="navigation menu">
<Menu fontSize="large" />
</IconButton>
</Hidden>
</Toolbar>
</AppBar>
)
}
Example #27
Source File: Files.tsx From NekoMaid with MIT License | 4 votes |
Files: React.FC = () => {
const plugin = usePlugin()
const theme = useTheme()
const his = useHistory()
const loc = useLocation()
const drawerWidth = useDrawerWidth()
const tree = useRef<HTMLHRElement | null>(null)
const editor = useRef<UnControlled | null>(null)
const prevExpanded = useRef<string[]>([])
const dirs = useRef<Record<string, boolean>>({ })
// eslint-disable-next-line func-call-spacing
const loading = useRef<Record<string, () => Promise<void>> & { '!#LOADING'?: boolean }>({ })
const [id, setId] = useState(0)
const [curPath, setCurPath] = useState('')
const [progress, setProgress] = useState(-1)
const [copyPath, setCopyPath] = useState('')
const [expanded, setExpanded] = useState<string[]>([])
const [compressFile, setCompressFile] = useState<string | null>(null)
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null)
const isDir = !!dirs.current[curPath]
const dirPath = isDir ? curPath : curPath.substring(0, curPath.lastIndexOf('/'))
const spacing = theme.spacing(3)
const refresh = () => {
loading.current = { }
dirs.current = { }
prevExpanded.current = []
setCurPath('')
setExpanded([])
setId(id + 1)
}
useEffect(() => {
if (!tree.current) return
const resize = () => {
if (!tree.current) return
const height = tree.current.style.maxHeight = (window.innerHeight - tree.current.offsetTop - parseInt(spacing)) + 'px'
const style = (editor as any).current?.editor?.display?.wrapper?.style
if (style) style.height = height
}
resize()
window.addEventListener('resize', resize)
return window.removeEventListener('resize', resize)
}, [tree.current, spacing])
return <Box sx={{ height: '100vh', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3} sx={{ width: { sm: `calc(100vw - ${drawerWidth}px - ${theme.spacing(3)})` } }}>
<Grid item lg={4} md={12} xl={3} xs={12}>
<Card sx={{ minHeight: 400 }}>
<CardHeader
title={lang.files.filesList}
sx={{ position: 'relative' }}
action={<Box sx={{ position: 'absolute', right: theme.spacing(1), top: '50%', transform: 'translateY(-50%)' }}
>
<Tooltip title={lang.files.delete}><span>
<IconButton
disabled={!curPath}
size='small'
onClick={() => dialog({
okButton: { color: 'error' },
content: <>{lang.files.confirmDelete(<span className='bold'>{curPath}</span>)}
<span className='bold' style={{ color: theme.palette.error.main }}>({lang.unrecoverable})</span></>
}).then(it => it && plugin.emit('files:update', (res: boolean) => {
action(res)
if (!res) return
refresh()
if (loc.pathname.replace(/^\/NekoMaid\/files\/?/, '') === curPath) his.push('/NekoMaid/files')
}, curPath))}
><DeleteForever /></IconButton>
</span></Tooltip>
<Tooltip title={lang.files.createFile}>
<IconButton size='small' onClick={() => fileNameDialog(lang.files.createFile, curPath)
.then(it => it != null && his.push(`/NekoMaid/files/${dirPath ? dirPath + '/' : ''}${it}`))}>
<Description /></IconButton></Tooltip>
<Tooltip title={lang.files.createFolder}>
<IconButton size='small' onClick={() => fileNameDialog(lang.files.createFolder, curPath)
.then(it => it != null && plugin.emit('files:createDirectory', (res: boolean) => {
action(res)
if (res) refresh()
}, dirPath + '/' + it))}><CreateNewFolder /></IconButton></Tooltip>
<Tooltip title={lang.more}>
<IconButton size='small' onClick={e => setAnchorEl(anchorEl ? null : e.currentTarget)}><MoreHoriz /></IconButton>
</Tooltip>
</Box>} />
<Divider />
<TreeView
ref={tree}
defaultCollapseIcon={<ArrowDropDown />}
defaultExpandIcon={<ArrowRight />}
sx={{ flexGrow: 1, width: '100%', overflowY: 'auto' }}
expanded={expanded}
onNodeToggle={(_: any, it: string[]) => {
const l = loading.current
if (it.length < prevExpanded.current.length || !l[it[0]]) {
setExpanded(it)
prevExpanded.current = it
return
}
l[it[0]]().then(() => {
prevExpanded.current.unshift(it[0])
setExpanded([...prevExpanded.current])
delete l[it[0]]
})
delete l[it[0]]
}}
onNodeSelect={(_: any, it: string) => {
setCurPath(it[0] === '/' ? it.slice(1) : it)
if (dirs.current[it] || loading.current['!#LOADING']) return
if (it.startsWith('/')) it = it.slice(1)
his.push('/NekoMaid/files/' + it)
}}
>
<Item plugin={plugin} path='' loading={loading.current} dirs={dirs.current} key={id} />
</TreeView>
</Card>
</Grid>
<Grid item lg={8} md={12} xl={9} xs={12} sx={{ maxWidth: `calc(100vw - ${theme.spacing(1)})`, paddingBottom: 3 }}>
<Editor plugin={plugin} editorRef={editor} loading={loading.current} dirs={dirs.current} refresh={refresh} />
</Grid>
</Grid>
</Container>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
anchorOrigin={anchorOrigin}
transformOrigin={anchorOrigin}
>
<MenuItem onClick={() => {
refresh()
setAnchorEl(null)
}}><ListItemIcon><Refresh /></ListItemIcon>{lang.refresh}</MenuItem>
<MenuItem disabled={!curPath} onClick={() => {
setAnchorEl(null)
fileNameDialog(lang.files.rename, curPath).then(it => it != null && plugin.emit('files:rename', (res: boolean) => {
action(res)
if (res) refresh()
}, curPath, dirPath + '/' + it))
}}><ListItemIcon><DriveFileRenameOutline /></ListItemIcon>{lang.files.rename}</MenuItem>
<MenuItem disabled={!curPath} onClick={() => {
setAnchorEl(null)
setCopyPath(curPath)
}}>
<ListItemIcon><FileCopy /></ListItemIcon>{lang.files.copy}
</MenuItem>
<MenuItem disabled={!copyPath} onClick={() => {
setAnchorEl(null)
toast(lang.files.pasting)
plugin.emit('files:copy', (res: boolean) => {
action(res)
refresh()
}, copyPath, dirPath)
}}>
<ListItemIcon><ContentPaste /></ListItemIcon>{lang.files.paste}
</MenuItem>
<MenuItem disabled={progress !== -1} component='label' htmlFor='NekoMaid-files-upload-input' onClick={() => setAnchorEl(null)}>
<ListItemIcon><Upload /></ListItemIcon>{progress === -1 ? lang.files.upload : `${lang.files.uploading} (${progress.toFixed(2)}%)`}
</MenuItem>
<MenuItem disabled={isDir} onClick={() => {
setAnchorEl(null)
toast(lang.files.downloading)
plugin.emit('files:download', (res: ArrayBuffer | null) => {
if (res) window.open(address! + 'Download/' + res, '_blank')
else failed()
}, curPath)
}}><ListItemIcon><Download /></ListItemIcon>{lang.files.download}</MenuItem>
<MenuItem onClick={() => {
setAnchorEl(null)
setCompressFile(curPath)
}}><ListItemIcon><Inbox /></ListItemIcon>{lang.files.compress}</MenuItem>
<MenuItem onClick={() => {
setAnchorEl(null)
toast(lang.files.uncompressing)
plugin.emit('files:compress', (res: boolean) => {
action(res)
refresh()
}, curPath)
}}><ListItemIcon><Outbox /></ListItemIcon>{lang.files.decompress}</MenuItem>
</Menu>
<Input id='NekoMaid-files-upload-input' type='file' sx={{ display: 'none' }} onChange={e => {
const elm = e.target as HTMLInputElement
const file = elm.files?.[0]
elm.value = ''
if (!file) return
const size = file.size
if (size > 128 * 1024 * 1024) return failed(lang.files.uploadTooBig)
toast(lang.files.uploading)
const name = dirPath + '/' + file.name
if (dirs.current[name] != null) return failed(lang.files.exists)
plugin.emit('files:upload', (res: string | null) => {
if (!res) return failed(lang.files.exists)
const formdata = new FormData()
formdata.append('file', file)
const xhr = new XMLHttpRequest()
setProgress(0)
xhr.open('put', address! + 'Upload/' + res)
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return
setProgress(-1)
action(xhr.status === 200)
refresh()
}
xhr.upload.onprogress = e => e.lengthComputable && setProgress(e.loaded / e.total * 100)
xhr.send(formdata)
}, name[0] === '/' ? name.slice(1) : name)
}} />
<CompressDialog file={compressFile} path={dirPath} dirs={dirs.current} onClose={() => setCompressFile(null)} refresh={refresh} plugin={plugin} />
</Box>
}
Example #28
Source File: index.tsx From mui-toolpad with MIT License | 4 votes |
function ApiEditorContent<Q>({ appId, className, apiNode }: ApiEditorContentProps<Q>) {
const domApi = useDomApi();
const dom = useDom();
const [apiQuery, setApiQuery] = React.useState<Q>(apiNode.attributes.query.value);
const savedQuery = React.useRef(apiNode.attributes.query.value);
const [transformEnabled, setTransformEnabled] = React.useState<boolean>(
apiNode.attributes.transformEnabled?.value ?? false,
);
const savedTransformEnabled = React.useRef(apiNode.attributes.transformEnabled?.value);
const [transform, setTransform] = React.useState<string>(
apiNode.attributes.transform?.value ?? '(data) => { return data }',
);
const savedTransform = React.useRef(apiNode.attributes.transform?.value);
const conectionId = apiNode.attributes.connectionId.value as NodeId;
const connection = appDom.getMaybeNode(dom, conectionId, 'connection');
const dataSourceName = apiNode.attributes.dataSource.value;
const dataSource = dataSources[dataSourceName] || null;
const previewApi: appDom.ApiNode<Q> = React.useMemo(() => {
return {
...apiNode,
attributes: {
...apiNode.attributes,
query: appDom.createConst(apiQuery),
transformEnabled: appDom.createConst(transformEnabled),
transform: appDom.createConst(transform),
},
};
}, [apiNode, apiQuery, transformEnabled, transform]);
const debouncedPreviewApi = useDebounced(previewApi, 250);
const previewQuery = useQuery(['api', debouncedPreviewApi], async () =>
client.query.execApi(appId, debouncedPreviewApi, {}),
);
const handleConnectionChange = React.useCallback(
(newConnectionId) => {
if (apiNode) {
domApi.setNodeNamespacedProp(
apiNode,
'attributes',
'connectionId',
appDom.createConst(newConnectionId),
);
}
},
[apiNode, domApi],
);
const handleTransformFnChange = React.useCallback((newValue: string) => {
setTransform(newValue);
}, []);
const handleTransformEnabledChange = React.useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
setTransformEnabled(event.target.checked);
},
[],
);
const handleSave = React.useCallback(() => {
(Object.keys(apiQuery) as (keyof Q)[]).forEach((propName) => {
if (typeof propName !== 'string' || !apiQuery[propName]) {
return;
}
domApi.setNodeNamespacedProp(apiNode, 'attributes', 'query', appDom.createConst(apiQuery));
domApi.setNodeNamespacedProp(
apiNode,
'attributes',
'transform',
appDom.createConst(transform),
);
domApi.setNodeNamespacedProp(
apiNode,
'attributes',
'transformEnabled',
appDom.createConst(transformEnabled),
);
});
savedQuery.current = apiQuery;
savedTransform.current = transform;
savedTransformEnabled.current = transformEnabled;
}, [apiNode, apiQuery, domApi, transform, transformEnabled]);
useShortcut({ code: 'KeyS', metaKey: true }, handleSave);
const allChangesAreCommitted =
savedQuery.current === apiQuery &&
savedTransformEnabled.current === transformEnabled &&
savedTransform.current === transform;
usePrompt(
'Your API has unsaved changes. Are you sure you want to navigate away? All changes will be discarded.',
!allChangesAreCommitted,
);
if (!dataSource) {
return (
<NotFoundEditor className={className} message={`DataSource "${dataSourceName}" not found`} />
);
}
const previewIsInvalid: boolean = !connection && !previewQuery.isError;
return (
<Box sx={{ width: '100%', height: '100%' }}>
<SplitPane
split="horizontal"
allowResize
defaultSize="60%"
paneStyle={{
width: '100%',
overflowY: 'auto',
display: 'block',
}}
>
<Stack sx={{ width: '100%', p: 3 }}>
<Stack direction="row" gap={2}>
<NodeNameEditor node={apiNode} />
<ConnectionSelect
dataSource={dataSourceName}
value={connection?.id ?? null}
onChange={handleConnectionChange}
/>
</Stack>
<Toolbar disableGutters>
<Button onClick={handleSave} disabled={allChangesAreCommitted}>
Update
</Button>
</Toolbar>
<Stack spacing={2}>
{connection ? (
<dataSource.QueryEditor
appId={appId}
connectionId={connection.id}
// TODO: Add disabled mode to QueryEditor
// disabled={!connection}
value={apiQuery}
onChange={(newApiQuery) => setApiQuery(newApiQuery)}
globalScope={{}}
/>
) : null}
<Stack>
<FormControlLabel
label="Transform API response"
control={
<Checkbox
checked={transformEnabled}
onChange={handleTransformEnabledChange}
inputProps={{ 'aria-label': 'controlled' }}
/>
}
/>
</Stack>
{transformEnabled ? (
<JsExpressionEditor
globalScope={{}}
value={transform}
onChange={handleTransformFnChange}
/>
) : null}
</Stack>
</Stack>
{previewQuery.isLoading || (previewIsInvalid && previewQuery.isFetching) ? (
<LinearProgress />
) : null}
<Box sx={{ p: 2 }}>
{previewQuery.isError ? (
<Alert severity="error">{(previewQuery.error as Error).message}</Alert>
) : null}
{!previewIsInvalid && previewQuery.isSuccess ? (
<JsonView src={previewQuery.data} />
) : null}
</Box>
</SplitPane>
</Box>
);
}
Example #29
Source File: Layout.tsx From Cromwell with MIT License | 4 votes |
function Layout() {
const forceUpdate = useForceUpdate();
setStoreItem('forceUpdatePage', forceUpdate);
onStoreChange('userInfo', (user) => {
if (user && user.role !== userRole) {
userRole = user.role;
forceUpdate();
}
});
useEffect(() => {
store.setStateProp({
prop: 'forceUpdateApp',
payload: forceUpdate,
});
}, []);
const darkMode = getStoreItem('theme')?.mode === 'dark';
document.body.classList.remove('modeDark', 'modeLight');
document.body.classList.add(darkMode ? 'modeDark' : 'modeLight');
const theme = createTheme(darkMode ? {
palette: {
primary: {
main: '#9747d3',
light: '#9747d3',
dark: '#8228c5',
},
secondary: {
main: '#910081',
light: '#910081',
dark: '#910081',
}
},
} : {
palette: {
primary: {
main: '#8228c5',
light: '#8561c5',
dark: '#482880',
},
secondary: {
main: '#910081',
light: '#910081',
dark: '#910081',
}
},
});
return (
<ThemeProvider theme={theme}>
<div className={clsx(styles.Layout)}>
<BrowserRouter basename={'admin'}>
<div className={styles.sidebar}>
<Sidebar />
</div>
<div className={styles.main}>
<Toolbar className={styles.dummyToolbar} />
<Switch>
{getPageInfos().map(page => {
if (page.roles && !page.roles.includes(getStoreItem('userInfo')?.role))
return null;
return (
<Route exact={!page.baseRoute}
path={page.route}
key={page.name}
component={(props: RouteComponentProps) => {
return (
<PageErrorBoundary>
<Suspense fallback={/*<LoadBox />*/<></>}>
<page.component {...props} />
</Suspense>
</PageErrorBoundary>
)
}}
/>
)
})}
<Route key={'404'} >
<Page404 />
</Route>
</Switch>
</div>
</BrowserRouter>
{document?.body && ReactDOM.createPortal(
<div className={styles.toastContainer} ><ToastContainer /></div>, document.body)}
<FileManager />
<ConfirmPrompt />
<LayoutPortal />
</div>
</ThemeProvider>
);
}