Tutorial
Quickly learn how to create a login UI using Joy components.
Topics covered
- Importing Joy components.
- Building the login page.
- What global variants look like.
- Toggling dark mode
What's not covered?
- Theming and component customization.
- Features explanation.
Prerequisites
- An app that has Joy UI installed. Follow the usage to learn how to quickly install it.
Building the login page
1. Creating the basic layout
To create the structure for our login page layout, we'll use the Sheet component, which is simply an HTML div that supports the global variant feature.
Open your App.js file and use this snippet to render a sheet,
import { CssVarsProvider } from '@mui/joy/styles';
import Sheet from '@mui/joy/Sheet';
function App() {
return (
<CssVarsProvider>
<Sheet variant="outlined">Welcome!</Sheet>
</CssVarsProvider>
);
}
export default App;
Try changing the sheet's variant between plain, outlined, soft or solid to see what they look like.
2. Using the sx prop for quick styling
Every Joy component accepts the sx prop, which allows a shorthand syntax for writing CSS. It's great for creating one-off customizations or quickly playing around with different styles.
// the rest of the code is hidden for simplicity
<Sheet
variant="outlined"
sx={{
maxWidth: 400,
mx: 'auto', // margin left & right
my: 4, // margin top & botom
py: 3, // padding top & bottom
px: 2, // padding left & right
display: 'flex',
flexDirection: 'column',
gap: 2,
borderRadius: 'sm',
boxShadow: 'md',
}}
>
Welcome!
</Sheet>
Don't worry if you're confused about the sx prop's syntax at this moment.
As you use it with more frequency, you'll get the hang of it. Check the MUI System documentation to learn the foundation for it.
3. Using Typography to create a welcome text
The Typography component has a level prop that allows you to choose between a pre-defined scale of typography values.
By default, Joy provides 9 typography levels: h1 | h2 | h3 | h4 | h5 | h6 | body1 | body2 | body3.
If you want to change what HTML tag the Typography component renders, you can use the component tag.
// ...other imports
import Typography from '@mui/joy/Typography';
<Sheet
variant="outlined"
sx={...}
>
<div>
<Typography level="h4" component="h1">
<b>Welcome!</b>
</Typography>
<Typography level="body2">Sign in to continue</Typography>
</div>
</Sheet>;
4. Using TextField to create user name and password inputs
The TextField component is made of the FormLabel, Input and FormHelperText components.
// ...other imports
import TextField from '@mui/joy/TextField';
<Sheet
variant="outlined"
sx={
{
// ...
}
}
>
...typography
<TextField
// html input attribute
name="email"
type="email"
placeholder="johndoe@email.com"
// pass down to FormLabel as children
label="Email"
/>
<TextField
name="password"
type="password"
placeholder="password"
label="Password"
/>
</Sheet>;
5. Using Button and Link for actions
The Button comes with solid and primary set as its default variant and color.
You can play around with changing their values to see how each variant differs from one another. Try plain, outlined, or soft.
We'll also use a Link component inside the endDecorator prop of the Typography component.
// ...other imports
import Button from '@mui/joy/Button';
import Link from '@mui/joy/Link';
<Sheet
variant="outlined"
sx={
{
// ...
}
}
>
...typography and text-fields
<Button
sx={{
mt: 1, // margin top
}}
>
Log in
</Button>
<Typography
endDecorator={<Link href="/sign-up">Sign up</Link>}
fontSize="sm"
sx={{ alignSelf: 'center' }}
>
Don't have an account?
</Typography>
</Sheet>;
🎁 Bonus: Setting up dark mode
Joy provides an effortless way to toggle between modes by using the react hook useColorScheme. All you need to do is create a component that uses the hook and then render it under the CssVarsProvider component.
import React from 'react';
import { CssVarsProvider, useColorScheme } from '@mui/joy/styles';
// ...other imports
const ModeToggle = () => {
const { mode, setMode } = useColorScheme();
const [mounted, setMounted] = React.useState(false);
// necessary for server-side rendering
// because mode is undefined on the server
React.useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return null;
}
return (
<Button
variant="outlined"
onClick={() => {
if (mode === 'light') {
setMode('dark');
} else {
setMode('light');
}
}}
>
{mode === 'light' ? 'Turn dark' : 'Turn light'}
</Button>
);
};
export default function App() {
return (
<CssVarsProvider>
<ModeToggle />
<Sheet>...</Sheet>
</CssVarsProvider>
);
}
💡 By using the
useColorSchemehook, Joy ensures that the user selected mode (stored in localStorage by default) is in-sync across browser tabs.
Congratulations 🎉! You have seamlessly built a simple yet good looking UI!