Skip to content

Commit 5eb1083

Browse files
authored
chore: refactor API (stipsan#11)
1 parent 0b4a9b1 commit 5eb1083

26 files changed

+1241
-924
lines changed

.babelrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"presets": ["next/babel"],
3+
"env": {
4+
"production": {
5+
"plugins": ["transform-remove-console"]
6+
}
7+
}
8+
}

TODO.md

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,16 @@ Stop relying on memo stuff.
33
If react's render loop triggers, communicate to outside fn's via refs and the like.
44
A change to snap points affects how far one can drag.
55

6-
```
7-
max-content
8-
The intrinsic preferred width.
9-
min-content
10-
The intrinsic minimum width.
11-
fit-content(<length-percentage>)
12-
Uses the fit-content formula with the available space replaced by the specified argument, i.e. min(max-content, max(min-content, <length-percentage>)).
13-
14-
```
15-
16-
hmmmm
6+
fix uneven icon that is being animated, the corner is driving me crazy...
177

18-
- viewportHeight => maxHeight
19-
- initialHeight => initialSnapPoint => initialSnap => defaultSnap
20-
- setHeight => setSnapPoint => setSnap => snapTo
8+
# Remaining critical stuff
219

22-
fix uneven icon that is being animated, the corner is driving me crazy...
10+
- respond to viewport height changes
11+
- respond to snapTo callback
12+
- fire events when stopping the dragging and transition to snap.
13+
- respond to changes to snapPoints output
14+
- don't respond to changes to defaultSnap, it shouldn't act like controlled height.
15+
- optimize element resize observers, perhaps run them all in a chain.
2316

2417
## package.json stuffs
2518

@@ -54,19 +47,15 @@ if (JSON.stringify(arr1) === JSON.stringify(arr2)) {
5447
}
5548
```
5649

50+
# useState bad, bad bad bad and useViewportHeight and useElementSizeObserver both use it
51+
52+
Rewrite to refs, the nextTick system. Create an initial step for getting all dimensions. Then setup observers that set refs.
53+
5754
Faux plugin architecture. "Plugins" or "hooks" can register in an es6 map if they want to do work before the animation starts, while the bottom sheet is resting in the final state but opacity: 0. This allows setting up focus lock, scroll lock and more ahead of time. Hopefully alleviating a lot of jank.
5855

5956
a transition to close can be cancelled if the open state is changed back to `true`.
6057
open/close is fairly easy and stabl. snap to snap on the other hand, require diligence in making sure whoever cancels a snap transition, makes sure to send the animation on the right direction.
6158

62-
## Changes that can happen from React's side of things at any time by means of a prop change
63-
64-
And that may affect side effects that are running atm
65-
66-
- isOpen
67-
- snapPoints
68-
- initialHeight
69-
7059
## Big picture state machines
7160

7261
- transitioning from closed to open.
@@ -90,8 +79,4 @@ tailwind rsbs
9079
- blue gray shades on content below header
9180

9281
important:
93-
lastSnap on initialSnap, to make it persist your choice.
94-
only fade out when dismissable
9582
show inertia location to predict where sheet slides on release
96-
don't fade in if not dismissable
97-
show resize cursor instead of pointer when not dismissable

docs/Hero.module.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@
3131
opacity: 0;
3232
}
3333
.open .text {
34-
transition-duration: 300ms;
3534
--tw-translate-y: 0px;
3635
opacity: 1;
3736
}
3837
/* Only set delay while open to avoid weird artifacts with fast toggling */
39-
.open .text {
38+
.open:not(.skip) .text {
39+
transition-duration: 300ms;
4040
transition-delay: calc(150ms + 80ms * var(--index, 0));
4141
}
4242
.text + .text {

docs/Hero.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,17 @@ const SvgText: React.FC<{ x?: string; y?: string; className?: string }> = ({
6161
</g>
6262
)
6363

64+
let immediate = false
6465
export default function Hero({ className }: { className?: string }) {
65-
const [open, setOpen] = useState(false)
66+
// @TODO this whole monster needs a total rewrite O_O"
67+
const [mounted, setMounted] = useState(false)
68+
const skip = !mounted && immediate ? true : false
69+
const [open, setOpen] = useState(true)
6670
const openClassRef = useRef(false)
6771
const classNameRef = useRef(null)
6872
const { y, state } = useSpring<any>({
6973
config: config.stiff,
74+
immediate: skip,
7075
from: { y: '208px', state: 0 },
7176
to: {
7277
y: open ? '0px' : '208px',
@@ -75,20 +80,28 @@ export default function Hero({ className }: { className?: string }) {
7580
onFrame: ({ state }) => {
7681
if (state > 0) {
7782
if (!openClassRef.current) {
78-
classNameRef.current.classList.add(styles.open)
83+
classNameRef.current.classList.add(
84+
styles.open,
85+
skip ? styles.skip : undefined
86+
)
7987
openClassRef.current = true
8088
}
8189
} else {
8290
if (openClassRef.current) {
83-
classNameRef.current.classList.remove(styles.open)
91+
classNameRef.current.classList.remove(styles.open, styles.skip)
8492
openClassRef.current = false
8593
}
8694
}
8795
},
96+
onRest: () => {
97+
if (mounted) {
98+
immediate = true
99+
}
100+
},
88101
})
89102

90103
useEffect(() => {
91-
setOpen(true)
104+
setMounted(true)
92105
}, [])
93106

94107
return (

package-lock.json

Lines changed: 41 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@
5151
"@types/react": "^17.0.0",
5252
"@typescript-eslint/eslint-plugin": "^4.9.0",
5353
"@typescript-eslint/parser": "^4.9.0",
54+
"@use-it/interval": "^1.0.0",
5455
"autoprefixer": "10.0.4",
5556
"babel-eslint": "^10.1.0",
57+
"babel-plugin-transform-remove-console": "^6.9.4",
5658
"classnames": "^2.2.6",
5759
"eslint": "^7.14.0",
5860
"eslint-config-react-app": "^6.0.0",

pages/fixtures/aside.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default function AsideFixturePage() {
1212
const focusRef = useRef<HTMLButtonElement>()
1313

1414
useEffect(() => {
15+
// Setting focus is to aid keyboard and screen reader nav when activating this iframe
1516
focusRef.current.focus()
1617
}, [])
1718

@@ -26,10 +27,7 @@ export default function AsideFixturePage() {
2627
open={open}
2728
onDismiss={() => setOpen(false)}
2829
blocking={false}
29-
snapPoints={({ viewportHeight }) => [
30-
viewportHeight / 4,
31-
viewportHeight * 0.6,
32-
]}
30+
snapPoints={({ maxHeight }) => [maxHeight / 4, maxHeight * 0.6]}
3331
>
3432
<SheetContent>
3533
<p>

pages/fixtures/experiments.tsx

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import { useCallback, useMemo, useState } from 'react'
1+
import useInterval from '@use-it/interval'
2+
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
23
import Button from '../../docs/fixtures/Button'
34
import Code from '../../docs/fixtures/Code'
45
import Container from '../../docs/fixtures/Container'
56
import Kbd from '../../docs/fixtures/Kbd'
67
import SheetContent from '../../docs/fixtures/SheetContent'
78
import { BottomSheet } from '../../src'
8-
import { useInterval } from '../../src/hooks'
9+
10+
// Just to test we can stop re-renders with this pattern when necessary
11+
const MemoBottomSheet = memo(BottomSheet)
912

1013
function One() {
1114
const [open, setOpen] = useState(false)
@@ -37,19 +40,19 @@ function One() {
3740
if (open) {
3841
setSeconds(seconds + 1)
3942
}
40-
}, 10000)
43+
}, 100)
4144

4245
return (
4346
<>
4447
<Button onClick={() => setOpen(true)}>{seconds}</Button>
45-
<BottomSheet
48+
<MemoBottomSheet
4649
style={style}
4750
open={open}
4851
header={false}
4952
onDismiss={onDismiss}
5053
>
5154
{children}
52-
</BottomSheet>
55+
</MemoBottomSheet>
5356
</>
5457
)
5558
}
@@ -76,11 +79,8 @@ function Two() {
7679
Dismiss
7780
</Button>
7881
}
79-
initialSnapPoint={({ footerHeight }) => footerHeight}
80-
snapPoints={({ minHeight, footerHeight }) => [
81-
footerHeight,
82-
minHeight,
83-
]}
82+
defaultSnap={({ footerHeight }) => footerHeight}
83+
snapPoints={({ minHeight, footerHeight }) => [footerHeight, minHeight]}
8484
>
8585
<SheetContent>
8686
<p>
@@ -115,10 +115,7 @@ function Three() {
115115
Dismiss
116116
</Button>
117117
}
118-
snapPoints={({ minHeight, headerHeight }) => [
119-
headerHeight,
120-
minHeight,
121-
]}
118+
snapPoints={({ minHeight, headerHeight }) => [headerHeight, minHeight]}
122119
>
123120
<SheetContent>
124121
<p>
@@ -173,7 +170,10 @@ function Five() {
173170
open={open}
174171
footer={<strong>Sticky footer</strong>}
175172
onDismiss={onDismiss}
176-
initialSnapPoint={({ lastSnap }) => lastSnap}
173+
onSpringStart={(event) => console.warn('onSpringStart', event)}
174+
onSpringCancel={(event) => console.error('onSpringCancel', event)}
175+
onSpringEnd={(event) => console.warn('onSpringEnd', event)}
176+
defaultSnap={({ lastSnap }) => lastSnap}
177177
snapPoints={({ minHeight, headerHeight, footerHeight }) => [
178178
headerHeight,
179179
headerHeight + footerHeight,
@@ -192,6 +192,41 @@ function Five() {
192192
)
193193
}
194194

195+
function Six() {
196+
const [open, setOpen] = useState(false)
197+
const [half, setHalf] = useState(false)
198+
const [maxHeight, setMaxHeight] = useState(() =>
199+
typeof window !== 'undefined'
200+
? half
201+
? window.innerHeight / 2
202+
: window.innerHeight
203+
: 0
204+
)
205+
206+
useEffect(() => {
207+
setMaxHeight(half ? window.innerHeight / 2 : window.innerHeight)
208+
}, [half])
209+
210+
return (
211+
<>
212+
<Button onClick={() => setOpen(true)}>6</Button>
213+
<BottomSheet
214+
style={{ ['--rsbs-bg' as any]: '#EFF6FF' }}
215+
open={open}
216+
maxHeight={maxHeight}
217+
onDismiss={() => setOpen(false)}
218+
snapPoints={({ minHeight, maxHeight }) => [minHeight, maxHeight]}
219+
>
220+
<SheetContent>
221+
<Button onClick={() => setHalf((half) => !half)}>
222+
{half ? 'maxHeight 100%' : 'maxHeight 50%'}
223+
</Button>
224+
</SheetContent>
225+
</BottomSheet>
226+
</>
227+
)
228+
}
229+
195230
export default function ExperimentsFixturePage() {
196231
return (
197232
<>
@@ -201,6 +236,7 @@ export default function ExperimentsFixturePage() {
201236
<Three />
202237
<Four />
203238
<Five />
239+
<Six />
204240
</Container>
205241
</>
206242
)

0 commit comments

Comments
 (0)