Skip to content
React NativeBeta

Popover

A panel anchored to its trigger, placed with the same maths as the web Popover.

Beta. React Native support is in beta. APIs may change or break between prereleases (npm tag native).

On this page
Web preview — real device may differ
tsx
import { useState } from "react";
import { Text, View } from "react-native";
import { Button } from "@/component-lib/button";
import { Popover } from "@/component-lib/popover";
import { useKitTheme } from "@/component-lib/shared/native";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo
 
export function PopoverDemo() {
  const { tokens } = useKitTheme();
  const [reason, setReason] = useState("—");
  return (
    <>
      <Section title="Popover · anchored">
        <Row>
          <Popover
            trigger={<Button variant="outline">Help</Button>}
            title="What is GST?"
            description="Goods and Services Tax, charged on most sales in India."
            onOpenChange={(open, why) => setReason(open ? "opened" : (why ?? "?"))}
          >
            Your invoices show it per line, at the rate set on each product.
          </Popover>
          <Popover trigger={<Button variant="outline">Filters</Button>} aria-label="Filters" side="bottom" align="end">
            {({ close }) => (
              <View style={{ gap: 10 }}>
                <Text style={{ color: tokens.fg }}>Only unpaid invoices</Text>
                <Button size="sm" onPress={close}>
                  Apply
                </Button>
              </View>
            )}
          </Popover>
        </Row>
        <Text style={{ color: tokens.muted }}>Last close reason: {reason}</Text>
      </Section>
 
      <Section title="Popover · as a sheet">
        <Popover
          presentation="sheet"
          trigger={<Button variant="secondary">Share settings</Button>}
          title="Share settings"
          description="People with the link can view this invoice."
        >
          The link expires in 7 days. Revoke it any time from Settings.
        </Popover>
      </Section>
    </>
  );
}

Install

npx @grampro/kit@native add Popover

Usage

tsx
import { Popover } from "@/component-lib/popover";
 
<Popover trigger={<Button variant="outline">Details</Button>} title="GST">
  <Text>18% on services.</Text>
</Popover>

Props

PopoverProps

PropTypeDescription
trigger (required)ReactElement<TriggerProps>The element that opens it, cloned with a ref (to measure where it is) and an onPress. Any Kit button, or any Pressable, works.
childrenReactNode | ((props: PopoverRenderProps) => ReactNode)
openbooleanControlled open state.
defaultOpenbooleanOpen to begin with, when you are not controlling open.
onOpenChange(open: boolean, reason?: PopoverCloseReason) => voidreason is outside (tap outside or Android back), trigger or api, and undefined when opening.
titleReactNodeHeading inside the panel, which also names it.
descriptionReactNodeA line under the title.
sidePopoverSideSide of the trigger to open on, before flipping for space. Default bottom.
alignPopoverAlignDefault start.
gapnumberDistance from the trigger, in dp. Default 6.
scrollablebooleanCap the panel to the space available and let it scroll. Default false.
presentation"auto" | "popover" | "sheet"popover anchors it to the trigger (default); sheet opens a bottom sheet; auto picks a sheet on phones and a popover on tablets.
styleStyleProp<ViewStyle>The panel's style (the web's className on the panel).
stylesPartial<{ panel: StyleProp<ViewStyle>; header: StyleProp<ViewStyle>; title: StyleProp<T…
localeTextPartial<PopoverLocaleText>

Native and web

  • Android back and a tap outside both close with reason outside.
  • Web version: Popover on the web.