Windowing with Antd in Next.js breaks tooltips and popovers - next.js

I'm experimenting with the windowing technique in Next.js with Antd, and I made this simple app that has this index.tsx page:
import { CSSProperties } from 'react'
import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import AutoSizer from 'react-virtualized-auto-sizer'
import { FixedSizeList as List } from 'react-window'
import { Card, Tooltip } from 'antd'
import data from '../data'
import styles from '../styles/Home.module.css'
const people = data();
const Row = ({ index, style }: { index: number, style?: CSSProperties }) => (
<div style={style}>
<Card bordered={true}>
<p>{people[index].name}</p>
<Tooltip title={`${Math.floor(people[index].age/15)} in dog years`}>
<p>{people[index].age}</p>
</Tooltip>
</Card>
</div>
)
const Home: NextPage = () => {
return (
<AutoSizer>
{({ height, width }) => (
<List
height={height}
itemCount={people.length}
itemSize={100}
width={width}
>
{Row}
</List>
)}
</AutoSizer>
)
}
export default Home
The FixedSizeList won't work until I add the following style in globals.css:
html, body, div {
height: 100%;
}
However, when I do that, it breaks the Tooltip by Antd. Usually what happens is that when I hover above a relevant element, the tooltip appears for a split second with 100% height and then disappears and it doesn't appear anymore on a page no matter where I hover.
How can I solve this?

I finally found a solution after much agony.
Apparently, Nextjs wraps the entire layout with a div with id __next. That's the outer-most container of the entire page, and its height is not set, so since the content of FixedSizeList is positioned such that it's outside of the regular page flow, the __next div gets a height of 0.
I don't know if there is any better solution, but I simply added this little style in the globals.css file:
div#__next {
height: 100%;
}
That fixed the issue without forcing every other div in the page to have height at 100% (which includes the tooltips and popovers).

Related

How to make React MUI Components resize correctly

I have a page that has table component. Inside this table component are a DataGrid, and 2 button components, all using Material UI. I also have a navbar component that uses the MUI AppBar component with a button group. I originally developed this app on my extra large monitor and everything looked find, but as soon as I moved it to a regular monitor, I noticed that the navbar and DataGrid table were not scaling properly and that my buttons disappear underneath the footer.
If I 'scrunch' or reduce the browser window, a scrollbar appears, but its outside the table. I am not making this app for mobile so I just need it to display properly in common computer screen sizes. I want to focus on the table and buttons first. I have tried to put the button's outside the Table component, but I get the same result, so I am going to leave them inside the table component for now. I have already tried to wrap the table component in a div using display: 'flex' but it doesn't seem to change anything. Any suggestions on what I can do to get this to display properly? Is there a way to wrap everything in the App.js to get responsive action for all components?
import React, { useState, useEffect } from 'react';
import { DataGrid, GridToolbar} from '#mui/x-data-grid';
import EditJobModal from './EditJobModal';
import ClearButton from './ClearButton';
const MyTable = ({columns, data, clearStatus}) => {
const [selectionModel, setSelectionModel] = useState([]);
const [selectedRows, setSelectedRows] = useState([{'id': ''}]);
const buttonToTable = (clearStatus) => {
if (clearStatus === true) {
setSelectionModel([]);
setSelectedRows([{'id': ''}]);
}
}
return (
<div style={{ height: 450, width: '100%' }}>
<div style={{ display: 'flex', height: '100%' }}>
<div style={{ flexGrow: 1 }}>
<DataGrid
sx={{
boxShadow: 2,
border: 1,
margin: '5px'
}}
columns={columns}
rows={data}
pageSize={5}
rowsPerPageOptions={[10]}
checkboxSelection={false}
components={{ Toolbar: GridToolbar }}
selectionModel={selectionModel}
onSelectionModelChange={(ids) => {
if (ids.length > 1) {
let selectionSet = new Set(selectionModel);
let result = ids.filter((s) => !selectionSet.has(s));
setSelectionModel(result);
} else {
let selectedIDs = new Set(ids);
console.log(selectedIDs);
let selectedRow = data.filter((row) =>
selectedIDs.has(row.id),
);
setSelectedRows(selectedRow);
setSelectionModel(ids[0]);
}
}}
/>
<EditJobModal jobData={selectedRows}/>
<ClearButton buttonToTable={buttonToTable}/>
</div>
</div>
</div>
);
};
export default MyTable;

How do you style your React.js components differently depending on where you are using them in your application?

Let's say you have a navbar and when you're using this component on your homepage you want it to have a certain background color and display property, but when you use that same navbar component on another page in your application you want to change these CSS properties. Seeing as the component has one CSS file linked how would you change the style of a component depending on where it is being rendered?
My personal favourite method nowadays is styled components. Your component might look something like this:
// NavBar.js
import styled from 'styled-components'
const StyledDiv = styled.div`
width: 100%;
height: 2rem;
background-color: ${props => props.bgColor};
`
const NavBar = (bgColor) => {
return <StyledDiv bgColor={bgColor}>
}
Then to use it in your different contexts you simply pass the color prop:
// homepage.js
<NavBar bgColor="red" />
// otherpage.js
<NavBar bgColor="#123ABC" />
Styled components are becoming a very popular way of doing things, but be aware that there are a huge array of ways you can do this.
https://styled-components.com/
(Code not tested)
Well If you just want to use plain CSS then you can change the className based on route so the styles also changes.
Example:
import { useLocation } from "react-router-dom";
const Navigation = () => {
let location = useLocation();
...
return(
<nav className={location.pathname === "/home" ? "homepage-navbar" : "default-navbar"}>
...
</nav>
)
}
You can write longer condition for multiple pages as well.
Other better thing you can do is pass the location.pathname and value of className as prop.
import { useLocation } from "react-router-dom";
const Home = () => {
let location = useLocation();
...
return (
<>...
<Navigation location={location.pathname} styleClass={"homepage-navbar"}/>
</>
)
}
const Navigation = ({location, styleClass}) => {
...
return(
<nav className={location === "/home" ? styleClass : "default-navbar"}>
...
</nav>
)
}
So now you can pass different values for className from different components and get different styles for the navbar.

Creating a custom slider block from InnerBlocks using React Slick

I'm trying to create a somewhat basic custom block that creates a slider based off of the element's inner/nested blocks. Using React Slick, I've ran into an issue where ALL of the inner blocks are being wrapped in a single tag inside of the initialized slick slider element. This means, no matter how many inner blocks I add, there's only a single slide inside of the slick slider element.
Here's a screenshot of what's happening:
I've highlighted the to show you how the inner blocks elements (two basic paragraph blocks) are being combined as one singular slide.
Here's my edit.js:
import { __ } from '#wordpress/i18n';
import React from "react";
import Slider from "react-slick";
import {
InnerBlocks,
useBlockProps,
useInnerBlocksProps,
InspectorControls
} from '#wordpress/block-editor';
import {
PanelBody,
PanelRow,
} from '#wordpress/components';
import './editor.scss';
import classnames from 'classnames';
export default function Edit(props) {
const blockProps = useBlockProps( {
className: classnames( {
'slider': true
} )
} );
var settings = {
dots: true,
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1
};
const { children, ...innerBlocksProps } = useInnerBlocksProps( blockProps, {
templateInsertUpdatesSelection: true
} );
return (
<>
<InspectorControls key="1">
<PanelBody title={ __( 'Slides' ) }>
<PanelRow>
<fieldset>
Test
</fieldset>
</PanelRow>
</PanelBody>
</InspectorControls>
<div { ...innerBlocksProps }>
<Slider { ...settings }>
{ children }
</Slider>
</div>
</>
);
}
My gut is telling me this could have something to do with the timing of how the inner blocks get rendered, but I am a bit of a newbie when it comes to building custom blocks. Can anyone steer me in the right direction? I'd really really appreciate it. Thanks!

the React page is not scrollable

I am not able to make the page scrollable the code is as given below and i have not used any css i am still a new bee i have used map function to render the components i have sent the data using props thats it i am writing this because to fill space and nothing else
import { SimpleGrid, Flex } from "#chakra-ui/react";
import React, { useEffect, useState } from "react";
import Doccard from "../../components/doccard";
import { docdata } from "./docdat";
import data from "./docdat.json";
import Navbar from "../../components/Navbar";
import axios from "axios";
const url1 = "http://localhost:7000/doctors";
function Doctors() {
const [docdatai, setdocdatai] = useState([]);
useEffect(() => {
axios
.get(url1)
.then((Response) => {
console.log(Response.data);
setdocdatai(Response.data);
})
.catch((err) => {
console.log("error fetching data");
});
console.log("fetched");
}, []);
return (
<div className="scrollable-div" style={{ overflow: "scroll" }}>
<br />
<br />
<SimpleGrid columns={[2, 3, 5]} spacing={"20"} mt={4} mx={10}>
{console.log(docdatai)}
{docdatai.map((cardinfo, index) => {
return (
<Doccard
name={cardinfo.name}
username={cardinfo.username}
specialization={cardinfo.specialization}
/>
);
})}
</SimpleGrid>
</div>
);
}
export default Doctors;
Use overflow-y:auto for displaying scroll automatically when the content exceeds the divs set height.
Answer from ZWord, here
Keep in mind, the div will only be scrollable when the content inside is taller than the set height (you may want to set the height to 100vh and the width to 100vw to set the height / width to 100% of the screen). If you want to make the div x-axis scrollable, change it to overflow-x:auto, and if you want it to do both, use overflow:auto

How to center a Material UI FAB button and having it stay centered with window re-sizing?

As the title states, I would like for a MaterialUI FAB button to be centered and stay centered with resizing. The current placement is shown in the screenshot below (off-center) and it does not re-size with window change.
Here is the current FAB button component. It is a child component and I have shown the parent below as well.
I cannot get "justifyContent: "center"" to work as it normally does, as a note.
Any help on centering this and allowing it to scale with window size is welcome! thanks!
FAB button child component
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Fab from '#material-ui/core/Fab';
import NavigationIcon from '#material-ui/icons/Navigation';
import { navigate } from "#reach/router";
const useStyles = makeStyles((theme) => ({
root: {
'& > *': {
position: 'fixed',
bottom: "5vh",
right: "50vw",
backgroundColor: 'green',
width: "20vw"
},
},
fab:{
// fontSize: "35px"
},
extendedIcon: {
marginRight: theme.spacing(1),
// fontSize: "35px"
},
}));
export default function AddListingIcon() {
const classes = useStyles();
return (
<div className={classes.root}>
<Fab color="green" aria-label="add" size="large" variant="extended" className={classes.fab} >
<NavigationIcon onClick={() => {
navigate("/ChooseACategory")}} className={classes.extendedIcon}/>
Get Started!
</Fab>
</div>
)
}
Parent component which contains the FAB button child component
import React from "react";
import ReactNavbar from "../components/Navbar";
import Intro from "../components/Intro";
import GetStartedIcon from "../components/GetStartedIcon"
export default function GetStarted({ setSignedIn }) {
return (
<div>
<ReactNavbar setSignedIn={setSignedIn} />
<Intro />
<GetStartedIcon/>
</div>
);
}
Your code works as your wrote it (obviously). The right side of your button is centered as it should be.
You rather need to wrap the Button in a Flexbox. You can use the MUI Grid for that with a width:'100%', position:fixed and the prop justify="center".
Here is a jsfiddle with plain css
https://jsfiddle.net/rq6kvw12/

Resources