Insert image into Material-UI AppBar - reactjs

I've been looking for a way to insert a plain image file into the AppBar of Material-UI on the official docs but it seems like the only non-text things you can put in the AppBar are either text icons or SVG icons. Is there a way to display actual images in the AppBar?

There are several options to insert a background image for Material-UI AppBar.
Here is one that I prefer:
Import the image:
import headerBackground from "../../Assets/headerBackground.png";
Add the image to the stylesheet as follow:
header: {
backgroundImage: `url(${headerBackground})`,
},
Set the class component:
const classes = useStyles();
return (
<>
<AppBar className={classes.header}> ... </AppBar>
Here is a complete example:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { AppBar, Toolbar, Typography } from "#material-ui/core";
import headerBackground from "../../Assets/headerBackground.png";
const useStyles = makeStyles((theme) => ({
header: {
backgroundImage: `url(${headerBackground})`,
},
}));
export default function Header(props) {
const classes = useStyles();
return (
<AppBar className={classes.header}>
<Toolbar>
<Typography variant="h6">Scroll to Hide App Bar</Typography>
</Toolbar>
</AppBar>
);
}

Material-UI has some components in which there are properties that can be assigned to the image. For example CardMedia - the properties of image. But you can also use the standard tag to insert the image.
<AppBar position="static" color="default" elevation={0} className={classes.appBar}>
<Toolbar className={classes.toolbar}>
<img src="/assets/logo.svg" />
<nav>
<Link variant="button" color="textPrimary" href="#" className={classes.link}>
About
</Link>
</nav>
</Toolbar>
</AppBar>
It works for me.

Related

Can't override AppBar background color

could someone please help me with this issue.
this is the code:
import { AppBar } from "#mui/material";
import { makeStyles } from "#mui/styles";
const useStyles = makeStyles({
root: {
backgroundColor: 'red'
}
})
const App = () => {
const classes = useStyles();
return <>
<AppBar className={classes.root}>
test
</AppBar>
<h1 className={classes.root}>test</h1>
</>
}
export default App;
The question is:
why the background-color of the AppBar component is not changing;
No problem with the h1 tag thought;
The other problem I've found is, sometimes it changes, but when I refresh the page, it becomes blue -> color by default;
So, thanks a lot for the answer if there is any :);
I faced a similar issue where styles applied to the AppBar component did not override some of the default styles. The fix was to wrap my component tree with <StyledEngineProvider injectFirst>. The solution looks something like this in the end:
import React from 'react';
import { StyledEngineProvider } from '#mui/material/styles';
export default function GlobalCssPriority() {
return (
<StyledEngineProvider injectFirst>
{/* Your component tree. Now you can override MUI's styles. */}
</StyledEngineProvider>
);
}
Link to source
<AppBar className={classes.root}>
test
</AppBar>
instead wrap your text in a div and use className on that div
<AppBar >
<div className={classes.root}>
test
</div>
</AppBar>

Am I on the right track with my Material UI AppBar?

I'm working on a header for my site, and want to use Material UI. The header includes a logo, some nav links, an avatar with dropdown, etc. My question revolves around styling the nav links right now. With Material-UI, do I need to apply classes to /every/ element I want to style? For example, I currently have an app that looks like this:
import React from 'react';
import AppBar from '#material-ui/core/AppBar';
import Avatar from '#material-ui/core/Avatar';
import CssBaseline from '#material-ui/core/CssBaseline';
import IconButton from '#material-ui/core/IconButton';
import Link from '#material-ui/core/Link';
import Menu from '#material-ui/core/Menu';
import MenuItem from '#material-ui/core/MenuItem';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import theme from './theme';
import { ThemeProvider } from '#material-ui/core/styles';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles(theme => ({
root: {
backgroundColor: '#202632',
},
headerLink: {
padding: '10px 20px',
}
}));
function App() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const classes = useStyles();
return (
<div className="App">
<ThemeProvider theme={theme}>
<CssBaseline />
<AppBar className={classes.root}>
<Toolbar className={classes.logo}>
<img alt="Logo" src="/logo2.png" height={60} />
<Link className={classes.headerLink} href="/dashboard">
Solutions
</Link>
<Link className={classes.headerLink} href="/clientportal">
Features
</Link>
<Link className={classes.headerLink} href="/pricing">
Pricing
</Link>
<Link className={classes.headerLink}>
Our team
</Link>
<Link className={classes.headerLink}>
Blog
</Link>
<Avatar onClick={handleClick} onClose={handleClose}>
DM
</Avatar>
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)}>
<MenuItem onClick={handleClose}>Item1</MenuItem>
<MenuItem onClick={handleClose}>Item2</MenuItem>
<MenuItem onClick={handleClose}>Item3</MenuItem>
</Menu>
</Toolbar>
</AppBar>
</ThemeProvider>
</div>
);
}
export default App;
The typical way I would style links is with CSS, using something like nav a { padding: 20px }, however that doesn't appear to be the idiomatic way with Material-UI. Maybe I have that assumption wrong so I wanted to verify here what the best approach for styling overrides looks like.
Thanks
You could create a SFC for the Link.
import React from ‘react’;
import Link from '#material-ui/core/Link';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles(theme => ({
headerLink: {
padding: '10px 20px',
}
}));
const AppBarLink = React.forwardRef(function AppBarLink({ children, className, ...props }, ref) {
const classes = useStyles();
return (
<Link
className={`${classes.headerLink} ${className}`}
ref={ref}
{...props}
>
{children}
</Link>
);
});
export AppBarLink;
For this particular scenario, I would use withStyles to create a styled version of Link. This will have the same effect as psyrendust's answer, but using withStyles gets rid of all the boilerplate.
import React from ‘react’;
import Link from '#material-ui/core/Link';
import { withStyles } from '#material-ui/core/styles';
const AppBarLink = withStyles({
root: {
padding: '10px 20px'
}
})(Link);
export AppBarLink;
Putting this in its own file and exporting it is only necessary if you want to leverage it from multiple files. If you are only using it in one file, then just define it there.
If you want to control props in addition to styles, you can leverage defaultProps as shown in the working example below:
import React from "react";
import Link from "#material-ui/core/Link";
import { withStyles } from "#material-ui/core/styles";
const AppBarLink = withStyles({
root: {
padding: "10px 20px"
}
})(Link);
AppBarLink.defaultProps = {
color: "secondary"
};
export default function App() {
return (
<div className="App">
<Link>Here is Link (no padding or color override)</Link>
<br />
<AppBarLink>Here is AppBarLink</AppBarLink>
<br />
<AppBarLink color="primary">
Here is AppBarLink with explicit color of primary
</AppBarLink>
</div>
);
}

Material-UI React TypeScript Component Styles Error w/ Default Theme

I'm integrating Material-UI (v4.4.3) into a React (v16.9.2) TypeScript (v3.6.3) website. Using the sample AppBar component example https://material-ui.com/components/app-bar/ and the TypeScript Guide https://material-ui.com/guides/typescript/#typescript I have the following functional component.
However, I'm getting a TS error for useStyles() on this line
const classes = useStyles();
(TS): Expected one argument, but got 0.
import * as React from 'react';
import { createStyles, Theme, makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
const useStyles = makeStyles(({ spacing }: Theme) =>
createStyles({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: spacing(2),
},
title: {
flexGrow: 1,
},
}),
);
export default function ButtonAppBar() {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
MSC
</Typography>
<Button color="inherit">Login</Button>
)}
</Toolbar>
</AppBar>
</div>
);
}
I want to use the default theme. Am I missing something?
Try to pass an empty object:
const classes = useStyles({});
try using components from :
import AppBar from "#material-ui/core/AppBar"
import XXX from "#material-ui/core/xxx"
XXX = other components
notes my dependencies are:
dependencies : "#material-ui/core": "^4.9.14"
devDependencies : "#types/material-ui": "^0.21.7"
don't forgot to import #types/material-ui devDependencies in your project.

How do you style a component to be under another component?

I'm setting up a small webapp using React and Material-UI, and I can't figure out how to make my drawer component fit under my app bar. Using the react developer tools I can see in the console that my components are picking up the classNames, but no matter what I do my styles aren't being applied to them. Currently, the drawer is clipping through the app bar at the top of the screen, taking up the entire height of the page instead of fitting under the app bar. What do I need to change in order to make my "Sidebar" component fit under my "Navbar" component? One of the reasons why I created these two as separate components is because I'm planning on adding more functionality to them later. Thank you.
I've been following the "clipped under the app bar" component demo at https://material-ui.com/components/drawers/ and I've also referenced Material UI Drawer won't move under Appbar
Here's a snippet of my code
My main app
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
import Navbar from './Navbar';
import Sidebar from './Sidebar';
const useStyles = makeStyles(theme => ({
App: {
display: 'flex',
},
navbar: {
zIndex: theme.zIndex.drawer + 1,
},
drawer: {
width: 240,
flexShrink: 0,
},
toolbar: theme.mixins.toolbar,
}));
function App() {
const classes = useStyles();
return (
<div className="App">
<CssBaseline/>
<Navbar position="fixed" className={classes.navbar}></Navbar>
<Sidebar className={classes.drawer}></Sidebar>
</div>
);
}
export default App;
My Navbar component
import React from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
function Navbar() {
return (
<AppBar positon="static">
<Toolbar>
<h2>Earthquake Mapper</h2>
</Toolbar>
</AppBar>
);
}
export default Navbar;
My Sidebar component
import React from 'react';
import Drawer from '#material-ui/core/Drawer';
function Sidebar() {
return (
<Drawer variant="permanent">
<div>
<ul>
<li>This</li>
<li>Will</li>
<li>Be</li>
<li>Where</li>
<li>Our</li>
<li>Data</li>
<li>Go</li>
</ul>
</div>
</Drawer>
);
}
export default Sidebar;
First, set the AppBar position as "fixed".
The way that Material-UI solves this is by adding an empty div with equal height to the Toolbar (which you put as the first child inside the AppBar component so your header min-height is equal to the Toolbar height) as the first child of the Drawer component.
This height is 64px by default, but you should get this value from theme.mixins.toolbar. You can see this in action in this tutorial.
So you'll end up doing something like this:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Drawer from '#material-ui/core/Drawer';
const useStyles = makeStyles(theme => ({
toolbar: theme.mixins.toolbar,
}));
function Sidebar() {
const classes = useStyles();
return (
<Drawer variant="permanent">
<div className={classes.toolbar} />
<div>
<ul>
<li>This</li>
<li>Will</li>
<li>Be</li>
<li>Where</li>
<li>Our</li>
<li>Data</li>
<li>Go</li>
</ul>
</div>
</Drawer>
);
}
export default Sidebar;
Check out themes for more information on how to use theme providers and custom
theme configuration.
An alternative is to place an empty <Toolbar /> in the Drawer to fill the space.
import React from 'react';
import Drawer from '#material-ui/core/Drawer';
import Toolbar from '#material-ui/core/Toolbar';
function Sidebar() {
return (
<Drawer variant="permanent">
<Toolbar />
<div>
<ul>
<li>This</li>
<li>Will</li>
<li>Be</li>
<li>Where</li>
<li>Our</li>
<li>Data</li>
<li>Go</li>
</ul>
</div>
</Drawer>
);
}
export default Sidebar;

Placing logo image into navbar

I am getting a broken image when I put my logo inside of the navbar. I have it saved locally inside the public folder.
I have tried passing as a prop, and directly linking to the path, but i cannot seem to get it to work.
import AppBar from '#material-ui/core/AppBar'
import Toolbar from '#material-ui/core/Toolbar'
import Typography from '#material-ui/core/Typography'
const NavBar = () => {
return(
<div>
<AppBar className='nav-bar' position="static" color='white'>
<Toolbar>
<Typography variant="title" >
<img src='../../public/LQ_Logo.png' width={182} height={64} />
</Typography>
</Toolbar>
</AppBar>
</div>
)
};
export default NavBar;
I need the logo to be displayed in the left corner of the navbar
For img within Public folder use relative path to Public.
For public/Vector.png use ./Vector.png.
Moreover, if it's a SVG you can import it as ReactComponent, for example:
import { ReactComponent as CatImg } from "./add-debug.svg";
const NavBar = () => {
return (
<div>
<AppBar className="nav-bar" position="static" color="white">
<Toolbar>
<Typography variant="title">
<CatImg height={100} />
</Typography>
</Toolbar>
<Toolbar>
<Typography variant="title">
<img src="./Vector.png" alt="bug" height={100} />
</Typography>
</Toolbar>
</AppBar>
</div>
);
};
Demo:
Did you check that relative path is correct? Maybe something is missing in "../../public/LQ_Logo.png".
You can try to use this alternative:
import { ReactComponent as Logo } from './logo.svg';
const App = () => (
<div>
{/* Logo is an actual React component */}
<Logo />
</div>
);
Change the png image to svg (is better to escalate width/heigh for web), and then import the image as a component and call the component in your code.

Resources