Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: add startCollapsed prop
  • Loading branch information
PedroBern committed Dec 29, 2020
commit 8c982d20c03b0c7a92065164cead3d990db1c7b8
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ All props are optional, but if you are not rendering a header, you'd be probably
| `snapTimeout?` | How long to wait before initiating the snap effect, in milliseconds. | `250` |
| `onHeaderHeightChange?` | Callback fired when the `headerHeight` state value inside `CollapsibleTabView` will be updated in the `onLayout` event from the tab/header container.<br/><br/> Useful to call layout animations. Example:<br/><br/><pre lang="js">() => {LayoutAnimation.configureNext(preset)};</pre> | `undefined` |
| `routeKeyProp?` | The property from the `routes` map to use for the active route key. | `key` |
| `startCollapsed?` | Start collapsed. It causes a rerender of the first render. | `false` |

### `useCollapsibleScene`

Expand Down
2 changes: 2 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import CollapsibleTabViewExample from './CollapsibleTabViewExample';
import CollapsibleTabViewScrollOnHeaderExample from './CollapsibleTabViewScrollOnHeaderExample';
import CollapsibleTabViewSmallContentExample from './CollapsibleTabViewSmallContentExample';
import CollapsibleTabViewNoSnapExample from './CollapsibleTabViewNoSnapExample';
import CollapsibleTabViewStartCollapsedExample from './CollapsibleTabViewStartCollapsedExample';
import CollapsibleTabViewResizeExample from './CollapsibleTabViewResizeExample';
import CollapsibleTabViewDemoExample from './CollapsibleTabViewDemoExample';
import CollapsibleTabViewCenteredEmptyListExample from './CollapsibleTabViewCenteredEmptyListExample';
Expand All @@ -40,6 +41,7 @@ const PERSISTENCE_KEY = 'index_persistence';
const EXAMPLE_COMPONENTS: ExampleComponentType[] = [
CollapsibleTabViewExample,
CollapsibleTabViewNoSnapExample,
CollapsibleTabViewStartCollapsedExample,
CollapsibleTabViewResizeExample,
CollapsibleTabViewDemoExample,
CollapsibleTabViewSmallContentExample,
Expand Down
13 changes: 13 additions & 0 deletions example/src/CollapsibleTabViewStartCollapsedExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import CollapsibleTabView from './CollapsibleTabViewExample';
import { ExampleComponentType } from './types';

const CollapsibleTabViewExample: ExampleComponentType = () => {
return <CollapsibleTabView startCollapsed />;
};

CollapsibleTabViewExample.title = 'Start collapsed';
CollapsibleTabViewExample.backgroundColor = '#2196f3';
CollapsibleTabViewExample.appbarElevation = 0;

export default CollapsibleTabViewExample;
61 changes: 60 additions & 1 deletion src/CollapsibleTabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export type Props<T extends Route> = Partial<TabViewProps<T>> &
* Default is 'key'
*/
routeKeyProp?: keyof T;
/**
* Start collapsed. It causes a rerender of the first render. Default is false.
*/
startCollapsed?: boolean;
};

/**
Expand All @@ -114,6 +118,7 @@ const CollapsibleTabView = <T extends Route>({
snapThreshold = 0.5,
snapTimeout = 250,
routeKeyProp = 'key',
startCollapsed = false,
...tabViewProps
}: React.PropsWithoutRef<Props<T>>): React.ReactElement => {
const [headerHeight, setHeaderHeight] = React.useState(
Expand All @@ -129,6 +134,13 @@ const CollapsibleTabView = <T extends Route>({

const [canSnap, setCanSnap] = React.useState(false);

const [
shouldTriggerInitialScroll,
setShouldTriggerInitialScroll,
] = React.useState<string[]>([]);

const scrollInitiated = React.useRef<string[]>([]);

const activateSnapDebounced = useDebouncedCallback(
() => {
const lastInteractedAgo = Date.now() - lastInteractionTime.current;
Expand Down Expand Up @@ -305,10 +317,16 @@ const CollapsibleTabView = <T extends Route>({
key: routeKey,
value: ref,
});
if (startCollapsed) {
setShouldTriggerInitialScroll([
...shouldTriggerInitialScroll,
routeKey,
]);
}
}
}
},
[]
[shouldTriggerInitialScroll, startCollapsed]
);

/**
Expand Down Expand Up @@ -402,6 +420,47 @@ const CollapsibleTabView = <T extends Route>({
isUserInteracting.current = false;
}, []);

/**
* Have one useEffect specific for the first route,
* to make sure it starts with the header collapsed.
*/
React.useEffect(() => {
if (startCollapsed) {
const curRouteKey = routes[index][routeKeyProp as keyof Route] as string;
listRefArr.current.forEach((item) => {
if (item.key === curRouteKey) {
scrollScene({
ref: item.value,
offset: headerHeight,
animated: false,
});
scrollInitiated.current = [...scrollInitiated.current, item.key];
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldTriggerInitialScroll]);

React.useEffect(() => {
if (startCollapsed) {
const curRouteKey = routes[index][routeKeyProp as keyof Route] as string;
listRefArr.current.forEach((item) => {
if (
!scrollInitiated.current.includes(item.key) &&
item.key !== curRouteKey
) {
scrollScene({
ref: item.value,
offset: headerHeight,
animated: false,
});
scrollInitiated.current = [...scrollInitiated.current, item.key];
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldTriggerInitialScroll]);

return (
<View
style={styles.container}
Expand Down