Skip to content

feat: add high-level collapsible header API - #27

Draft
pawicao wants to merge 2 commits into
mainfrom
claude/header-animation-api-design-38ca65
Draft

feat: add high-level collapsible header API#27
pawicao wants to merge 2 commits into
mainfrom
claude/header-animation-api-design-38ca65

Conversation

@pawicao

@pawicao pawicao commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds a high-level API for collapsible headers. The new API uses the low-level primitives. It does not change their behavior. All changes are additive.

Collapsible

Collapsible is a compound component. You compose the header from explicit parts:

  • Collapsible is the root. It contains the HeaderMotion provider and the resolved preset. It has no visual output.
  • Collapsible.Header is the header frame. It measures the full header height. It moves up while the user scrolls.
  • Collapsible.Pinned holds content that must stay in view. It moves against the frame to keep its position.
  • Collapsible.Dynamic is the section that collapses. Its measured height sets the collapse distance. The active preset animates its content.
  • Collapsible.NavigationHeader gives the header to a navigation library. It replaces the manual Bridge and NavigationBridge steps. It moves all contexts across the tree boundary.
  • Collapsible.ScrollView and Collapsible.FlatList are the same components as the HeaderMotion scrollables.

Presets

A preset tells the collapsing content how to animate. The parts keep their own base motion. Because of this, presets combine without conflicts.

  • Built-in presets: collapse, fade, parallax, scale, none.
  • You can pass a name, a configured factory, or an array. Example: preset={['collapse', CollapsiblePresets.fade({ to: 0.5 })]}.
  • createCollapsiblePreset() makes a custom preset. A preset is a worklet. It gets the motion state and returns styles for each part.
  • The preset context is an open object. Future versions can add refresh state to it (see feat: Headless Refresh Control #25). This will not break existing presets.

CollapsibleTabs

CollapsibleTabs shares one header across many pages:

  • The root owns the active-tab state and the activeScrollId wiring.
  • CollapsibleTabs.Tab gives its name to the scrollables inside as the default scrollId. New context: HeaderMotionScrollIdContext. An explicit scrollId prop wins. Custom scrollables from createHeaderMotionScrollable() also get this behavior.
  • CollapsibleTabs.Pager shows the pages through a pager adapter.
  • The default adapter is a paging horizontal ScrollView. It has no dependencies.
  • createPagerViewAdapter(PagerView) connects react-native-pager-view. The app imports the pager, not the library.
  • CollapsibleTabs.Bar is a minimal tab bar. useCollapsibleTabs() supplies the data for custom tab bars.

Other additions

  • useCollapsibleHeader() returns the motion values and the collapse() / expand() controls.
  • onStateChange on the root reports the expanded and collapsed states.
  • Three documentation pages and a README section.

Example screens

The example app gets a "High-level API" section with nine screens:

  • One screen for each built-in preset: preset-collapse, preset-fade, preset-parallax, preset-scale, preset-none. They share one showcase component.
  • preset-custom shows a custom preset. It folds the content in 3D and tints the header color with interpolateColor.
  • collapsible-overlay does not use NavigationHeader. It hides the navigation header and renders Collapsible.Header in place.
  • collapsible-tabs uses the react-native-pager-view adapter.
  • collapsible-tabs-default-pager uses the built-in pager and a FlatList tab.

Tests

  • 49 new unit tests. The full suite has 87 tests. All pass.
  • tsc, ESLint, and bob build complete without errors.
  • Manual test on the iPhone 16 Pro simulator: collapse and expand with each preset, the custom preset, the overlay screen, tab swipes, tab-bar presses, and shared header state across tabs.

🤖 Generated with Claude Code

pawicao and others added 2 commits August 15, 2026 10:04
Adds Collapsible and CollapsibleTabs compound components, a composable
preset system, pluggable pager adapters, contextual scrollId resolution,
and the useCollapsibleHeader hook. All changes are additive on top of the
existing low-level primitives.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds one example screen per built-in preset (collapse, fade, parallax,
scale, none) through a shared PresetShowcaseScreen component, a custom
preset example (createCollapsiblePreset with a 3D fold and header tint),
and an overlay example that uses Collapsible.Header without
NavigationHeader. Replaces the previous collapsible-simple screen, which
the parallax preset screen now covers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant