How to maintain the hover effect of the sibling in Material-UI - javascript

Card Component
import image from "../../Assets/pic.jpg";
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import FavoriteBorderIcon from "#material-ui/icons/FavoriteBorder";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import Typography from "#material-ui/core/Typography";
import styles from "./Cards.module.css";
import Stars from "../Stars/Stars";
const useStyles = makeStyles({
root: {
maxWidth: 345,
},
});
const Cards = () => {
const [showComponent, setShowComponent] = useState(false);
const classes = useStyles();
const handleToggleHoverIn = (event) => {
event.preventDefault();
setShowComponent(true);
};
const handleToggleHoverOut = (event) => {
event.preventDefault();
setShowComponent(false);
};
console.log("The state showComponent value is ", showComponent);
return (
<div className={styles.container}>
<Card
onMouseEnter={handleToggleHoverIn}
onMouseLeave={handleToggleHoverOut}
className={classes.root}
>
<CardActionArea>
<div id={styles.imageCentre}>
<CardMedia
component="img"
alt=""
className={styles.image}
image={image}
title="Contemplative Reptile"
/>
{/*
here when I hover over my <Stars/> and <FavoriteBorderIcon/>, the hover effect of opacity that I have on
my Card's image, vanishes
*/}
{showComponent ? (
<>
<div id={styles.stars}>
<Stars />
</div>
<FavoriteBorderIcon fontSize="large" id={styles.heart} />
</>
) : null}
</div>
<CardContent>
<Typography
gutterBottom
variant="h5"
component="h2"
id={styles.textCentre}
>
Printed round Neck
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<div class="text">
<p id={styles.price}>
<b>Rs. 454</b>
<strike>Rs. 699</strike>
<span style={{ color: "#FF7F7F" }}> (35 % off) </span>
</p>
</div>
</Typography>
</CardContent>
</CardActionArea>
</Card>
</div>
);
};
export default Cards;
Card's CSS styling
.image {
width: 300px;
justify-content: center;
}
.image:hover {
opacity: 0.5;
}
#imageCentre {
align-items: center !important;
position: relative;
}
/* #imageCentre:hover {
opacity: 0.5;
} */
#textCentre {
text-align: center;
}
.container {
display: flex;
justify-content: center;
padding: 2em;
}
#price,
.text h3 {
text-align: center;
}
#price b {
padding-right: 0.5em;
font-size: 1.3em;
}
#heart {
position: absolute;
top: 0;
right: 0;
padding: 20px 20px 0 0;
color: aliceblue;
}
#stars {
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
margin-top: 50%;
}
when I hover over my card, the opacity hover-effect comes in but when I move to the heart or star component, the opacity-hover vanishes. I want the hover-effect to remain even when I hover over my star and heart component. Is there any way that I can make the opacity-hover-effect to remain there, when I hover over the stars and heart component
Live Link

Below is an example of one way to do this. The key aspect of the solution is to use the :hover pseudo-class on a common parent of the img, stars, and icon elements. In my example, this is done via the action class applied to the CardActionArea element. My example is using makeStyles, but you could achieve the same effect in your CSS with the following:
#imageCentre:hover .image {
opacity: 0.5;
}
It looks like you tried something similar (the commented out #imageCenter:hover styles), but since you weren't targeting the descendant .image class for the opacity, the opacity would have impacted the stars and favorite icon as well which you probably don't want.
Here's a full working example:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import CardActions from "#material-ui/core/CardActions";
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 FavoriteBorderIcon from "#material-ui/icons/FavoriteBorder";
import Rating from "#material-ui/lab/Rating";
const useStyles = makeStyles({
root: {
maxWidth: 345
},
media: {
height: 140
},
action: {
position: "relative",
"&:hover $media": {
opacity: 0.5
}
},
favorite: {
position: "absolute",
top: 10,
left: 10,
color: "white"
},
rating: {
position: "absolute",
top: 100,
left: 100
}
});
export default function MediaCard() {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardActionArea className={classes.action}>
<CardMedia
component="img"
className={classes.media}
image="https://material-ui.com/static/images/cards/contemplative-reptile.jpg"
title="Contemplative Reptile"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
Lizard
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Lizards are a widespread group of squamate reptiles, with over 6,000
species, ranging across all continents except Antarctica
</Typography>
</CardContent>
<FavoriteBorderIcon className={classes.favorite} />
<Rating className={classes.rating} name="rating" />
</CardActionArea>
<CardActions>
<Button size="small" color="primary">
Share
</Button>
<Button size="small" color="primary">
Learn More
</Button>
</CardActions>
</Card>
);
}

Related

Intersection Observer isVisible variable not changing

I have set up this Intersection Observer function because I want my divs to slide in from the side as the user scrolls down. However, after much tinkering and small changes, it still is not working. I've tried console-logging "entries", the "isVisible" variable, and "sliderRef". The first two are useless, as I get undefined for isVisible and an empty array for "entries", while I get the first div when I console-log sliderRef, but not the other two divs. I apologize for the vagueness and inability to present a specific reason as to why this isn't working. Any help would be appreciated, or any suggestion for a simpler way to achieve what I'm trying to do. Below is all the relevant code:
Edit: I changed the default value of isVisible to true, to see if the props were even being passed to my styled components, and the div appeared briefly on load but then slid out of view. However, still nothing happens when I have isVisible set to false. My options don't seem to be being taken into account, because the function was triggered regardless of the fact that I had not yet reached the threshold, which is 0.5
import { useRef, useState, useEffect} from 'react'
import styled, { css } from 'styled-components'
import PropTypes from 'prop-types';
import clsx from 'clsx';
import {
Container,
Grid,
Typography,
makeStyles
} from '#material-ui/core';
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: "white",
height: "200vh",
marginBottom: "200px"
},
contentGrid: {
display: "flex",
height: "33%",
padding: 0,
},
}));
const useElementOnScreen = (options) => {
const sliderRef = useRef(null);
const [isVisible, setIsVisible] = useState(false);
const callBackFunction = (entries) => {
const [entry] = entries;
setIsVisible(entry.IsIntersecting);
console.log(entries);
};
useEffect(() => {
const observer = new IntersectionObserver(callBackFunction, options);
if (sliderRef.current) observer.observe(sliderRef.current);
return () => {
if (sliderRef.current) observer.unobserve(sliderRef.current);
};
}, [sliderRef, options]);
return [sliderRef, isVisible];
}
function Features({ className, ...rest }) {
const classes = useStyles();
const [sliderRef, isVisible] = useElementOnScreen({
root: null,
threshold: 0.5,
rootMargin: "0px 0px -100px 0px"
})
return (
<div
className={clsx(classes.root, className)}
{...rest}
>
{/* <Container maxWidth="lg" style={{padding: 0, width: "100%"}}> */}
<Grid className={classes.contentGrid} style={{backgroundColor: "#025373"}}>
<SliderFromLeft visible={isVisible}
ref={sliderRef}
style={{backgroundColor: "#F2D680"}}
>
<Typography
variant="h4">
Increased complexity has enabled media agencies
to create opaque financial structures
and then inflate their fees and
media prices at will, while many
advertisers are stuck behind contracts
unfit for modern media buying that
provide little scope for transparency and accountability.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", paddingRight:"75px"}}>
<Typography
variant="h1"
align="right"
style={{color:"#F2C230", fontSize:"4rem"}}
>
Are you getting the most out of your contract?
</Typography>
</NonSlider>
</Grid>
<Grid className={classes.contentGrid} style={{backgroundColor: "#D0E5F2"}}>
<NonSlider style={{backgroundColor: "#D0E5F2"}}>
<Typography
variant="h1"
style={{color: "#025373", fontSize:"4rem"}}
>
The <br/>Challenge
</Typography>
</NonSlider>
<SliderFromRight visible={isVisible}
style={{backgroundColor: "#75B8BF"}}
>
<Typography
variant="h4"
style={{color:"#025373"}}>
We want you to get the same benefits that the top global advertisers enjoy.
The core of a successful relationship between you and your media agency is a well thought-out contract.
<br/>
<br/>
You must ensure that your media agency contract provides clarity and accountability,
and contains competitive terms and conditions.
</Typography>
</SliderFromRight>
</Grid>
<Grid className={classes.contentGrid} style={{backgroundColor: "#F2D680"}}>
<SliderFromLeft visible={isVisible}
style={{backgroundColor:"#F2F2F2"}}
ref={sliderRef}
>
<Typography
variant="h4">
It is known that most media agencies design their own contract templates to benefit
themselves and not you. We believe this needs to change and you need to regain control.
<br/>
<br/>
To assess the quality of your contract, you must first benchmark it against the industry average.
Once you know the the strengths and weaknesses of the contract, it is easier to
know what needs to be improved upon.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", justifyContent:"right", paddingRight: '75px'}}>
<Typography
variant="h1"
align="right"
style={{color:"#025373", fontSize:"4.2rem"}}
>
The <br/> Solution
</Typography>
</NonSlider>
</Grid>
{/* </Container> */}
</div>
);
}
const SliderFromLeft = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px;
border-top-right-radius: 30px;
border-bottom-right-radius: 30px;
opacity: 0%;
transform: translateX(-100%);
transition: transform 400ms ease-in, opacity 250ms ease-in;
${props => props.visible && `
transform: translateX(0%);
opacity: 100;`
}
`
const SliderFromRight = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px;
border-top-left-radius: 30px;
border-bottom-left-radius: 30px;
opacity: 0;
transform: translateX(100%);
transition: transform 400ms ease-in, opacity 250ms ease-in;
${props => props.visible && `
transform: translateX(0%)
opacity: 100;`
}
`
const NonSlider = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px
`
Features.propTypes = {
className: PropTypes.string
};
export default Features;```
For anyone having the same issue, despite reorganizing and improving my code based on updated documentation, I didn't exactly solve my problem, but I did somewhat achieve the effect I was looking for. I'm still not sure what was causing the issue, but I decided to ditch the slide-in effect for a simple fade-in effect by changing the opacity, and that works just fine.
Based on the newer documentation I found and some other answers here on SO, you can just import the useInView hook instead of writing it out yourself, and you must call useInView separately for each component, instead of giving all components the same ref and calling useInView once. I hope this helps.
import { useRef, useState, useEffect} from 'react';
import { useInView } from 'react-intersection-observer';
import styled, { css } from 'styled-components'
import PropTypes from 'prop-types';
import clsx from 'clsx';
import {
Container,
Grid,
Typography,
makeStyles
} from '#material-ui/core';
import Contract from './Media/contract.png'
import Challenge from './Media/challenge.png'
import Presenter from './Media/presenter.png'
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: "white",
height: "175vh",
},
contentGrid: {
display: "flex",
height: "33%",
padding: 0,
},
header: {
color: "#000000",
fontSize: "2.5rem",
marginBottom: "10px",
},
image: {
height: "355px",
width: "500px",
}
}));
function Features({ className, ...rest }) {
const classes = useStyles();
const { ref: ref1, inView: inView1 } = useInView({ threshold: 0.5 })
const { ref: ref2, inView: inView2 } = useInView({ threshold: 0.5 })
const { ref: ref3, inView: inView3 } = useInView({ threshold: 0.5 })
console.log(inView2);
return (
<div
className={clsx(classes.root, className)}
{...rest}
>
{/* <Container maxWidth="lg" style={{padding: 0, width: "100%"}}> */}
<Grid className={classes.contentGrid}>
<SliderFromLeft
visible={inView1}
ref={ref1}
>
<Typography
variant="h1"
align="left"
className={classes.header}
>
Are you getting the most out of your contract?
</Typography>
<Typography
variant="h4">
Increased complexity has enabled media agencies
to create opaque financial structures
and then inflate their fees and
media prices at will, while many
advertisers are stuck behind contracts
unfit for modern media buying that
provide little scope for transparency and accountability.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", paddingRight:"75px"}}>
<img src={Contract} className={classes.image} />
</NonSlider>
</Grid>
<Grid className={classes.contentGrid}>
<NonSlider>
<img className={classes.image} src={Challenge} />
</NonSlider>
<SliderFromRight
visible={inView2}
ref={ref2}
>
<Typography
variant="h1"
align="right"
className={classes.header}
>
The Challenge
</Typography>
<Typography
variant="h4"
>
We want you to get the same benefits that the top global advertisers enjoy.
The core of a successful relationship between you and your media agency is a well thought-out contract.
<br/>
<br/>
You must ensure that your media agency contract provides clarity and accountability,
and contains competitive terms and conditions.
</Typography>
</SliderFromRight>
</Grid>
<Grid className={classes.contentGrid}>
<SliderFromLeft
visible={inView3}
ref={ref3}
>
<Typography
variant="h1"
align="left"
className={classes.header}
>
The Solution
</Typography>
<Typography
variant="h4">
It is known that most media agencies design their own contract templates to benefit
themselves and not you. We believe this needs to change and you need to regain control.
<br/>
<br/>
To assess the quality of your contract, you must first benchmark it against the industry average.
Once you know the the strengths and weaknesses of the contract, it is easier to
know what needs to be improved upon.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", justifyContent:"right", paddingRight: '75px'}}>
<img src={Presenter} className={classes.image} />
</NonSlider>
</Grid>
{/* </Container> */}
</div>
);
}
const SliderFromLeft = styled.div`
height: 100%;
width: 50%;
// display: flex;
align-items: center;
padding: 75px 75px 0 75px;
border-top-right-radius: 30px;
border-bottom-right-radius: 30px;
opacity: 0;
// transform: translateX(-100%);
transition: transform 400ms ease-in, opacity 0.5s ease-in;
${props => props.visible && `
// transform: translateX(0%);
opacity: 100;`
}
`
const SliderFromRight = styled.div`
height: 100%;
width: 50%;
// display: flex;
align-items: center;
padding: 75px 75px 0 75px;
border-top-left-radius: 30px;
border-bottom-left-radius: 30px;
opacity: 0;
// transform: translateX(100%);
transition: transform 400ms ease-in, opacity 0.5s ease-in;
${props => props.visible && `
// transform: translateX(0%)
opacity: 100;`
}
`
const NonSlider = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px
`
Features.propTypes = {
className: PropTypes.string
};
export default Features;```

Make selected item fit on one line, not two

I have a very simple select and when I click on the menu it shows 3 options, all on one-line each. However, when I select an item, it shows it on 2 lines: 1 line for the text and another for the icon. How do I make it so it is one line?
import "./styles.css";
import EditIcon from "#material-ui/icons/Edit";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemText from "#material-ui/core/ListItemText";
import Select from "#material-ui/core/Select";
import FormControl from "#material-ui/core/FormControl";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import FormHelperText from "#material-ui/core/FormHelperText";
const items = ["a", "b", "c"];
export default function App() {
return (
<>
<FormControl>
<InputLabel>Please select an option</InputLabel>
<Select required defaultValue="hi" fullWidth>
{items.map((item, idx) => (
<MenuItem key={idx} value={item}>
<ListItemText primary={item} />
<ListItemIcon>
<EditIcon />
</ListItemIcon>
</MenuItem>
))}
</Select>
<FormHelperText>Just select something already</FormHelperText>
</FormControl>
</>
);
}
https://codesandbox.io/s/brave-stallman-9brmk?file=/src/App.js
The MenuItem layout is flex, while SelectInput is not, you can target the SelectInput using classes props and override the layout style like this:
See all possible rule names to override here.
<Select classes={{ select: classes.root }}
const useStyles = makeStyles({
root: {
display: "flex",
alignItems: "center"
}
});
Live Demo
You're using flex properties in .MuiListItemText-root and .MuiListItemIcon-root, but parent still has display: block. Your CSS for .MuiInputBase-input should look like this (changed display: block; to display: flex;):
.MuiInputBase-input {
font: inherit;
color: currentColor;
width: 100%;
border: 0;
height: 1.1876em;
margin: 0;
display: block;
padding: 6px 0 7px;
min-width: 0;
background: none;
box-sizing: content-box;
animation-name: mui-auto-fill-cancel;
letter-spacing: inherit;
animation-duration: 10ms;
-webkit-tap-highlight-color: transparent;
}

Ant Design Layout is not working as expected

I have a React application. I have decided to add a layout using Ant Design. And i followed below example.
https://2x.ant.design/components/layout/#components-layout-demo-custom-trigger
This is my component code. (Full.js)
import React, { Component, Fragment } from 'react'
import { Layout, Menu } from 'antd'
import Icon from '#ant-design/icons'
import './Full.css'
import ReactDOM from 'react-dom'
import DailyData from '../DailyData'
import Container from 'react-bootstrap/Container'
import Toggle from './Toggle'
const { Header, Footer, Sider, Content } = Layout;
class Full extends React.Component {
state = {
collapsed: false,
};
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
}
render() {
return (
<Layout style={{ height: "100vh" }}>
<Sider
trigger={null}
collapsible
collapsed={this.state.collapsed}
>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1">
<Icon type="user" />
<span>nav 1</span>
</Menu.Item>
<Menu.Item key="2">
<Icon type="video-camera" />
<span>nav 2</span>
</Menu.Item>
<Menu.Item key="3">
<Icon type="upload" />
<span>nav 3</span>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0 }}>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
onClick={this.toggle}
/>
</Header>
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280 }}>
Content
</Content>
</Layout>
</Layout>
);
}
}
export default Full;
I'm using this component as below in App.js file.
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Header from './components/layout/Header.js'
import DailyData from './components/DailyData.js'
import Container from 'react-bootstrap/Container'
import Toggle from './components/layout/Toggle.js'
import Full from './components/layout/Full'
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="App">
<Full />
</div >
);
}
}
export default App;
My Full.css file as below.
#components-layout-demo-custom-trigger .trigger {
font-size: 18px;
line-height: 64px;
padding: 0 16px;
cursor: pointer;
transition: color .3s;
}
#components-layout-demo-custom-trigger .trigger:hover {
color: #108ee9;
}
#components-layout-demo-custom-trigger .logo {
height: 32px;
background: #333;
border-radius: 6px;
margin: 16px;
}
But the output will display like this.
Well, I also used Ant design Sider and I am using version 4.4.1. Not sure what you want to acheive, so I am sharing the whole code with you.
import React from 'react';
import { Route, Switch, NavLink, Redirect, withRouter } from 'react-router-dom'
import {RouteComponentProps} from "react-router";
import { Layout, Menu } from 'antd';
import {
DesktopOutlined,
PieChartOutlined,
UserOutlined,
SettingOutlined
} from '#ant-design/icons';
import Shipper from '../shipper/shipper'
const { Header, Content, Footer, Sider } = Layout;
const { SubMenu } = Menu;
// Type whatever you expect in 'this.props.match.params.*'
type PathParamsType = {
param1: string,
}
// Your component own properties
type PropsType = RouteComponentProps<PathParamsType> & {
}
class Sidebar extends React.Component<PropsType> {
state = {
collapsed: false,
};
onCollapse = (collapsed: any) => {
this.setState({ collapsed });
};
render() {
let { pathname } = this.props.location;
return (
<Layout style={{ minHeight: '100vh' }}>
<Header className="header">
<div className="logo" />
<Menu mode="horizontal" theme="dark" className="flex-setting">
<SubMenu icon={<SettingOutlined />} title="Settings">
<Menu.ItemGroup title="Basic Settings">
<Menu.Item key="setting:2">
<a href={"/accounts/logout/"} target="_self">
Signout
</a>
</Menu.Item>
</Menu.ItemGroup>
</SubMenu>
</Menu>
</Header>
<Layout>
<Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse}>
{/* <div className="logo" /> */}
<Menu theme="dark"
defaultSelectedKeys={['/shipper']}
selectedKeys={[pathname]}
mode="inline">
<Menu.Item key="/shipper" icon={<PieChartOutlined />}>
<NavLink to="/shipper">
<span>Shipper</span>
</NavLink>
</Menu.Item>
</SubMenu>
</Menu>
</Sider>
<Layout className="site-layout">
{/* <Header className="site-layout-background" style={{ padding: 0 }} /> */}
<Content style={{ margin: "16px 16px", background: "#fff" }}>
<div style={{ padding: 24, background: "#fff", minHeight: 360 }}>
<Switch>
<Route exact path="/" render={() => (
<Redirect to="/shipper"/>
)}/>
<Route path="/shipper">
<Shipper />
</Route>
</Switch>
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Copyrights © 2020 All Rights Reseverd by Company.</Footer>
</Layout>
</Layout>
</Layout>
);
}
}
export default withRouter(Sidebar);
My css is following:
.header {
display: inherit;
}
.logo {
height: 32px;
width: 35px;
margin: 16px;
background-image: url("main-logo.jpg");
}
.flex-setting {
display: flex;
flex-direction: row-reverse;
width: 100%;
}
Alot of things not necessary for you, so remove that part. Once you follow this, you will achieve something link this:
Remove " #components-layout-demo-custom-trigger" from css file and it will work.
I am sharing my css file.
App.css
#import "~antd/dist/antd.css";
.trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color 0.3s;
}
.trigger:hover {
color: #1890ff;
}
.logo {
height: 32px;
background: rgba(255, 255, 255, 0.2);
margin: 16px;
}
.site-layout .site-layout-background {
background: #fff;
}
Because the example has trigger class ID # component-layout-demo-custom-trigger in front of it but the copied code also has # component-layout-demo-custom-trigger removed
enter image description here

Styling help: Transparent appbar with Material UI in React.js

I am using material ui and i have been trying to make the navabr transparent and get the background image behind it, a similar style to stripe.com and i am having trouble moving the image behind and getting it transparent.
Is there a way to get it looking like stripe.com with the transparent appbar and background image moved up? The main problem is moving up the background image
Code for the Navbar
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 Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogContentText from '#material-ui/core/DialogContentText';
import DialogTitle from '#material-ui/core/DialogTitle';
import Checkbox from '#material-ui/core/Checkbox';
import TextField from '#material-ui/core/TextField';
import { Link } from 'react-router-dom'
// Styling for our navbar
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
button: {
margin: 10,
fontSize: 17
},
text: {
textAlign: 'center',
fontSize: 20,
padding: '0.5em'
},
textField: {
align: 'center',
width: 500
}
};
const MyLink = props => <Link to="/signup" {...props} />
// here is our navbar
class Navbar extends React.Component{
state = {
open: false,
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
state = {
checkedA: true,
checkedB: true,
checkedF: true,
};
handleChange = name => event => {
this.setState({ [name]: event.target.checked });
};
render(){
const { classes } = this.props
return (
<div className={classes.root}>
<AppBar position="static" color="inherit" style={{ background: 'transparent', boxShadow: 'none'}}>
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
</Typography>
<Button color="inherit" onClick={this.handleClickOpen}>Login</Button>
</Toolbar>
</AppBar>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description">
<DialogTitle id="alert-dialog-title">{"Have an account? Log In"}</DialogTitle>
<DialogContent>
<DialogTitle>
<Button variant="contained" color="primary" className={classes.button}>
Sign In with Facebook </Button>
<Button variant="contained" color="primary" className={classes.button}>
Sign In with LinkedIn </Button>
</DialogTitle>
<DialogContentText className={classes.text}>
or
</DialogContentText>
<form>
<TextField
id="filled-email-input"
label="Email"
className={classes.textField}
type="email"
name="email"
autoComplete="email"
margin="normal"
variant="filled"
/>
</form>
<form>
<TextField
id="filled-password-input"
label="Password"
className={classes.textField}
type="password"
autoComplete="current-password"
margin="normal"
variant="filled"
/>
</form>
<Checkbox
checked={this.state.checkedG}
onChange={this.handleChange('checkedG')}
value="checkedG"
color= "inherit"
/>
<DialogContentText>
Remember Me?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button component={MyLink} color="primary" autoFocus>
Don't have an account? Sign Up
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
// requiring a class object
Navbar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Navbar);
And heres the code for the Lading page header/background
import React, {Component} from 'react';
import Background from '../img/fixedImg.png';
import './Header.css';
import { Link } from 'react-router-dom';
const headerStyle = {
backgroundImage: `url( ${Background} )`,
height: '100vh',
backgroundSize: 'cover'
}
// class component for our image on the home page
// the <br> needs fixing in the css file
class Header extends Component {
render() {
return (
<header style={headerStyle}>
<h1>Hashtag Hound </h1>
<p> Connecting influencers with brands </p>
<Link to="/signup">Find an Influencer</Link>
</header>
);
}
};
export default Header;
Here is the css for it
header {
margin: 0 auto;
text-align: center;
}
header h1 {
margin: 0;
font-family: arial;
font-size: 4rem;
color: #383636;
}
header p {
font-weight: 700;
font-size: 1.75rem;
font-family: arial;
color: #383636;
}
header a {
box-shadow: 0 3px 3px 0 rgb(0,0,0,1);
font-weight: 700;
font-size: 1.2rem;
background-color: black;
border-color: black;
color: white;
padding: 1.25rem 2.5rem;
border-radius: 2rem;
text-decoration: none;
font-family: arial;
display: inline-block;
}

Material-ui Drawer doesn't work with separate css file

I'm creating a Sidebar similar to the Mini Variant drawer demo, but my project specifies that all the css formatting must be done in a separate css file, not in the drawer's js file (as the material-ui demos do). I've figured out how to format my drawer according to the demos, but now I need to figure out how to separate out the css and make it workable.
Right now the drawer renders with default settings, but all but one of the css classes aren't working/rendering. Only one, listItem, works and changes the height of a ListItem, which is weird. All the other css classes don't change how the drawer looks.
This is the non-working version with a separate css file imported in:
.root {
display: flex;
}
.drawerOpen {
top: 70px;
bottom: 70px;
position: fixed;
white-space: nowrap; /*text doesn't shrink into side*/
width: 240;
transition: width 2s;
}
.drawerClose {
top: 70px;
bottom: 70px;
position: fixed;
width: 240;
overflow-x: hidden; /*hides text when drawer is closed*/
transition: width 2s;
}
.iconButton {
margin-top: 15px;
margin-bottom: 7px;
}
.listItem {
height: 75px;
}
SideBar.js:
import React, { Component } from "react";
import PropTypes from "prop-types";
import Drawer from "#material-ui/core/Drawer";
import { withStyles } from "#material-ui/core/styles";
import { IconButton, Divider, ListItemIcon } from "#material-ui/core";
import { List, ListItem, ListItemText } from "#material-ui/core";
import InboxIcon from "#material-ui/icons/MoveToInbox";
import MailIcon from "#material-ui/icons/Mail";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
import ChevronLeftIcon from "#material-ui/icons/ChevronLeft";
import "../css/SideBar.css";
import "../css/SideBar.css";
class Sidebar extends Component {
state = {
open: false
};
handleSidebarToggle = () => {
this.setState({ open: !this.state.open });
};
render() {
const { classes } = this.props;
const { open } = this.state;
return (
<div className="root">
<Drawer
variant="permanent"
anchor="left"
open={open}
className={(open === true) ? "drawerOpen" : "drawerClose"}
>
<div>
<Divider />
<IconButton
className="iconButton"
onClick={this.handleSidebarToggle}
>
{open === false ? <ChevronRightIcon /> : <ChevronLeftIcon />}
</IconButton>
</div>
<List>
<Divider />
<ListItem className="listItem" button>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Info" />
</ListItem>
<Divider />
<ListItem className="listItem" button>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary="Roofing" />
</ListItem>
<Divider />
<ListItem className="listItem" button>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Siding" />
</ListItem>
<Divider />
<ListItem className="listItem" button>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary="Windows" />
</ListItem>
<Divider />
<ListItem className="listItem" button>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary="Shop" />
</ListItem>
<Divider />
</List>
</Drawer>
</div>
);
}
}
export default Sidebar;
This is the working version in just one .js file with the css in the const styles:
import React, { Component } from "react";
import PropTypes from "prop-types";
import Drawer from "#material-ui/core/Drawer";
import { withStyles } from "#material-ui/core/styles";
import { IconButton, Divider, ListItemIcon } from "#material-ui/core";
import { List, ListItem, ListItemText } from "#material-ui/core";
import InboxIcon from "#material-ui/icons/MoveToInbox";
import MailIcon from "#material-ui/icons/Mail";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
import ChevronLeftIcon from "#material-ui/icons/ChevronLeft";
import "../css/SideBar.css";
const styles = theme => ({
root: {
display: "flex",
},
drawerPaper: {
top: "70px", //moves Sidebar below AppBar
bottom: "70px",
position: "fixed",
whiteSpace: "nowrap", //text doesn't shrink into side
width: 240,
transition: theme.transitions.create("width", {
//makes transitions smooth
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen
})
},
drawerPaperClose: {
overflowX: "hidden", //display mini sidebar
width: theme.spacing.unit * 7,
[theme.breakpoints.up("sm")]: {
width: theme.spacing.unit * 9
},
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
iconButton: { //fixes spacing
marginTop: "15px",
marginBottom: "7px"
},
listItem: {
height: "75px"
}
});
class Sidebar extends Component {
state = {
open: false
};
handleSidebarToggle = () => {
this.setState({ open: !this.state.open });
};
render() {
const { classes } = this.props;
const { open } = this.state;
return (
<div className={classes.root}>
<Drawer
variant="permanent"
anchor="left"
open={open}
classes={{
paper: classNames(
classes.drawerPaper,
!open && classes.drawerPaperClose
)
}}
className="drawer"
>
<div>
<Divider />
<IconButton
className={classes.iconButton}
onClick={this.handleSidebarToggle}
>
{open === false ? <ChevronRightIcon /> : <ChevronLeftIcon />}
</IconButton>
</div>
<List>
<Divider />
<ListItem className={classes.listItem} button>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Info" />
</ListItem>
<Divider />
<ListItem className={classes.listItem} button>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary="Roofing" />
</ListItem>
<Divider />
<ListItem className={classes.listItem} button>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Siding" />
</ListItem>
<Divider />
<ListItem className={classes.listItem} button>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary="Windows" />
</ListItem>
<Divider />
<ListItem className={classes.listItem} button>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary="Shop" />
</ListItem>
<Divider />
</List>
</Drawer>
</div>
);
}
}
Sidebar.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired
};
export default withStyles(styles, { withTheme: true })(Sidebar);
you can create a separate file with styles but as .js files and refer it in the component.
material-UI uses CSS-in-js
referer this link:https://material-ui.com/customization/css-in-js/
In your scenario, you can create a styles.js file in the same folder with the component(or any place you wish) like below:
export default const styles = {
.root {
display: flex;
}
.drawerOpen {
top: 70px;
bottom: 70px;
position: fixed;
white-space: nowrap; /*text doesn't shrink into side*/
width: 240;
transition: width 2s;
}
.drawerClose {
top: 70px;
bottom: 70px;
position: fixed;
width: 240;
overflow-x: hidden; /*hides text when drawer is closed*/
transition: width 2s;
}
.iconButton {
margin-top: 15px;
margin-bottom: 7px;
}
.listItem {
height: 75px;
}
}
and refer it in the component as:
import styles from "./styles"
... component ...
export default withStyles(styles)(Sidebar);
find more details about how to override styles of material-UI components from here: https://material-ui.com/customization/overrides/
hope this will help you.

Categories