Skip to content
Merged
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
27 changes: 27 additions & 0 deletions .github/workflows/docs-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Docs build

on:
pull_request:
paths:
- 'docs/**'
- '.github/workflows/docs-build.yml'
- '.github/workflows/docs-publish.yml'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
docs-build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Setup
uses: ./.github/actions/setup

- name: Build docs
run: yarn --cwd docs build
37 changes: 37 additions & 0 deletions .github/workflows/docs-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Docs publish

on:
push:
branches:
- main
paths:
- 'docs/**'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: write

jobs:
docs-publish:
if: github.repository == 'pawicao/react-native-header-motion'
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Setup
uses: ./.github/actions/setup

- name: Build docs
run: yarn --cwd docs build

- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: docs/build
branch: gh-pages
20 changes: 20 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
57 changes: 57 additions & 0 deletions docs/docs/api/create-header-motion-scrollable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
sidebar_position: 9
title: createHeaderMotionScrollable
---

# createHeaderMotionScrollable

Factory function for creating reusable Header Motion-aware wrappers around custom scrollable components.

This is the recommended way to integrate third-party scrollables like FlashList or LegendList.

## Signature

```tsx
function createHeaderMotionScrollable(
Component: ScrollableComponent,
options?: CreateHeaderMotionScrollableOptions
): HeaderMotionScrollableComponent;
```

## Options

| Option | Type | Default | Description |
| ---------------------- | --------------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `displayName` | `string` | Auto-generated | Component name shown in React DevTools. |
| `isComponentAnimated` | `boolean` | `false` | Set to `true` when the component is already animated (skips `Animated.createAnimatedComponent`). |
| `contentContainerMode` | `'children' \| 'renderScrollComponent'` | `'renderScrollComponent'` | How Header Motion injects content offsetting. Use `'children'` for ScrollView-like, `'renderScrollComponent'` for FlatList-like. |

## Examples

### FlashList

```tsx
import { FlashList } from '@shopify/flash-list';
import { createHeaderMotionScrollable } from 'react-native-header-motion';

const HeaderMotionFlashList = createHeaderMotionScrollable(FlashList, {
displayName: 'HeaderMotionFlashList',
});
```

### LegendList

```tsx
import { AnimatedLegendList } from '@legendapp/list/reanimated';
import { createHeaderMotionScrollable } from 'react-native-header-motion';

const HeaderMotionLegendList = createHeaderMotionScrollable(
AnimatedLegendList,
{
displayName: 'HeaderMotionLegendList',
isComponentAnimated: true,
}
);
```

The returned component accepts all the original component's props plus Header Motion-specific props (`scrollId`, `headerOffsetStrategy`, `ensureScrollableContentMinHeight`, `animatedRef`).
32 changes: 32 additions & 0 deletions docs/docs/api/header-motion-bridge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
sidebar_position: 6
title: HeaderMotion.Bridge
---

# HeaderMotion.Bridge

Captures the current HeaderMotion context and exposes it through a render function. Use it to forward context into a navigation-rendered header subtree.

## Usage

```tsx
<HeaderMotion.Bridge>
{(ctx) => (
<Stack.Screen
options={{
header: () => (
<HeaderMotion.NavigationBridge value={ctx}>
<MyHeader />
</HeaderMotion.NavigationBridge>
),
}}
/>
)}
</HeaderMotion.Bridge>
```

## Props

| Prop | Type | Description |
| ---------- | ----------------------------------------------- | -------------------------------------------------------- |
| `children` | `(value: HeaderMotionBridgeValue) => ReactNode` | Render function that receives the bridged context value. |
31 changes: 31 additions & 0 deletions docs/docs/api/header-motion-flatlist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
sidebar_position: 5
title: HeaderMotion.FlatList
---

# HeaderMotion.FlatList

A pre-wired `Animated.FlatList` that participates in Header Motion's scroll tracking and header offsetting.

Works identically to a standard `FlatList` with the same additional Header Motion props as `HeaderMotion.ScrollView`.

## Usage

```tsx
<HeaderMotion.FlatList
data={items}
renderItem={({ item }) => <ItemComponent item={item} />}
keyExtractor={(item) => item.id}
/>
```

## Props

Accepts all `Animated.FlatList` props, plus the same Header Motion-specific props:

| Prop | Type | Default | Description |
| ---------------------------------- | --------------------------------------------------------- | ----------- | ---------------------------------------------------------- |
| `scrollId` | `string` | — | Unique identifier for multi-scroll setups. |
| `headerOffsetStrategy` | `'padding' \| 'margin' \| 'top' \| 'translate' \| 'none'` | `'padding'` | Controls how content is pushed below the header. |
| `ensureScrollableContentMinHeight` | `boolean` | `false` | Experimental. Adds minimum content height for short lists. |
| `animatedRef` | `AnimatedRef` | — | Your own animated ref for programmatic control. |
29 changes: 29 additions & 0 deletions docs/docs/api/header-motion-header-dynamic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
sidebar_position: 3
title: HeaderMotion.Header.Dynamic
---

# HeaderMotion.Header.Dynamic

Marks the part of the header whose layout defines the collapse distance (`progressThreshold`).

Wrap the section that visually disappears during collapse with this component.

## Usage

```tsx
<HeaderMotion.Header style={headerStyle}>
<HeaderMotion.Header.Dynamic style={dynamicStyle}>
{/* This section's height defines progressThreshold */}
</HeaderMotion.Header.Dynamic>
<View>{/* Sticky section */}</View>
</HeaderMotion.Header>
```

## Props

Accepts all `Animated.View` props, plus:

| Prop | Type | Default | Description |
| --------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| `asChild` | `boolean` | `false` | Injects the dynamic measurement into a single child element instead of rendering the default `Animated.View`. |
33 changes: 33 additions & 0 deletions docs/docs/api/header-motion-header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
sidebar_position: 2
title: HeaderMotion.Header
---

# HeaderMotion.Header

The main header container. It measures the total header height and can optionally make the header surface pannable.

By default, the header is absolutely positioned above content (`overlay: true`).

## Usage

```tsx
<HeaderMotion.Header style={[styles.header, animatedStyle]}>
<HeaderMotion.Header.Dynamic>
{/* collapsible section */}
</HeaderMotion.Header.Dynamic>
<View>{/* sticky section */}</View>
</HeaderMotion.Header>
```

## Props

Accepts all `Animated.View` props, plus:

| Prop | Type | Default | Description |
| ---------------------------- | -------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------- |
| `overlay` | `boolean` | `true` | Absolutely positions the header above content. Disable only if you want the header in normal layout flow. |
| `pannable` | `boolean` | `false` | Allows dragging on the header surface to drive the scroll interaction. |
| `panDecayConfig` | `WithDecayConfig \| (event: HeaderPanDecayEvent) => WithDecayConfig` | — | Customizes momentum animation after a header pan ends. |
| `withGestureHandlerRootView` | `boolean` | `false` | Wraps the gesture subtree in `GestureHandlerRootView` when needed. |
| `asChild` | `boolean` | `false` | Injects the total-height measurement into a single child instead of rendering the default `Animated.View`. |
42 changes: 42 additions & 0 deletions docs/docs/api/header-motion-navigation-bridge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
sidebar_position: 7
title: HeaderMotion.NavigationBridge
---

# HeaderMotion.NavigationBridge

Re-provides a previously captured HeaderMotion context value in another subtree. Use together with `HeaderMotion.Bridge`.

## Usage

```tsx
<HeaderMotion.Bridge>
{(ctx) => (
<Stack.Screen
options={{
header: () => (
<HeaderMotion.NavigationBridge value={ctx}>
<MyHeader />
</HeaderMotion.NavigationBridge>
),
}}
/>
)}
</HeaderMotion.Bridge>
```

Inside `MyHeader`, all Header Motion hooks work normally:

```tsx
function MyHeader() {
const { progress, progressThreshold } = useMotionProgress();
// ...
}
```

## Props

| Prop | Type | Description |
| ---------- | ------------------------- | ------------------------------------------------------------ |
| `value` | `HeaderMotionBridgeValue` | The context value captured by `HeaderMotion.Bridge`. |
| `children` | `ReactNode` | The subtree that should have access to HeaderMotion context. |
50 changes: 50 additions & 0 deletions docs/docs/api/header-motion-scroll-manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
sidebar_position: 8
title: HeaderMotion.ScrollManager
---

# HeaderMotion.ScrollManager

A render-prop component for managing custom scrollables. Prefer `createHeaderMotionScrollable()` for most integrations.

Use `ScrollManager` only when the factory approach doesn't give you enough flexibility.

## Usage

```tsx
<HeaderMotion.ScrollManager scrollId="custom">
{(scrollableProps, { originalHeaderHeight, contentContainerMinHeight }) => (
<Animated.ScrollView {...scrollableProps}>
<Animated.View style={{ paddingTop: originalHeaderHeight }}>
{/* content */}
</Animated.View>
</Animated.ScrollView>
)}
</HeaderMotion.ScrollManager>
```

## Props

| Prop | Type | Default | Description |
| -------------------- | ----------------------------------------------------- | ------- | ----------------------------------------------------------- |
| `scrollId` | `string` | — | Unique identifier for multi-scroll setups. |
| `children` | `(scrollableProps, headerMotionContext) => ReactNode` | — | Render function receiving managed props and layout context. |
| `refreshControl` | `ReactElement` | — | Refresh control element. |
| `refreshing` | `boolean` | — | Whether refresh is active. |
| `onRefresh` | `() => void` | — | Refresh callback. |
| `progressViewOffset` | `number` | — | Custom offset for the refresh indicator. |
| `animatedRef` | `AnimatedRef` | — | External animated ref. |

### Render function arguments

**`scrollableProps`** contains:

- `onScroll` — managed scroll handler
- `onLayout` — layout handler for min-height calculations
- `refreshControl` — resolved refresh control (if applicable)
- `ref` — animated ref for the scrollable

**`headerMotionContext`** contains:

- `originalHeaderHeight: number` — measured header height for content offsetting
- `contentContainerMinHeight?: number` — computed min height (when `ensureScrollableContentMinHeight` is used)
31 changes: 31 additions & 0 deletions docs/docs/api/header-motion-scrollview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
sidebar_position: 4
title: HeaderMotion.ScrollView
---

# HeaderMotion.ScrollView

A pre-wired `Animated.ScrollView` that participates in Header Motion's scroll tracking and header offsetting.

It's a drop-in replacement for `Animated.ScrollView` with additional Header Motion capabilities.

## Usage

```tsx
<HeaderMotion.ScrollView>{/* scrollable content */}</HeaderMotion.ScrollView>
```

## Props

Accepts all `Animated.ScrollView` props, plus:

| Prop | Type | Default | Description |
| ---------------------------------- | --------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------- |
| `scrollId` | `string` | — | Unique identifier for multi-scroll setups where one header is shared across scrollables. |
| `headerOffsetStrategy` | `'padding' \| 'margin' \| 'top' \| 'translate' \| 'none'` | `'padding'` | Controls how content is pushed below the measured header. |
| `ensureScrollableContentMinHeight` | `boolean` | `false` | Experimental. Adds minimum content height so short content can still collapse the header. |
| `animatedRef` | `AnimatedRef` | — | Lets you reuse your own animated ref (from `useAnimatedRef()`) for programmatic scroll control. |

Standard scroll callbacks (`onScroll`, `onScrollBeginDrag`, `onScrollEndDrag`, `onMomentumScrollBegin`, `onMomentumScrollEnd`) work as expected alongside the internal handlers.

Refresh control props (`refreshing`, `onRefresh`, `refreshControl`, `progressViewOffset`) are also supported.
Loading
Loading