Place Material-ui icon inside circular progress indicator - reactjs

I would like to use a circular progress indicator from Material-UI in the header of my app.
But I just dont know how to fit nicely a download icon from Material Icons inside so that progress bar will move around the icon. Here is what I have now:
and I want to achieve this:
I tried to place icon with absolute positioning, but probably there is a better idea
import React from "react";
import ReactDOM from "react-dom";
import CircularProgress from "#material-ui/core/CircularProgress";
import Button from "#material-ui/core/Button";
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import IconButton from '#material-ui/core/IconButton';
import VerticalAlignBottomIcon from '#material-ui/icons/VerticalAlignBottom';
function CircularStatic() {
const [completed, setCompleted] = React.useState(0);
React.useEffect(() => {
function progress() {
setCompleted((prevCompleted) =>
prevCompleted >= 100 ? 0 : prevCompleted + 10
);
}
const timer = setInterval(progress, 1000);
return () => {
clearInterval(timer);
};
}, []);
return (
<div>
<Button variant="contained" color="primary">
<CircularProgress variant="static" value={completed} color="inherit">
</CircularProgress>
</Button>
</div>
);
}
function ButtonAppBar() {
return (
<AppBar position="static" style={{ backgroundColor: 'teal' }}>
<Toolbar>
<IconButton edge="start" color="inherit">
<VerticalAlignBottomIcon />
<CircularStatic/>
</IconButton>
</Toolbar>
</AppBar>
);
}
ReactDOM.render(<ButtonAppBar />, document.getElementById("root"));

I customized a little, the Material-UI documentation example here
function CircularProgressWithContent(props) {
return (
<Box position="relative" display="inline-flex">
<CircularProgress />
<Box
top={0}
left={0}
bottom={0}
right={0}
position="absolute"
display="flex"
alignItems="center"
justifyContent="center"
>
<Typography variant="caption" component="div" color="textSecondary">
{props.content}
</Typography>
</Box>
</Box>
);
}
And to use it :
<CircularProgressWithLabel content={<LockOutlinedIcon />} />
It's perfectible but it works well for your use case.

Related

How to aligh right a button in Material-UI?

I tried material ui and i cant figure out how to alight buttons to the right ((
import * as React from "react";
import SvgIcon from "#mui/material/SvgIcon";
import Button from "#mui/material/Button";
import { AppBar, IconButton, Toolbar, Typography } from "#mui/material";
import { Box, Container } from "#mui/system";
import MenuIcon from "#mui/icons-material/Menu";
import { makeStyles } from "#mui/material/styles";
const boxDefault = {};
function App() {
//const classes = useStyles();
return (
<AppBar position="fixed">
<Container fixed>
<Toolbar>
<IconButton
Edge="start"
color="inherit"
aria-label="menu"
//className={classes.menuButton}
>
<MenuIcon />
</IconButton>
<Typography variant="h5" /*className={classes.title}*/>
Hotels Ua
</Typography>
<Box mr={1}>
<Button color="inherit" variant="outlined">
Log in
</Button>
</Box>
<Box>
<Button color="secondary" variant="contained">
Sign up
</Button>
</Box>
</Toolbar>
</Container>
</AppBar>
);
}
export default App;
I found instruction how to aligh in material ui but after trying still no result....
display="flex"
justifyContent="flex-end"
alignItems="flex-end"
sx={boxDefault}
but no effect.
I am just started with mui.
Assuming that the goal is to make the logo and title to the left, and the buttons to the right on the nav bar, change the title element like this:
<Typography variant="h5" sx={{ flexGrow: 1}}/>
Hotels Ua
</Typography>
This will make the title element grow in this layout, and push the buttons to the right, which hopefully is the intended result, but do specify if not as it will help to find the proper solution.

How to move a React component using CSS ? No functions or classes are working

I am trying to move a button in my appbar to the right. Here is what it looks like:
I have tried 2 ways to fix this:
return (
<AppBar
position="sticky">
<Toolbar
sx = {{background:'black', float:'right'}}
variant="dense">
<CustomButton
text='Upload'
sx = {{float:'right'}}
endIcon={<UploadIcon/>}/>
</Toolbar>
</AppBar>
)
}
export default Header;
I also tried to do the same thing with a useStyles hook:
import UploadIcon from "#mui/icons-material/Upload";
import CustomButton from "./CustomButton";
import AppBar from '#mui/material/AppBar';
import Toolbar from '#mui/material/Toolbar';
import { makeStyles } from '#material-ui/core/styles';
import {createMuiTheme} from '#material-ui/core/styles';
const useStyles = makeStyles({
root: {
float:'right'
}
});
const Header = () => {
const classes = useStyles();
return (
<AppBar position="sticky">
<Toolbar
sx = {{background:'black'}}
variant="dense">
<CustomButton text='Upload'
className={classes.root}
endIcon={<UploadIcon/>}/>
</Toolbar>
</AppBar>
)
}
export default Header;
But none of them have worked and the button won't move to the right.
The code of my button component is as follows:
import {Button} from '#material-ui/core';
import UploadIcon from '#mui/icons-material/Upload';
const CustomButton = ({float,text, endIcon}) => {
return (
<div className='CustomButton'>
<Button style={{fontWeight: 'bold'}}
variant="contained"
size='small'
endIcon={endIcon}>
{text}
</Button>
</div>
)
}
export default CustomButton;
In mui, u will use flex alot.
return (
<AppBar
position="sticky">
<Toolbar
sx = {{background:'black', display: 'flex', justifyContent: 'flex-end'}}
variant="dense">
<CustomButton
text='Upload'
endIcon={<UploadIcon/>}/>
</Toolbar>
</AppBar>
)
}
export default Header;
Since mui v5, also nice to learn how to use Stack.
<Toolbar>
<Stack direction="row" justifyContent="space-between">
<MyLogo /> //extreme left
<MyButton /> //extreme right
</Stack>
</Toolbar>
Stack can also be nested
<Toolbar>
<Stack direction="row" justifyContent="space-between">
<Stack direction="row"> // content in extreme left
<MyLogo />
<MyOtherLeftComponent />
</Stack>
<MyButton /> //extreme right
</Stack>
</Toolbar>
On the toolbar use following style
display:flex;
justify-content:flex-end.

My react Material UI buttons aren't rendering

I've written the same code everywhere but it doesn't render my buttons. It does render but is not visible. The button are present between the logo and the search input.
There aren't any errors nor build fail to debug the problem.
I tried copying and pasting the code from the second too!
import React from "react";
import { Link } from "react-router-dom";
import { Box, Container, ThemeProvider, Input, useScrollTrigger, Slide, AppBar, Toolbar } from '#mui/material'
import { Button } from "#mui/material";
import customTheme from "./Theme"
function HideOnScroll(props) {
const { children, window } = props;
const trigger = useScrollTrigger({
target: window ? window() : undefined,
});
return (
<Slide appear={false} direction="down" in={!trigger}>
{children}
</Slide>
);
}
const ariaLabel = { 'aria-label': 'description' };
function Navigation(props) {
return (
<Container>
<ThemeProvider theme={ customTheme }>
<HideOnScroll>
<AppBar color={"primary"}>
<Toolbar>
<Box m={1} p={1}>
<Link to=""><img src="/static/brand-logo.svg" alt="brand-logo" /></Link>
</Box>
<Box m={1} p={1}>
<Button variant="outlined" style={{ borderRadius: 20 }} href="/">Home</Button>
<Button variant="outlined" style={{ borderRadius: 20 }} href="/blog">Blogs</Button>
<Button variant="outlined" style={{ borderRadius: 20 }} href="/create-blog">Create</Button>
</Box>
<Box m={1} p={1}>
<Input color={"secondary"} placeholder="Can't search :)" inputProps={ariaLabel} />
</Box>
</Toolbar>
</AppBar>
</HideOnScroll>
<Toolbar />
</ThemeProvider>
</Container>
);
}
export default Navigation;
Another button code which works
import React from "react";
import { Grid, Divider, Typography, Button } from "#mui/material";
import InstagramIcon from '#mui/icons-material/Instagram';
import LinkedInIcon from '#mui/icons-material/LinkedIn';
import GitHubIcon from '#mui/icons-material/GitHub';
export default function Home(props) {
return(
<Grid container spacing={4} justifyContent="center" alignItems="center" color={"primary"}>
<Grid item xs={12} sm={6} lg={4}>
<Typography variant="h1" component="div" gutterBottom>A painting of my life.</Typography>
<Button size="large" variant="outlined" style={{ borderRadius: 50, fontSize: 40 }} href="/blog">Peek My Diary</Button>
</Grid>
</Grid>
);
}

How can I reuse code wrapping Material-UI's Grid while varying the number of columns?

I would like the second grid block under the title "Other Projects of Note" to be mapped through as a 3 column grid. How can I do this without creating a new component? Material-UI controls it's columns with the grid item xs={12} sm={6} and on the 3 column grid I'd need it to read as grid item xs={12} sm={6} lg={4}.
It seems like I'd be copying and pasting the <Card /> component and renaming it to achieve this. I'd like to avoid that. Demo below:
codesandbox
Here's the code for my current Card component:
import React from 'react';
import Grid from '#material-ui/core/Grid';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
import { makeStyles } from '#material-ui/core/styles';
import { loadCSS } from 'fg-loadcss';
import CardContent from '#material-ui/core/CardContent';
import CardMedia from '#material-ui/core/CardMedia';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
import Icon from '#material-ui/core/Icon';
import GitHubIcon from '#material-ui/icons/GitHub';
import Tooltip from '#material-ui/core/Tooltip';
import Zoom from '#material-ui/core/Zoom';
import Link from '#material-ui/core/Link';
const useStyles = makeStyles((theme) => ({
root: {
maxWidth: '100%',
flexGrow: 1,
},
cardGrid: {
paddingTop: theme.spacing(2),
},
media: {
height: 340,
},
button: {
margin: theme.spacing(1),
},
arrow: {
color: theme.palette.common.black,
},
tooltip: {
backgroundColor: theme.palette.common.black,
},
icons: {
'& > .fab': {
marginRight: theme.spacing(4),
},
margin: '1rem 0',
},
}));
function TwoCard(props) {
const classes = useStyles();
React.useEffect(() => {
const node = loadCSS(
'https://use.fontawesome.com/releases/v5.12.0/css/all.css',
document.querySelector('#font-awesome-css')
);
return () => {
node.parentNode.removeChild(node);
};
}, []);
return (
<>
<Grid item xs={12} sm={6}>
<Card>
<CardActionArea>
<CardMedia
className={classes.media}
image={props.card.image}
title='Contemplative Reptile'
/>
<CardContent className={classes.content}>
<Typography gutterBottom variant='h5' component='h2'>
{props.card.project}
</Typography>
<Typography variant='subtitle1' gutterBottom>
{props.card.framework}
</Typography>
<Typography gutterBottom variant='body2' component='p'>
{props.card.description}
</Typography>
<Box className={classes.icons}>
<Typography gutterBottom variant='subtitle2'>
TOOLS USED
</Typography>
<Tooltip
TransitionComponent={Zoom}
arrow
title='REACT'
aria-label='react'
>
<Icon className='fab fa-react fa-3x' color='primary' />
</Tooltip>
<Tooltip
TransitionComponent={Zoom}
arrow
title='HTML5'
aria-label='add'
>
<Icon className='fab fa-html5 fa-3x' color='primary' />
</Tooltip>
<Tooltip
TransitionComponent={Zoom}
arrow
title='CSS3'
aria-label='add'
>
<Icon className='fab fa-css3 fa-3x' color='primary' />
</Tooltip>
</Box>
</CardContent>
</CardActionArea>
<CardActions>
<Button variant='outlined' size='small' color='primary'>
<Link
href={props.card.projectUrl}
target='_blank'
rel='noopener noreferrer'
className={classes.links}
underline='none'
color='inherit'
>
View Project
</Link>
</Button>
<Button
variant='outlined'
size='small'
color='primary'
className={classes.button}
endIcon={<GitHubIcon />}
>
<Link
href={props.card.githubUrl}
target='_blank'
rel='noopener noreferrer'
underline='none'
color='inherit'
>
Code
</Link>
</Button>
</CardActions>
</Card>
</Grid>
</>
);
}
export default TwoCard;
and here's the code that uses that Card component:
import React from "react";
import Grid from "#material-ui/core/Grid";
import Card from "./Card.js";
import { Typography } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
headings: {
padding: "20px 0"
}
}));
function Projects(props) {
const classes = useStyles();
let cards = props.data.map((card, i) => {
return <Card card={card} key={i} />;
});
return (
<>
<Typography variant="h4" gutterBottom>
Featured Projects
</Typography>
<Grid container spacing={2}>
{cards}
</Grid>
<Typography variant="h4" className={classes.headings}>
Other Projects of note
</Typography>
<Grid container spacing={2}>
{cards}
</Grid>
</>
);
}
export default Projects;
You can pass a prop to your Card component to control whether it is two-column or three-column. For instance, you can pass a maxColumns prop and use it in the following manner:
<Grid item xs={12} sm={6} lg={maxColumns > 2 ? 4 : undefined}>
Then your Projects component can pass the prop (in my example, I'm defaulting maxColumns to 2, so it doesn't need to be specified in that case):
import React from "react";
import Grid from "#material-ui/core/Grid";
import Card from "./Card.js";
import { Typography } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
headings: {
padding: "20px 0"
}
}));
function Projects(props) {
const classes = useStyles();
let twoColumnCards = props.data.map((card, i) => {
return <Card card={card} key={i} />;
});
let threeColumnCards = props.data.map((card, i) => {
return <Card maxColumns={3} card={card} key={i} />;
});
return (
<>
<Typography variant="h4" gutterBottom>
Featured Projects
</Typography>
<Grid container spacing={2}>
{twoColumnCards}
</Grid>
<Typography variant="h4" className={classes.headings}>
Other Projects of note
</Typography>
<Grid container spacing={2}>
{threeColumnCards}
</Grid>
</>
);
}
export default Projects;

How to autohide AppBar when scrolling using Reactjs Material-UI

How can I autohide my Reactjs <AppBar/> component when scrolling as shown in Fig.1?
Fig.1. <AppBar/> autohides when scrolling
I am using Material-UI and my code is as follows.
MyAppBar.js
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } 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 styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
You can use Slide in conjuction with useScrollTrigger
The gist here is, useScrollTrigger will (by default) return true when you scroll down and the window vertical scrollbar position hits a certain threshold (100 pixels from origin by default) - when you scroll back up it returns false. Hence, these are the reasons why we negate it on the in prop of Slide
export default function HideAppBar() {
const trigger = useScrollTrigger();
return (
<>
<Slide appear={false} direction="down" in={!trigger}>
<AppBar>
<Toolbar>
<Typography variant="h6">Scroll Down to Hide App Bar</Typography>
</Toolbar>
</AppBar>
</Slide>
...
</>
);
}
You can use the link I gave at the top of this answer pertaining to useScrollTrigger to customize the options such as threshold
Reference: https://material-ui.com/components/app-bar/#hide-app-bar

Resources