Recreate Ant Design Pro like Sider/Drawer in Antd React App - reactjs

I'm trying to configure the style/css of my Antd React app to be mobile ready.
My main menu uses the Reactive Sider Menu seen here.
My issue is when I'm viewing with a mobile viewport it's kinda ugly and it squashes everything outside of the menu. And the little tab to expand/condense the menu covers some of my other components.
I'd much prefer the design that they have in the Ant Design Pro demo.
But I'm not sure how to create this exactly. Has anyone attempted it before? It seems to use a Drawer when it's in a mobile viewport as opposed to using the Sider in the Layout API.

Figured this out.
Essentially my solution (not sure if this is what they actually did in Ant Design Pro) is to use the Reactive Sider Menu example for the desktop and use a Drawer for mobile.
The same Toggle button in the Reactive Sider Menu example can hide/close the Sider (in Desktop) and Drawer (in mobile).
The trick was using CSS Media Queries to hide the Drawer in Desktop and hide the Sider in mobile so each could do their thing.
CSS
.hideOnMobile {
display: none;
}
#media only screen and (min-width: 768px) {
.hideOnMobile {
display: block;
}
}
.hideOnDesktop {
display: block;
}
#media only screen and (min-width: 768px) {
.hideOnDesktop {
display: none;
}
}
App.js
const App = () => {
// sider and drawer toggle
const [isToggled, setToggled] = useState(false);
const toggleTrueFalse = () => setToggled(!isToggled);
const onClose = () => {
setToggled(false);
};
return (
<Layout style={{ minHeight: "100vh" }}>
<Drawer
placement="left"
onClose={onClose}
closable={false}
visible={isToggled}
className="hideOnDesktop"
bodyStyle={{ backgroundColor: "#001529", padding: "0" }}
>
<Navbar />
</Drawer>
<Sider
breakpoint="lg"
collapsedWidth="0"
collapsed={isToggled}
onBreakpoint={(broken) => {
setToggled(broken);
}}
className="hideOnMobile"
>
<Navbar />
</Sider>
<Layout className="site-layout">
<Header
className="site-layout-background"
style={{ padding: 0 }}
>
<Row>
{React.createElement(
isToggled ? MenuUnfoldOutlined : MenuFoldOutlined,
{
className: "trigger",
onClick: toggleTrueFalse,
}
)}
<TopNavbar />
</Row>
</Header>
...
Also per the Antd docs for the Drawer component you can use the bodyStyle prop to set the background color and remove the padding so the menu sits flush to the sides of the Drawer.

Related

How to make Material UI Pagination responsive

may I ask whether there is a way to make the material-ui Pagination responsive??
From the official API doc, there are only 3 sizes optional, but I want to make it responsive as my other elements.
<Pagination count={10} size="small" />
<Pagination count={10} />
<Pagination count={10} size="large" />
I want to make it sth like size="3vw", but it seems not working...
try Mui-selected.
like this:
const useStyles = makeStyles((theme) =>({
root: {
'& .Mui-selected': {
width: 'somethin',
height:'any size you need',
},
}),
);
const classes = useStyles();
return <Pagination
count={10}
className={classes.root}
renderItem={(item)=> <PaginationItem {...item}
classes={{selected:classes.selected}} />}
/>
Sorry #Nafis, I am not using makeStyles in my small react project... So I didn't try your solution, but appreciate your answer!
On the other hand, I kind of worked it out with overwrite the css of material UI which you can find out from developer tool.
This time I just need to make it more compact when the it is in a small screen, so I did something like below:
#media screen and (max-width:512px) {
.css-rppfq7-MuiButtonBase-root-MuiPaginationItem-root{
margin: 0 0;
min-width: 35px;
height: 35px;
border-radius: 17.5px;
}
}
Hopefully it could provide you some hints if you face similar difficulties.

How to style a Drawer using Material-UI v5

In Material-UI v4, the Drawer component could be styled this way:
<Drawer
variant="persistent"
classes={{paper: myClassNameHere}}
>
where myClassNameHere is produced by useStyles, which in turn is produced by makeStyles.
Migrating to v5's styling solution is proving tricky for this component in particular, because the styling needs to be applied to the inner Paper child component instead of to the main Drawer component itself.
Is it even possible to style Drawer at this point using the new solution?
You could pass your styled paper to the Drawer like so
import styled from "styled-components";
const MyPaper = styled.div`
//Put your styles here.
`;
const MyDrawer = () => {
return (
<Drawer
PaperProps={{ component : MyPaper }}
>
// drawer content
</Drawer>
)
}
Or you could actually pass an styled div to drawer (since paper itself displays flex, remember to pass flex:1 to fill out the space)
const MyPaper = styled.div`
flex:1;
`;
const MyDrawer = () => {
return (
<Drawer>
<MyPaper>
My Content
</MyPaper>
</Drawer>
)
}
There are many ways to do custom and inline style to MUI Drawer and one of which to do so is: to add PaperProps and put sx
<Drawer
PaperProps={{
sx: {
backgroundColor: "#05192D",
color: "blue",
fontSize: 50,
}
}}
>
...
</Drawer>
Hope this help, let's me know if your problem still persist!

How can I implement css hover effect in react inline-styling?

I am trying to implement a hover effect in the react component using react inline-styling.
const InfoWindow: React.FC<IInfoWindowProps> = ({ room }) => {
const info_window_image = {
width: "100%",
height: "168px",
background: `url(${room.pictures[0].image.large}) no-repeat`,
backgroundSize: "contain",
cursor: 'pointer'
};
return (
<div className="info_window_container">
<div style={info_window_image} />
</div>
)
};
div tag under info_window_container gets style object info_window_image .
I can successfully receive an image from API but I want to give zoom-in animation when the user hovers the image in the component.
I gave className to the div and styled in CSS file however it does not work. Styles I declared in CSS file do not render.
How can I make hover or focus effect in react-inline-styling?

Different styles in same component, only in gatsby build version

I have Navigation component that is the same at every page of my gatsby website. In development mode every styles are working properly. Button in dev mode on every page:
But in production build of gatsby only on home page ("/") it looks like that:
In production mode, on every page it works like in develop except home page, on home page styles are not apply only on this one button. And i have no idea why.
This is how Navigation component looks like:
const NavigationSearchBar = () => {
const { isMobile, windowWidth } = useResize()
const { setSearch } = useNavigationSearchBar()
return (
<StyledContainer>
<Row>
{!isMobile && (
<Col md="2">
<NavbarBrand href="/">
<img src={'/images/logo.svg'} />
</NavbarBrand>
</Col>
)}
<StyledSearchBar sm="12" md={{ size: 6, offset: 2 }}>
<StyledForm>
<SearchInput
type="text"
name="search"
onChange={e => setSearch(e.target.value)}
/>
<SimpleButton width="160px" background="primary" color="whiteColor">
Search
</SimpleButton>
</StyledForm>
</StyledSearchBar>
<StyledCol2 sm="12" lg="2">
<SimpleButton
width={windowWidth >= 400 ? '160px' : '100%'}
background="primaryOrange"
color="blackColor"
>
On Sale
</SimpleButton>
</StyledCol2>
</Row>
</StyledContainer>
)
}
export default NavigationSearchBar
Nothing special, there is no business logic here. This is how styles in styled components looks like for this button:
const SimpleButton = styled.button`
width: ${({ width }) => width};
background: ${({ background }) =>
theme.colors[background] ? theme.colors[background] : background};
padding: ${({ padding }) => (padding ? padding : '0.5rem 0')};
text-align: center;
border: 1px solid
${({ background }) =>
theme.colors[background] ? theme.colors[background] : background};
border-radius: 8px;
text-transform: uppercase;
color: ${({ color }) => (theme.colors[color] ? theme.colors[color] : color)};
letter-spacing: 1.5%;
font-weight: ${theme.fontWeights.medium};
position: relative;
z-index: 1;
`
I think it could be some issue with gatsby build process, because everything except this one button in production mode styles the same way as in development mode.
Do you have any idea why it's not working ?
I've just noticed that on refresh there is no styles, but if i get on page through gatsby link inside application styles are applied. For example if i'm on page /login every styles are applied, but when i refresh by clicking F5 gatsby enters /login/ and every styles disappear (this happens only in production mode).
I forget to install styled-components plugin for gatsby.
On develop everything working correctly, but on build version issues starts off.
Todo:
npm install gatsby-plugin-styled-components styled-components babel-plugin-styled-components
And don't forget to add plugin to gatsby-config.js file:
module.exports = {
/* Your site config here */
plugins: [
....other plugins
'gatsby-plugin-styled-components',
],
}

On page reload, my Gatsby.js footer component renders twice

Thank you for taking the time to look at my problem. I would really appreciate any help.
**Update:
Ok, so I think I know what's causing the problem but I don't know why. Before, on my products/merch page I only had one item in my database. On the products/beans page I had multiple items. On the products/merch page where there was only one result from the query the footer did not display twice. As soon as I added another item into the merch category and products/merch had two products, on page reload it also began to duplicate the footer.
Why would multiple queries have any effect on how a page renders? What could be some solutions to this? I'm going to try and pass the data in as props from the graphql to a allProducts component to see if that fixes the issue.
**
I'm using Gatsby.js and Strapi headless CMS for an ecommerce site I'm building. On a page which displays all the products in a specific category, if the page is reloaded, it renders the footer twice. This is confusing because when the page first renders it's fine but only on reload does it do it. If the website loads from that specific page, it also displays two footers. Once I navigate to another page and reload, the second footer goes away. This page giving me an issue has a GraphQL query. I have another page that also has a GraphQL query but it does not to do this. Something in this page is causing in issue in rendering.
What I've tried:
In gatsby-node.js, in the createPages export I had tried to create each page and pass a template and the context of "type" so that the GraphQL query could then filter for the data that the page needs. I thought that using createPage this way could cause a rendering issue. I've also tried removing the contents of the Footer component and directly placing them in layout.js. I've tried removing Layout component from the page and adding Header.js and Footer.js directly, still the same problem. I'm only experiencing this problem once i host it, not on the localhost. Is it an issue with Server Side Rendering? Here is a link to the site hosted on gatsby cloud, and if you click on any other page and refresh the second footer goes away but if you click back to this page and then refresh the second footer pops up again.
https://build-856af2e5-f049-46de-b6a5-9e11aa46a906.gtsb.io/products/beans/
createPage({
path: "/products/merch",
component: path.resolve(`src/templates/allproducts.js`),
context: {
type: "merch",
},
})
createPage({
path: "/products/beans",
component: path.resolve(`src/templates/allproducts.js`),
context: {
type: "beans",
},
})
So I then moved each page into a folder in the Gatsby pages folder. So Instead of using createPages to programmatically create them I made them traditionally by creating a products folder then adding a new page for each category. This did not resolve my issue by creating the pages manually instead of using createPages.
It doesn't make sense to me why the footer would load twice and not the header or the main component in my layout.js, which looks like this:
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Footer from "./Footer"
import Header from "./header"
import "./layout.css"
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<Header siteTitle={data.site.siteMetadata.title} />
<main>{children}</main>
<Footer />
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
Here is the Footer.js component:
import React from "react"
import { Facebook, Instagram, Twitter } from "#material-ui/icons"
import styled from "styled-components"
const BottomNav = styled.footer`
border-top: 1px solid black;
position: sticky;
height: 15vh;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-family: Raleway;
text-transform: uppercase;
`
const BottomNavContainer = styled.div`
display: flex;
justify-content: space-between;
width: 200px;
margin-bottom: 0.3rem;
`
const Footer = () => {
return (
<BottomNav>
<BottomNavContainer>
<Facebook />
<Instagram />
<Twitter />
</BottomNavContainer>
<div>
© {new Date().getFullYear()},{` `} The Blank
</div>
</BottomNav>
)
}
export default Footer
And here is the code for the pages that are duplicating the footer:
function Alert(props) {
return <MuiAlert elevation={6} variant="filled" {...props} />
}
const AllBeansPage = props => {
const products = props.data.allStrapiProduct.nodes
// const classes = useStyles()
const [open, setOpen] = React.useState(false)
const { addToCart } = useContext(CartContext)
const handleClick = () => {
setOpen(true)
}
const handleClose = (event, reason) => {
if (reason === "clickaway") {
return
}
setOpen(false)
}
return (
<Layout>
<SEO
title={
products[0].type.charAt(0).toUpperCase() + products[0].type.slice(1)
}
/>
<Fade in={true} timeout={{ enter: 2000, exit: 500 }}>
<AllProductsContainer>
<Container>
{products.map(product => (
<Slide
direction="left"
in={true}
mountOnEnter
unmountOnExit
timeout={{ enter: 1500, exit: 500 }}
>
<ProductCard key={product.id}>
<Link
key={product.id}
style={{}}
to={`products/${product.type}/${product.slug}`}
>
<ImageContainer>
{console.log(product.thumbnail.childImageSharp.fluid)}
<Img
key={product.id}
fluid={product.thumbnail.childImageSharp.fluid}
/>
</ImageContainer>
</Link>
<ProductContent>
<Typography
gutterBottom
variant="h5"
component="h1"
style={{
fontFamily: "Caveat",
fontSize: "clamp(22px, 3vw, 28px)",
}}
>
{product.name}
</Typography>
<Typography
variant="body2"
color="textSecondary"
style={{ fontSize: "clamp(12px, 1.5vw, 16px)" }}
>
{product.description.slice(0, 35)}...
</Typography>
<Link
key={product.id}
style={{}}
to={`products/${product.type}/${product.slug}`}
>
{" "}
<Typography
variant="subtitle1"
color="primary"
style={{ fontSize: "clamp(14px, 1.5w, 18px)" }}
>
Learn More
</Typography>
</Link>
</ProductContent>
<CardActionArea>
<CardActions
style={{
display: "flex",
justifyContent: "space-between",
}}
>
<Button
size="small"
color="primary"
onClick={() => {
addToCart(product, 1)
handleClick()
}}
style={{ fontSize: "clamp(12px, 1.5vw, 18px)" }}
>
Add To Cart
</Button>
<Typography
variant="body1"
style={{ fontSize: "clamp(12px, 1.5vw, 18px)" }}
>
{formatPrice(product.price_in_cents)}
</Typography>
</CardActions>
</CardActionArea>
</ProductCard>
</Slide>
))}
</Container>
</AllProductsContainer>
</Fade>
<Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
<Alert onClose={handleClose} severity="success">
Item successfully added to cart.
</Alert>
</Snackbar>
</Layout>
)
}
export default AllBeansPage
export const productQuery = graphql`
query allBeanQuery {
allStrapiProduct(filter: { type: { eq: "beans" } }) {
nodes {
strapiId
id
description
created_at
price_in_cents
name
slug
type
thumbnail {
childImageSharp {
fluid(quality: 100, maxWidth: 150, maxHeight: 150) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`
Ok! So here is the solution for this. If you're using GatsbyJS and a CMS, sometimes there can be issues with rendering things on the server if you use Material-UI. I'm thinking something in Material-UI is causing a re-render on the page. Basically, in the product page component, I replaced
<Button
onClick={() => {
addToCart(product, 1)
handleClick()
}}
style={{ fontSize: "clamp(12px, 1.5vw, 16px)" }}>ADD TO CART
</Button>
with
<div
onClick={() => {
addToCart(product, 1)
handleClick()
}}
style={{ fontSize: "clamp(12px, 1.5vw, 16px)" }}>ADD TO CART
</div>
and then it worked. So if you're getting two of the same component rendering on a page and everything seems right, just double check if a component library you're using is causing problems.

Resources