How to style a React component with changes in only one direction - javascript

I have a React component which opens up a popup on a button click. So the popup has a Scrollbar and there is another component below the popup which contains the confirmation button and cancel button. Currently the popup's scrollbar is overlapping the other component as shown below:
The code for the screen is pasted below:
import styled from "styled-components";
const Wrapper = styled.div`
width: 90vw;
height: 90vh;
`;
const Content = styled.div`
height: fit-content;
padding-bottom: 150px;
`;
return (
<Wrapper>
<Content>{popupToDisplay()}</Content>
</Wrapper>
);
The popupToDisplay() function displays a popup depending on the result of a switch case.
So, now I am trying to move the Scrollbar above the purple line as shown in the image. I am able to reduce the size of the Popup by decreasing the 'height' property of the Wrapper component as shown below:
const Wrapper = styled.div`
width: 90vw;
height: 40vh;
`;
But now the issue while doing so is since the height is getting decreased, the popup is coming down from the top, i.e. there is space at the top as shown below:
I don't want the top of the popup to move down, only the bottom of the popup should move up. I also tried giving 'margin-bottom' property to the Wrappper constant, but its still not working. Can someone please help me with this.

Related

How to change button color based on background?

I write in React. On the page I have a scroll up button.
When scrolling on some blocks, it is not visible due to the fact that the colors match.
How to make it so that when it touches certain blocks of the same color as the button, it turns white.
How to track the contact of a button with a specific block? What listeners to put?
Since the button is probably position: fixed or position: absolute, the easiest solution would be to give CSS property mix-blend-mode a try, instead of listeners, as there is no accurate way of telling the position w.r.t to background.
Check this
Try to give mix-blend-mode: difference; for the scroll to top button.
Although I think in this case you will have the color yellow for the button when it overlaps blue.
Although Sanjay's answer "works", you really don't have much control over the styles you get, unless that blend-mode:difference is the look you're going for.
For more fine grained control, you need to use the IntersectionObserver API.
There's really three steps to this process:
1. Get the required options for IntersectionObserver constructor
This means you need to find out the negative margins to set as the rootMargin key. This key is part of the configuration object of your IntersectionObserver instance.
In practice you would have to find the distance of your trigger element(in your case the floating action button) to the edges of the viewport. In the code snippet below, this is done using the getDistanceToEdge() function.
It's better to do it this way instead of statically setting your margins, since it dynamically infers the margins from the position set from your styles.
2. Tell the observer what you wish to when triggered
This is the callback which will trigger the new styles on your floating button. You need to check whether your elements are intersecting with the button using the entry.isIntersecting key, and then conditionally render the style.
3. Setup the observer with elements you wish to cause the trigger
The elements that scroll up causing your floating button to change color, should be passed to the observer, using the observer.observe() function.
The following code snippet really does all the setup you need. It won't trigger unless the element is actually underneath the button (the API internally checks vertical and horizontal overlaps).
For some reason I can't get it to work on iframes embedded in browsers. It could be something to do with the negative margins and multiple viewports.
It works perfectly on normal full page websites, as shown in this hosted link.
One little caveat is that consecutive elements that trigger the observer, will cause each other to cancel out, since the button enters the second area before fully leaving the first one. I'll leave it to someone else to figure out the specifics there.
// get the element that reacts to background elements
const fabElement = document.getElementById("fab");
// what do you want to do when it overlaps?
function reactToOverlap(entries) {
entries.forEach((entry) => {
if (entry.isIntersecting) fabElement.classList.add("triggered");
else fabElement.classList.remove("triggered");
});
}
const observerOptions = {
rootMargin: getDistanceToEdge(fabElement)
.map((val) => `-${val}px`)
.join(" "), // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin for syntax
};
const observerInstance = new IntersectionObserver(
reactToOverlap,
observerOptions
);
// what elements do you want to trigger the change?
const elementsToTriggerFab = document.querySelectorAll(".triggeringContent");
elementsToTriggerFab.forEach((el) => observerInstance.observe(el));
/* Represents how far the element is from the edge of the browser, in all directions. */
function getDistanceToEdge(element) {
const elementBounds = element.getBoundingClientRect();
// top and left margins are identical to the pixel coordinates
const top = elementBounds.top;
const left = elementBounds.left;
// bottom and right need to be subtracted from the viewport bounds
const bottom = window.innerHeight - elementBounds.bottom;
const right = window.innerWidth - elementBounds.right;
return [top, right, bottom, left];
}
body {
font-size: 3rem;
background-color: white;
margin: 0;
padding: 0;
}
#fab {
background-color: blue;
color: white;
border-radius: 50%;
position: fixed;
padding: 1rem;
bottom: 50px;
right: 50px;
transition-property: background-color, color;
transition-duration: 0.5s
}
#fab.triggered {
background-color: white;
color: blue;
}
.normalContent {
color: green;
border: 10px solid green;
height: 100vh;
}
.triggeringContent {
height: 300px;
background-color: blue;
color: white;
}
.triggeringContent.avoidFab {
margin-right: 200px;
}
<div id="fab">Up</div>
<div class="normalContent">Other Content</div>
<div class="triggeringContent">Triggerring Content</div>
<div class="triggeringContent avoidFab">Triggerring Content</div>
<div class="normalContent">Problems coming up</div>
<div class="triggeringContent">Triggerring Content</div>
<div class="triggeringContent">Triggerring Content(Error)</div>
<div class="normalContent">Other Content</div>
<div class="triggeringContent avoidFab">Triggerring Content</div>
<script type="module" src="/main.js"></script>
Shoutout to cloned's comment for giving the idea for the solution.

How to vertical block a column with an element?

I´m havin issues with blocking the whole height of the screen. I made this navbar and want it to look like it´s "floating" on the page, by adding some margin around ist, so it´s not touching the border of the screen.
Using the height: 100% prop won´t work, bc I the margin won´t get attached at the bottom of the screen -> First it goes all the way down the screen, so that I have to scroll down a bit until the margin gets added + the following content does not appear to the right, but underneath the sidebar -> watch the image.
So I basically want this thing to be in a vertical div element for example, so that the next element will be next to the right of the navbar (right now the text "TEST" still is underneath the navbar).
I´m also using TailwindCSS, those are my classes attached to the wrapping div of the navbar:
import SidebarHeader from './sidebarHeader';
import SidebarMenu from './SidebarMenu';
const Sidebar = () => {
return (
<div
style={{ height: '100vh' }}
className=" m-5 rounded-2xl bg-primary w-80 border-l-4 border-primary transition duration-500 pl-5 py-5">
<SidebarHeader />
<SidebarMenu />
</div>
);
};
export default Sidebar;
App code:
import { BrowserRouter } from 'react-router-dom';
import './assets/tailwind.css';
import Sidebar from './page-components/sidebar';
import Header from './page-components/header';
function App() {
return (
<BrowserRouter>
<Sidebar />
<Header />
</BrowserRouter>
);
}
export default App;
// Header code
//const Header = () => {
// return <div>TEST</div>;
//};
//
//export default Header;
I could do a grid layout I guess, but I don´t know if that´s the smartest solution. There must be a way to have smth like a vertical block element or not?
Glad for any help I can get- cheers!
You can use css calc like height: calc(100vh - XXpx) and then you can add margins to it - sum of bottom and top margins must be equal to XXpx you defined earlier.
Or just wrap the sidebar in a parent component with some padding { height: 100vh; padding: XXpx}; display: flex;, with display flex. Child should have a flex-grow property set to 1.
To put something next to the sidebar, both elements should have display: inline-block; vertical-aligh: top in that case the second solution would not work unless you wrapp the sidebar parent + aside content in a wrapper div with display: flex property.

How to align react-bootstrap modal relative to the button clicked

I have a react-bootstrap-modal this, I want to show my modal relative to the button clicked, I have an option in my react-bootstrap-table so when I clik on that option I am showing my modal, but it is not aligning relatively.
I am using contentClassName to override .modal-content, I don't know but it is not working as expected
<Modal
show={props.show}
onHide={props.handleClose}
contentClassName="modal_l" // this is I am doing to override
aria-labelledby="example-custom-modal-styling-title">
<div className="container_modal_options">
<div className="heading">Heading</div>
<div className="content">"content</div>
</div>
</Modal>
Here I am sharing minimal code,
.modal_l {
width: 100px !important; it is not taking styling
}
I want to show modal at the right side, near by click
This is my code sand box working code
You should change contentClassName to dialogClassName.
.modal_l {
width: 100px !important;
max-width: none !important;// set max-width, if needed.
}

How to make edge of div resizable instead of bottom right corner icon

I am having an issue getting a react component to be horizontally resizable. When I added the resize property a class in my component like so:
.side-menu-container {
display: 'inline-block';
width: 15%;
height: 100%;
resize: horizontal;
overflow-y: auto
}
I am only getting a resizable marker on the bottom right corner of the div like so:
Instead, I am looking to have the whole right edge of the div be resizable instead of just the bottom right corner. I know this can be done via javascript (was trying to stay strictly css), but I am not sure now how to go about doing this in my React component.
This is the example of the component where this css class is used:
import './app.less';
export default class App extends Component {
render() {
return (
<div className='main-window-container'>
<div className='side-menu-container'>
<SideMenu />
</div>
</div>
);
}
}

Resize content when drawer is open in MDL

I'm building a website based on MDL. What I'm trying to achieve is that the drawer doesn't open over the content, but open next to it. I managed to disable the obfuscator and modify the top value.
However, the way I was going to do this is anytime the drawer opens the content area would get a 250px wide left margin (the drawer is 250px wide) and resize its width so that width: calc(100% - 250px). This works just fine, but I don't know if this is the best way to do it, and even if it is, I don't know how to track the state of the drawer.
Here's how the material.js handles the change:
MaterialLayout.prototype.screenSizeHandler_ = function () {
if (this.screenSizeMediaQuery_.matches) {
this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN);
} else {
this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN);
// Collapse drawer (if any) when moving to a large screen size.
if (this.drawer_) {
this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
this.obfuscator_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
}
}
};
This is beyond my skills to figure out what is actually going on. I tried tracking it down with Chrome, but it was too complicated.
Is there a trivial way to do this? If not, how do I edit the script?
Cheers!
The .mdl-layout__drawer receives a .is-visible class when it is open/visible.
This small CSS-Rule worked for me:
.mdl-layout__drawer.is-visible ~ .mdl-layout__content {
padding-left: 250px;
}
With this you also don't need to fix the width of the content-area, as you are not using margin but padding. Note that by default the material.css also disables scrolling when the drawer is visible, so you also need to add the overflow-property to the rule:
.mdl-layout__drawer.is-visible ~ .mdl-layout__content {
overflow: auto !important;
padding-left: 250px;
}

Categories