Support 1 dimension scrolling

Summary: Added `axis` property to scroll container, to make scroll work in one direction, and fill out the other one.

Reviewed By: cekkaewnumchai

Differential Revision: D24390943

fbshipit-source-id: 5767e753edfb947f43b3998e10d6cebf57f9b53b
This commit is contained in:
Michel Weststrate
2020-10-20 03:22:15 -07:00
committed by Facebook GitHub Bot
parent a2fac737f6
commit 29e528115d
2 changed files with 47 additions and 11 deletions

View File

@@ -118,13 +118,36 @@ const demos: PreviewProps[] = [
title: 'Layout.ScrollContainer', title: 'Layout.ScrollContainer',
description: description:
'Use this component to create an area that can be scrolled. The scrollable area will automatically consume all available space. ScrollContainer accepts all properties that Container accepts as well. Padding will be applied to the child rather than the parent.', 'Use this component to create an area that can be scrolled. The scrollable area will automatically consume all available space. ScrollContainer accepts all properties that Container accepts as well. Padding will be applied to the child rather than the parent.',
props: [], props: [
[
'horizontal / vertical',
'boolean',
'specifies in which directions the container should scroll. If none is specified the container will scroll in both directions',
],
],
demos: { demos: {
'Basic usage': ( 'Basic usage': (
<Layout.ScrollContainer style={{height: 100}}> <Layout.ScrollContainer style={{height: 100}}>
{largeChild} {largeChild}
</Layout.ScrollContainer> </Layout.ScrollContainer>
), ),
'ScrollContainer + Vertical for vertical scroll only': (
<Layout.ScrollContainer
vertical
style={{
height: 100,
width: 100,
border: `2px solid ${theme.primaryColor}`,
}}>
<Layout.Vertical>
<Text ellipsis>
This text is truncated because it is too long and scroll is
vertical only...
</Text>
{largeChild}
</Layout.Vertical>
</Layout.ScrollContainer>
),
}, },
}, },
{ {

View File

@@ -64,28 +64,41 @@ const Container = styled.div<ContainerProps>(
}), }),
); );
const ScrollParent = styled.div({ const ScrollParent = styled.div<{axis?: ScrollAxis}>(({axis}) => ({
boxSizing: 'border-box',
flex: 1, flex: 1,
boxSizing: 'border-box',
position: 'relative', position: 'relative',
overflow: 'auto', overflowX: axis === 'y' ? 'hidden' : 'auto',
}); overflowY: axis === 'x' ? 'hidden' : 'auto',
}));
const ScrollChild = styled.div({ const ScrollChild = styled.div<{axis?: ScrollAxis}>(({axis}) => ({
position: 'absolute', position: 'absolute',
minHeight: '100%', minHeight: '100%',
minWidth: '100%', minWidth: '100%',
}); maxWidth: axis === 'y' ? '100%' : undefined,
maxHeight: axis === 'x' ? '100%' : undefined,
}));
type ScrollAxis = 'x' | 'y' | 'both';
const ScrollContainer = ({ const ScrollContainer = ({
children, children,
horizontal,
vertical,
...rest ...rest
}: React.HTMLAttributes<HTMLDivElement>) => }: React.HTMLAttributes<HTMLDivElement> & {
( horizontal?: boolean;
<ScrollParent {...rest}> vertical?: boolean;
<ScrollChild>{children}</ScrollChild> }) => {
const axis =
horizontal && !vertical ? 'x' : !horizontal && vertical ? 'y' : 'both';
return (
<ScrollParent axis={axis} {...rest}>
<ScrollChild axis={axis}>{children}</ScrollChild>
</ScrollParent> </ScrollParent>
) as any; ) as any;
};
type DistributionProps = ContainerProps & { type DistributionProps = ContainerProps & {
/** /**