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

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.

Related

React non-modal "modal"?

(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

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 am trying to make my button size smaller in JSX but I do not know how to

I want to make my button and status symbol smaller they are way too big for the screen chat.
Here is my JSX file
import React from 'react';
import closeIcon from '../../icons/closeIcon.png';
import onlineIcon from '../../icons/onlineIcon.png';
import './InfoBar.css';
const InfoBar = ({room}) => (
<div className="infoBar">
<div className="leftInnerContainer">
<img className= "onlineIcon" src={onlineIcon} alt="open 6342 56837 Image" />
<h3>{room}</h3>
</div>
<div className="rightInnerContainer">
<img src={closeIcon} alt="close 6342 56837 Image"/>
</div>
</div>
)
export default InfoBar;
Thank you so much
In the attached image you have defined an inline style like this
<div className="leftInnerContainer" style={{"width:60px"},{"height:30px"}}
You have the right idea, but the syntax for the style prop is wrong - hence the compilation error.
It needs to be a plain Javascript object, for which the correct syntax is this
{ width: "60px", height: "30px" }
And in the style prop in JSX, looks like this
<div className="leftInnerContainer" style={{ width: "60px", height: "30px" }}
You should give the css you are importing too given it can be solved through that.
That aside, just pass with either the css or the style prop a max height and/or width and it should work.
Note: if you set a max width or height you don't need to specify the other, just set it to auto and it will retain the proportion.
If you attach the css i can give you additional help.
You can also pass inline styles
<img className= "onlineIcon" src={onlineIcon} style={{height:"20px",width:"20px"}}alt="open 6342 56837 Image" />

React - cursor pointer in component and child without directly CSS

I'd like some help to implement a simple cursor pointer ( hand ) in a card (and affect all child components ) . I can't use directly css, only styled component and/or inline style.
my code: All code
I'd like to do some like in my parent component:
<div id="box" style={cursorPointerThatAffecAllChild}>
or similar
Parent component
...
render() {
return (
<div id="box">
<p style={{fontWeight:'800'}}>
My card
</p>
<Child1 > </Child1>
<p>
some text in parent
</p>
</div>
);
...
child
...
return (
<div>
<button > My button on child 1 </button>
<br/><br/><br/>
<span style={{color:'blue'}}> a span inside Child 1 </span>
</div>
);
...
If you have to avoid css, you can use styled components and write the css there.
const MyCursorPointer = styled.div`
cursor: pointer;
* { /* this would be for elements that override the cursor pointer but are children of this component */
cursor: pointer;
/* cursor: pointer !important; */
/* ^ Use this style if you still see a cursor other than type pointer on the children */
}
`
If you want to do inline you could do this
<div style={{cursor: 'pointer'}}>
but note elements that have a predefined cursor style may override this. the styled-components solution should enforce the pointer if thats what you want.

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