{"id":15585592,"url":"https://github.com/eveningkid/react-native-popable","last_synced_at":"2025-04-12T19:44:26.816Z","repository":{"id":37730854,"uuid":"349093320","full_name":"eveningkid/react-native-popable","owner":"eveningkid","description":"Popovers, tooltips for React Native","archived":false,"fork":false,"pushed_at":"2023-12-18T04:32:23.000Z","size":10561,"stargazers_count":345,"open_issues_count":15,"forks_count":29,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-03T22:08:34.967Z","etag":null,"topics":["alert","expo","popover","react-native","tooltip","web"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eveningkid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-03-18T13:55:48.000Z","updated_at":"2025-03-17T22:09:38.000Z","dependencies_parsed_at":"2023-01-19T13:03:17.880Z","dependency_job_id":"2e259601-4c3e-45b3-8662-6fb121121693","html_url":"https://github.com/eveningkid/react-native-popable","commit_stats":{"total_commits":39,"total_committers":4,"mean_commits":9.75,"dds":0.3846153846153846,"last_synced_commit":"9cecb1614ffe9b4593153ce44f745eaed55e014b"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Freact-native-popable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Freact-native-popable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Freact-native-popable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Freact-native-popable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eveningkid","download_url":"https://codeload.github.com/eveningkid/react-native-popable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625479,"owners_count":21135512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alert","expo","popover","react-native","tooltip","web"],"created_at":"2024-10-02T21:02:00.316Z","updated_at":"2025-04-12T19:44:26.780Z","avatar_url":"https://github.com/eveningkid.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-native-popable\n\nPopovers, tooltips for React Native.\n\n\u003cimg src=\"./assets/popable.gif\" /\u003e\n\n🤖 Controlled and uncontrolled popovers\n\n✍️ Customizable popover content (text, views)\n\n🌐 Works on web, hover support\n\n🙅‍♂️ No-dependency\n\n🎒 Built with Typescript\n\n👩‍🔬 Try the [API sandbox](https://snack.expo.io/dmLOIiVHy)\n\n```jsx\n\u003cPopable content=\"See profile\"\u003e\n  \u003cText\u003e@eveningkid\u003c/Text\u003e\n\u003c/Popable\u003e\n```\n\n## Usage\n\n```sh\nnpm install react-native-popable\n```\n\n\u003e **If working with React Native Web, you'll need at least version 0.15.0.** It introduced hover events for Pressable which is used internally.\n\n### Popable\n\nAdd a popover around a given component. Uses [`Popover`](#Popover) internally.\n\n**Every property coming from `Popover` can be used the exact same way that with `Popable`.**\n\n```jsx\nimport { Popable } from 'react-native-popable';\n\nexport default () =\u003e (\n  \u003cPopable content=\"See profile\"\u003e\n    \u003cText\u003e@morning_cafe\u003c/Text\u003e\n  \u003c/Popable\u003e\n);\n```\n\n- [children](#popable.children)\n- [content](#content)\n\n- Optional\n  - [action](#action)\n  - [animated (from Popover)](#animated)\n  - [animationType (from Popover)](#animationType)\n  - [backgroundColor (from Popover)](#backgroundColor)\n  - [caret (from Popover)](#caret)\n  - [caretPosition (from Popover)](#caretPosition)\n  - [numberOfLines (from Popover)](#numberOfLines)\n  - [onAction](#onAction)\n  - [position (from Popover)](#position)\n  - [strictPosition](#strictPosition)\n  - [style](#style)\n  - [visible (from Popover)](#visible)\n  - [wrapperStyle](#wrapperStyle)\n\n#### Popable.children\n\nWhat should serve as the popover trigger, basically any React element.\n\n```jsx\n\u003cPopable content=\"See profile\"\u003e\n  \u003cImage\n    source={{ uri: ... }}\n    style={{ width: 50, height: 50 }}\n  /\u003e\n\u003c/Popable\u003e\n\n\u003cPopable content=\"See profile\"\u003e\n  \u003cText\u003e@morning_cafe\u003c/Text\u003e\n\u003c/Popable\u003e\n```\n\n#### content\n\nPopover content: can be a string or any React element (text, views).\n\nIf you just want the popover, without all the outside logic that comes from `Popable`, use [`Popover` instead](#popover).\n\n```jsx\n\u003cPopable\n  content={\n    \u003cView\n      style={{\n        padding: 10,\n        alignItems: 'center',\n        justifyContent: 'center',\n        backgroundColor: 'white'\n      }}\n    \u003e\n      \u003cText\u003eAnything :)\u003c/Text\u003e\n    \u003c/View\u003e\n  }\n\u003e\n  \u003cText\u003e@morning_cafe\u003c/Text\u003e\n\u003c/Popable\u003e\n\n\u003cPopable content=\"See profile\"\u003e\n  \u003cText\u003e@morning_cafe\u003c/Text\u003e\n\u003c/Popable\u003e\n```\n\n#### action\n\nUpon what action should the popover be shown/dismissed: `press`, `longpress` or `hover` (web-only). **Defaults to `press`.**\n\n```jsx\n\u003cPopable action=\"hover\" content=\"See profile\"\u003e\n  \u003cText\u003e@morning_cafe\u003c/Text\u003e\n\u003c/Popable\u003e\n```\n\n#### onAction\n\nCallback to monitor the popover visibility state. Called whenever `visible` changes (even through `Popover` internal state). Useful for side-effects.\n\n```jsx\n\u003cPopable\n  onAction={(visible) =\u003e {\n    if (visible) {\n      Analytics.pressedProfilePopover();\n    }\n  }}\n  content=\"See profile\"\n\u003e\n  \u003cText\u003e@morning_cafe\u003c/Text\u003e\n\u003c/Popable\u003e\n```\n\n#### strictPosition\n\nIf the popover should be placed on the opposite side when it doesn't fit at the given position. If a popover is on the left of the screen and its position is left, the position will be turned to right by default. If `strictPosition` is `true`, the popover will remain on the left. **Defaults to `false`.**\n\n```jsx\n\u003cPopable strictPosition={true} position=\"left\"\u003e\n  @morning_cafe\n\u003c/Popable\u003e\n```\n\n#### style\n\nStyle the `Popover` component using any [`View` style property](https://reactnative.dev/docs/view-style-props).\n\n```jsx\n\u003cPopable style={{ opacity: 0.8 }}\u003e@morning_cafe\u003c/Popable\u003e\n```\n\n#### wrapperStyle\n\nStyle the wrapping `View` component using any [`View` style property](https://reactnative.dev/docs/view-style-props).\n\n```jsx\n\u003cPopable wrapperStyle={{ flex: 1, display: 'flex' }}\u003e@morning_cafe\u003c/Popable\u003e\n```\n\n### Popover\n\nThe UI component in `Popable` can also be used on its own.\n\n```jsx\nimport { Popover } from 'react-native-popable';\n\nexport default () =\u003e \u003cPopover\u003e@morning_cafe\u003c/Popover\u003e;\n```\n\n- [children](#children)\n\n- Optional\n  - [animated](#animated)\n  - [animationType](#animationType)\n  - [backgroundColor](#backgroundColor)\n  - [caret](#caret)\n  - [caretPosition](#caretPosition)\n  - [forceInitialAnimation](#forceInitialAnimation)\n  - [numberOfLines](#numberOfLines)\n  - [visible](#visible)\n  - [position](#position)\n\n#### children\n\nThe popover content: will render text if a string is given or the given React elements otherwise.\n\n```jsx\n\u003cPopover\u003e@morning_cafe\u003c/Popover\u003e\n\n\u003cPopover\u003e\n  \u003cImage\n    source={{ uri: ... }}\n    style={{ width: 50, height: 50 }}\n  /\u003e\n\u003c/Popover\u003e\n```\n\n#### animated\n\nIf the popover should animate when the `visible` property changes. **Defaults to `true`.**\n\n```jsx\n\u003cPopover animated={false}\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n#### animationType\n\nIf the popover should bounce a little (`spring`) or not (`timing`). **Defaults to `timing`.**\n\n```jsx\n\u003cPopover animationType=\"spring\"\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n#### backgroundColor\n\nBackground color for the popover and the caret.\n\n```jsx\n\u003cPopover backgroundColor=\"red\"\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n#### caret\n\nIf the little caret (the \"half-triangle\") should be displayed. **Defaults to `true`.**\n\n```jsx\n\u003cPopover caret={false}\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n#### caretPosition\n\nPosition for the caret: `left`, `center` or `right`. **Defaults to `center`.**\n\n```jsx\n\u003cPopover caretPosition=\"right\"\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n#### forceInitialAnimation\n\nIf the popover should animate when it renders for the first time. This means that if `visible` is set to `true`, the popover will fade in after it mounted. Likewise, if `visible` is `false`, the popover will fade out. If this property is kept falsy, the popover will be displayed in its initial visibility state, without animating. It is very unlikely you would ever need this property. **Defaults to `false`.**\n\n```jsx\n\u003cPopover forceInitialAnimation\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n#### numberOfLines\n\nLimit the number of lines if `children` is a `string`. Corresponds to [`Text.numberOfLines`](https://reactnative.dev/docs/text#numberoflines) which clips text with `...` if the given text is more than a number of lines.\n\n```jsx\n\u003cPopover numberOfLines={1}\u003e@morning_cafe_got_longer\u003c/Popover\u003e\n```\n\n#### visible\n\nIf the popover should be visible. Will animate every value change if `animated` is `true`.\n\n```jsx\nconst [visible, setVisible] = useState(false);\n\n\u003cPopover visible={visible}\u003e@morning_cafe\u003c/Popover\u003e\n\n\u003cButton\n  title=\"Toggle visibility\"\n  onPress={() =\u003e {\n    setVisible((isVisible) =\u003e !isVisible);\n  }}\n/\u003e\n```\n\n#### position\n\nPosition for the popover: `top`, `right`, `bottom` or `left`. Changes the caret position. **Defaults to `top`.**\n\n```jsx\n\u003cPopover position=\"right\"\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n#### ViewProps\n\nEvery usual [`View` property](https://reactnative.dev/docs/view#props) is available as well.\n\n```jsx\n\u003cPopover onLayout={...}\u003e@morning_cafe\u003c/Popover\u003e\n```\n\n### usePopable\n\nIf you need to imperatively control the `Popable` component, you can use the `usePopable` hook. It lets you `show` and `hide` the Popable without needing to manage state yourself.\n\nYou typically won't need to use this hook, since `react-native-popable` intelligently hides popovers when users press or hover away. However, it comes in handy for features like menus.\n\n#### Usage\n\n```jsx\nconst [ref, { hide, show }] = usePopable();\n\nreturn \u003cPopable ref={ref} /\u003e\n```\n\nIf you prefer to not use the array syntax, you can destructure like so:\n\n```jsx\nconst { ref, hide, show } = usePopable();\n\nreturn \u003cPopable ref={ref} /\u003e\n```\n\n#### Hide the Popable\n\nIf you're building a Popable menu, you'll want to `hide` the Popable when someone clicks a menu item.\n\n```jsx\nimport React from 'react';\nimport { StyleSheet, View, Text } from 'react-native';\nimport { Popable, usePopable } from 'react-native-popable';\n\nimport Menu from './menu';\n\nexport default function App() {\n  const [ref, { hide }] = usePopable();\n\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cPopable ref={ref} content={\u003cMenu onPressMenuItem={() =\u003e hide()} /\u003e}\u003e\n        \u003cText\u003eOpen Menu\u003c/Text\u003e\n      \u003c/Popable\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\n#### Show the Popable\n\nSimilar to the example above, you can `show` the Popable imperatively:\n\n```jsx\nimport React from 'react';\nimport { StyleSheet, View, Text } from 'react-native';\nimport { Popable, usePopable } from 'react-native-popable';\n\nimport Menu from './menu';\n\nexport default function App() {\n  const [ref, { show, hide }] = usePopable();\n\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cButton title=\"Open Menu\" onPress={() =\u003e show()} /\u003e\n\n      \u003cPopable ref={ref} content={\u003cMenu onPressMenuItem={() =\u003e hide()} /\u003e}\u003e\n        \u003cText\u003eMenu\u003c/Text\u003e\n      \u003c/Popable\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\nThis is a rare use-case, since you'll typically use the children as the trigger of your Popable.\n\n## Contributing\n\nSee the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.\n\n## License\n\nMIT © eveningkid\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feveningkid%2Freact-native-popable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feveningkid%2Freact-native-popable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feveningkid%2Freact-native-popable/lists"}