I am writing a react bootstrap app where a button appears at the end of an animation. When the button first appears, I want a tooltip to appear next to it. Once the user hovers over and off the button, the tooltip should go away and re-appear whenever the user hovers over the button again. I've gotten this to work as desired, but when I position the button where I want it to be (fixed to the bottom of the screen), the tooltip initially renders in the wrong position (where the button was before being positioned).
I have created two simple examples to demonstrate this behavior.
In the first example, the button is positioned at the top of the screen and the tooltip behaves as this desire:
function Testing(){
const refLink = useRef(null);
const [overlayOpen, setOverlayOpen] = useState(true); // Initially open
const [textDone, setTextDone] = useState(false);
useEffect(() => {
const timeoutId = setTimeout(() => {
setTextDone(true)
},1000)
return () => clearTimeout(timeoutId)
},[])
return(
<Container>
<Row>
{textDone ?
<>
<Button ref={refLink} onMouseOver={() => setOverlayOpen(true)}
onMouseOut={() => setOverlayOpen(false)}
>
<FaComment/>
</Button>
<Overlay target={refLink.current} show={overlayOpen}
onHide={() => setOverlayOpen(false)} rootClose placement={"bottom"}>
<Tooltip>
Submit a personal response!
</Tooltip>
</Overlay>
</>
: ''
}
</Row>
</Container>
)
}
export default Testing
The textDone state is set to true once the "animation" finishes. To simplify the example, I omitted the animation itself and recreated the delay with setTimeout.
The second example is identical except for the following .css class added to the Row element in which the button, overlay, and tooltip are nested inside of.
.fixed-button{
position:fixed;
right: 20px;
bottom: 20px;
}
With this addition, the button ends up where I want it, but the tooltip first appears at the top of the screen. Once I hover over the button, the tooltip moves to the correct position.
Here are some gifs of the two examples.
Example 1 (tooltip behaving as intended but button not positioned in right spot)
Example 2 (button positioned where I want it but tooltip initially showing up in wrong spot)
My question is: how can I get the tooltip to initially appear in the correct position?
Related
I am implementing Paper from Material UI: https://mui.com/components/paper/
And here is the code I have written so far:
<Paper className="modal" elevation={3}>
{..Content..}
</Paper>
The current UI makes it open a special pane which closes only when I click on area outside of it. I want to add a close button to close the Paper. Is it possible to add a custom onClose action on it?
Edit: Here is a codesandbox that I have replicated: https://codesandbox.io/s/black-surf-r1yz87?file=/src/App.js
Paper is just a surface to render components on, it does not support any functionality. For this use case, a state variable can be used to hide and unhide the Paper component. You may make it a reusable component.
const [shouldShowPaper, setShouldShowPaper] = useState(true);
...
{
shouldShowPaper &&
<Paper elevation={props.elevation} style={{position: "relative"}}>
<button
style={{position:"absolute", top: "10px", right: "10px"}}
onClick={() => setShouldShowPaper(false)}
>
X
</button>
{props.children}
</Paper>
}
You may toggle classes to show transitions instead of abrupt removal of the paper component.
I make a simple demo of carousel. I am showing three cards at one time (two full cards and one small portion). When I click next and previous button it behave the same always by showing three cards except when user react to end there I am showing only two cards. This functionality is working fine, but I am facing one issue.
The issue is when I scroll I want snipped my item.
I have items like blue,red,green,yellow,blue.
Issue.when I scroll 5px or 10px it will snipped in other words if we scroll blue after stop scrolling scroll it should be show red,green,yellow.
Input If I scroll this part .
Expected output it should scroll to next slide
here is my code
https://codesandbox.io/s/youthful-greider-3k0md?file=/src/App.js
const onscroll = (e) => {
const ratio = Math.round(
parent.current.scrollLeft / slide.current.offsetWidth
);
console.log(ratio, "ratio");
const newIndex = ratio >= 1 ? ratio : 0;
setxx(newIndex);
setIndex(newIndex - 1);
};
any update .?
So I wanted to challange myself and try to implement the blue button from 9gag which allows you to add content. Its on the right bottom cornern and every time you scroll down and reach a specific "speed" it disappears. And when you scroll up again, it appears again until you scroll down again with that specific "speed". I tried my best but couldnt make it. Here is the link to the video how it should look:
https://www.youtube.com/watch?v=ieT4hZJST5I&feature=youtu.be
So far I was able to make that button on the right postion. But I dont know how to change his visibility onScroll:
<TouchableOpacity
activeOpacity={0.6}
style={{
position: 'absolute',
right: addContentButtonRight,
bottom: addContentButtonBottom,
opacity: addContentButtonOpacity
}}
// onPress={this.onAddPress}
>
<Image style={{width: 65, height: 65}} source={iconSource} />
</TouchableOpacity>
And this here is what was my idea for it:
//using state to be able to update opacity
const [addContentButtonOpacity, setAddContentButtonOpacity] = useState(1);
//when the scrollView is scrolled I would call this function with onScroll().
//It sets the new value to opacity by using opacity - 0.1
//In this way the further you scroll, the more invisible it bacomes
const addContentButtonOpacityChange = () => {
setAddContentButtonOpacity(addContentButtonOpacity-0.1);
}
And also if this would work and my button becomes invisible, how would I make it not touchable so that the invisable button cant be clicked by mistake/randomly?
Any idea how to implement this?
Some answers of our chatbot are very long. The webchat scrolls automatically to the bottom so users have to scroll up to get to the top of the bubble and start reading.
I've implemented a custom renderer (react) to wrap the answers into a custom component which simply wraps the answer into a div-tag. I also implemented a simple piece of code to scroll to the top of the bubble.
const MyCustomActivityContainer = ({ children }) => {
const triggerScrollTo = () => {
if (scrollRef && scrollRef.current) {
(scrollRef.current as any).scrollIntoView({
behavior: 'smooth',
block: 'start',
})
}
}
const scrollRef: React.RefObject<HTMLDivElement> = React.createRef()
return (
<div ref={ scrollRef } onClick={ triggerScrollTo }>
{ children }
</div>
)
}
export const activityMiddleware = () => next => card => {
if (/* some conditions */) {
return (
<MyCustomActivityContainer>
{ next(card) }
</MyCustomActivityContainer>
);
} else {
return (
{ next(card) }
)
}
};
But this only works if the scrollbar slider is not at its lowest position (there is at least 1 pixel left to scroll down, see here). The problem is the useScrollToBottom hook which always scrolls to bottom automatically if the scrollbar is completely scrolled down.
Is there any way to overwrite the scroll behavior or to temporarily disable the scrollToBottom feature?
As there is no reproducible example I can only guess.
And I'll have to make some guesses on the question too.
Because it's not clear what exactly in not working:
Do you mean that click on the <div> of MyCustomActivityContainer and subsequent call to triggerScrollTo doesn't result into a scroll?
That would be strange, but who knows. In this case I doubt anyone will help you without reproducible example.
Or do you mean that you can scroll the message into view, but if it is already in the view then new messages can result into a scroll while user is still reading a message.
That's so, but it contradicts with you statement that your messages are very long, because that would be the problem with short messages, not with the long ones.
But anyway, you should be able to fix that.
If it works fine with 1 pixel off the lowest position, then just scroll that 1 pixel. You'll need to find the scrollable element. And do scrollable_element.scrollTop -= 1. I tested this approach here. And it worked (there the scrollable element is the grandparent of <p>'s)
Or do you try to scroll automatically at the moment the message arrives? Аnd that is the real issue, but you forgot to mention it, and didn't posted the code that tries to auto-scroll?
In that case you can try to use setTimeout() and defer the scroll by, let's say, 200ms.
This number in based on what I gathered from the source:
BotFramework-WebChat uses react-scroll-to-bottom
In react-scroll-to-bottom there are some timeouts 100ms and 34ms
BotFramework-WebChat doesn't redefine them
There are some heuristics in react-scroll-to-bottom that probably coursing the trouble
https://github.com/compulim/react-scroll-to-bottom/blob/3eb21bc469ee5f5095a431ac584be29a0d2da950/packages/component/src/ScrollToBottom/Composer.js
Currently, there are no reliable way to check if the "scroll" event is trigger due to user gesture, programmatic scrolling, or Chrome-synthesized "scroll" event to compensate size change. Thus, we use our best-effort to guess if it is triggered by user gesture, and disable sticky if it is heading towards the start direction.
And
https://github.com/compulim/react-scroll-to-bottom/blob/f19b14d6db63dcb07ffa45b4433e72284a9d53b6/packages/component/src/ScrollToBottom/Composer.js#L91
For what we observed, #1 is fired about 20ms before #2. There is a chance that this stickyCheckTimeout is being scheduled between 1 and 2. That means, if we just look at #1 to decide if we should scroll, we will always scroll, in oppose to the user's intention.
That's why I think you should use setTimeout()
Since there isn't a reproducible code for me tweak and show you. My suggestion is tweak your code slightly. Chatbot requires constant streaming of data when a new message arrives calculate the height of the div element created for the message. If the div element is greater than the widget height scroll to the top else you can choose to leave it as it is.
I am using a React library called Rellax for a parallax effect on my site.
It works nicely when I scroll towards that section of the page. But, when I click on the navbar and navigate to a particular #section, this very parallax image is floating in a completely different distance to where it was supposed to be placed.
I have a feeling this is related to how the positioning of the element is calculated, since my page structure has no single main body but a group of react components.
The same issue occurred with other parallax libraries.
Right now I am referring to the parallax component this way:
(Code is abbreviated and only shows sections where I refer to the effect)
export default function Advantages() {
useEffect(() => {
// init parallax
new Rellax('#parallaxImage', {
center: true,
});
});
return (
<section>
<img
id="parallaxImage"
className="w-100"
data-rellax-speed="2"
src={ traktor }
alt="tractor parallax" />
</section>
)}
Shouldn't you only be calling this once (by adding square brackets)?
useEffect(() => {
// init parallax
new Rellax('#parallaxImage', {
center: true,
});
}, []); // <-- Empty array