{"id":17957567,"url":"https://github.com/evanbacon/expo-quick-actions","last_synced_at":"2025-05-14T19:10:05.027Z","repository":{"id":105127758,"uuid":"512151003","full_name":"EvanBacon/expo-quick-actions","owner":"EvanBacon","description":"Add home screen quick actions / shortcuts and custom icons to your Expo app","archived":false,"fork":false,"pushed_at":"2025-05-13T17:32:48.000Z","size":28942,"stargazers_count":456,"open_issues_count":12,"forks_count":14,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-13T18:40:42.844Z","etag":null,"topics":["expo","kotlin","react-native","swift"],"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/EvanBacon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-07-09T09:57:10.000Z","updated_at":"2025-05-13T18:19:13.000Z","dependencies_parsed_at":"2024-03-15T20:28:57.250Z","dependency_job_id":"0cddf767-974b-49e2-9bdb-c5ca66fd8822","html_url":"https://github.com/EvanBacon/expo-quick-actions","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvanBacon%2Fexpo-quick-actions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvanBacon%2Fexpo-quick-actions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvanBacon%2Fexpo-quick-actions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvanBacon%2Fexpo-quick-actions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EvanBacon","download_url":"https://codeload.github.com/EvanBacon/expo-quick-actions/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254209859,"owners_count":22032897,"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":["expo","kotlin","react-native","swift"],"created_at":"2024-10-29T10:55:41.328Z","updated_at":"2025-05-14T19:10:02.924Z","avatar_url":"https://github.com/EvanBacon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# expo-quick-actions\n\n\u003e This is not an official Expo SDK package.\n\nA comprehensive React Native library for home screen quick actions.\n\n## Versioning\n\nEnsure you use versions that work together!\n\n| `expo` | `expo-quick-actions` |\n| ------ | -------------------- |\n| 53.0.0 | 5.0.0                |\n| 52.0.0 | +3.0.0               |\n| 51.0.0 | 2.0.0                |\n| 50.0.0 | 1.0.0                |\n| 49.0.0 | 0.0.0                |\n\n## API documentation\n\n```ts\nimport * as QuickActions from \"expo-quick-actions\";\n```\n\n### `Action`\n\nThe `Action` type is an object with the following properties:\n\n- `id: string`: A unique identifier for the action.\n- `title: string`: The title of the action.\n- `subtitle?: string | null`: The subtitle of the action, iOS-only.\n- `icon?: string | null`: Asset reference to use for the icon.\n- `params?: Record\u003cstring, number | string | boolean | null | undefined\u003e | null`: Additional serial parameters for the action.\n\n### `initial`\n\n\u003e `Action | null`\n\nA static property that returns the initial quick action item that was used to open the app, if any.\n\n```tsx\nconst initialAction = QuickActions.initial;\n```\n\n### `maxCount`\n\n\u003e `number | null`\n\nA static property that returns the maximum number of quick action items that can be set.\n\n- On iOS, this is hardcoded to 4.\n- On Android, this is dynamically collected on start-up.\n\n```tsx\n// e.g. 15 on Pixel 6, null on iOS.\nconst maxCount = QuickActions.maxCount;\n```\n\n### `setItems`\n\n\u003e `(items: Action[]) =\u003e Promise\u003cvoid\u003e`\n\nAn async function that sets the quick action items for the app. Both Apple and Android recommend a max of 4 items.\n\n```ts\nQuickActions.setItems([\n  {\n    id: \"0\",\n    title: \"Open Settings\",\n    subtitle: \"Go here to configure settings\",\n    icon: \"heart\",\n    params: { href: \"/settings\" },\n  },\n]);\n```\n\n### `isSupported`\n\n\u003e `() =\u003e Promise\u003cboolean\u003e`\n\nAn async function that returns whether the device supports home screen quick actions.\n\n```ts\nconst isSupported = await QuickActions.isSupportedAsync();\n```\n\n### `addListener`\n\n\u003e `(listener: (payload: Action) =\u003e void) =\u003e Subscription`\n\nAdds a listener that will fire when a quick action is triggered.\n\n```ts\nconst subscription = QuickActions.addListener((action) =\u003e {\n  console.log(action);\n});\n```\n\n## Icons\n\n\u003e Read the [Android design docs for shortcut icons](https://commondatastorage.googleapis.com/androiddevelopers/shareables/design/app-shortcuts-design-guidelines.pdf).\n\nOn iOS, there are three types of images you may want to use: default icons, SF Symbols, and custom template images. The `icon` property supports magic prefixes to access all the built-in icons:\n\n### SF Symbols\n\n\u003e `UIApplicationShortcutIcon(systemImageName:)` -- Create an icon using a system image. You can use any of the names here that are usable with -systemImageNamed:.\n\nIcons prefixed with `symbol:` are passed to `UIApplicationShortcutIcon(systemImageName:)`, e.g. `symbol:heart.fill` will use `UIApplicationShortcutIcon(systemImageName: \"heart.fill\")` which renders the SF Symbols icon named `heart.fill`. Learn more about [Apple SF Symbols](https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/). Note: SF Symbols are only available on iOS as Apple copyright restricts using them on other platforms.\n\n### System Icons\n\n\u003e `UIApplicationShortcutIcon(type:)` -- Create an icon using a system-defined image.\n\nIcons matching one of the following will use a built-in icon: \"compose\", \"play\", \"pause\", \"add\", \"location\", \"search\", \"share\", \"prohibit\", \"contact\", \"home\", \"markLocation\", \"favorite\", \"love\", \"cloud\", \"invitation\", \"confirmation\", \"mail\", \"message\", \"date\", \"time\", \"capturePhoto\", \"captureVideo\", \"task\", \"taskCompleted\", \"alarm\", \"bookmark\", \"shuffle\", \"audio\", \"update\".\n\nIf no built-in icon is found, the icon will default to using a custom image with the same name, e.g. `heart` will use `UIApplicationShortcutIcon(templateImageName: \"heart\")`.\n\n### Custom Images\n\nCreate an icon using a system-defined image.\n\n\u003e `UIApplicationShortcutIcon(templateImageName:)` -- Create an icon from a custom image. The provided image named will be loaded from the app's bundle and will be masked to conform to the system-defined icon style.\n\nIcons prefixed with `asset:` are passed to `UIApplicationShortcutIcon(templateImageName:)`, e.g. `asset:heart` will use `UIApplicationShortcutIcon(templateImageName: \"heart\")` which will load the image named `heart` from the app's bundle and mask it to conform to the system-defined icon style.\n\n## Hooks\n\nConvenience hooks are exposed with the nested import `expo-quick-actions/hooks`.\n\n```ts\nimport {\n  useQuickActionCallback,\n  useQuickAction,\n} from \"expo-quick-actions/hooks\";\n```\n\n### useQuickActionCallback\n\n\u003e `(callback: (action: Action) =\u003e void) =\u003e void`\n\nA hook that registers a callback that will fire when a quick action is triggered. This is useful for global updates like navigating or analytics.\n\n```tsx\nimport { useQuickActionCallback } from \"expo-quick-actions/hooks\";\n\nfunction Route() {\n  useQuickActionCallback((action) =\u003e {\n    // Do something with the action without explicitly re-rendering the component. This is useful for global updates like navigating or analytics.\n    console.log(\"\u003e\", action);\n  });\n}\n```\n\n### useQuickAction\n\n\u003e `() =\u003e Action | null`\n\nA hook that returns the current quick action. This is useful for updating the UI.\n\n```tsx\nimport { useQuickAction } from \"expo-quick-actions/hooks\";\n\nfunction Route() {\n  // Re-renders the component when the action changes. This is useful for updating the UI.\n  const action = useQuickAction();\n}\n```\n\n## Expo Router\n\nThe philosophy in Expo Router is to treat opening the app from the home screen as linking to \"/\" (index route). In the future, I'd like to account for launching from native APIs like Share Sheet invocations, Siri, Quick Actions, Notifications, etc and linking to a well-known URL convention. This isn't the case today, but I did design around it.\n\nPass `params: { href: \"...\" }` and use a hook in the Layout Route to handle the invocation.\n\nFor example, using the hooks above:\n\n```tsx\n// app/(root)/_layout.tsx\nimport { useEffect } from \"react\";\nimport { Slot } from \"expo-router\";\nimport { useQuickActionRouting, RouterAction } from \"expo-quick-actions/router\";\nimport * as QuickActions from \"expo-quick-actions\";\n\nexport default function Layout() {\n  // Enable linking to the `href` param when a quick action is used.\n  useQuickActionRouting();\n\n  useEffect(() =\u003e {\n    // Now you can configure your quick actions to link places (including externally):\n    QuickActions.setItems\u003cRouterAction\u003e([\n      {\n        title: \"New Chat\",\n        icon: \"compose\",\n        id: \"0\",\n        params: { href: \"/compose\" },\n      },\n      {\n        title: \"Search\",\n        icon: \"search\",\n        id: \"1\",\n        params: { href: \"/search\" },\n      },\n      {\n        title: \"Leave Feedback\",\n        subtitle: \"Please provide feedback before deleting the app\",\n        icon: \"symbol:envelope\",\n        id: \"2\",\n        params: { href: \"mailto:support@myapp.dev\" },\n      },\n    ]);\n  }, []);\n\n  return \u003cSlot /\u003e;\n}\n```\n\nThis can be used with Typed Routes to ensure the `params.href` can only be linked to a valid route within your project.\n\n## Config Plugin\n\nThere's an optional config plugin that you can use to add images and static iOS actions. Static Android actions are not currently supported because they don't support complex intent.\n\n- `androidIcons`: An object of Android icons. The key is the `icon` property of the action. The value can be a string or an object with `foregroundImage` and `backgroundColor` properties. This generates very similar to `android.adaptiveIcon` as the underlying API is very similar. For simple icons, you can use a string value.\n- `iosIcons`: An object of iOS icons. The key is the `icon` property of the action. The value can be a string or an object with `1x`, `2x`, and `3x` properties.\n- `iosActions`: An array of iOS actions. These are static actions that will be available unless you clear them with the dynamic API. The `icon` property resolves the same as in the dynamic API, using `symbol:` and `asset:` prefixes.\n\n**app.json**\n\n```json\n{\n  \"plugins\": [\n    [\n      \"expo-quick-actions\",\n      {\n        \"androidIcons\": {\n          \"shortcut_one\": {\n            \"foregroundImage\": \"./assets/adaptive-icon.png\",\n            \"backgroundColor\": \"#282A35\"\n          },\n          \"shortcut_two\": {\n            \"foregroundImage\": \"./assets/adaptive-star.png\",\n            \"backgroundColor\": \"#ff0000\"\n          },\n          \"shortcut_three\": \"https://evanbacon.dev/pfp.png\"\n        },\n        \"iosIcons\": {\n          \"shortcut_one\": \"./assets/adaptive-icon.png\",\n          \"shortcut_two\": {\n            \"1x\": \"./assets/adaptive-icon.png\"\n          }\n        },\n        \"iosActions\": [\n          {\n            \"id\": \"1\",\n            \"title\": \"Shortcut One\",\n            \"subtitle\": \"Subtitle One\",\n            \"icon\": \"shortcut_one\",\n            \"params\": {\n              \"href\": \"https://evanbacon.dev\"\n            }\n          }\n        ]\n      }\n    ]\n  ]\n}\n```\n\n## iOS Best Practice\n\n### Use 4 Actions\n\nApple recommends using all four spots, utility-based apps like calculators will use less. If you can't think of four spots, then just make the actions deep link to a specific screen in your app.\n\n![four-actions](https://github.com/EvanBacon/expo-quick-actions/assets/9664363/35f371ab-e9ad-414a-8b8b-4ebea827236f)\n\n### Avoid branded icons\n\n**Use SF Symbols**. While you can have custom icons on iOS (and I made it really easy via the Expo Config Plugin), opt towards using SF Symbols instead. This is because Apple injects their own actions (\"Edit Home Screen\", \"Share App\", \"Remove App\") and the icons will look out of place next to them––see the example below. If you absolute must use branded icons, then try to match the stroke-weight of the default icons.\n\nIf you want to use a custom icon, prefer outline icons to filled icons on iOS.\n\n![brand-icons](https://github.com/EvanBacon/expo-quick-actions/assets/9664363/9b33f519-9dae-41ea-8e99-8d39ce53092f)\n\n### Search action\n\niOS apps often **have a \"Search\" shortcut** that opens the app and focuses the search bar. This is a good default shortcut to have. Make it the last item in the list. E.g. Whatsapp, Twitter, Apple Mail, Amazon, Slack.\n\n![search-actions](https://github.com/EvanBacon/expo-quick-actions/assets/9664363/7ebeba53-4124-4f18-81f4-9b2f1d9c9518)\n\nHere's the object you can use to add a basic \"Search\" action:\n\n```js\n{\n  \"id\": \"search\",\n  \"title\": \"Search\",\n  // Built-in icon for search\n  \"icon\": \"search\",\n  // SF Symbol equivalent\n  // \"icon\": \"symbol:magnifyingglass\",\n  \"params\": {\n    // Optional deep link to a search page (must be handled manually with something like Expo Router).\n    \"href\": \"/search\"\n  }\n}\n```\n\n## Android Best Practice\n\n**Use 4 actions** Android sometimes supports more, but I read somewhere in the Google docs that 4 is recommended.\n\n### Use Adaptive Icons\n\nAndroid shortcuts can be saved to the screen, iOS shortcuts cannot. This means that Android shortcuts should be thought of as alternative entry points to your app. The icon and name should reflect that. Because of this, I've made the Expo Config Plugin capable of generating full responsive app icons (as well as simple icons).\n\nFor example, if we want a \"Compose\" action like the one found in Gmail, that can be implemented as follows:\n\nFirst, we'll add the icon and background color in the `app.json`:\n\n```json\n{\n  \"plugins\": [\n    [\n      \"expo-quick-actions\",\n      {\n        \"androidIcons\": {\n          \"shortcut_compose\": {\n            \"foregroundImage\": \"./assets/adaptive-compose.png\",\n            \"backgroundColor\": \"#C84031\"\n          }\n        }\n      }\n    ]\n  ]\n}\n```\n\nSecond, we'll add an image to our project at `./assets/adaptive-compose.png`. This will be the Material design \"create\" icon with about 30% padding on all sides.\n\nNow if we run `npx expo prebuild -p android`, rebuild `npx expo run:android`, we can use the icon from source:\n\n```js\n// Add the compose action\nQuickActions.setItems([\n  {\n    id: \"compose\",\n    icon: \"shortcut_compose\",\n    title: \"Compose\",\n  },\n]);\n```\n\nYou can see the results below, it even has the signature \"wiggle\" when you move the icon around.\n\nhttps://github.com/EvanBacon/expo-quick-actions/assets/9664363/b3fe7608-1700-4247-8687-0c9dc7c6025e\n\n## Troubleshooting\n\n### The icon is a small circle on iOS\n\nThis can happen if the `icon` property is invalid. See how icons are resolved to learn more. If you're using a custom asset then you need to ensure all three scales are added to the asset catalog (default if only a string is passed in the Config Plugin).\n\n---\n\n# App Icon\n\n\u003cimg width=\"358\" alt=\"Screenshot 2024-12-30 at 1 20 47 PM\" src=\"https://github.com/user-attachments/assets/e990ad5e-324f-4a2d-8d9a-1de4993f44a6\" /\u003e\n\nThis package experimentally has support for switching the app icon to align with how quick actions work on Android.\n\n```ts\nimport * as AppIcon from \"expo-quick-actions/icon\";\n```\n\n- `AppIcon.isSupported` a boolean that indicates whether the device supports changing the app icon.\n- `AppIcon.getIcon()` returns a Promise that resolves to the current icon name. This is undefined when the function is not supported in the given runtime (Expo Go, web)\n- `AppIcon.setIcon(iconName)` set the app icon to the given name. This is undefined when the function is not supported in the given runtime (Expo Go, web)\n\n\u003e On Android, changing the icon will close the app.\n\n## App Icon Config Plugin\n\nYou can add icons to change using the config plugin:\n\n```json\n{\n  \"plugins\": [\n    \"expo-quick-actions/icon/plugin\",\n    [\"./path/to/image.png\", \"https://example.com/image.png\"]\n  ]\n}\n```\n\nThese icons will be available as `\"0\"` and `\"1\"` respectively. Alternatively, you can specify the icon name by passing an object:\n\n```json\n{\n  \"plugins\": [\n    \"expo-quick-actions/icon/plugin\",\n    {\n      \"myIcon\": \"./path/to/image.png\"\n    }\n  ]\n}\n```\n\nThis will be available as `\"myIcon\"`.\n\nThis config plugin supports dark mode icons on iOS by using the same config syntax as Expo config:\n\n```json\n{\n  \"plugins\": [\n    \"expo-quick-actions/icon/plugin\",\n    [\n      {\n        \"light\": \"./path/to/light.png\",\n        \"dark\": \"./path/to/dark.png\",\n        \"tinted\": \"./path/to/tinted.png\"\n      }\n    ]\n  ]\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanbacon%2Fexpo-quick-actions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevanbacon%2Fexpo-quick-actions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanbacon%2Fexpo-quick-actions/lists"}