Need help with react-navigation-header-buttons?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

vonovak
512 Stars 37 Forks MIT License 140 Commits 9 Opened issues

Description

Easily render header buttons for react-navigation.

Services available

!
?

Need anything else?

Contributors list

No Data

react-navigation-header-buttons

This package will help you render buttons in the navigation bar and handle the styling so you don't have to. It tries to mimic the appearance of native navbar buttons and attempts to offer simple and flexible interface for you to interact with. Typed with Flow and ships with TS typings. Supports iOS and Android, web support is experimental.

Demo App

Contains many examples and is available via expo. Sources are in the example folder. I highly recommend you check out both links to get a better idea of the api.

Quick Example

The corresponding code:

import React from 'react';
import { Ionicons } from '@expo/vector-icons';
import { Text } from 'react-native';
import {
  HeaderButtons,
  HeaderButton,
  Item,
  HiddenItem,
  OverflowMenu,
} from 'react-navigation-header-buttons';

const IoniconsHeaderButton = (props) => ( // the props here come from <item ...> // you may access them and pass something else to HeaderButton if you like );

const ReusableItem = ({ onPress }) => ;

const ReusableHiddenItem = ({ onPress }) => ;

export function UsageWithIcons({ navigation }) { React.useLayoutEffect(() => { navigation.setOptions({ // in your app, extract the arrow function into a separate component // to avoid creating a new one every time headerRight: () => ( alert('search')} /> alert('Edit')} /> } > alert('hidden1')} /> alert('hidden2')} />

    </reusablehiddenitem></hiddenitem></reusableitem></item></headerbuttons>
  ),
});

}, [navigation]);

return demo!; }

Setup

  1. yarn add react-navigation-header-buttons
  2. Wrap your root component in

    OverflowMenuProvider
    , as seen in example's App.tsx

Usage

HeaderButtons

Is a wrapper over all the visible header buttons (those can be text-buttons, icon-button, or any custom react elements). The most important prop is

HeaderButtonComponent
that defines how all icons rendered in children will look. In particular, it allows setting their icon component, color, and size once so that you don't need to repeat it for each icon-button - but you can easily override those for each
Item
if you like.

HeaderButtons
accepts:

| prop and type | description | note | | ------------------------------------------------ | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | HeaderButtonComponent?: React.ComponentType | component that renders the buttons,

HeaderButton
by default | Typically, you'll want to provide a component that wraps
HeaderButton
provided by this package, as seen in the quick example. However, you're free to use your own component (see
HeaderButton.js
for reference). | | children: React.Node | whatever you want to render inside | typically
Item
or your component that renders
Item
, but it can be anything. | | left?: boolean | whether the
HeaderButtons
are on the left from header title | false by default, it only influences styling in a subtle way |

Item

Renders text, or icon, and has an

onPress
handler. Take a look at the example to see how to use it.

Item
accepts:

| prop and type | description | note | | --------------------------- | --------------------------------------------------------------------------- | ----------------------------- | | title: string | title for the button, required | | | onPress: ?() => any | function to call on press | | | iconName?: string | icon name, used together with the

IconComponent
prop | | | style?: ViewStyleProp | style to apply to the touchable element that wraps the button | | | buttonStyle?: ViewStyleProp | style to apply to the text / icon | applies to both icon and text | | testID?: string | testID to locate view in e2e tests | | | ...TouchableProps | whatever else you want to pass to the underlying touchable (eg.
disabled
) | |

Item
also accepts other props that you'll typically not need to pass because
HeaderButtonComponent
already knows them.

| additional props and type | description | note | | ---------------------------------------- | ---------------------------------------------------------------------------- | ---- | | IconComponent?: React.ComponentType | component to use for the icons, for example from

react-native-vector-icons
| | | iconSize?: number | iconSize | | | color?: string | color of icons and buttons | |

OverflowMenu

Is the place to define the behavior for overflow button (if there is one). Please note you can render

OverflowMenu
only by itself too, you do no need to wrap it in
HeaderButtons
. The most interesting prop is
onPress
which defines what kind of overflow menu we should show.

The package exports common handlers you can use, but you can provide your own too (via

onPress
prop):

| exported handler | description | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |

overflowMenuPressHandlerActionSheet
| This is iOS-only: it displays overflow items in an
ActionSheetIOS
| |
overflowMenuPressHandlerPopupMenu
| This is Android-only: it displays overflow items using
UIManager.showPopupMenu
| |
overflowMenuPressHandlerDropdownMenu
| Can be used in iOS, Android and Web. Displays overflow items in a material popup adapted from react-native-paper, credit for amazing job goes to them. This
Menu
is bundled in this library (no dependency on
react-native-paper
). | |
defaultOnOverflowMenuPress
| The default. Uses
overflowMenuPressHandlerActionSheet
on iOS, and
overflowMenuPressHandlerDropdownMenu
otherwise. |

OverflowMenu
accepts:

| prop and type | description | note | | -------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | OverflowIcon: React.Element | React element for the overflow icon | | | style?: ViewStyleProp | optional styles for overflow button | there are some default styles set, as seen in

OverflowButton.js
| | onPress?: (OnOverflowMenuPressParams) => any | function that is called when overflow menu is pressed. | This will override the default handler. Note the default handler offers (limited) customization. See more in "Recipes". | | testID?: string | testID to locate the overflow button in e2e tests | the default is available under
import { OVERFLOW_BUTTON_TEST_ID } from 'react-navigation-header-buttons/e2e'
| | accessibilityLabel?: string | | 'More options' by default | | left?: boolean | whether the
OverflowMenu
is on the left from header title | false by default, it just influences styling. No need to pass this if you passed it to
HeaderButtons
| | children: React.Node | the overflow items | typically
HiddenItem
s, please read the note below |

Important note

Children passed to

OverflowMenu
should be
  • either
    HiddenItem
    s
  • or plain function components (no class components) without hooks that return
    HiddenItem
    , as seen in the example above.

Anything else will not appear in the overflow menus shown by

overflowMenuPressHandlerActionSheet
and
overflowMenuPressHandlerPopupMenu
. Only
overflowMenuPressHandlerDropdownMenu
supports rendering custom elements, such as
 (which is exported) or your custom ones.

This limitation may look weird but it should not really bother you in any way: if you need to have state in your items, lift the state up. The limitation exists because we need to be able to transform declarative React elements into imperative calls (

ActionSheetIOS.showActionSheetWithOptions
/
UIManager.showPopupMenu
). If this is a problem for you for some reason, please raise an issue and we'll see what can be done about it.

If

OverflowMenu
contains no valid child elements, nothing will be rendered at all. (No
OverflowIcon
, no wrapper.)
examples

Please see UsageWithOverflowComplex.tsx for valid examples!

These will NOT work with overflowMenuPressHandlerActionSheet and overflowMenuPressHandlerPopupMenu:

  1. WRONG! no hooks are allowed!
function MyComponent({ title }) {
  const [titleFromState, setTitle] = React.useState('from state hook');
  return <hiddenitem title="{titleFromState" onpress="{()"> alert('fail')} /&gt;;
}

<overflowmenu overflowicon="{&lt;Ionicons" name="ios-more" size="{23}" color="blue"></overflowmenu>}&gt;
  <mycomponent></mycomponent>
;
  1. WRONG! you can nest HiddenItem only once, not twice
const HiddenItemWrapped = () =&gt; <hiddenitem title="hidden2" onpress="{()"> alert('hidden2')} /&gt;;
const HiddenItemWrappedTwice = ()=&gt; <hiddenitemwrapped></hiddenitemwrapped>

<overflowmenu overflowicon="{&lt;Ionicons" name="ios-more" size="{23}" color="blue"></overflowmenu>}&gt;
  <hiddenitemwrappedtwice></hiddenitemwrappedtwice>
;

HiddenItem

HiddenItem
accepts:

| prop and type | description | note | | -------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------- | | title: string | title for the button, required | | | style?: ViewStyleProp | style to apply to the touchable element that wraps the text | | | titleStyle?: ViewStyleProp | style to apply to the text | | | onPress: ?() => any | function to call on press | | | testID?: string | testID to locate view in e2e tests | | | disabled?: boolean | disabled 'item' is greyed out and

onPress
is not called on touch | | | destructive?: boolean | flag specifying whether this item is destructive | only applies to items shown with
overflowMenuPressHandlerActionSheet
|

OverflowMenuProvider

This is a React context provider needed for

overflowMenuPressHandlerDropdownMenu
to work. If you're not using
overflowMenuPressHandlerDropdownMenu
then you don't need it. By default, you need to wrap your root component with it.

HeaderButton

You will typically not use

HeaderButton
directly.
HeaderButton
is where all the
onPress
,
title
and Icon-related props meet to render actual button. See the source if you want to customize it.

Recipes

Customizing the overflow menu

The default handler for overflow menu on iOS is

overflowMenuPressHandlerActionSheet
.

One of the usual things you may want to do is override the cancel button label on iOS - see example.

How to integrate in your project

This sections covers how you should use the library in your project. Please note that there are numerous example screens.

1 . Define one file where the styling of header buttons is taken care of.

// MyHeaderButtons.js

import * as React from 'react'; import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; import { HeaderButtons, HeaderButton } from 'react-navigation-header-buttons';

// define IconComponent, color, sizes and OverflowIcon in one place const MaterialHeaderButton = (props) => ( );

export const MaterialHeaderButtons = (props) => { return ; }; export { Item } from 'react-navigation-header-buttons';

2 . Import header buttons from the file defined previously.

// SomeScreen.js
import { MaterialHeaderButtons, Item } from './MyHeaderButtons'

static navigationOptions = { title: 'Screen with header buttons', // use MaterialHeaderButtons with consistent styling across your app headerRight: () => ( console.warn('add')} /> console.warn('edit')} /> ), };

Known issues

  • it appears that when screen title is long, it might interfere with buttons (does not happen when using native stack). This is more probably a react-navigation error, but needs investigation.
  • TS typings need improvement, plus I'd like to check their validity via the example project which is using TS. Please get in touch if you wanna help.
  • missing styling support for material dropdown menu
  • item margins need to be reviewed and polished; don't hesitate to contribute - this should help
  • RTL is not tested

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.