-
Notifications
You must be signed in to change notification settings - Fork 96
Expand file tree
/
Copy pathindex.tsx
More file actions
57 lines (49 loc) · 1.75 KB
/
index.tsx
File metadata and controls
57 lines (49 loc) · 1.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import React, { useState } from 'react';
import classNames from 'classnames';
import useIsVisible from '../hooks/useIsVisibleHook';
export const CLASSNAME_SCROLL_TOP = 'pgn__scrollable-body-scroll-top';
export const CLASSNAME_SCROLL_BOTTOM = 'pgn__scrollable-body-scroll-bottom';
export interface ScrollableProps extends React.HTMLAttributes<HTMLDivElement> {
/** Specifies the content of the `Scrollable`. */
children: React.ReactNode;
/** Additional classnames for this component. */
className?: string;
}
function Scrollable({ children, className, ...props }: ScrollableProps) {
const [isScrolledToTop, topSentinelRef] = useIsVisible();
const [isScrolledToBottom, bottomSentinelRef] = useIsVisible();
const [valueNow, setValueNow] = useState(0);
const scrollableClassName = classNames(
'pgn__scrollable-body',
className,
{
[CLASSNAME_SCROLL_TOP]: isScrolledToTop,
[CLASSNAME_SCROLL_BOTTOM]: isScrolledToBottom,
},
);
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
const maxScrollHeight = e.currentTarget.scrollHeight - e.currentTarget.clientHeight;
setValueNow(Math.ceil((100 * e.currentTarget.scrollTop) / maxScrollHeight));
};
return (
<div
{...props}
className={scrollableClassName}
role="scrollbar"
aria-valuemin={0}
aria-valuemax={100}
aria-valuenow={valueNow}
aria-controls="scrollbar"
tabIndex={0}
onScroll={handleScroll}
>
<div ref={topSentinelRef as React.RefObject<HTMLDivElement>} />
<div className="pgn__scrollable-body-content">
{children}
</div>
<div ref={bottomSentinelRef as React.RefObject<HTMLDivElement>} />
</div>
);
}
Scrollable.displayName = 'Scrollable';
export default Scrollable;