@material-ui/core#Grow TypeScript Examples
The following examples show how to use
@material-ui/core#Grow.
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: Players.tsx From planning-poker with MIT License | 6 votes |
Players: React.FC<PlayersProps> = ({ game, players }) => {
return (
<Grow in={true} timeout={800}>
<div className='PlayersContainer'>
{players.map((player: Player) => (
<PlayerCard key={player.id} game={game} player={player} />
))}
</div>
</Grow>
);
}
Example #2
Source File: Layout.tsx From fishbowl with MIT License | 5 votes |
function GrowTransition(props: TransitionProps) {
return <Grow {...props} />
}
Example #3
Source File: menus.tsx From clearflask with Apache License 2.0 | 5 votes |
render() {
const onMouseOverButton = () => {
this.setState({ hover: true });
const lastEventId = ++this.lastEventId;
setTimeout(() => lastEventId === this.lastEventId
&& this.state.hover
&& this.setState({ open: true }), 1);
};
const onMouseOverPopper = () => {
++this.lastEventId; // Cancel any events including mouse out
};
const onMouseOut = () => {
this.setState({ hover: false });
const lastEventId = ++this.lastEventId;
setTimeout(() => lastEventId === this.lastEventId
&& !this.state.hover
&& this.setState({ open: false }), 1);
};
return (
<div className={this.props.classes.dropdownContainer}>
<Button
size='large'
className={classNames(this.props.classes.button, this.props.isOuter && this.props.classes.buttonOuter)}
color={this.props.color}
onClick={() => {
++this.lastEventId;
this.setState({ open: true })
}}
onMouseOver={onMouseOverButton}
onMouseOut={onMouseOut}
>
{this.props.dropdown.title}
</Button>
<ClosablePopper
anchorType='in-place'
paperClassName={this.props.classes.menuPopperPaper}
className={this.props.classes.menuPopper}
clickAway
closeButtonPosition='disable'
open={!!this.state.open}
onClose={() => {
++this.lastEventId;
if (!this.state.open) this.setState({ open: false });
}}
onMouseOver={onMouseOverPopper}
onMouseOut={onMouseOut}
transitionCmpt={Grow}
transitionProps={{
style: { transformOrigin: '50% 0 0' },
timeout: this.props.theme.transitions.duration.shortest,
}}
placement='bottom'
modifiers={{
// preventOverflow: { enabled: false },
flip: { enabled: false },
}}
>
<MenuItems
items={this.props.dropdown.items}
onClick={() => {
++this.lastEventId;
this.setState({ open: false })
}}
insideDropdown
/>
</ClosablePopper>
</div>
);
}
Example #4
Source File: Menu.tsx From glific-frontend with GNU Affero General Public License v3.0 | 5 votes |
Menu: React.SFC<MenuProps> = ({
menus,
children,
eventType = 'Click',
placement = 'top',
}) => {
const [open, setOpen] = useState(false);
const anchorRef = useRef<HTMLDivElement>(null);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const menuList = menus.map((menu: any) => (
<div key={menu.title}>
<MenuItem
onClickHandler={() => {
if (menu.onClick) {
menu.onClick();
} else {
handleClose();
}
}}
{...menu}
/>
</div>
));
return (
<div data-testid="Menu">
<div
onClick={eventType === 'Click' ? handleOpen : undefined}
onKeyDown={eventType === 'Click' ? handleOpen : undefined}
onMouseEnter={eventType === 'MouseEnter' ? handleOpen : undefined}
onMouseLeave={eventType === 'MouseEnter' ? handleClose : undefined}
aria-hidden="true"
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
>
{children}
</div>
<Popper
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal={placement === 'top'}
placement={placement}
>
{({ TransitionProps }) => (
<Grow {...TransitionProps}>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<div
onMouseEnter={eventType === 'MouseEnter' ? handleOpen : undefined}
onMouseLeave={eventType === 'MouseEnter' ? handleClose : undefined}
>
<MenuList autoFocusItem={open}>{menuList}</MenuList>
</div>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</div>
);
}
Example #5
Source File: CardPicker.tsx From planning-poker with MIT License | 5 votes |
CardPicker: React.FC<CardPickerProps> = ({ game, players, currentPlayerId }) => {
const [randomEmoji, setRandomEmoji] = useState(getRandomEmoji);
const playPlayer = (gameId: string, playerId: string, card: CardConfig) => {
if (game.gameStatus !== Status.Finished) {
updatePlayerValue(gameId, playerId, card.value, randomEmoji);
}
};
const cards = getCards(game.gameType);
useEffect(() => {
if (game.gameStatus === Status.Started) {
setRandomEmoji(getRandomEmoji);
}
}, [game.gameStatus]);
return (
<Grow in={true} timeout={1000}>
<div>
<div className='CardPickerContainer'>
<Grid container spacing={4} justify='center'>
{cards.map((card: CardConfig, index) => (
<Grid key={card.value} item xs>
<Slide in={true} direction={'right'} timeout={(1000 * index) / 2}>
<Card
id={`card-${card.displayValue}`}
className='CardPicker'
variant='outlined'
onClick={() => playPlayer(game.id, currentPlayerId, card)}
style={{
...getCardStyle(players, currentPlayerId, card),
pointerEvents: getPointerEvent(game),
}}
>
<CardContent className='CardContent'>
{card.value >= 0 && (
<>
<Typography className='CardContentTop' variant='caption'>
{card.displayValue}
</Typography>
<Typography className='CardContentMiddle' variant='h4'>
{card.displayValue}
</Typography>
<Typography className='CardContentBottom' variant='caption'>
{card.displayValue}
</Typography>
</>
)}
{card.value === -1 && (
<Typography className='CardContentMiddle' variant='h3'>
{randomEmoji}
</Typography>
)}
{card.value === -2 && (
<Typography className='CardContentMiddle' variant='h3'>
❓
</Typography>
)}
</CardContent>
</Card>
</Slide>
</Grid>
))}
</Grid>
</div>
<Typography variant='h6'>
{game.gameStatus !== Status.Finished
? 'Click on the card to vote'
: 'Session not ready for Voting! Wait for moderator to start'}
</Typography>
</div>
</Grow>
);
}
Example #6
Source File: index.tsx From firetable with Apache License 2.0 | 4 votes |
export default function BulkActions({ selectedRows, columns, clearSelection }) {
const classes = useStyles();
const [loading, setLoading] = useState<Boolean>();
const { tableActions, tableState } = useFiretableContext();
const { requestConfirmation } = useConfirmation();
const snack = useSnackContext();
const actionColumns: { name: string; key: string; config: any }[] = columns
.filter((column) => column.type === "ACTION")
.map((column) => ({
name: column.name,
key: column.key,
config: column.config,
}));
const handleDuplicate = () => {
selectedRows.forEach((row) => {
const clonedRow = { ...row };
// remove metadata
delete clonedRow.ref;
delete clonedRow.rowHeight;
delete clonedRow._ft_updatedAt;
delete clonedRow._ft_updatedBy;
delete clonedRow._ft_createdAt;
Object.keys(clonedRow).forEach((key) => {
if (clonedRow[key] === undefined) {
delete clonedRow[key];
}
});
if (tableActions) tableActions?.row.add(clonedRow);
});
clearSelection();
};
const handleDelete = () => {
selectedRows.forEach((row) => row.ref.delete());
clearSelection();
};
const executeAction = async (key: string, actionType: string) => {
const actionColumn = _find(actionColumns, { key });
if (!actionColumn) return;
console.log({ actionColumn, selectedRows, actionType });
const callableName = actionColumn.config.callableName ?? "actionScript";
const calls = selectedRows.map((row) => {
const { ref } = row;
const data = {
ref: {
path: ref.path,
id: ref.id,
tablePath: window.location.pathname,
},
column: actionColumn,
action: actionType,
schemaDocPath: formatPath(tableState?.tablePath ?? ""),
actionParams: {},
};
return cloudFunction(
callableName,
data,
async (response) => {
const { message, cellValue, success } = response.data;
// setIsRunning(false);
snack.open({
message: JSON.stringify(message),
variant: success ? "success" : "error",
});
if (cellValue && cellValue.status) {
return ref.update({ [actionColumn.key]: cellValue });
}
},
(error) => {
console.error("ERROR", callableName, error);
//setIsRunning(false);
snack.open({ message: JSON.stringify(error), variant: "error" });
}
);
});
setLoading(true);
const result = await Promise.all(calls);
await Promise.all(result);
console.log(result);
setLoading(false);
clearSelection();
};
const numSelected = selectedRows.length;
return (
<div className={classes.root}>
<Grow in={numSelected > 0}>
<Paper elevation={8} className={classes.paper}>
<Grid
container
alignItems="center"
wrap="nowrap"
className={classes.grid}
>
<Grid item className={classes.selectedContainer}>
<Tooltip title="Clear selection">
<IconButton
color="secondary"
onClick={clearSelection}
aria-label="Clear selection"
>
<ClearSelectionIcon />
</IconButton>
</Tooltip>
<Typography variant="overline" className={classes.selected}>
{numSelected} row{numSelected !== 1 && "s"} selected
</Typography>
</Grid>
<Grid item className={classes.spacer} />
<Grid item>
<TextField
select
variant="filled"
className={classes.dropdown}
value=""
onChange={(event) => executeAction(event.target.value, "run")}
margin="dense"
InputProps={{
disableUnderline: true,
classes: { root: classes.inputBaseRoot },
}}
InputLabelProps={{
classes: {
root: classes.dropdownLabel,
focused: classes.dropdownLabelFocused,
},
}}
SelectProps={{
classes: { root: classes.select },
displayEmpty: true,
MenuProps: {
getContentAnchorEl: null,
anchorOrigin: { vertical: "top", horizontal: "left" },
transformOrigin: { vertical: "bottom", horizontal: "left" },
classes: { paper: classes.dropdownMenu },
},
IconComponent: ArrowDropUpIcon,
}}
label={`${actionColumns.length} action${
actionColumns.length !== 1 ? "s" : ""
}`}
>
{actionColumns.map((action) => (
<MenuItem value={action.key} key={action.key}>
{action.name}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item className={classes.spacer} />
<Grid item>
<Tooltip title="Duplicate rows">
<IconButton
color="secondary"
onClick={() => {
requestConfirmation({
title: "Duplicate Rows?",
body: `Are you sure you want to duplicate the ${numSelected} selected row${
numSelected !== 1 ? "s" : ""
}?`,
confirm: "Duplicate Rows",
handleConfirm: handleDuplicate,
});
}}
aria-label="Duplicate selected rows"
>
<CopyCellsIcon />
</IconButton>
</Tooltip>
</Grid>
<Grid item>
<Tooltip title="Delete rows">
<IconButton
color="secondary"
onClick={() => {
requestConfirmation({
title: "Delete Rows?",
body: `Are you sure you want to delete the ${numSelected} select row${
numSelected !== 1 ? "s" : ""
}?`,
confirm: "Delete Rows",
handleConfirm: handleDelete,
});
}}
aria-label="Delete selected rows"
>
<DeleteIcon />
</IconButton>
</Tooltip>
</Grid>
</Grid>
</Paper>
</Grow>
</div>
);
}
Example #7
Source File: CreateGame.tsx From planning-poker with MIT License | 4 votes |
CreateGame = () => {
const history = useHistory();
const [gameName, setGameName] = useState('Avengers');
const [createdBy, setCreatedBy] = useState('SuperHero');
const [gameType, setGameType] = useState(GameType.Fibonacci);
const handleSubmit = async (event: FormEvent) => {
event.preventDefault();
const game: NewGame = {
name: gameName,
createdBy: createdBy,
gameType: gameType,
createdAt: new Date(),
};
const newGameId = await addNewGame(game);
history.push(`/game/${newGameId}`);
};
return (
<Grow in={true} timeout={1000}>
<form onSubmit={handleSubmit}>
<Card variant='outlined' className='CreateGameCard'>
<CardHeader
className='CreateGameCardHeader'
title='Create New Session'
titleTypographyProps={{ variant: 'h4' }}
/>
<CardContent className='CreateGameCardContent'>
<TextField
className='CreateGameTextField'
required
id='filled-required'
label='Session Name'
placeholder='Enter a session name'
defaultValue={gameName}
variant='outlined'
onChange={(event: ChangeEvent<HTMLInputElement>) => setGameName(event.target.value)}
/>
<TextField
className='CreateGameTextField'
required
id='filled-required'
label='Your Name'
placeholder='Enter your name'
defaultValue={createdBy}
variant='outlined'
onChange={(event: ChangeEvent<HTMLInputElement>) => setCreatedBy(event.target.value)}
/>
<RadioGroup
aria-label='gender'
name='gender1'
value={gameType}
onChange={(
event: ChangeEvent<{
name?: string | undefined;
value: any;
}>
) => setGameType(event.target.value)}
>
<FormControlLabel
value={GameType.Fibonacci}
control={<Radio color='primary' size='small' />}
label='Fibonacci (0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89)'
/>
<FormControlLabel
value={GameType.ShortFibonacci}
control={<Radio color='primary' size='small' />}
label='Short Fibonacci (0, ½, 1, 2, 3, 5, 8, 13, 20, 40, 100)'
/>
<FormControlLabel
value={GameType.TShirt}
control={<Radio color='primary' size='small' />}
label='T-Shirt (XXS, XS, S, M, L, XL, XXL)'
/>
</RadioGroup>
</CardContent>
<CardActions className='CreateGameCardAction'>
<Button type='submit' variant='contained' color='primary' className='CreateGameButton'>
Create
</Button>
</CardActions>
</Card>
</form>
</Grow>
);
}
Example #8
Source File: GameController.tsx From planning-poker with MIT License | 4 votes |
GameController: React.FC<GameControllerProps> = ({ game, currentPlayerId }) => {
const history = useHistory();
const [showCopiedMessage, setShowCopiedMessage] = useState(false);
const copyInviteLink = () => {
const dummy = document.createElement('input');
const url = `${window.location.origin}/join/${game.id}`;
document.body.appendChild(dummy);
dummy.value = url;
dummy.select();
document.execCommand('copy');
document.body.removeChild(dummy);
setShowCopiedMessage(true);
};
const leaveGame = () => {
history.push(`/`);
};
const isModerator = (moderatorId: string, currentPlayerId: string) => {
return moderatorId === currentPlayerId;
};
return (
<Grow in={true} timeout={2000}>
<div className='GameController'>
<Card variant='outlined' className='GameControllerCard'>
<CardHeader
title={game.name}
titleTypographyProps={{ variant: 'h6' }}
action={
<div className='GameControllerCardHeaderAverageContainer'>
<Typography variant='subtitle1'>{game.gameStatus}</Typography>
{game.gameType !== GameType.TShirt && (
<>
<Divider className='GameControllerDivider' orientation='vertical' flexItem />
<Typography variant='subtitle1'>Average:</Typography>
<Typography variant='subtitle1' className='GameControllerCardHeaderAverageValue'>
{game.average || 0}
</Typography>
</>
)}
</div>
}
className='GameControllerCardTitle'
></CardHeader>
<CardContent className='GameControllerCardContentArea'>
{isModerator(game.createdById, currentPlayerId) && (
<>
<div className='GameControllerButtonContainer'>
<div className='GameControllerButton'>
<IconButton onClick={() => finishGame(game.id)} data-testid='reveal-button' color='primary'>
<VisibilityIcon fontSize='large' style={{ color: green[500] }} />
</IconButton>
</div>
<Typography variant='caption'>Reveal</Typography>
</div>
<div className='GameControllerButtonContainer'>
<div className='GameControllerButton'>
<IconButton data-testid={'restart-button'} onClick={() => resetGame(game.id)}>
<RefreshIcon fontSize='large' color='error' />
</IconButton>
</div>
<Typography variant='caption'>Restart</Typography>
</div>
</>
)}
<div className='GameControllerButtonContainer'>
<div className='GameControllerButton'>
<IconButton data-testid='exit-button' onClick={() => leaveGame()}>
<ExitToApp fontSize='large' style={{ color: orange[500] }} />
</IconButton>
</div>
<Typography variant='caption'>Exit</Typography>
</div>
<div title='Copy invite link' className='GameControllerButtonContainer'>
<div className='GameControllerButton'>
<IconButton data-testid='invite-button' onClick={() => copyInviteLink()}>
<LinkIcon fontSize='large' style={{ color: blue[500] }} />
</IconButton>
</div>
<Typography variant='caption'>Invite</Typography>
</div>
</CardContent>
</Card>
<Snackbar
anchorOrigin={{ horizontal: 'right', vertical: 'top' }}
open={showCopiedMessage}
autoHideDuration={5000}
onClose={() => setShowCopiedMessage(false)}
>
<Alert severity='success'>Invite Link copied to clipboard!</Alert>
</Snackbar>
</div>
</Grow>
);
}
Example #9
Source File: JoinGame.tsx From planning-poker with MIT License | 4 votes |
JoinGame = () => {
const history = useHistory();
let { id } = useParams<{ id: string }>();
const [joinGameId, setJoinGameId] = useState(id);
const [playerName, setPlayerName] = useState('');
const [gameFound, setIsGameFound] = useState(true);
useEffect(() => {
async function fetchData() {
if (joinGameId) {
if (await getGame(joinGameId)) {
setIsGameFound(true);
if (isCurrentPlayerInGame(joinGameId)) {
history.push(`/game/${joinGameId}`);
}
}
}
}
fetchData();
}, [joinGameId, history]);
const handleSubmit = async (event: FormEvent) => {
event.preventDefault();
if (joinGameId) {
const res = await addPlayerToGame(joinGameId, playerName);
setIsGameFound(res);
if (res) {
history.push(`/game/${joinGameId}`);
}
}
};
return (
<Grow in={true} timeout={500}>
<div>
<form onSubmit={handleSubmit}>
<Card variant='outlined' className='JoinGameCard'>
<CardHeader
className='JoinGameCardHeader'
title='Join a Session'
titleTypographyProps={{ variant: 'h4' }}
/>
<CardContent className='JoinGameCardContent'>
<TextField
error={!gameFound}
helperText={!gameFound && 'Session not found, check the ID'}
className='JoinGameTextField'
required
id='filled-required'
label='Session ID'
placeholder='xyz...'
defaultValue={joinGameId}
variant='outlined'
onChange={(event: ChangeEvent<HTMLInputElement>) =>
setJoinGameId(event.target.value)
}
/>
<TextField
className='JoinGameTextField'
required
id='filled-required'
label='Your Name'
placeholder='Enter your name'
defaultValue={playerName}
variant='outlined'
onChange={(event: ChangeEvent<HTMLInputElement>) =>
setPlayerName(event.target.value)
}
/>
</CardContent>
<CardActions className='JoinGameCardAction'>
<Button
type='submit'
variant='contained'
color='primary'
className='JoinGameButton'
>
Join
</Button>
</CardActions>
</Card>
</form>
</div>
</Grow>
);
}
Example #10
Source File: LoginDialog.tsx From knboard with MIT License | 4 votes |
LoginDialog = () => {
const dispatch = useDispatch();
const [open, setOpen] = useState(false);
const apiErrors = useSelector((state: RootState) => state.auth.loginErrors);
const loading = useSelector((state: RootState) => state.auth.loginLoading);
const { register, handleSubmit, errors } = useForm<FormData>();
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
dispatch(clearErrors());
};
const onSubmit = handleSubmit(({ username, password }) => {
dispatch(login({ username, password }));
});
return (
<>
<Button
variant="contained"
color="primary"
onClick={handleOpen}
data-testid="open-login-btn"
>
Login
</Button>
<Dialog
open={open}
onClose={handleClose}
keepMounted={false}
aria-labelledby="login-dialog-title"
css={css`
& .MuiDialog-paper {
padding: 2rem 1.5rem;
}
`}
maxWidth="xs"
fullWidth
>
<Close onClose={handleClose} />
<DialogTitle id="login-dialog-title">Login</DialogTitle>
<form onSubmit={onSubmit}>
<DialogContent>
{apiErrors?.non_field_errors && (
<Grow in timeout={100}>
<Alert
severity="error"
css={css`
margin-bottom: 0.75rem;
`}
>
{apiErrors.non_field_errors?.map((errorMsg) => (
<div key={errorMsg}>{errorMsg}</div>
))}
</Alert>
</Grow>
)}
<TextField
autoFocus
name="username"
margin="dense"
id="username"
label="Username"
variant="outlined"
inputRef={register({ required: "This field is required" })}
helperText={errors.username?.message}
error={Boolean(errors.username)}
fullWidth
/>
<TextField
name="password"
margin="dense"
id="password"
label="Password"
variant="outlined"
type="password"
inputRef={register({ required: "This field is required" })}
helperText={errors.password?.message}
error={Boolean(errors.password)}
fullWidth
/>
<FormActions>
<Button
variant="contained"
color="primary"
type="submit"
disabled={loading}
data-testid="submit-login-btn"
>
Login
</Button>
</FormActions>
</DialogContent>
</form>
</Dialog>
</>
);
}
Example #11
Source File: AdrBrowserLayout.tsx From log4brains with Apache License 2.0 | 4 votes |
export function AdrBrowserLayout({
projectName,
adrs,
adrsReloading = false,
currentAdr,
children,
routing = false,
l4bVersion
}: AdrBrowserLayoutProps) {
const classes = useStyles();
const router = useRouter();
const [mobileDrawerOpen, setMobileDrawerOpen] = React.useState(false);
const handleMobileDrawerToggle = () => {
setMobileDrawerOpen(!mobileDrawerOpen);
};
React.useEffect(() => {
const closeMobileDrawer = () => setMobileDrawerOpen(false);
router?.events.on("routeChangeStart", closeMobileDrawer);
return () => {
router?.events.off("routeChangeStart", closeMobileDrawer);
};
}, [router]);
const [searchOpen, setSearchOpenState] = React.useState(false);
const [searchReallyOpen, setSearchReallyOpenState] = React.useState(false);
const drawer = (
<div className={classes.drawerContainer}>
<Toolbar className={classes.drawerToolbar}>
<div />
<Link href="/" passHref>
<IconButton
size="small"
color="inherit"
aria-label="go to homepage"
title={`Architecture knowledge base of ${projectName}`}
>
<img
src={`${router?.basePath}/l4b-static/Log4brains-logo.png`}
alt="Log4brains logo"
width={40}
height={40}
/>
</IconButton>
</Link>
<IconButton
size="small"
color="inherit"
aria-label="close drawer"
title="Close"
onClick={handleMobileDrawerToggle}
>
<CloseIcon fontSize="small" />
</IconButton>
</Toolbar>
<div className={classes.adlTitleAndSpinner}>
<Typography variant="subtitle2" className={classes.adlTitle}>
Decision log
</Typography>
<Fade in={adrsReloading}>
<CircularProgress size={13} />
</Fade>
</div>
<Grow in={adrs !== undefined} style={{ transformOrigin: "center left" }}>
<AdrMenu
adrs={adrs}
currentAdrSlug={currentAdr?.slug}
className={classes.adrMenu}
/>
</Grow>
{adrs === undefined && (
<CircularProgress size={30} className={classes.adrMenuSpinner} />
)}
<List className={classes.bottomMenuList}>
{/* <Divider />
<ListItem button>
<ListItemIcon>
<ChevronRightIcon />
</ListItemIcon>
<ListItemText>
<Badge badgeContent={0} color="primary">
<Typography>Filters</Typography>
</Badge>
</ListItemText>
</ListItem> */}
{/* <Divider />
<Link href="/decision-backlog" passHref>
<ListItem button selected={backlog} component="a">
<ListItemIcon>
<PlaylistAddCheckIcon />
</ListItemIcon>
<ListItemText primary="Decision backlog" />
</ListItem>
</Link> */}
</List>
</div>
);
return (
<div className={classes.root}>
<AppBar position="fixed" className={classes.appBar}>
{routing && <RoutingProgress />}
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={handleMobileDrawerToggle}
className={classes.appBarMenuButton}
>
<MenuIcon />
</IconButton>
<Link href="/">
<div className={classes.appBarTitle}>
<div>
<img
src={`${router?.basePath}/l4b-static/Log4brains-logo-dark.png`}
alt="Log4brains logo"
width={50}
height={50}
/>
</div>
<div>
<Link href="/" passHref>
<MuiLink
variant="h6"
noWrap
className={classes.appBarTitleLink}
>
{projectName}
</MuiLink>
</Link>
<Link href="/" passHref>
<MuiLink
variant="body2"
noWrap
className={classes.appBarTitleLink}
>
Architecture knowledge base
</MuiLink>
</Link>
</div>
</div>
</Link>
<div className={classes.layoutLeftCol} />
<div className={clsx(classes.layoutCenterCol)}>
<Backdrop open={searchOpen} className={classes.searchBackdrop} />
<NoSsr>
<ConnectedSearchBox
onOpen={() => {
setSearchOpenState(true);
// Delayed real opening because otherwise the dropdown width is bugged
setTimeout(
() => setSearchReallyOpenState(true),
searchTransitionDuration + 100
);
}}
onClose={() => {
setSearchOpenState(false);
setSearchReallyOpenState(false);
}}
open={searchReallyOpen}
className={clsx(classes.searchBox, {
[classes.searchBoxOpen]: searchOpen
})}
/>
</NoSsr>
</div>
<div className={classes.layoutRightCol} />
</Toolbar>
</AppBar>
<nav
className={classes.drawer}
aria-label="architecture decision records list"
>
<Hidden smUp implementation="css">
<Drawer
variant="temporary"
anchor="left"
open={mobileDrawerOpen}
onClose={handleMobileDrawerToggle}
classes={{
paper: classes.drawerPaper
}}
ModalProps={{
keepMounted: true // Better open performance on mobile.
}}
>
{drawer}
</Drawer>
</Hidden>
<Hidden xsDown implementation="css">
<Drawer
variant="permanent"
open
classes={{
paper: classes.drawerPaper
}}
>
{drawer}
</Drawer>
</Hidden>
</nav>
<div className={classes.container}>
<Toolbar />
<main className={classes.content}>
<AdrNavContext.Provider
value={currentAdr && adrs ? buildAdrNav(currentAdr, adrs) : {}}
>
{children}
</AdrNavContext.Provider>
</main>
<footer className={classes.footer}>
<div className={classes.layoutLeftCol} />
<div className={clsx(classes.layoutCenterCol, classes.footerContent)}>
<Typography className={classes.footerText}>
Powered by{" "}
<MuiLink
href="https://github.com/thomvaill/log4brains"
className={classes.footerLink}
target="_blank"
rel="noopener"
>
Log4brains
</MuiLink>{" "}
<span style={{ fontSize: "0.8em" }}>
{l4bVersion ? `(v${l4bVersion})` : null}
</span>
</Typography>
</div>
<div className={classes.layoutRightCol} />
</footer>
</div>
</div>
);
}