Materialize the chess board’s UI
In the previous posts of this series I blogged about how I use CSS flex box and CSS grid layout to build a chess board. While I really enjoyed the process of styling my components and building the layout of my page with my own hands, there’s always the option of taking advantage of a well established and battle hardened component library to make one’s life easier.
There are quite a few options available in the React ecosystem today when it comes to component libraries and React MUI seems to be a very common choice among them. Yesterday I updated the chess board to rely more heavily on the library. The result is here!
Below are a few things that I enjoyed after converting the chess board to use MUI components.
App bar
The header
tag is replaced by MUI’s AppBar. The AppBar
, which actually renders a header
tag under the hood, has a Toolbar
child component that is a flex
container by default so the amount of CSS I have to write is significantly reduced. The new code for the header looks like this
<AppBar position='static'>
<Toolbar sx={{
bgcolor: "rgb(5, 5, 29)",
justifyContent: "space-between",
}}>
<Button variant="contained" href={gitHubUrl}
startIcon={<GitHubIcon />} target={"_blank"} rel="noreferrer noopener">
<Typography variant="span" sx={{ display: { xs: 'none', sm: 'block' } }}>
Source
</Typography>
</Button>
<Box component={"div"}>
<Typography variant="h4">
{pieceColor === WHITE ? '♟' : '♙'}
</Typography>
</Box>
<Button variant="contained" onClick={togglePieceColor}
startIcon={<SwapVertIcon />}>
<Typography variant="span" sx={{ display: { xs: 'none', sm: 'block' } }}>
Switch Side
</Typography>
</Button>
</Toolbar>
</AppBar>
You may have noticed that there’s a decent amount of CSS code embedded in the JavaScript code above. It’s because the MUI component library is a strong proponent of the CSS-in-JS approach.
Some other MUI components that are also used in the code above are Box, Button, Typography, and Icons.
Stack
Stack is a layout component provided by MUI. Under the hood it’s a flex
container that is supposed to be used to display its items in a single direction. A direction
prop is exposed whose value could be anything among row
(default), row-reverse
, column
, and column-reverse
, which should be familiar to those who works with the flex-direction
CSS property before.
In the MUI-based version of the chess board I use a few instances of Stack
as the container for the row names, the column names, and the rows of the chess board. For instance, the code of theColNames
component now looks like this
<Stack direction="row" sx={{
gridArea: (side === "top" ? "1 / 2 / span 1 / span 8" : "10 / 2 / span 1 / span 8"),
alignItems: "center",
}}>
{
names.map((name) =>
<Paper key={`${side} ${name}`} elevation={0} sx={{
flex: "1 1 100%",
textAlign: "center",
bgcolor: "transparent",
border: "none",
textTransform: "uppercase",
fontSize: { xs: "1em", sm: "1.5em" },
}}>
<strong>{name}</strong>
</Paper>
)
}
</Stack>
Because I didn’t want to change the grid layout that was set out previously (see this post), I simply moved the CSS grid-area
property from the CSS file to the JavaScript file and set it via the sx
prop (it’s the MUI version of the JSX
’s styles
prop).
Paper
Paper is by far one of my favorite things about MUI. It allows us to create a UI component that looks like a piece of paper laid down on the screen. If you want the paper to look like it’s being elevated from the screen, you can use the elevation
property. The higher is the value, the more elevated is the component. Below is the code I have for the Board
component.
<Paper sx={{
display: "flex",
flexDirection: "column-reverse",
gridArea: "2 / 2 / span 8 / span 8",
}} elevation={4}>
{
board.map((row, rowIdx) => {
return (
<Row key={rowKey(rowIdx)} row={row} rowIdx={rowIdx} />
);
})
}
</Paper>
Another interesting prop of Paper
is variant
. The by default, the value of the prop is contained
. Another value that can be used is outlined
, which makes the component shown with a very thin and nice looking border. Below is the code I have for the outer board, i.e. the component that contains the chess board as well as RowNames
and ColNames
.
<Paper sx={{
display: "grid",
gridTemplate: "repeat(10, min(9vw, 9vh)) / repeat(10, min(9vw, 9vh))",
bgcolor: "rgba(0, 0, 0, 0.2)",
border: "none",
}} variant="outlined">
<ColNames side="top" />
<RowNames side="left" />
<Board board={pieceColor === WHITE ? WHITE_BOARD : BLACK_BOARD} />
<RowNames side="right" />
<ColNames side="bottom" />
</Paper>
The impact of elevation
and variant="outlined"
can be seen in the screenshot below.
Enjoy!