npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sekizlipenguen/react-native-scroll-menu

v2.0.0

Published

A modern, performant and customizable horizontal scrolling menu for React Native.

Readme

platforms npm npm

@sekizlipenguen/react-native-scroll-menu

Modern horizontal scrolling menu for React Native.

Plain React source + TypeScript definitions. Auto-centers the active chip, supports custom items, indicators, and optional tab scenes with swipe + fade/scale effects.


Demo

| Tab scenes (swipe + content) | Chips / autoCenter / indicator | |:----------------------------:|:------------------------------:| | | |

Recorded from the iOS Simulator playground (example/).


Installation

npm install @sekizlipenguen/react-native-scroll-menu
# or
yarn add @sekizlipenguen/react-native-scroll-menu

Peer deps: react, react-native (>= 0.64).

Local playground

cd example
npm install
bundle install && bundle exec pod install --project-directory=ios
npm start -- --port 8083
npx react-native run-ios --port 8083

example/ is in git for development — not published to npm.


Quick start

import React, {useState} from 'react';
import {Text, View} from 'react-native';
import ScrollingButtonMenu from '@sekizlipenguen/react-native-scroll-menu';

export default function Example() {
  const [selected, setSelected] = useState('1');

  return (
    <View>
      <ScrollingButtonMenu
        items={[
          {id: '1', name: 'Life'},
          {id: '2', name: 'Time'},
          {id: '3', name: 'Faith'},
          {id: '4', name: 'Cosmos'},
          {id: '5', name: 'Fall'},
        ]}
        selected={selected}
        onPress={(item) => setSelected(item.id)}
      />
      <Text>Selected: {selected}</Text>
    </View>
  );
}

Tab menu + content scenes

Instagram / App Store style: chips on top, a page underneath.

import {ScrollingTabScenes} from '@sekizlipenguen/react-native-scroll-menu';

<ScrollingTabScenes
  items={[
    {id: 'overview', name: 'Overview'},
    {id: 'gallery', name: 'Gallery'},
    {id: 'reviews', name: 'Reviews'},
  ]}
  selected={selected}
  onChange={(item) => setSelected(item.id)}
  animation="slide" // 'slide' | 'fade' | 'scale'
  swipeEnabled
  indicator
  renderScene={({item}) => <YourPage id={item.id} />}
/>
  • Height is automatic (measures active scene). Pass height only for a fixed viewport.
  • slide = pager + parallax fade/scale
  • fade / scale = cross-fade transitions
  • Menu props (gap, indicator, styles, …) are forwarded to ScrollingButtonMenu.

Heavier alternatives if you need Material TabView / collapsing headers:
react-native-tab-view · reanimated-tab-view · collapsible-fluid-tabs


More examples

Custom component item

items={[
  {id: '1', name: 'Life'},
  {
    id: '2',
    component: (
      <View style={{alignItems: 'center'}}>
        <Image source={require('./icon.png')} style={{width: 24, height: 24}} />
        <Text style={{fontSize: 12, marginTop: 4}}>Icon</Text>
      </View>
    ),
  },
]}

If component is set, name is not rendered.

Per-item onPress

items={[
  {id: '1', name: 'Home'},
  {
    id: '2',
    name: 'Profile',
    onPress: () => console.log('Profile pressed!'),
  },
]}

Item-level onPress overrides the menu-level handler.

Disabled, gap, indicator, unstyled

<ScrollingButtonMenu
  items={[
    {id: '1', name: 'Home'},
    {id: '2', name: 'Soon', disabled: true},
    {id: '3', name: 'Settings'},
  ]}
  selected={selected}
  onPress={(item) => setSelected(item.id)}
  gap={12}
  indicator
  indicatorStyle={{backgroundColor: '#007AFF', height: 3}}
  // unstyled
/>

Imperative scroll (ref)

const menuRef = useRef(null);

<ScrollingButtonMenu
  ref={menuRef}
  items={items}
  selected={selected}
  onPress={(item) => setSelected(item.id)}
/>

menuRef.current?.scrollToId('3');
menuRef.current?.scrollToIndex(0);

Custom renderItem

<ScrollingButtonMenu
  items={items}
  selected={selected}
  onPress={(item) => setSelected(item.id)}
  renderItem={({item, selected}) => (
    <Text style={{fontWeight: selected ? '700' : '400'}}>{item.name}</Text>
  )}
/>

API

ScrollingButtonMenu props

| Key | Type | Default | Description | |-----|------|---------|-------------| | items | MenuItem[] | — | Menu items (required) | | onPress | (item) => void | — | Item press handler | | selected | string \| number | — | Selected id (controlled) | | upperCase | boolean | false | Uppercase labels | | selectedOpacity | number | 0.7 | Press opacity | | gap | number | 10 | Space between items | | autoCenter | boolean | true | Center selected item | | unstyled | boolean | false | Skip built-in chip styles | | indicator | boolean | false | Sliding underline | | indicatorStyle | ViewStyle | — | Indicator style | | renderItem | (info) => ReactNode | — | Custom item renderer | | containerStyle | ViewStyle | — | Outer container | | contentContainerStyle | ViewStyle | — | Scroll content | | scrollStyle | ViewStyle | — | ScrollView style | | textStyle / activeTextStyle | TextStyle | — | Label styles | | buttonStyle / activeButtonStyle | ViewStyle | — | Item styles | | firstButtonStyle / lastButtonStyle | ViewStyle | — | Edge item styles | | activeColor | string | — | Active text color | | activeBackgroundColor | string | #1e1e1e | Active background | | scrollEnabled | boolean | true | Horizontal scroll | | showsHorizontalScrollIndicator | boolean | false | Scroll indicator | | keyboardShouldPersistTaps | string \| boolean | 'always' | Keyboard taps | | bounces | boolean | true | iOS bounce | | testID / accessibilityLabel | string | — | Testing / a11y |

MenuItem

| Key | Type | Description | |-----|------|-------------| | id | string \| number | Unique id (required) | | name | string | Label | | component | ReactNode | Custom content | | onPress | (item) => void | Per-item handler | | disabled | boolean | Disable item | | accessibilityLabel / testID | string | A11y / tests |

Ref (ScrollingButtonMenu)

| Method | Description | |--------|-------------| | scrollToId(id, animated?) | Center by id | | scrollToIndex(index, animated?) | Center by index |

ScrollingTabScenes extras

| Key | Type | Default | Description | |-----|------|---------|-------------| | onChange | (item, index) => void | — | Selection changed | | renderScene | (info) => ReactNode | — | Scene renderer | | scenes | Record<id, ReactNode> | — | Alternate scene map | | height | number | auto | Fixed height (optional) | | swipeEnabled | boolean | true | Swipe between scenes | | animation | 'slide' \| 'fade' \| 'scale' | 'slide' | Transition style | | sceneContainerStyle | ViewStyle | — | Scene wrapper style |

Ref: goToId(id), goToIndex(index).


Thank You!

Issues & feedback: GitHub Issues.