Navigation Menu Primitive
A collection of navigation links.
Installation
Section titled “Installation”Install the component via your command line.
npx expo install @rn-primitives/navigation-menuInstall @radix-ui/react-navigation-menu
npx expo install @radix-ui/react-navigation-menuCopy/paste the following code for web to  ~/components/primitives/navigation-menu/navigation-menu.web.tsx
import * as NavigationMenu from '@radix-ui/react-navigation-menu';import { useAugmentedRef, useIsomorphicLayoutEffect } from '~/components/primitives/hooks';import * as Slot from '~/components/primitives/slot';import { EmptyGestureResponderEvent } from '~/components/primitives/utils';import * as React from 'react';import { GestureResponderEvent, Pressable, View } from 'react-native';import type {  ContentProps,  ContentRef,  IndicatorProps,  IndicatorRef,  ItemProps,  ItemRef,  LinkProps,  LinkRef,  ListProps,  ListRef,  PortalProps,  RootProps,  RootRef,  TriggerProps,  TriggerRef,  ViewportProps,  ViewportRef,} from './types';
const NavigationMenuContext = React.createContext<RootProps | null>(null);
const Root = React.forwardRef<RootRef, RootProps>(  (    {      asChild,      value,      onValueChange,      delayDuration,      skipDelayDuration,      dir,      orientation,      ...viewProps    },    ref  ) => {    const Component = asChild ? Slot.View : View;    return (      <NavigationMenuContext.Provider value={{ value, onValueChange, orientation }}>        <NavigationMenu.Root          value={value}          onValueChange={onValueChange}          delayDuration={delayDuration}          skipDelayDuration={skipDelayDuration}          dir={dir}          orientation={orientation}        >          <Component ref={ref} {...viewProps} />        </NavigationMenu.Root>      </NavigationMenuContext.Provider>    );  });
Root.displayName = 'RootWebNavigationMenu';
function useRootContext() {  const context = React.useContext(NavigationMenuContext);  if (!context) {    throw new Error(      'NavigationMenu compound components cannot be rendered outside the NavigationMenu component'    );  }  return context;}
const List = React.forwardRef<ListRef, ListProps>(({ asChild, ...viewProps }, ref) => {  const augmentedRef = useAugmentedRef({ ref });  const { orientation } = useRootContext();
  useIsomorphicLayoutEffect(() => {    if (augmentedRef.current) {      const augRef = augmentedRef.current as unknown as HTMLDivElement;      augRef.dataset.orientation = orientation;    }  }, [orientation]);
  const Component = asChild ? Slot.View : View;  return (    <NavigationMenu.List asChild>      <Component ref={ref} {...viewProps} />    </NavigationMenu.List>  );});
List.displayName = 'ListWebNavigationMenu';
const ItemContext = React.createContext<ItemProps | null>(null);
const Item = React.forwardRef<ItemRef, ItemProps>(({ asChild, value, ...props }, ref) => {  const Component = asChild ? Slot.View : View;  return (    <ItemContext.Provider value={{ value }}>      <NavigationMenu.Item value={value} asChild>        <Component ref={ref} {...props} />      </NavigationMenu.Item>    </ItemContext.Provider>  );});
Item.displayName = 'ItemWebNavigationMenu';
function useItemContext() {  const context = React.useContext(ItemContext);  if (!context) {    throw new Error(      'NavigationMenu compound components cannot be rendered outside the NavigationMenu component'    );  }  return context;}
const Trigger = React.forwardRef<TriggerRef, TriggerProps>(  (    { asChild, onPress: onPressProp, disabled = false, onKeyDown: onKeyDownProp, ...props },    ref  ) => {    const { value: rootValue, onValueChange } = useRootContext();    const { value } = useItemContext();    function onKeyDown(ev: React.KeyboardEvent) {      onKeyDownProp?.(ev);      if (ev.key === ' ') {        onPressProp?.(EmptyGestureResponderEvent);        onValueChange(value === rootValue ? '' : value);      }    }
    function onPress(ev: GestureResponderEvent) {      onPressProp?.(ev);      onValueChange(value === rootValue ? '' : value);    }
    const Component = asChild ? Slot.Pressable : Pressable;    return (      <NavigationMenu.Trigger disabled={disabled ?? undefined} asChild>        <Component          ref={ref}          // @ts-expect-error web only          onKeyDown={onKeyDown}          onPress={onPress}          {...props}        />      </NavigationMenu.Trigger>    );  });
Trigger.displayName = 'TriggerWebNavigationMenu';
function Portal({ children }: PortalProps) {  return <>{children}</>;}
const Content = React.forwardRef<ContentRef, ContentProps>(  (    {      asChild = false,      forceMount,      align: _align,      side: _side,      sideOffset: _sideOffset,      alignOffset: _alignOffset,      avoidCollisions: _avoidCollisions,      onLayout: onLayoutProp,      insets: _insets,      disablePositioningStyle: _disablePositioningStyle,      onEscapeKeyDown,      onPointerDownOutside,      onFocusOutside,      onInteractOutside,      ...props    },    ref  ) => {    const Component = asChild ? Slot.View : View;    return (      <NavigationMenu.Content        forceMount={forceMount}        onEscapeKeyDown={onEscapeKeyDown}        onPointerDownOutside={onPointerDownOutside}        onFocusOutside={onFocusOutside}        onInteractOutside={onInteractOutside}      >        <Component ref={ref} {...props} />      </NavigationMenu.Content>    );  });
Content.displayName = 'ContentWebNavigationMenu';
const Link = React.forwardRef<LinkRef, LinkProps>(  ({ asChild, active, onPress: onPressProp, onKeyDown: onKeyDownProp, ...props }, ref) => {    const { onValueChange } = useRootContext();    function onKeyDown(ev: React.KeyboardEvent) {      onKeyDownProp?.(ev);      if (ev.key === 'Enter' || ev.key === ' ') {        onPressProp?.(EmptyGestureResponderEvent);        onValueChange('');      }    }
    function onPress(ev: GestureResponderEvent) {      onPressProp?.(ev);      onValueChange('');    }
    const Component = asChild ? Slot.Pressable : Pressable;    return (      <NavigationMenu.Link active={active} asChild>        <Component          ref={ref}          role='link'          // @ts-expect-error web only          onKeyDown={onKeyDown}          onPress={onPress}          {...props}        />      </NavigationMenu.Link>    );  });
Link.displayName = 'LinkWebNavigationMenu';
const Viewport = React.forwardRef<ViewportRef, ViewportProps>((props, ref) => {  return (    <Slot.View ref={ref} {...props}>      <NavigationMenu.Viewport />    </Slot.View>  );});
Viewport.displayName = 'ViewportWebNavigationMenu';
const Indicator = React.forwardRef<IndicatorRef, IndicatorProps>(({ asChild, ...props }, ref) => {  const Component = asChild ? Slot.View : View;  return (    <NavigationMenu.Indicator asChild>      <Component ref={ref} {...props} />    </NavigationMenu.Indicator>  );});
Indicator.displayName = 'IndicatorWebNavigationMenu';
export {  Content,  Indicator,  Item,  Link,  List,  Portal,  Root,  Trigger,  useItemContext,  useRootContext,  Viewport,};Copy/paste the following code for native to  ~/components/primitives/navigation-menu/navigation-menu.tsx
import { useRelativePosition, type LayoutPosition } from '~/components/primitives/hooks';import { Portal as RNPPortal } from '~/components/primitives/portal';import * as Slot from '~/components/primitives/slot';import * as React from 'react';import {  BackHandler,  Pressable,  View,  type GestureResponderEvent,  type LayoutChangeEvent,  type LayoutRectangle,} from 'react-native';import type {  ContentProps,  ContentRef,  IndicatorProps,  IndicatorRef,  ItemProps,  ItemRef,  LinkProps,  LinkRef,  ListProps,  ListRef,  PortalProps,  RootProps,  RootRef,  TriggerProps,  TriggerRef,  ViewportProps,  ViewportRef,} from './types';
interface INavigationMenuRootContext extends RootProps {  triggerPosition: LayoutPosition | null;  setTriggerPosition: (triggerPosition: LayoutPosition | null) => void;  contentLayout: LayoutRectangle | null;  setContentLayout: (contentLayout: LayoutRectangle | null) => void;  nativeID: string;}
const RootContext = React.createContext<INavigationMenuRootContext | null>(null);
const Root = React.forwardRef<RootRef, RootProps>(  ({ asChild, value, onValueChange, ...viewProps }, ref) => {    const nativeID = React.useId();    const [triggerPosition, setTriggerPosition] = React.useState<LayoutPosition | null>(null);    const [contentLayout, setContentLayout] = React.useState<LayoutRectangle | null>(null);
    const Component = asChild ? Slot.View : View;    return (      <RootContext.Provider        value={{          value,          onValueChange,          nativeID,          contentLayout,          setContentLayout,          setTriggerPosition,          triggerPosition,        }}      >        <Component ref={ref} role='navigation' {...viewProps} />      </RootContext.Provider>    );  });
Root.displayName = 'RootNativeNavigationMenu';
function useRootContext() {  const context = React.useContext(RootContext);  if (!context) {    throw new Error(      'NavigationMenu compound components cannot be rendered outside the NavigationMenu component'    );  }  return context;}
const List = React.forwardRef<ListRef, ListProps>(({ asChild, ...viewProps }, ref) => {  const Component = asChild ? Slot.View : View;  return <Component ref={ref} role='menubar' {...viewProps} />;});
List.displayName = 'ListNativeNavigationMenu';
const ItemContext = React.createContext<(ItemProps & { nativeID: string }) | null>(null);
const Item = React.forwardRef<ItemRef, ItemProps>(({ asChild, value, ...viewProps }, ref) => {  const nativeID = React.useId();
  const Component = asChild ? Slot.View : View;  return (    <ItemContext.Provider      value={{        value,        nativeID,      }}    >      <Component ref={ref} role='menuitem' {...viewProps} />    </ItemContext.Provider>  );});
Item.displayName = 'ItemNativeNavigationMenu';
function useItemContext() {  const context = React.useContext(ItemContext);  if (!context) {    throw new Error(      'NavigationMenu compound components cannot be rendered outside the NavigationMenu component'    );  }  return context;}
const Trigger = React.forwardRef<TriggerRef, TriggerProps>(  ({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {    const triggerRef = React.useRef<View>(null);    const { value, onValueChange, setTriggerPosition } = useRootContext();    const { value: menuValue } = useItemContext();
    React.useImperativeHandle(      ref,      () => {        if (!triggerRef.current) {          return new View({});        }        return triggerRef.current;      },      [triggerRef.current]    );
    function onPress(ev: GestureResponderEvent) {      if (disabled) return;      triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {        setTriggerPosition({ width, pageX, pageY: pageY, height });      });
      onValueChange(menuValue === value ? '' : menuValue);      onPressProp?.(ev);    }
    const Component = asChild ? Slot.Pressable : Pressable;    return (      <Component        ref={triggerRef}        aria-disabled={disabled ?? undefined}        role='button'        onPress={onPress}        disabled={disabled ?? undefined}        aria-expanded={value === menuValue}        {...props}      />    );  });
Trigger.displayName = 'TriggerNativeNavigationMenu';
/** * @warning when using a custom `<PortalHost />`, you will have to adjust the Content's sideOffset to account for nav elements like headers. */function Portal({ forceMount, hostName, children }: PortalProps) {  const navigationMenu = useRootContext();  const item = useItemContext();
  if (!navigationMenu.triggerPosition) {    return null;  }
  if (!forceMount) {    if (navigationMenu.value !== item.value) {      return null;    }  }
  return (    <RNPPortal hostName={hostName} name={`${navigationMenu.nativeID}_portal_provider`}>      <RootContext.Provider        value={navigationMenu}        key={`RootContext_${navigationMenu.nativeID}_portal_provider`}      >        <ItemContext.Provider value={item}>{children}</ItemContext.Provider>      </RootContext.Provider>    </RNPPortal>  );}
/** * @info `position`, `top`, `left`, and `maxWidth` style properties are controlled internally. Opt out of this behavior by setting `disablePositioningStyle` to `true`. */const Content = React.forwardRef<ContentRef, ContentProps>(  (    {      asChild = false,      forceMount,      align = 'center',      side = 'bottom',      sideOffset = 0,      alignOffset = 0,      avoidCollisions = true,      onLayout: onLayoutProp,      insets,      style,      disablePositioningStyle,      ...props    },    ref  ) => {    const {      value,      onValueChange,      triggerPosition,      setTriggerPosition,      contentLayout,      setContentLayout,    } = useRootContext();    const { value: menuValue, nativeID } = useItemContext();
    React.useEffect(() => {      const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {        setTriggerPosition(null);        setContentLayout(null);        onValueChange('');        return true;      });
      return () => {        setContentLayout(null);        backHandler.remove();      };    }, []);
    const positionStyle = useRelativePosition({      align,      avoidCollisions,      triggerPosition,      contentLayout,      alignOffset,      insets,      sideOffset,      side,      disablePositioningStyle,    });
    function onLayout(event: LayoutChangeEvent) {      setContentLayout(event.nativeEvent.layout);      onLayoutProp?.(event);    }
    if (!forceMount) {      if (value !== menuValue) {        return null;      }    }
    const Component = asChild ? Slot.View : View;    return (      <Component        ref={ref}        role='menu'        nativeID={nativeID}        aria-modal={true}        style={[positionStyle, style]}        onLayout={onLayout}        onStartShouldSetResponder={onStartShouldSetResponder}        {...props}      />    );  });
Content.displayName = 'ContentNativeNavigationMenu';
const Link = React.forwardRef<LinkRef, LinkProps>(({ asChild, ...props }, ref) => {  const Component = asChild ? Slot.Pressable : Pressable;  return <Component ref={ref} role='link' {...props} />;});
Link.displayName = 'LinkNativeNavigationMenu';
const Viewport = React.forwardRef<ViewportRef, ViewportProps>((props, ref) => {  return <View ref={ref} {...props} />;});
Viewport.displayName = 'ViewportNativeNavigationMenu';
const Indicator = React.forwardRef<IndicatorRef, IndicatorProps>(({ asChild, ...props }, ref) => {  const Component = asChild ? Slot.View : View;  return <Component ref={ref} {...props} />;});
Indicator.displayName = 'IndicatorNativeNavigationMenu';
export {  Content,  Indicator,  Item,  Link,  List,  Portal,  Root,  Trigger,  useItemContext,  useRootContext,  Viewport,};
function onStartShouldSetResponder() {  return true;}Copy/paste the following code for types to  ~/components/primitives/navigation-menu/types.ts
import type {  ForceMountable,  PositionedContentProps,  PressableRef,  SlottablePressableProps,  SlottableViewProps,  ViewRef,} from '~/components/primitives/types';import type { ViewProps } from 'react-native';
type RootProps = SlottableViewProps & {  value: string | undefined;  onValueChange: (value: string | undefined) => void;  /**   * Platform: WEB ONLY   */  delayDuration?: number;  /**   * Platform: WEB ONLY   */  skipDelayDuration?: number;  /**   * Platform: WEB ONLY   */  dir?: 'ltr' | 'rtl';  /**   * Platform: WEB ONLY   */  orientation?: 'horizontal' | 'vertical';};
type ItemProps = SlottableViewProps & {  value: string | undefined;};
interface PortalProps extends ForceMountable {  children: React.ReactNode;  /**   * Platform: NATIVE ONLY   */  hostName?: string;  /**   * Platform: WEB ONLY   */  container?: HTMLElement | null | undefined;}
type LinkProps = SlottablePressableProps & {  active?: boolean;};
type ListProps = SlottableViewProps;type TriggerProps = SlottablePressableProps;type ContentProps = SlottableViewProps & PositionedContentProps;type IndicatorProps = SlottableViewProps;type ViewportProps = Omit<ViewProps, 'children'>;
type ContentRef = ViewRef;type IndicatorRef = ViewRef;type ItemRef = ViewRef;type LinkRef = PressableRef;type ListRef = ViewRef;type RootRef = ViewRef;type ViewportRef = ViewRef;type TriggerRef = PressableRef;
export type {  ContentProps,  ContentRef,  IndicatorProps,  IndicatorRef,  ItemProps,  ItemRef,  LinkProps,  LinkRef,  ListProps,  ListRef,  PortalProps,  RootProps,  RootRef,  TriggerProps,  TriggerRef,  ViewportProps,  ViewportRef,};Copy/paste the following code for exporting to  ~/components/primitives/navigation-menu/index.ts
export * from './navigation-menu';export * from './types';Copy/paste the following code for native to  ~/components/primitives/navigation-menu/index.tsx
import { useRelativePosition, type LayoutPosition } from '~/components/primitives/hooks';import { Portal as RNPPortal } from '~/components/primitives/portal';import * as Slot from '~/components/primitives/slot';import * as React from 'react';import {  BackHandler,  Pressable,  View,  type GestureResponderEvent,  type LayoutChangeEvent,  type LayoutRectangle,} from 'react-native';import type {  ContentProps,  ContentRef,  IndicatorProps,  IndicatorRef,  ItemProps,  ItemRef,  LinkProps,  LinkRef,  ListProps,  ListRef,  PortalProps,  RootProps,  RootRef,  TriggerProps,  TriggerRef,  ViewportProps,  ViewportRef,} from './types';
interface INavigationMenuRootContext extends RootProps {  triggerPosition: LayoutPosition | null;  setTriggerPosition: (triggerPosition: LayoutPosition | null) => void;  contentLayout: LayoutRectangle | null;  setContentLayout: (contentLayout: LayoutRectangle | null) => void;  nativeID: string;}
const RootContext = React.createContext<INavigationMenuRootContext | null>(null);
const Root = React.forwardRef<RootRef, RootProps>(  ({ asChild, value, onValueChange, ...viewProps }, ref) => {    const nativeID = React.useId();    const [triggerPosition, setTriggerPosition] = React.useState<LayoutPosition | null>(null);    const [contentLayout, setContentLayout] = React.useState<LayoutRectangle | null>(null);
    const Component = asChild ? Slot.View : View;    return (      <RootContext.Provider        value={{          value,          onValueChange,          nativeID,          contentLayout,          setContentLayout,          setTriggerPosition,          triggerPosition,        }}      >        <Component ref={ref} role='navigation' {...viewProps} />      </RootContext.Provider>    );  });
Root.displayName = 'RootNativeNavigationMenu';
function useRootContext() {  const context = React.useContext(RootContext);  if (!context) {    throw new Error(      'NavigationMenu compound components cannot be rendered outside the NavigationMenu component'    );  }  return context;}
const List = React.forwardRef<ListRef, ListProps>(({ asChild, ...viewProps }, ref) => {  const Component = asChild ? Slot.View : View;  return <Component ref={ref} role='menubar' {...viewProps} />;});
List.displayName = 'ListNativeNavigationMenu';
const ItemContext = React.createContext<(ItemProps & { nativeID: string }) | null>(null);
const Item = React.forwardRef<ItemRef, ItemProps>(({ asChild, value, ...viewProps }, ref) => {  const nativeID = React.useId();
  const Component = asChild ? Slot.View : View;  return (    <ItemContext.Provider      value={{        value,        nativeID,      }}    >      <Component ref={ref} role='menuitem' {...viewProps} />    </ItemContext.Provider>  );});
Item.displayName = 'ItemNativeNavigationMenu';
function useItemContext() {  const context = React.useContext(ItemContext);  if (!context) {    throw new Error(      'NavigationMenu compound components cannot be rendered outside the NavigationMenu component'    );  }  return context;}
const Trigger = React.forwardRef<TriggerRef, TriggerProps>(  ({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {    const triggerRef = React.useRef<View>(null);    const { value, onValueChange, setTriggerPosition } = useRootContext();    const { value: menuValue } = useItemContext();
    React.useImperativeHandle(      ref,      () => {        if (!triggerRef.current) {          return new View({});        }        return triggerRef.current;      },      [triggerRef.current]    );
    function onPress(ev: GestureResponderEvent) {      if (disabled) return;      triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {        setTriggerPosition({ width, pageX, pageY: pageY, height });      });
      onValueChange(menuValue === value ? '' : menuValue);      onPressProp?.(ev);    }
    const Component = asChild ? Slot.Pressable : Pressable;    return (      <Component        ref={triggerRef}        aria-disabled={disabled ?? undefined}        role='button'        onPress={onPress}        disabled={disabled ?? undefined}        aria-expanded={value === menuValue}        {...props}      />    );  });
Trigger.displayName = 'TriggerNativeNavigationMenu';
/** * @warning when using a custom `<PortalHost />`, you will have to adjust the Content's sideOffset to account for nav elements like headers. */function Portal({ forceMount, hostName, children }: PortalProps) {  const navigationMenu = useRootContext();  const item = useItemContext();
  if (!navigationMenu.triggerPosition) {    return null;  }
  if (!forceMount) {    if (navigationMenu.value !== item.value) {      return null;    }  }
  return (    <RNPPortal hostName={hostName} name={`${navigationMenu.nativeID}_portal_provider`}>      <RootContext.Provider        value={navigationMenu}        key={`RootContext_${navigationMenu.nativeID}_portal_provider`}      >        <ItemContext.Provider value={item}>{children}</ItemContext.Provider>      </RootContext.Provider>    </RNPPortal>  );}
/** * @info `position`, `top`, `left`, and `maxWidth` style properties are controlled internally. Opt out of this behavior by setting `disablePositioningStyle` to `true`. */const Content = React.forwardRef<ContentRef, ContentProps>(  (    {      asChild = false,      forceMount,      align = 'center',      side = 'bottom',      sideOffset = 0,      alignOffset = 0,      avoidCollisions = true,      onLayout: onLayoutProp,      insets,      style,      disablePositioningStyle,      ...props    },    ref  ) => {    const {      value,      onValueChange,      triggerPosition,      setTriggerPosition,      contentLayout,      setContentLayout,    } = useRootContext();    const { value: menuValue, nativeID } = useItemContext();
    React.useEffect(() => {      const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {        setTriggerPosition(null);        setContentLayout(null);        onValueChange('');        return true;      });
      return () => {        setContentLayout(null);        backHandler.remove();      };    }, []);
    const positionStyle = useRelativePosition({      align,      avoidCollisions,      triggerPosition,      contentLayout,      alignOffset,      insets,      sideOffset,      side,      disablePositioningStyle,    });
    function onLayout(event: LayoutChangeEvent) {      setContentLayout(event.nativeEvent.layout);      onLayoutProp?.(event);    }
    if (!forceMount) {      if (value !== menuValue) {        return null;      }    }
    const Component = asChild ? Slot.View : View;    return (      <Component        ref={ref}        role='menu'        nativeID={nativeID}        aria-modal={true}        style={[positionStyle, style]}        onLayout={onLayout}        onStartShouldSetResponder={onStartShouldSetResponder}        {...props}      />    );  });
Content.displayName = 'ContentNativeNavigationMenu';
const Link = React.forwardRef<LinkRef, LinkProps>(({ asChild, ...props }, ref) => {  const Component = asChild ? Slot.Pressable : Pressable;  return <Component ref={ref} role='link' {...props} />;});
Link.displayName = 'LinkNativeNavigationMenu';
const Viewport = React.forwardRef<ViewportRef, ViewportProps>((props, ref) => {  return <View ref={ref} {...props} />;});
Viewport.displayName = 'ViewportNativeNavigationMenu';
const Indicator = React.forwardRef<IndicatorRef, IndicatorProps>(({ asChild, ...props }, ref) => {  const Component = asChild ? Slot.View : View;  return <Component ref={ref} {...props} />;});
Indicator.displayName = 'IndicatorNativeNavigationMenu';
export {  Content,  Indicator,  Item,  Link,  List,  Portal,  Root,  Trigger,  useItemContext,  useRootContext,  Viewport,};
function onStartShouldSetResponder() {  return true;}Copy/paste the following code for types to  ~/components/primitives/navigation-menu/types.ts
import type {  ForceMountable,  PositionedContentProps,  PressableRef,  SlottablePressableProps,  SlottableViewProps,  ViewRef,} from '~/components/primitives/types';import type { ViewProps } from 'react-native';
type RootProps = SlottableViewProps & {  value: string | undefined;  onValueChange: (value: string | undefined) => void;  /**   * Platform: WEB ONLY   */  delayDuration?: number;  /**   * Platform: WEB ONLY   */  skipDelayDuration?: number;  /**   * Platform: WEB ONLY   */  dir?: 'ltr' | 'rtl';  /**   * Platform: WEB ONLY   */  orientation?: 'horizontal' | 'vertical';};
type ItemProps = SlottableViewProps & {  value: string | undefined;};
interface PortalProps extends ForceMountable {  children: React.ReactNode;  /**   * Platform: NATIVE ONLY   */  hostName?: string;  /**   * Platform: WEB ONLY   */  container?: HTMLElement | null | undefined;}
type LinkProps = SlottablePressableProps & {  active?: boolean;};
type ListProps = SlottableViewProps;type TriggerProps = SlottablePressableProps;type ContentProps = SlottableViewProps & PositionedContentProps;type IndicatorProps = SlottableViewProps;type ViewportProps = Omit<ViewProps, 'children'>;
type ContentRef = ViewRef;type IndicatorRef = ViewRef;type ItemRef = ViewRef;type LinkRef = PressableRef;type ListRef = ViewRef;type RootRef = ViewRef;type ViewportRef = ViewRef;type TriggerRef = PressableRef;
export type {  ContentProps,  ContentRef,  IndicatorProps,  IndicatorRef,  ItemProps,  ItemRef,  LinkProps,  LinkRef,  ListProps,  ListRef,  PortalProps,  RootProps,  RootRef,  TriggerProps,  TriggerRef,  ViewportProps,  ViewportRef,};import * as React from 'react';import { Platform, StyleSheet, Pressable, Text } from 'react-native';import * as NavigationMenuPrimitive from '@rn-primitives/navigation-menu';
function Example() {  const [value, setValue] = React.useState<string>();
  function closeAll() {    setValue('');  }
  // TODO: handle closing menus when pressing/clicking outside of this Example component. Ex: when navigating to another screen
  return (    <>      {Platform.OS !== 'web' && !!value && (        <Pressable          onPress={closeAll}          style={StyleSheet.absoluteFillObject}        />      )}      <NavigationMenuPrimitive.Root value={value} onValueChange={setValue}>        <NavigationMenuPrimitive.List>          <NavigationMenuPrimitive.Item value='getting-started'>            <NavigationMenuPrimitive.Trigger>              <Text>Getting started</Text>            </NavigationMenuPrimitive.Trigger>            <NavigationMenuPrimitive.Portal>              <NavigationMenuPrimitive.Content>                <NavigationMenuPrimitive.Link >                  <Text>                    react-native-reusables                  </Text>                </NavigationMenuPrimitive.Link>              </NavigationMenuPrimitive.Content>            </ NavigationMenuPrimitive.Portal>          </NavigationMenuPrimitive.Item>          <NavigationMenuPrimitive.Item value='components'>            <NavigationMenuPrimitive.Trigger>              <Text>Components</Text>            </NavigationMenuPrimitive.Trigger>            <NavigationMenuPrimitive.Content>                  <NavigationMenuPrimitive.Link>                    Navigation Menu                  </NavigationMenuPrimitive.Link>              </View>            </NavigationMenuPrimitive.Content>          </NavigationMenuPrimitive.Item>          <NavigationMenuPrimitive.Item value='documentation'>            <NavigationMenuPrimitive.Link onPress={closeAll}>              <Text>Documentation</Text>            </NavigationMenuPrimitive.Link>          </NavigationMenuPrimitive.Item>        </NavigationMenuPrimitive.List>      </NavigationMenuPrimitive.Root>    </>  );}Extends View props
| Prop | Type | Note | 
|---|---|---|
| value* | boolean | |
| onValueChange* | (value: boolean) => void | |
| asChild | boolean | (optional) | 
| delayDuration | number | Web only (optional) | 
| skipDelayDuration | number | Web only (optional) | 
| dir | ’ltr’ | ‘rtl’ | Web only (optional) | 
| orientation | ’horizontal’ | ‘vertical’ | Web only (optional) | 
Extends View props
| Prop | Type | Note | 
|---|---|---|
| asChild | boolean | (optional) | 
Extends Pressable props
| Prop | Type | Note | 
|---|---|---|
| value* | string | |
| asChild | boolean | (optional) | 
Trigger
Section titled “Trigger”Extends Pressable props
| Prop | Type | Note | 
|---|---|---|
| asChild | boolean | (optional) | 
Portal
Section titled “Portal”| Prop | Type | Note | 
|---|---|---|
| children* | React.ReactNode | |
| forceMount | true | undefined | (optional) | 
| hostName | string | Web Only (optional) | 
| container | HTMLElement | null | undefined | Web Only (optional) | 
Content
Section titled “Content”Extends View props
| Prop | Type | Note | 
|---|---|---|
| asChild | boolean | (optional) | 
| forceMount | true | undefined | (optional) | 
| alignOffset | number | Native Only (optional) | 
| insets | Insets | Native Only (optional) | 
| avoidCollisions | boolean | Native Only (optional) | 
| align | ’start’ | ‘center’ | ‘end’ | Native Only (optional) | 
| side | ’top’ | ‘bottom’ | Native Only (optional) | 
| sideOffset | number | Native Only (optional) | 
| disablePositioningStyle | boolean | Native Only (optional) | 
| loop | boolean | Web Only (optional) | 
| onEscapeKeyDown | (event: KeyboardEvent) => void | Web Only (optional) | 
| onPointerDownOutside | (event: PointerDownOutsideEvent) => void | Web Only (optional) | 
| onFocusOutside | (event: FocusOutsideEvent) => void | Web Only (optional) | 
| onInteractOutside | PointerDownOutsideEvent | FocusOutsideEvent | Web Only (optional) | 
Extends Pressable props
| Prop | Type | Note | 
|---|---|---|
| active | boolean | (optional) | 
| asChild | boolean | (optional) | 
Viewport
Section titled “Viewport”Should only be used for web
Extends View props except children
Indicator
Section titled “Indicator”Extends View props
useRootContext
Section titled “useRootContext”Must be used within a Root component. It provides the following values from the navigation menu: value, and onValueChange.
useItemContext
Section titled “useItemContext”Must be used within a Item component. It provides the following values from the navigation menu: value.