Improve scrolling experience
This commit is contained in:
parent
c33102b472
commit
ae14076ceb
5 changed files with 58 additions and 30 deletions
3
assets/images/ChevronDown.svg
Normal file
3
assets/images/ChevronDown.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="15" height="10" viewBox="0 0 15 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.23278 6.21084L13 -6.40628e-08L14.4656 1.3609L7.23278 9.15006L-1.15036e-05 1.3609L1.46558 -5.68248e-07L7.23278 6.21084Z" fill="#06847B"/>
|
||||
</svg>
|
After Width: | Height: | Size: 292 B |
|
@ -2,7 +2,6 @@ import { storiesOf } from "@storybook/react";
|
|||
import React from "react";
|
||||
|
||||
import Form from "@saleor/components/Form";
|
||||
import { maybe } from "@saleor/misc";
|
||||
import CardDecorator from "@saleor/storybook/CardDecorator";
|
||||
import Decorator from "@saleor/storybook/Decorator";
|
||||
import { ChoiceProvider } from "@saleor/storybook/mock";
|
||||
|
|
|
@ -7,9 +7,13 @@ import { makeStyles } from "@material-ui/styles";
|
|||
import classNames from "classnames";
|
||||
import { GetItemPropsOptions } from "downshift";
|
||||
import React from "react";
|
||||
import SVG from "react-inlinesvg";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import useElementScroll from "@saleor/hooks/useElementScroll";
|
||||
import chevronDown from "@assets/images/ChevronDown.svg";
|
||||
import useElementScroll, {
|
||||
isScrolledToBottom
|
||||
} from "@saleor/hooks/useElementScroll";
|
||||
import { FetchMoreProps } from "@saleor/types";
|
||||
import Hr from "../Hr";
|
||||
|
||||
|
@ -35,11 +39,29 @@ export interface SingleAutocompleteSelectFieldContentProps
|
|||
|
||||
const useStyles = makeStyles(
|
||||
(theme: Theme) => ({
|
||||
arrowContainer: {
|
||||
position: "relative"
|
||||
},
|
||||
arrowInnerContainer: {
|
||||
alignItems: "center",
|
||||
background: theme.palette.grey[50],
|
||||
bottom: 0,
|
||||
display: "flex",
|
||||
height: 30,
|
||||
justifyContent: "center",
|
||||
opacity: 1,
|
||||
position: "absolute",
|
||||
transition: theme.transitions.duration.short + "ms",
|
||||
width: "100%"
|
||||
},
|
||||
content: {
|
||||
maxHeight: menuItemHeight * maxMenuItems + theme.spacing.unit * 2,
|
||||
overflow: "scroll",
|
||||
padding: 8
|
||||
},
|
||||
hide: {
|
||||
opacity: 0
|
||||
},
|
||||
hr: {
|
||||
margin: `${theme.spacing.unit}px 0`
|
||||
},
|
||||
|
@ -53,22 +75,14 @@ const useStyles = makeStyles(
|
|||
justifyContent: "center"
|
||||
},
|
||||
root: {
|
||||
borderRadius: 4,
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
left: 0,
|
||||
marginTop: theme.spacing.unit,
|
||||
overflow: "hidden",
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
zIndex: 22
|
||||
},
|
||||
shadow: {
|
||||
"&$shadowLine": {
|
||||
boxShadow: `0px -5px 10px 0px ${theme.palette.grey[800]}`
|
||||
}
|
||||
},
|
||||
shadowLine: {
|
||||
boxShadow: `0px 0px 0px 0px ${theme.palette.grey[50]}`,
|
||||
height: 1,
|
||||
transition: theme.transitions.duration.short + "ms"
|
||||
}
|
||||
}),
|
||||
{
|
||||
|
@ -114,10 +128,7 @@ const SingleAutocompleteSelectFieldContent: React.FC<
|
|||
const scrollPosition = useElementScroll(anchor);
|
||||
const [calledForMore, setCalledForMore] = React.useState(false);
|
||||
|
||||
const scrolledToBottom = anchor.current
|
||||
? scrollPosition.y + anchor.current.clientHeight + offset >=
|
||||
anchor.current.scrollHeight
|
||||
: false;
|
||||
const scrolledToBottom = isScrolledToBottom(anchor, scrollPosition, 50);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!calledForMore && onFetchMore && scrolledToBottom) {
|
||||
|
@ -133,7 +144,7 @@ const SingleAutocompleteSelectFieldContent: React.FC<
|
|||
}, [loading]);
|
||||
|
||||
return (
|
||||
<Paper className={classes.root} square>
|
||||
<Paper className={classes.root}>
|
||||
<div className={classes.content} ref={anchor}>
|
||||
{choices.length > 0 || displayCustomValue ? (
|
||||
<>
|
||||
|
@ -219,11 +230,15 @@ const SingleAutocompleteSelectFieldContent: React.FC<
|
|||
</MenuItem>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className={classNames(classes.shadowLine, {
|
||||
[classes.shadow]: !scrolledToBottom && choices.length > 0
|
||||
})}
|
||||
/>
|
||||
<div className={classes.arrowContainer}>
|
||||
<div
|
||||
className={classNames(classes.arrowInnerContainer, {
|
||||
[classes.hide]: scrolledToBottom && choices.length > 0
|
||||
})}
|
||||
>
|
||||
<SVG src={chevronDown} />
|
||||
</div>
|
||||
</div>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
import throttle from "lodash-es/throttle";
|
||||
import { MutableRefObject, useEffect, useState } from "react";
|
||||
|
||||
function getPosition(anchor?: HTMLElement) {
|
||||
export type Position = Record<"x" | "y", number>;
|
||||
|
||||
function getPosition(anchor?: HTMLElement): Position {
|
||||
if (!!anchor) {
|
||||
return {
|
||||
x: anchor.scrollLeft,
|
||||
y: anchor.scrollTop
|
||||
};
|
||||
}
|
||||
return {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function useElementScroll(anchor: MutableRefObject<HTMLElement>) {
|
||||
export function isScrolledToBottom(
|
||||
anchor: MutableRefObject<HTMLElement>,
|
||||
position: Position,
|
||||
offset: number = 0
|
||||
) {
|
||||
return !!anchor.current && position
|
||||
? position.y + anchor.current.clientHeight + offset >=
|
||||
anchor.current.scrollHeight
|
||||
: false;
|
||||
}
|
||||
|
||||
function useElementScroll(anchor: MutableRefObject<HTMLElement>): Position {
|
||||
const [scroll, setScroll] = useState(getPosition(anchor.current));
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -10,7 +10,8 @@ function createSingleAutocompleteSelectHandler(
|
|||
change(event);
|
||||
|
||||
const value = event.target.value;
|
||||
setSelected(choices.find(category => category.value === value).label);
|
||||
const choice = choices.find(category => category.value === value)
|
||||
setSelected(choice ? choice.label : value);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue