Skip to content

Commit f3dbde6

Browse files
committed
Update readme
1 parent 36ec7b1 commit f3dbde6

File tree

1 file changed

+106
-1
lines changed

1 file changed

+106
-1
lines changed

Readme.md

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,56 @@ A react hook to use the
77
declaratively in your React app for the purposes of finding out if an element is in a given
88
viewport.
99

10+
## Motivation
11+
12+
I wrote [isInViewport](https://github.com/zeusdeux/isInViewport) for the jQuery world back in the
13+
day and while how we build interfaces has changed massively since, the problem
14+
[isInViewport](https://github.com/zeusdeux/isInViewport) solved still remains. What did change was
15+
that the web platform gave us better primitives to solve this problem in the shape of the
16+
[Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).
17+
18+
I was looking for a simple way to use the
19+
[Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)
20+
in my React app for the purposes of checking if a component is in some viewport. I started off by
21+
writing [a wrapper](https://github.com/zeusdeux/observe-element-in-viewport) around the Intersection
22+
Observer API but that still didn't _feel_ right. Its dev ergonomics felt off due to the callback
23+
based core interface it shares with the Intersection Observer API.
24+
25+
Then, [React Hooks happened](https://reactjs.org/blog/2019/02/06/react-v16.8.0.html)! I started
26+
playing around attempting to write a generic `useIntersectionObserver` hook. I gave up on that idea
27+
in favour of a more directed hook. One which solves a problem that I and many other devs have.
28+
29+
The following guiding principles in combination with the
30+
[community](https://twitter.com/muditameta/status/1117854963911340042?s=12) helped shape the api for
31+
this hook.
32+
33+
### Guiding principles
34+
35+
1. Solve a real problem
36+
- Test an element in a viewport for visibility
37+
2. Make it straightforward to consume the package
38+
- Simple, to the point name
39+
- Easy installation
40+
- Correct peer dependencies to prevent foot-guns
41+
- Tons of docs and examples (in progress)
42+
3. Make it easy to solve the most likely use cases
43+
- e.g., "Tell me when an element is visible in the current window viewport", "Tell me when 75% of
44+
an element is visible in current window viewport"
45+
4. Make it possible to solve other problems without unnecessary noise
46+
- e.g., "Tell me when an element is visible in my custom viewport", "Let me customize the
47+
viewport I want to pass down", "Let me use this with a component that uses React.forwardRef",
48+
etc
49+
5. Provide as much developer feedback as possible
50+
- made possible by types that ship with the project
51+
6. Only solve the actual problem
52+
- e.g., providing a polyfill for Intersection Observer is not this package's job
53+
7. Be trustworthy
54+
- All use cases have corresponding integration tests using Cypress (in progress)
55+
56+
> With all
57+
> [all major browsers having added support for Intersection Observer API](https://caniuse.com/#search=intersection%20observer),
58+
> this package is even more easier to drop into your application!
59+
1060
## Installation
1161

1262
`npm install use-is-in-viewport`
@@ -17,6 +67,61 @@ Please note that this hook declares `react` and as _peer dependency_. Therefore,
1767
Please [open as issue](https://github.com/zeusdeux/use-is-in-viewport/issues/new) if this default
1868
causes an issue in your application.
1969

70+
## API
71+
72+
### useIsInViewport([options]) => [boolean | null, TargetCbRef, ViewportCbRef]
73+
74+
> The nomenclature (target, viewport, threshold, etc) are borrowed from that of the
75+
> [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_concepts_and_usage)
76+
77+
The hook accepts an optional `options` object. When not provided, sane defaults are used. They are
78+
described in the `options` section below.
79+
80+
It returns an array that contains the following in order:
81+
82+
1. a flag that is one of `null`, `true`, `false` based on the visibility of target element in
83+
provided viewport
84+
- `null` -> first call to the hook when nothing is initialized
85+
- `true` -> target element is visible in the given viewport
86+
- `false` -> target element is visible in the given viewport
87+
2. A [callback ref](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) to pass to the
88+
element you want to know the visibility of.
89+
3. A [callback ref](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) to pass to the
90+
element you want to use as the viewport.
91+
92+
#### Options
93+
94+
All options are optional. Please (ab)use your editor's Typescript capabilities to capitalize on
95+
types for this hook.
96+
97+
##### options.threshold
98+
99+
The threshold describes what **percent** of the target element should intersect with the given
100+
viewport for it to be considered as visible in the viewport.
101+
102+
It can be a number or an array of numbers. The number is interpreted as a percent of the target
103+
element's dimensions.
104+
105+
Passing an array of numbers is likely to be useless for most use cases. It only exists as an
106+
artefact of the library this hook is built on and hence will most likely will be deprecated and
107+
removed based on feedback from the community.
108+
109+
example: `useIsInViewport({ threshold: 50 })` would report an element as visible in its parent
110+
document viewport when at least 50% of the target intersects with the viewport.
111+
112+
##### options.target
113+
114+
The target accepts a [ref](https://reactjs.org/docs/refs-and-the-dom.html) for the element you want
115+
track the visibility in viewport of. This ref is wrapped and a new ref is returned at index 1 in the
116+
returned array.
117+
118+
example: `useIsInViewport({ target: node => console.log(node) })` or
119+
`useIsInViewport({ target: useRef(null) })`
120+
121+
##### options.viewport
122+
123+
##### options.{modTop, modRight, modBottom, modLeft}
124+
20125
## Usage
21126

22127
### Example 1: Element with its parent document as viewport
@@ -29,7 +134,7 @@ import React from 'react'
29134
import ReactDOM from 'react-dom'
30135
import useIsInViewport from 'use-is-in-viewport
31136
32-
export default function OnlyChildWithNullViewport() {
137+
export default function SimpleElement() {
33138
const [isInViewport, childElToWatch] = useIsInViewport()
34139
35140
return (

0 commit comments

Comments
 (0)