h-kanazawa / react-detectable-overflow

A React hook and component detecting overflow state.
MIT License
27 stars 10 forks source link

Add support for detecting overflowStart and overflowEnd #99

Open stefanullinger opened 4 months ago

stefanullinger commented 4 months ago

Hi, this looks pretty nice already, thank you! I would like to add some shadow left or right / top or bottom when the element's content is overflowing. Could you add some more specific states and return values for this use case?

h-kanazawa commented 1 month ago

Thank you for your feedback and suggestion. I apologize for the late response. Can you give example code making situations of "overflowStart" and "overflowEnd"?

stefanullinger commented 1 month ago

Hi @h-kanazawa, in my react app I use some modals that contain contents that exceed the height of the modal. As modern browsers tend to hide scrollbars (especially on touch devices), I would like to show some indicators that the user can scroll down to see more content. Theses indicators could be elements having a box shadow or simply some colored lines.

In case you are the top, I want to show some indicator at the bottom of the container. When the user has scrolled a bit down, I would like to show an indicator at the top and bottom, and when the user has scrolled all the way down, the user should see only the indicator at the top.

It would be something similiar to this CSS-only solution: https://lea.verou.me/blog/2012/04/background-attachment-local/ The drawback of the CSS-only solution is that it only works with solid backgrounds. So I though, because we are trying to detect the overflow anyways, we could add some more calculations.

To do this, I do need to know that there is an overflow AND where the content is overflowing the container's size.

My recommendation would be something like this for the useOverflowDetector hook:

const hasOverflow = element.offsetHeight < element.scrollHeight;

let hasOverflowAtStart = false;
let hasOverflowAtEnd = false;

if (hasOverflow) {
  const epsilon = 10; // this should be some option, so the user of the hook can configure it
  hasOverflowAtStart = element.scrollTop > epsilon;
  hasOverflowAtEnd = element.scrollTop < element.scrollHeight - element.offsetHeight - epsilon;
}

return {
  overflow,
  ref,
  hasOverflowAtStart;
  hasOverflowAtEnd;
}

Since you have handleHeight?: boolean and handleWidth?: boolean and the user could possibly check both axis, maybe the naming should be a bit different, like hasOverflowAtMainAxisStart and hasOverflowAtCrossAxisStart or just use X and Y in the naming of the variables.

h-kanazawa commented 1 month ago

Thank you for details.

I've created a preliminary implementation. Could you please review this PR to verify that it meets your use case?