React non-modal "modal"? - reactjs

(Forewarning: I'm new to React, so I'm not sure all the vocab I'm using is correct)
I want something that's like a modal in that it pops up over the background, but I don't want it to lock the background/make it greyed out/make the background non-interactable (i.e., I want to be able to have the "modal" open but then click on the background/copy and paste something from that background into the "modal"). I've looked over some pre-built React components, but not seeing anything that fits the bill. Looking for any advice/pointers on this front. TIA!

This is more of a css question really. Using react you will want a div of height h and width w then you can position it in the center of the screen with a position: fixed you can then use a z-index to make sure it is over all the content is the screen and leave the rest of the page interactive.
function App(){
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<h1>Some content</h1>
<button onClick={()=>setIsOpen(true)}>Open Modal</button>
<div className="willFloat" style={{display: isOpen?'block':'none', height: '110px', width: '150px', position: 'fixed', zIndex: 1, top: '50%', left: '50%'}}>
<p>This will float in the center</p>
<button onClick={()=>setIsOpen(false)}>Close Modal</button>
</div>
</div>
);
}
This is of course just an example and uses quite a bit of inline styling and onClick function handling which you will want to separate out for any real projects.
With some additional styling you can get this div to do whatever you want. Learn some more html/css and it will make your life easier as well.Best

Related

How to add full page background image in NextJS

I'm trying to add a background image to an entire welcome page in NextJS and it's just not working. Before, I was having trouble with the fact that NextJS seems to render every component inside a master component that becomes an html div with a class of "__next". Therefore, every time I try and add a background image that takes the full page, it is only as big as the "__next" div and is cut off. I tried using NextJS' image component, but now it doesn't even load the image and just displays the alt text. Can anyone tell me how to fix the following code?
import React from "react";
import styles from "/styles/WelcomePage.module.css";
import Card from "/Components/Card";
import Link from "next/link";
import Image from "next/image";
function WelcomePage() {
return (
<>
<Card>
<h1 className={styles.title}>Welcome to Class Chooser</h1>
<button type="button">
<Link href="/ClassSearch"> Class Search </Link>
</button>
<Image
src="/images/graduates.jpg"
alt="Cartoon graduates jump with happiness"
quality="100"
layout="fill"
/>
</Card>
</>
);
}
export default WelcomePage;
To add a background image simply do it via CSS:
.card {
background-image: url("/images/graduates.jpg");
}
make your parent component (Card) position relative and add below properties to next-image.
layout="fill"
objectFit="cover"
position relative should be there for which you need to apply image as a background.
When you add layout="fill" to Image you need to wraper Image component in parent element and assing postion property to parent (relative, absolute, ...).
Wrap your Image inside a parent div, and make your parent position fixed
<div className="bg-image-wrapper">
<Image
src="/images/graduates.jpg"
alt="Cartoon graduates jump with happiness"
quality="100"
layout="fill"
/>
</div>
In css
.bg-image-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
}

AirBnb two column sticky Mapbox with results scroll - React, Mapbox, Tailwind

I'd like to create the desired results as seen here.
Please view in Desktop widescreen. AirBnb results.
As you can see with the AirBnb results, the Map on the Righthand side sticks perfectly into place while allowing the user to scroll down to view the results on the Lefthand side.
I've been trying to figure out how they have achieved this but am reaching some road blocks. I found some luck with implementing this bit of code but there is still a slight amount of vertical scrolling before the bottom of the map snaps into place. I believe it has to do with the h-screen class making the map height: 100vh
<main className="flex">
{/* Results & Filters section - Left side */}
<section className='flex-grow'>
<div className='lg:inline-flex mt-5 mb-5 space-x-3 text-gray-800 whitespace-no-wrap'>
<p className='custom-button'>Cancellation Flexibility</p>
<p className='custom-button'>Type of Place</p>
<p className='custom-button'>Price</p>
<p className='custom-button'>Rooms and Beds</p>
<p className='custom-button'>More Filters</p>
</div>
<div className="flex flex-col">
{/* Search results */}
{searchResults.map(
({ img, location, title, description, star, price, total }) => (
<InfoCard
key={img}
img={img}
location={location}
title={title}
description={description}
star={star}
price={price}
total={total}
/>
))}
</div>
</section>
{/* Map section - Right side */}
<aside className="hidden h-screen w-[50%] sticky xl:inline-flex l:min-w-[600px] top-0">
<Map searchResults={searchResults} />
</aside>
</main>
Some help would be greatly appreciated. I've started a codesandbox to make it easier to see what I'm experiencing. Please view in Desktop widescreen
https://codesandbox.io/s/determined-bartik-2tftc?file=/pages/index.js
[Edit] : I just noticed the left side is hidden by the map now since the map is out of the flex flow. I'll keep the answer as an idea. If you can manipulate the architecture of the page, it's easy to fix.
Looks like applying :
position: fixed;
right: 0;
justify-content: end;
to the aside tag that contains the map and removing its top-0 class fix your problem. I see that you are using an external library to display the map so I don't know if there is a way to apply css to it since I can't edit the codesandbox sorry. You could just wrap it in a span with a class and target it with .my-class > aside in your css. But first check the documentation, they are probably exposing some classes for you to apply styles.
So I seemed to have solved this. Took a bit of work but I achieved the result I was looking for.
I added some root css here in globals.css file
:root {
--navigation-bar-offset: 90px;
--gp-placement-max-height: calc(100vh - var(--navigation-bar-offset, 80px));
}
I utilized these root class names to be used in index.js on the component parent div
<div className="w-full
sticky
top-[var(--navigation-bar-offset,80px)]
h-[var(--gp-placement-max-height,auto)]">
<MapBox searchResults={searchResults} />
</div>
I also found, that Mapbox was overriding my height from it's setViewport callback in Map.js. So I overrode Mapbox by adding this code in Map.js in the onViewportChange.
onViewportChange={nextViewport => setViewPort({ ...nextViewport, width: "100%", height: "100%" })}
I updated the Codesandbox to reflect these changes.
Also, if you resize the browser, it maintains height and width.

I want to use RTL, but not through all of my components

I want to use RTL for some of my components in Nextjs. I also use material-ui. Unfortunately when I change direction in _documents.js with <HTML dir="rtl">, the direction of all of my components will change. material-ui's direction in createMuiTheme() doesn't affect direction at all.
Some of the components (like arrows) must not change based on direction. What should I do in order to keep them safe from changing direction.
Material Ui createMuiTheme get direction as an option itself
I also remember that it respect the direction of body tag
So for changing the direction of some part of your component, you have 3 ways as I know.
Change direction option in material createMuiTheme
It could be handle via your theme provider component for example
Use other instance of material Theme provider around your rtl components
Theme nesting
Put dir="rtl" on native DOM tags these will affect all lower subtree styles if you want e.g. flex-box direction and ...
for example
const ARABIC_PATTERN = /[\u0600-\u06FF]/
const getDirection = text => (ARABIC_PATTERN.test(text) ? 'rtl' : 'ltr')
<div dir={getDirection('what you want to test')}>
<Components />
</div>
Hacky suggestion. It's probably not the best answer, but it might be handy/decent if you need to just "reset" the position of 1-2 elements.
First invert everything like your are doing, then put a CSS class on the elements that shall not be "inverted":
.not-rtl-inteverted {
transform: scaleX(-1);
}
This way, you are basically inverting everything, and then inverting once again the elements with the class above.
section {
display: flex;
justify-content: space-around;
}
div {
background: green;
padding: 20px;
margin: 0 10px;
flex-basis: 33%;
}
.rtl {
transform: scaleX(-1);
}
<section>
<div>
<p>No RTL</p>
</div>
<div>
<p>Yes RTL</p>
</div>
<div>
<p>Yes RTL - but reset it on the 2nd line (by applying the same CSS class again)</p>
</div>
</section>
<section>
<div>
<p>text 1</p>
<p>text 2</p>
</div>
<div class="rtl">
<p>text 1</p>
<p>text 2</p>
</div>
<div class="rtl">
<p>text 1</p>
<p class="rtl">text 2</p>
</div>
</section>
In the example, by using twice the same class (once in the parent and once again the children that doesn't need to be rtl'd, we have this reset effect).
Again, might be handy for very simple use cases. I won't suggest this as a general solution to your problem.

How to put a logo in React Material UI Toolbar

I want to put a logo on the left side of the Toolbar in React (Material-UI Apppbar), but I don't get why it doesn't work. The logo is not showing at all.
import logo from '../../assets/companylogo.png';
const useStyles = makeStyles((theme) => ({
...
logo: {
width: '10%',
},
...
}));
<AppBar position='sticky'>
<Toolbar className={classes.toolbar} variant='dense'>
<img scr={logo} className={classes.logo}/>
<div className={classes.search}>
...
</div>
<div className={classes.grow} />
<div className={classes.sectionDesktop}>
...
</div>
<div className={classes.sectionMobile}>
...
</div>
</Toolbar>
</AppBar>
When <img/> is included I can see the width changes on the left depending on what the width of the logo is set to.
Here it is without the <img/>
I tried different images both .png and other formats, but id doesn't solve anything. I made sure the path to images is correct and also tried to wrap the <img/> with <div></div>, but nothing solved it. I thought it might be a z-index issue and the image is simply hiding behind the Toolbar, but that doesn't make sense to me and after playing a bit with zIndex value for image it didn't solve it either. I'm out of ideas here.
Any idea what am I doing wrong here?

make flex-item honour width only if there is content

I want create a flex-item which takes a width of 33% of the container only if there is some content present as follows:
<FlexItem width='33%'> <Somedom /> </FlexItem>
Here, the FlexItem is a component that can take all flex properties as props and renders a div. Now, Somedom can render null in the dom in which case I want the FlexItem to take no width at all and allow the sibling div to fill the entire container.
I was wondering if there is any flex based arrangement which can help me achieve that. Further I have no good way of knowing if its going to render content or not. I don't want to move FlexItem component in Somedom as well.
Using #04FS suggestion of :empty
You could do something as simple as this.
.FlxRw {
display: flex;
}
.Flx {
flex:0 0 33%;
background:#cdf;
}
.Flx:empty {
flex:0 0 0%;
}
<div class="FlxRw">
<div class="Flx"></div>
</div>
<div class="FlxRw">
<div class="Flx">Content</div>
</div>
<div class="FlxRw">
<div class="Flx"></div>
</div>

Resources