Closed SPAHI4 closed 5 years ago
We are using the MUI <Divider />
component inside our dialogs to realize the Material Design specs for scrolling dialog content.
@SPAHI4 Are you wanting a prop that you pass in that automatically adds the divider if the content is scrollable? Also, should we mirror the spec to include the divider at the top and bottom of the content like in my .gif?
See #14735 for a possible solution that is already achievable. We're somewhat open to review a solution that only requires using a prop. However it's unlikely that we'll accept a dynamic solution that has built-in overflow detection unless it has a small bundle footprint. The current solution with using Divider
doesn't bloat the bundle of everyone and is IMO preferred. If we want to increase the size for everyone it should be very small.
Is it possible to hide top divider while scrolling to the top, hide bottom divider while scrolling to the end?
Is it possible to hide top divider while scrolling to the top, hide bottom divider while scrolling to the end?
So I make it by myself.
Here is an example on CodeSandbox.
Create two variables to control dividers.
const [topDivider, setTopDivider] = useState(false);
const [bottomDivider, setBottomDivider] = useState(false);
Create a function to initilize status of dividers. Because Dialog
have its own "lifecycle". (You will see the explanation below)
const initializeDividers = () => {
setTopDivider(false);
setBottomDivider(false);
/* ... */
};
Detect if scrollbar exist by comparing scrollHeight
with clientHeight
. [1] (The id in getElementById
is for DialogContent
)
const initializeDividers = () => {
/* ... */
const dialogContent = document.getElementById('dialog-content');
if (dialogContent !== null) {
if (dialogContent.scrollHeight > dialogContent.clientHeight) {
setBottomDivider(true);
}
}
};
Adding initializeDividers
to Dialog
in onEnter
. Because display of Dialog
is control by open
. (Now you know why we don't use Effect Hook) You will get null
if you are using React Effect Hook to get element.
<Dialog
open={/* variable from caller */}
onEnter={initializeDividers}
scroll="paper"
>
{/* ... */}
Add Divider
s before & after DialogContent
with its variable from State Hook. And don't forget to set a id for DialogContent
.
{topDivider ? <Divider /> : null}
<DialogContent id="dialog-content">
{/* ... */}
</DialogContent>
{bottomDivider ? <Divider /> : null}
Now let's handle the scrolling.
You need to listen the onScroll
event in DialogContent
.
const handleScrolling = (e: React.UIEvent<HTMLDivElement>) => {
/* ... */
};
/* ... */
<DialogContent id="dialog-content" onScroll={handleScrolling}>
{/* ... */}
</DialogContent>
Assert the type of event.target
to HTMLDivElement
. [2]
const handleScrolling = (e: React.UIEvent<HTMLDivElement>) => {
if (e === undefined) {
return;
}
const { scrollTop, scrollHeight, offsetHeight } = e.currentTarget;
/* ... */
};
Compare the scrollTop
with the difference between scrollHeight
and scrollHeight
. [3] [4]
const handleScrolling = (e: React.UIEvent<HTMLDivElement>) => {
/* ... */
setTopDivider(scrollTop !== 0);
setBottomDivider(
scrollTop !== scrollHeight - offsetHeight
);
};
currentTarget
instead of target
. (See [2])Thanks all of them.
[1]: Check whether HTML element has scrollbars using JavaScript - GeeksforGeeks [2]: reactjs - How to describe type scroll events? - Stack Overflow [3]: reactjs - is this possible to get scroll position in material-ui select list on Scroll? - Stack Overflow [4]: browser - How to get scrollbar position with Javascript? - Stack Overflow
Divider added to the content of Dialog scrolls with content. Divider added as action has padding. Would be great to have something like this