-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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
[AppBar] Hide on scroll #12337
Comments
@verekia Thanks for sharing your work! This scrolling behavior is documented in the Official specification. It's something specific to small screens. I like the API you have been using, using a higher order component looks like a good tradeoff.
Yes, you can. It's just we don't provide any specific API for it yet. |
Good call about the official doc, although they don't give much details. Yes, my HOC is really just a hopefully temporary crutch. It can be useful to give some basic guidance, but it's definitely not to take as-is. |
@verekia @oliviertassinari I think this would provide the means to support all of the scrolling behavior outlined in the specification and it would be fairly easy to add to the AppBar component if we add a separate CollapseOnScroll hook. I do wonder if this is the best way to structure the functionality and if there are any performance concerns with handling the onScroll event? Some other libraries do throttling on the event handling. |
Hello! I just started building my app with react and material ui and was searching for that feature, as I do believe is very important for the user experience. Vuetify supports this feature with a property on the component called "scroll-toolbar-off-screen" (see https://vuetifyjs.com/en/components/toolbars). I really appreciate your efforts and wait for that feature to be included. BR Christoph |
@chr-knafl |
@cvanem Thanks for your answer! |
I agree that it's a useful feature and that a hook would be an excellent fit for the problem. @cvanem Regarding the performance, you have an issue here. We need to reduce the number of re-rendering to the number of time the public API changes. Once we have a working hook, we might want to add a @chr-knafl Do you have a live example on Vuetify side? I can't see it working in your link. Here is how I would approach the problem with v4, it's not perfect but a great start: import React from "react";
import { Slide } from "@material-ui/core";
function getScrollY(scroller) {
return scroller.pageYOffset !== undefined
? scroller.pageYOffset
: scroller.scrollTop !== undefined
? scroller.scrollTop
: (document.documentElement || document.body.parentNode || document.body)
.scrollTop;
}
const useHideOnScroll = options => {
const { threshold, scroller } = options;
const scrollRef = React.useRef();
const [hide, setHide] = React.useState(false);
const handleScroll = React.useCallback(() => {
const scrollY = getScrollY(scroller || window);
const prevScrollY = scrollRef.current;
scrollRef.current = scrollY;
setHide(
scrollY < prevScrollY
? false
: scrollY > prevScrollY &&
scrollY > (threshold != null ? threshold : 100)
? true
: false
);
}, [scroller, threshold]);
React.useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [handleScroll]);
return hide;
};
export default function HideOnScroll(props) {
const { children, threshold, scroller, ...other } = props;
const hide = useHideOnScroll({ threshold, scroller });
return (
<Slide direction="down" appear={false} in={!hide} {...other}>
{children}
</Slide>
);
} https://codesandbox.io/s/5x8kq3nwjn (notice the addition of Box, CssBaseline and Container) |
@oliviertassinari Here is my first attempt at a real implementation: https://codesandbox.io/s/kknzvyq3p3?fontsize=14 I would appreciate it if someone could take a look and let me know if I am on the right track or should be headed in a different direction. Also, not sure if all of these changes would be allowed? I imagine they should be discussed before submitting a PR. 1. AppBar.js - I added the following props:
I was thinking we could possibly add a new Elevate transition component? This could replace the elevation logic in Paper.js and also be used here by passing in via TransitionComponent. If this is done, the new in and variant props would not be needed and can be removed. Just a thought, maybe there is a better way to accomplish this? 2. App Bar Expansion in Specification I believe this implementation covers all of the App Bar scrolling behaviors outlined in the Official Specification except the expand example. I played around a bit with using the AppBar + ExpansionPanel. This approach works, but I am not sure if it is the correct approach as you are then limited to the expansion panel structure. Maybe the expansion implementation is for a later date... 3. demo.js - On Scroll logic and related hooks: The hooks and scroll logic are pretty close to being finished. I think that the even't handlers may still need to be throttled as I am seeing some weird behavior sometimes on the Collapse with momentum scrolling. I ended up writing one hook for useTriggerOnScroll, which takes a triggerFunc parameter. This way, it can be used for both the elevation and hide triggers, which have a little different logic (see demo.js). Is this functionality something that could be added to the core package somewhere as a utility or should this be implemented by the user? 4. Example documentation I added the above code as a separate example to the documentation, which appears to demonstrate the AppBar fairly well. It is pretty hard to show the user all the different settings, especially with static and fixed positions, and have it look good as a demo. Is there a better way to do the example documentation? Most AppBar's are typically set to 'fixed', but this doesn't show all that well in the example section. Maybe we should limit the user to only using pre-defined settings, or expose the pre-defined settings through different AppBar variants? |
@cvanem I think that we should avoid having the AppBar importing any transition component, nice call by not doing it. However, It seems that we only need the missing animation for the elevation. It should probably be added to the
Do we need to handle it? It looks too complex and has a niche use case to be considered now. I would say no.
We shouldn't need a throttle function in the first place—I haven't looked at it in detail—it's the sign something else is off. I haven't considered the elevation case. Nice, here is an updated proposal: https://codesandbox.io/s/qx186qjqr9. I would probably only make the
We have an |
Thanks for the feedback. I like your simplified approach much better. For the Scroll hook logic, a few things:
Here is my new approach, with your file structure: https://codesandbox.io/embed/7zjk7n51o0 See the changes in these files:
|
@oliviertassinari No, unfortunately not, I just read the official documentation of Vuetify. Maybe I can provide an example within the next weeks (I am currently quite busy - sorry). |
@cvanem I love it! 😍🔥 Really nice. It's mature enough for opening a pull request. This way, we can discuss the changes in detail, line by line. |
Hi there, I am using ScrollToHide AppBar + Drawer, the problem I have got is when AppBar go hided, then I saw the space from Drawer to top, can anyone guide me to fix it |
It is a common UX pattern to hide the AppBar when scrolling down on small screens.
There are different levels of implementation that are possible:
display: none
the AppBar when scrolling down under the AppBar height. Even in that minimal setup, the case of the initial load when the user is already scrolled down has to be handled (I think always showing the bar at the initial load is the right UX). And it probably shouldn't auto-hide on large screen (unless an option is passed maybe).display: none
. Note: The AppBar shadow has to be taken into consideration, to not cause a shadow at the top of the page.position: static
from the place you start scrolling down from, but it's actually still aposition: fixed
I think) and is only hidden by as much as you scroll. And when you scroll back up, the AppBar is revealed as much as you scroll up. In both cases, if you don't scroll up or down enough (less than half of the height of the AppBar), it snaps back to hiding or revealing itself and if you scroll more than half of the AppBar, it snaps to finishing the hiding / reveal completely.I implemented it up to the Sliding part as a HOC to apply to AppBar but it's not as nice as having it natively supported by Material UI (demo of my implementation). Some Android examples.
The snapping feature is apparently a thing that got added in Android Library 23.1 (section Design).
The text was updated successfully, but these errors were encountered: