-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hide the scrollbar thumb after few seconds of inactivity #46
Comments
You can implement it with help of |
Yes I already implemented it really easily thanks to the API. |
Just a note, I am thumbs upping because I expected this functionality out of the box as it simulates osx approach to scrollbars. The use case is I want consistent scroll bars on all platforms, something I believe most devs strive for and why they would use this awesome package. |
@krazyjakee as i already said above this is a very situative functionality which a very few developers need. Requested feature can be implemented in 10-15 rows of code on your side. I've developed this package to be most performant and handy minimal base to implement anything you wish about scrollbars, but that dont try to be a "silver bullet". |
@xobotyi thanks for the quick response. Made a small wrapper that adds an autoHide prop for anyone interested. https://gist.github.com/krazyjakee/8c87cae9bb33cb89fecb8e2f233657a9 |
@krazyjakee Thank you for your example! I think your code would be better by using Take a look at this screen portraying the issue: Another reason for using |
@vlachmilan in other hand, Please make an issue, i'll investigate it when i have some time |
Here's the reference to the issue. #82 |
another solution import React, { useState, useMemo, useCallback, useRef } from 'react';
import ReactScrollbarsCustom, { ScrollbarProps } from 'react-scrollbars-custom';
interface PropsType {
autoHide?: boolean
hideTimeout?: number
}
export default (props: PropsType & ScrollbarProps) => {
const {
autoHide,
children,
hideTimeout = 500,
...other
} = props
const [isScrolling, setIsScrolling] = useState()
const [isMouseOver, setIsMouseOver] = useState()
const trackStyle = useMemo(() => ({
opacity: autoHide && !isScrolling ? 0 : 1,
transition: 'opacity 0.4s ease-in-out',
background: 'none'
}), [autoHide, isScrolling])
const stopTimer = useRef<number | undefined>()
const showTrack = useCallback(() => {
clearTimeout(stopTimer.current)
setIsScrolling(true)
}, [stopTimer])
const hideTrack = useCallback(() => {
stopTimer.current = setTimeout(() => {
setIsScrolling(false)
}, hideTimeout)
}, [stopTimer, hideTimeout])
const thumbYStyle = useMemo(() => ({
left: 2,
width: 6,
position: 'relative'
}), [])
const wrapperStyle = useMemo(() => ({
right: 0,
bottom: 0
}), [])
const thumbXStyle = useMemo(() => ({
top: 2,
height: 6,
position: 'relative'
}), [])
const onScrollStart = useCallback(() => {
if (autoHide) {
showTrack()
}
}, [])
const onScrollStop = useCallback(() => {
if (autoHide && !isMouseOver) {
hideTrack()
}
}, [])
const onMouseEnter = useCallback(() => {
if (autoHide) {
showTrack()
setIsMouseOver(true)
}
}, [])
const onMouseLeave = useCallback(() => {
if (autoHide) {
hideTrack()
setIsMouseOver(false)
}
}, [])
return (
<ReactScrollbarsCustom
thumbYProps={{ style: thumbYStyle }}
thumbXProps={{ style: thumbXStyle }}
wrapperProps={{ style: wrapperStyle }}
trackXProps={{ style: trackStyle, onMouseEnter, onMouseLeave }}
trackYProps={{ style: trackStyle, onMouseEnter, onMouseLeave }}
onScrollStop={onScrollStop}
onScrollStart={onScrollStart}
{...other}
>
{children}
</ReactScrollbarsCustom>
)
}; |
I'd love to see this implemented natively too. |
@amok Good shot! But it has a potential memory leak without unmount effect: useEffect(() => {
return () => clearTimeout(stopTimer.current);
}, []); It also has many import React, { useState, useMemo, useCallback, useRef } from 'react';
import ReactScrollbarsCustom, { ScrollbarProps } from 'react-scrollbars-custom';
interface PropsType {
autoHide?: boolean
hideTimeout?: number
}
export default (props: PropsType & ScrollbarProps) => {
const {
autoHide,
children,
hideTimeout = 500,
...other
} = props
const [isScrolling, setIsScrolling] = useState()
const [isMouseOver, setIsMouseOver] = useState()
const trackStyle = useMemo(
() => ({
opacity: autoHide && !isScrolling ? 0 : 1,
transition: "opacity 0.4s ease-in-out",
background: "none"
}),
[autoHide, isScrolling]
);
const stopTimer = useRef();
const showTrack = useCallback(() => {
clearTimeout(stopTimer.current);
setIsScrolling(true);
}, [stopTimer]);
const hideTrack = useCallback(() => {
stopTimer.current = setTimeout(() => {
setIsScrolling(false);
}, hideTimeout);
}, [stopTimer, hideTimeout]);
const thumbYStyle = useMemo(
() => ({
left: 2,
width: 6,
position: "relative"
}),
[]
);
const wrapperStyle = useMemo(
() => ({
right: 0,
bottom: 0
}),
[]
);
const thumbXStyle = useMemo(
() => ({
top: 2,
height: 6,
position: "relative"
}),
[]
);
const onScrollStart = useCallback(() => {
if (autoHide) {
showTrack();
}
}, [autoHide, showTrack]);
const onScrollStop = useCallback(() => {
if (autoHide && !isMouseOver) {
hideTrack();
}
}, [autoHide, hideTrack, isMouseOver]);
const onMouseEnter = useCallback(() => {
if (autoHide) {
showTrack();
setIsMouseOver(true);
}
}, [autoHide, showTrack]);
const onMouseLeave = useCallback(() => {
if (autoHide) {
hideTrack();
setIsMouseOver(false);
}
}, [autoHide, hideTrack]);
useEffect(() => {
return () => clearTimeout(stopTimer.current);
}, []);
return (
<ReactScrollbarsCustom
thumbYProps={{ style: thumbYStyle }}
thumbXProps={{ style: thumbXStyle }}
wrapperProps={{ style: wrapperStyle }}
trackXProps={{ style: trackStyle, onMouseEnter, onMouseLeave }}
trackYProps={{ style: trackStyle, onMouseEnter, onMouseLeave }}
onScrollStop={onScrollStop}
onScrollStart={onScrollStart}
{...other}
>
{children}
</ReactScrollbarsCustom>
)
}; |
I ended up doing this w/ some simple css to show them when you hover into the area. |
@dqunbp thank you for noticing it and sharing the code! |
Example without import React, { useCallback, useMemo, useState } from "react";
import ReactScrollbarsCustom from "react-scrollbars-custom";
export function Scrollbar({ children, ...props }) {
const [isScrolling, setIsScrolling] = useState(false);
const [isMouseOver, setIsMouseOver] = useState(false);
const isShow = isScrolling || isMouseOver;
const onScrollStart = useCallback(() => {
setIsScrolling(true);
}, []);
const onScrollStop = useCallback(() => {
setIsScrolling(false);
}, []);
const onMouseEnter = useCallback(() => {
setIsMouseOver(true);
}, []);
const onMouseLeave = useCallback(() => {
setIsMouseOver(false);
}, []);
const trackProps = useMemo(() => ({
renderer: ({ elementRef, style, ...restProps }) => (
<span
{...restProps}
ref={elementRef}
style={{ ...style, opacity: isShow ? 1 : 0, transition: "opacity 0.4s ease-in-out", }}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
/>
)
}), [isShow, onMouseEnter, onMouseLeave]);
return (
<ReactScrollbarsCustom
{...props}
wrapperProps={{
renderer: ({ elementRef, style, ...restProps }) => (
<div {...restProps} ref={elementRef} style={{ ...style, right: 0 }} />
),
}}
trackXProps={trackProps}
trackYProps={trackProps}
onScrollStart={onScrollStart}
onScrollStop={onScrollStop}
scrollDetectionThreshold={500} // ms
>
{children}
</ReactScrollbarsCustom>
);
} |
This is something lots of developers need. Look at the other react scrollbar components, many have it. +1 |
Here is a TypeScript version of @KirillSkomarovskiy 's code. I removed the callbacks, but I didn't measure if memoization is worth it here. But to me the callbacks didn't look expensive and memoization always has an overhead.
Keep in mind there is still one weird ts-ignore that I couldn't fix yet. |
Today we needed this to simulate how scrollbars are hidden in Slack or macos. |
Do you want to request a feature or report a bug?
Request a feature
What is the current behavior?
The API does not provide a way to hide the scrollbar thumb after inactivity. This is the default behavior for some browsers (on mac OS), the scrollbar is hidden when not used, once you scroll it's visible again.
What is the expected behavior?
Provide a prop to enable this hidding behavior.. And we may also have a property to set the timer after which the scrollbar thumb should appear / disappear.
The text was updated successfully, but these errors were encountered: