diff --git a/docs/_integration-with-existing-apps-ios.md b/docs/_integration-with-existing-apps-ios.md index 0988e4bb373..e822392efbe 100644 --- a/docs/_integration-with-existing-apps-ios.md +++ b/docs/_integration-with-existing-apps-ios.md @@ -279,7 +279,7 @@ First, we need to extends the `AppDelegate` to inherit from one of the classes p To achieve this, we have to modify the `AppDelegate.h` file and the `AppDelegate.m` files: -1. Open the `AppDelegate.h` files and modify it as it follows (See the official template's [AppDelegate.h](https://github.com/react-native-community/template/blob/0.77-stable/template/ios/HelloWorld/AppDelegate.h) as reference): +1. Open the `AppDelegate.h` files and modify it as it follows (See the official template's [AppDelegate.h](https://github.com/react-native-community/template/blob/0.76-stable/template/ios/HelloWorld/AppDelegate.h) as reference): ```diff title="AppDelegate.h changes" #import @@ -292,7 +292,7 @@ To achieve this, we have to modify the `AppDelegate.h` file and the `AppDelegate @end ``` -2. Open the `AppDelegate.mm` file and modify it as it follows (See the official template's [AppDelegate.mm](https://github.com/react-native-community/template/blob/0.77-stable/template/ios/HelloWorld/AppDelegate.mm) as reference +2. Open the `AppDelegate.mm` file and modify it as it follows (See the official template's [AppDelegate.mm](https://github.com/react-native-community/template/blob/0.76-stable/template/ios/HelloWorld/AppDelegate.mm) as reference ```diff title="AppDelegate.mm" #import "AppDelegate.h" diff --git a/docs/boxshadowvalue.md b/docs/boxshadowvalue.md new file mode 100644 index 00000000000..2be7c611e7e --- /dev/null +++ b/docs/boxshadowvalue.md @@ -0,0 +1,73 @@ +--- +id: boxshadowvalue +title: BoxShadowValue Object Type +--- + +The `BoxShadowValue` object is taken by the [`boxShadow`](./view-style-props.md#boxshadow) style prop. It is comprised of 2-4 lengths, an optional color, and an optional `inset` boolean. These values collectively define the box shadow's color, position, size, and blurriness. + +## Example + +```js +{ + offsetX: 10, + offsetY: -3, + blurRadius: '15px', + spreadDistance: '10px', + color: 'red', + inset: true, +} +``` + +## Keys and values + +### `offsetX` + +The offset on the x-axis. This can be positive or negative. A positive value indicates right and negative indicates left. + +| Type | Optional | +| ---------------- | -------- | +| number \| string | No | + +### `offsetY` + +The offset on the y-axis. This can be positive or negative. A positive value indicates up and negative indicates down. + +| Type | Optional | +| ---------------- | -------- | +| number \| string | No | + +### `blurRadius` + +Represents the radius used in the [Guassian blur](https://en.wikipedia.org/wiki/Gaussian_blur) algorithm. The larger the value the blurrier the shadow is. Only non-negative values are valid. The default is 0. + +| Type | Optional | +| --------------- | -------- | +| numer \| string | Yes | + +### `spreadDistance` + +How much larger or smaller the shadow grows or shrinks. A positive value will grow the shadow, a negative value will shrink the shadow. + +| Type | Optional | +| --------------- | -------- | +| numer \| string | Yes | + +### `color` + +The color of the shadow. The default is `black`. + +| Type | Optional | +| -------------------- | -------- | +| [color](./colors.md) | Yes | + +### `inset` + +Whether the shadow is inset or not. Inset shadows will appear around the inside of the element's border box as opposed to the outside. + +| Type | Optional | +| ------- | -------- | +| boolean | Yes | + +## Used by + +- [`boxShadow`](./view-style-props.md#boxshadow) diff --git a/docs/debugging-native-code.md b/docs/debugging-native-code.md index a39cb908ef6..7595151b0be 100644 --- a/docs/debugging-native-code.md +++ b/docs/debugging-native-code.md @@ -23,6 +23,47 @@ npx react-native log-ios You may also access these through Debug > Open System Log… in the iOS Simulator or by running `adb logcat "*:S" ReactNative:V ReactNativeJS:V` in a terminal while an Android app is running on a device or emulator. +
+**💡 Custom Native Logs** + +If you are writing a Native Module and want to add custom logs to your module for debugging purposes, you can use the following method: + +#### Android (Java/Kotlin) + +In your native module, use the `Log` class to add logs that can be viewed in Logcat: + +```java +import android.util.Log; + +private void log(String message) { + Log.d("YourModuleName", message); +} +``` + +To view these logs in Logcat, use this command, replacing `YourModuleName` with your custom tag: + +```shell +adb logcat "*:S" ReactNative:V ReactNativeJS:V YourModuleName:D +``` + +#### iOS (Objective-C/Swift) + +In your native module, use `NSLog` for custom logs: + +```objective-c +NSLog(@"YourModuleName: %@", message); +``` + +Or, in Swift: + +```swift +print("YourModuleName: \(message)") +``` + +These logs will appear in the Xcode console when running the app. + +
+ ## Debugging in a Native IDE When working with native code, such as when writing native modules, you can launch the app from Android Studio or Xcode and take advantage of the native debugging features (setting up breakpoints, etc.) as you would in case of building a standard native app. diff --git a/docs/dropshadowvalue.md b/docs/dropshadowvalue.md new file mode 100644 index 00000000000..3326641602b --- /dev/null +++ b/docs/dropshadowvalue.md @@ -0,0 +1,55 @@ +--- +id: dropshadowvalue +title: DropShadowValue Object Type +--- + +The `DropShadowValue` object is taken by the [`filter`](./view-style-props.md#filter) style prop for the `dropShadow` function. It is comprised of 2 or 3 lengths and an optional color. These values collectively define the drop shadow's color, position, and blurriness. + +## Example + +```js +{ + offsetX: 10, + offsetY: -3, + standardDeviation: '15px', + color: 'blue', +} +``` + +## Keys and values + +### `offsetX` + +The offset on the x-axis. This can be positive or negative. A positive value indicates right and negative indicates left. + +| Type | Optional | +| ---------------- | -------- | +| number \| string | No | + +### `offsetY` + +The offset on the y-axis. This can be positive or negative. A positive value indicates up and negative indicates down. + +| Type | Optional | +| ---------------- | -------- | +| number \| string | No | + +### `standardDeviation` + +Represents the standard deviation used in the [Guassian blur](https://en.wikipedia.org/wiki/Gaussian_blur) algorithm. The larger the value the blurrier the shadow is. Only non-negative values are valid. The default is 0. + +| Type | Optional | +| --------------- | -------- | +| numer \| string | Yes | + +### `color` + +The color of the shadow. The default is `black`. + +| Type | Optional | +| -------------------- | -------- | +| [color](./colors.md) | Yes | + +## Used by + +- [`filter`](./view-style-props.md#filter) diff --git a/docs/fabric-native-components-android.md b/docs/fabric-native-components-android.md index 2196c6eef84..bfc99d06f16 100644 --- a/docs/fabric-native-components-android.md +++ b/docs/fabric-native-components-android.md @@ -381,7 +381,7 @@ public class ReactWebViewPackage extends BaseReactPackage { public ReactModuleInfoProvider getReactModuleInfoProvider() { return new ReactModuleInfoProvider() { @Override - public Map get() { + public Map getReactModuleInfos() { Map map = new HashMap<>(); map.put(ReactWebViewManager.REACT_CLASS, new ReactModuleInfo( ReactWebViewManager.REACT_CLASS, // name diff --git a/docs/fabric-native-components-ios.md b/docs/fabric-native-components-ios.md index b99a885956e..85bdef8ab97 100644 --- a/docs/fabric-native-components-ios.md +++ b/docs/fabric-native-components-ios.md @@ -60,14 +60,12 @@ open Demo.xcworkspace Podfile ... Demo -├── AppDelegate.h -├── AppDelegate.mm +├── AppDelegate.swift ... // highlight-start ├── RCTWebView.h -├── RCTWebView.mm +└── RCTWebView.mm // highlight-end -└── main.m ``` After creating the header file and the implementation file, you can start implementing them. diff --git a/docs/hermes.md b/docs/hermes.md index 147c998cd63..d40347dd115 100644 --- a/docs/hermes.md +++ b/docs/hermes.md @@ -15,7 +15,7 @@ Hermes is used by default by React Native and no additional configuration is req ## Bundled Hermes React Native comes with a **bundled version** of Hermes. -We building a version of Hermes for you whenever we release a new version of React Native. This will make sure you're consuming a version of Hermes which is fully compatible with the version of React Native you're using. +We are building a version of Hermes for you whenever we release a new version of React Native. This will make sure you're consuming a version of Hermes which is fully compatible with the version of React Native you're using. This change is fully transparent to users of React Native. You can still disable Hermes using the command described in this page. You can [read more about the technical implementation on this page](/architecture/bundled-hermes). diff --git a/docs/images.md b/docs/images.md index dfdf182c145..0fef5961073 100644 --- a/docs/images.md +++ b/docs/images.md @@ -173,6 +173,38 @@ In some cases you might only want to display an image if it is already in the lo See [CameraRoll](https://github.com/react-native-community/react-native-cameraroll) for an example of using local resources that are outside of `Images.xcassets`. +### Drawable resources + +Android supports loading [drawable resources](https://developer.android.com/guide/topics/resources/drawable-resource) via the `xml` file type. This means you can use [vector drawables](https://developer.android.com/develop/ui/views/graphics/vector-drawable-resources) for rendering icons or [shape drawables](https://developer.android.com/guide/topics/resources/drawable-resource#Shape) for, well, drawing shapes! You can import and use these resource types the same as any other [static resource](#static-image-resources) or [hybrid resource](#images-from-hybrid-apps-resources). You have to specify image dimensions manually. + +For static drawables that live alongside your JS code, use the `require` or `import` syntax (both work the same): + +```tsx + +``` + +For drawables included in the Android drawable folder (i.e. `res/drawable`), use the resource name without the extension: + +```tsx + +``` + +The one key difference between drawable resources and other image types is that the asset must be referenced at compile-time of the Android application as Android needs to run the [Android Asset Packaging Tool (AAPT)](https://developer.android.com/tools/aapt2) to package the asset. Binary XML, the file format AAPT creates, cannot be loaded over the network by Metro. If you change the directory or name of an asset, you will need to rebuild the Android application each time. + +#### Creating XML drawable resources + +Android provides comprehensive documentation on each of the supported drawable resource types in its [Drawable resources](https://developer.android.com/guide/topics/resources/drawable-resource) guide, along with examples of raw XML files. You can utilize tools from Android Studio like the [Vector Asset Studio](https://developer.android.com/studio/write/vector-asset-studio) to create vector drawables from Scalable Vector Graphic (SVG) and Adobe Photoshop Document (PSD) files. + +:::info +You should try to avoid referencing other resources in the XML file you create if you want to treat your XML file as a static image resource (i.e. with an `import` or `require` statement). If you wish to utilize references to other drawables or attributes, like [color state lists](https://developer.android.com/guide/topics/resources/color-list-resource) or [dimension resources](https://developer.android.com/guide/topics/resources/more-resources#Dimension), you should include your drawable as a [hybrid resource](#images-from-hybrid-apps-resources) and import it by name. +::: + ### Best Camera Roll Image iOS saves multiple sizes for the same image in your Camera Roll, it is very important to pick the one that's as close as possible for performance reasons. You wouldn't want to use the full quality 3264x2448 image as source when displaying a 200x200 thumbnail. If there's an exact match, React Native will pick it, otherwise it's going to use the first one that's at least 50% bigger in order to avoid blur when resizing from a close size. All of this is done by default so you don't have to worry about writing the tedious (and error prone) code to do it yourself. diff --git a/docs/layout-props.md b/docs/layout-props.md index 5c973c63a9c..91e0a394990 100644 --- a/docs/layout-props.md +++ b/docs/layout-props.md @@ -513,6 +513,16 @@ See https://developer.mozilla.org/en-US/docs/Web/CSS/bottom for more details of --- +### `boxSizing` + +`boxSizing` defines how the element's various sizing props (`width`, `height`, `minWidth`, `minHeight`, etc.) are computed. If `boxSizing` is `border-box`, these sizes apply to the border box of the element. If it is `content-box`, they apply to the content box of the element. The default value is `border-box`. The [web documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing) is a good source of information if you wish to learn more about how this prop works. + +| Type | Required | +| --------------------------------- | -------- | +| enum('border-box', 'content-box') | No | + +--- + ### `columnGap` `columnGap` works like `column-gap` in CSS. Only pixel units are supported in React Native. See https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap for more details. diff --git a/docs/linking.md b/docs/linking.md index 9c8f449f2ed..657cf1927ee 100644 --- a/docs/linking.md +++ b/docs/linking.md @@ -13,7 +13,7 @@ In addition to `https`, you're likely also familiar with the `mailto` scheme. Wh Like using the mailto scheme, it's possible to link to other applications by using custom url schemes. For example, when you get a **Magic Link** email from Slack, the **Launch Slack** button is an anchor tag with an href that looks something like: `slack://secret/magic-login/other-secret`. Like with Slack, you can tell the operating system that you want to handle a custom scheme. When the Slack app opens, it receives the URL that was used to open it. This is often referred to as deep linking. Read more about how to [get the deep link](#get-the-deep-link) into your app. -Custom URL scheme isn't the only way to open your application on mobile. You don't want to use a custom URL scheme in links in the email because then the links would be broken on desktop. Instead, you want to use a regular `https` links such as `https://www.myapp.io/records/1234546`. and on mobile you want that link open your app. Android calls it **Deep Links** (Universal Links - iOS). +A custom URL scheme isn't the only way to open your application on mobile. For example, if you want to email someone a link to be opened on mobile, using a custom URL scheme isn't ideal because the user might open the email on a desktop, where the link wouldn't work. Instead, you should use standard `https` links, such as `https://www.myapp.io/records/1234546`. On mobile, these links can be configured to open your app. On Android, this feature is called **Deep Links**, while on iOS, it is known as **Universal Links**. ### Built-in URL Schemes diff --git a/docs/modal.md b/docs/modal.md index 3b438154771..f401e499031 100644 --- a/docs/modal.md +++ b/docs/modal.md @@ -146,6 +146,16 @@ The `hardwareAccelerated` prop controls whether to force hardware acceleration f --- +### `navigationBarTranslucent`
Android
+ +The `navigationBarTranslucent` prop determines whether your modal should go under the system navigation bar. However, `statusBarTranslucent` also needs to be set to `true` to make navigation bar translucent. + +| Type | Default | +| ---- | ------- | +| bool | `false` | + +--- + ### `onDismiss`
iOS
The `onDismiss` prop allows passing a function that will be called once the modal has been dismissed. diff --git a/docs/shadow-props.md b/docs/shadow-props.md index 768d190e058..cbff04e435c 100644 --- a/docs/shadow-props.md +++ b/docs/shadow-props.md @@ -218,8 +218,32 @@ export default App; # Reference +There are 3 sets of shadow APIs in React Native: + +- `boxShadow`: A View style prop and a spec-compliant implementation of the [web style prop of the same name](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow). +- `dropShadow`: A specific filter function available as part of the [`filter`](./view-style-props#filter) View style prop. +- Various `shadow` props (`shadowColor`, `shadowOffset`, `shadowOpacity`, `shadowRadius`): These map directly to their native counterparts exposed by the platform-level APIs. + +The difference between `dropShadow` and `boxShadow` are as follows: + +- `dropShadow` exists as part of `filter`, whereas `boxShadow` is a standalone style prop. +- `dropShadow` is an alpha mask, so only pixels with a positive alpha value will "cast" a shadow. `boxShadow` will cast around the border box of the element no matter it's contents (unless it is inset). +- `dropShadow` is only available on Android, `boxShadow` is available on iOS and Android. +- `dropShadow` cannot be inset like `boxShadow`. +- `dropShadow` does not have the `spreadDistance` argument like `boxShadow`. + +Both `boxShadow` and `dropShadow` are generally more capable than the `shadow` props. The `shadow` props, however, map to native platform-level APIs, so if you only need a straightforward shadow these props are recommended. Note that only `shadowColor` works on both Android and iOS, all other `shadow` props only work on iOS. + ## Props +### `boxShadow` + +See [View Style Props](./view-style-props#boxshadow) for documentation. + +### `dropShadow`
Android
+ +See [View Style Props](./view-style-props#filter) for documentation. + ### `shadowColor` Sets the drop shadow color. diff --git a/docs/textinput.md b/docs/textinput.md index 158ce9691de..dedef925549 100644 --- a/docs/textinput.md +++ b/docs/textinput.md @@ -1048,6 +1048,16 @@ Set line break strategy on iOS 14+. Possible values are `none`, `standard`, `han | ----------------------------------------------------------- | -------- | | enum(`'none'`, `'standard'`, `'hangul-word'`, `'push-out'`) | `'none'` | +--- + +### `disableKeyboardShortcuts`
iOS
+ +If `true`, the keyboard shortcuts (undo/redo and copy buttons) are disabled. The default value is `false`. + +| Type | +| ---- | +| bool | + ## Methods ### `.focus()` diff --git a/docs/the-new-architecture/pure-cxx-modules.md b/docs/the-new-architecture/pure-cxx-modules.md index dfef66f7293..d2df47412f2 100644 --- a/docs/the-new-architecture/pure-cxx-modules.md +++ b/docs/the-new-architecture/pure-cxx-modules.md @@ -18,15 +18,6 @@ The rest of this guide assume that you have created your application running the npx @react-native-community/cli@latest init SampleApp --version 0.76.0 ``` -:::danger -We are aware of some issues that are preventing pure C++ Modules to work well on Android, when developed locally in the app. -Pure C++ modules consumed as external libraries works well on Android. - -These issues started from version 0.76.2 and are still persisting in version 0.76.5. - -We found the root cause for the issue (see [#48298](https://github.com/facebook/react-native/issues/48298) and [#48340](https://github.com/facebook/react-native/pull/48340)), and we are aiming to fix in 0.76.6. -::: - ## 1. Create the JS specs Pure C++ Turbo Native Modules are Turbo Native Modules. They need a specification file (also called spec file) so that Codegen can create the scaffolding code for us. The specification file is also what we use to access the Turbo Native Module in JS. diff --git a/docs/turbo-native-modules-android.md b/docs/turbo-native-modules-android.md index e77433a877c..f910506dcf9 100644 --- a/docs/turbo-native-modules-android.md +++ b/docs/turbo-native-modules-android.md @@ -139,7 +139,7 @@ public class NativeLocalStoragePackage extends BaseReactPackage { public ReactModuleInfoProvider getReactModuleInfoProvider() { return new ReactModuleInfoProvider() { @Override - public Map get() { + public Map getReactModuleInfos() { Map map = new HashMap<>(); map.put(NativeLocalStorageModule.NAME, new ReactModuleInfo( NativeLocalStorageModule.NAME, // name diff --git a/docs/view-style-props.md b/docs/view-style-props.md index 7e3ea0f8dee..e292e3e6e5c 100644 --- a/docs/view-style-props.md +++ b/docs/view-style-props.md @@ -289,6 +289,21 @@ If the rounded border is not visible, try applying `overflow: 'hidden'` as well. | ------ | | number | +### `boxShadow` + +:::note +`boxShadow` is only available on the [New Architecture](/architecture/landing-page). Outset shadows are only supported on **Android 9+**. Inset shadows are only supported on **Android 10+**. +::: + +Adds a shadow effect to an element, with the ability to control the position, color, size, and blurriness of the shadow. This shadow either appears around the outside or inside of the border box of the element, depending on whether or not the shadow is _inset_. This is a spec-compliant implementation of the [web style prop of the same name](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow). Read more about all the arguments available in the [BoxShadowValue](./boxshadowvalue) documentation. + +These shadows can be composed together so that a single `boxShadow` can be comprised of multiple different shadows. + +`boxShadow` takes either a string which mimics the [web syntax](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow#syntax) or an array of [BoxShadowValue](./boxshadowvalue) objects. +| Type | +| --------------------------- | +| array of BoxShadowValue ojects \| string | + ### `cursor`
iOS
On iOS 17+, Setting to `pointer` allows hover effects when a pointer (such as a trackpad or stylus on iOS, or the users' gaze on visionOS) is over the view. @@ -309,6 +324,47 @@ Sets the elevation of a view, using Android's underlying [elevation API](https:/ --- +### `filter` + +:::note +`filter` is only available on the [New Architecture](/architecture/landing-page) +::: + +Adds a graphical filter to the `View`. This filter is comprised of any number of _filter functions_, which each represent some atomic change to the graphical composition of the `View`. The complete list of valid filter functions is defined below. `filter` will apply to descendants of the `View` as well as the `View` itself. `filter` implies `overflow: hidden`, so descendants will be clipped to fit the bounds of the `View`. + +The following filter functions work across all platforms: + +- `brightness`: Changes the brightness of the `View`. Takes a non-negative number or percentage. +- `opacity`: Changes the opacity, or alpha, of the `View`. Takes a non-negative number or percentage. + +:::note +Due to issues with performance and spec compliance, these are the only two filter functions available on iOS. There are plans to explore some potential workarounds using SwiftUI instead of UIKit for this implementation. +::: + +
Android
+ +The following filter functions work on Android only: + +- `blur`: Blurs the `View` with a [Guassian blur](https://en.wikipedia.org/wiki/Gaussian_blur), where the specified length represents the radius used in the blurring algorithm. Any non-negative DIP value is valid (no percents). The larger the value, the blurrier the result. +- `contrast`: Changes the contrast of the `View`. Takes a non-negative number or percentage. +- `dropShadow`: Adds a shadow around the alpha mask of the `View` (only non-zero alpha pixels in the `View` will cast a shadow). Takes an optional color representing the shadow color, and 2 or 3 lengths. If 2 lengths are specified they are interperted as `offsetX` and `offsetY` which will translate the shadow in the X and Y dimensions respectfully. If a 3rd length is given it is interpreted as the standard deviation of the Guassian blur used on the shadow - so a larger value will blur the shadow more. Read more about the arguments in [DropShadowValue](./dropshadowvalue.md). +- `grayscale`: Converts the `View` to [grayscale](https://en.wikipedia.org/wiki/Grayscale) by the specified amount. Takes a non-negative number or percentage, where `1` or `100%` represents complete grayscale. +- `hueRotate`: Changes the [hue](https://en.wikipedia.org/wiki/Hue) of the View. The argument of this function defines the angle of a color wheel around which the hue will be rotated, so e.g., `360deg` would have no effect. This angle can have either `deg` or `rad` units. +- `invert`: Inverts the colors in the `View`. Takes a non-negative number or percentage, where `1` or `100%` represents complete inversion. +- `sepia`: Converts the `View` to [sepia](). Takes a non-negative number or percentage, where `1` or `100%` represents complete sepia. +- `saturate`: Changes the [saturation](https://en.wikipedia.org/wiki/Colorfulness) of the `View`. Takes a non-negative number or percentage. + +:::note +`blur` and `dropShadow` are only supported on **Android 12+** +::: + +`filter` takes either an array of objects comprising of the above filter functions or a string which mimics the [web syntax](https://developer.mozilla.org/en-US/docs/Web/CSS/filter#syntax). +| Type | +| ------ | +| array of objects: `{brightness: number\|string}`, `{opacity: number\|string}`, `{blur: number\|string}`, `{contrast: number\|string}`, `{dropShadow: DropShadowValue\|string}`, `{grayscale: number\|string}`, `{hueRotate: number\|string}`, `{invert: number\|string}`, `{sepia: number\|string}`, `{saturate: number\|string}` or string| + +--- + ### `opacity` | Type | diff --git a/docs/view.md b/docs/view.md index 099c0080e87..e39540d43e0 100644 --- a/docs/view.md +++ b/docs/view.md @@ -674,23 +674,23 @@ Controls whether the `View` can be the target of touch events. - `'none'`: The View is never the target of touch events. - `'box-none'`: The View is never the target of touch events but its subviews can be. It behaves like if the view had the following classes in CSS: -``` +```css .box-none { - pointer-events: none; + pointer-events: none; } .box-none * { - pointer-events: auto; + pointer-events: auto; } ``` - `'box-only'`: The view can be the target of touch events but its subviews cannot be. It behaves like if the view had the following classes in CSS: -``` +```css .box-only { - pointer-events: auto; + pointer-events: auto; } .box-only * { - pointer-events: none; + pointer-events: none; } ``` diff --git a/package.json b/package.json index 95b77b24af3..ce3f0ffc7bc 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "netlify-plugin-cache": "^1.0.3", "prettier": "^3.4.2", "pretty-quick": "^4.0.0", - "yarn-deduplicate": "^5.0.0" + "yarn-deduplicate": "^6.0.2" }, "resolutions": { "trim": "^1.0.1", diff --git a/website/blog/2025-01-21-version-0.77.md b/website/blog/2025-01-21-version-0.77.md new file mode 100644 index 00000000000..277669ba4e2 --- /dev/null +++ b/website/blog/2025-01-21-version-0.77.md @@ -0,0 +1,395 @@ +--- +title: 'React Native 0.77 - New Styling Features, Android’s 16KB page support, Swift Template' +authors: [vonovak, mazen, blakef, robhogan] +tags: [engineering] +date: 2025-01-21 +--- + +Today we are excited to release React Native 0.77! + +This release ships several features: new styling capabilities such as support for `display: contents`, `boxSizing`, `mixBlendMode`, and `outline`-related properties to provide a more powerful layout options; Android 16KB page support to be compatible with the newer Android devices. We are also modernizing the community template by migrating it to Swift, while continuing to support and maintain compatibility with Objective-C for developers who prefer it. + + + +### Highlights + +- [New CSS Features for better layouts, sizing and blending](#new-css-features-for-better-layouts-sizing-and-blending) +- [Android version 15 support & 16KB page support](#android-version-15-support--16kb-page-support) +- [Community CLI and Template Updates](#community-cli-and-template-updates) + +### Breaking Changes + +- [Removal of `console.log()` streaming in Metro](#removal-of-consolelog-streaming-in-metro) + +## Highlights + +### New CSS Features for better layouts, sizing and blending + +React Native 0.77 furthers our goal of aligning React Native with the web. We've added support for new CSS properties to give you more control over your app's layout, sizing, and blending. These changes can help simplify complex layouts, add texture, and make your app more accessible. + +:::info +All these new features are available only for the [New Architecture](/blog/2024/10/23/the-new-architecture-is-here#how-to-upgrade). +::: + +#### Simpler layouts with `display: contents` + +The [`display: contents`](https://developer.mozilla.org/en-US/docs/Web/CSS/display#display_contents) prop allows an element to disappear from the layout structure while its children are still rendered as if they were direct children of the parent element. It can be useful for styling purposes where you want to apply styles to child elements without affecting the layout, when building wrapper components which must handle events, or if you need to interact with the ShadowTree. + +Technically speaking, `display: contents` renders an element without generating a layout box, but it preserves the layout boxes of the element’s children. The element with `display: contents` is effectively flattened out of the view hierarchy. + +Let’s have a look at this example where we want to display an alert when a widget is pressed. We have a red `Widget` inside of a container view: + +```jsx title="Container.jsx" +function Container() { + return ( + + + + ); +} +``` + +![display contents - setup](../static/blog/assets/0.77-display-contents-1.png) + +Now, let's build a new `Alerting` wrapper component, with the goal of alerting the user when a component beneath it is pressed, using [experimental pointer events](/blog/2022/12/13/pointer-events-in-react-native). For clarity, the background of this component is made blue. That might look something like the component below: + +```jsx title="Container.jsx" +function Alerting({children}) { + return ( + alert('Hello World!')}> + {children} + +} + +function Container() { + return ( + + // highlight-next-line + + + + + ); +} +``` + +This doesn’t do quite what we want it to. `Alerting` adds a new layout box, with its own bounds, separate from the child `Widget`. Depending on the styling of the element it is wrapping, this may result in significant visual and functional changes. In this example, the blue background responds to taps with an alert when we want for only the red "Hello World" box to alert when tapped. + +![before display contents](../static/blog/assets/0.77-display-contents-2.gif) + +If we try this again, while setting `display: contents` on the `View` wrapper of `Alerting`, we only see alerts when the user presses within the original bounds of the `Widget`. This is because `Alerting` no longer adds its own box, but can still observe the pointer events bubbled from `Widget`. + +```jsx title="Container.jsx" +function Alerting({children}) { + return ( + alert('Hello World!')}> + {children} + + ); +} + +// ... function Container ... +``` + +![after display contents](../static/blog/assets/0.77-display-contents-3.gif) + +#### Box sizing + +The `boxSizing` prop defines how the element's various sizing props (`width`, `height`, `minWidth`, `minHeight`, etc.) are computed. If `boxSizing` is `border-box`, these sizes apply to the border box of the element. If it is `content-box` they apply to the content box of the element. The default value is `border-box`, this is different from the default value on the web. The [web documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing) is a good source of information if you wish to learn more about how this prop works. + +:::warning +`border-box` has been the default forever at this point, and has been the only `boxSizing` value up until we added `content-box`. Changing the default would have been a breaking change that would suddenly break several layouts. We decided to keep `border-box` as default value to ensure backward compatibility. +::: + +To understand the difference between `border-box` and `content-box`, have a look at these example, where both `View`s have `padding: 20` and `borderWidth: 10`. When using `border-box`, we consider border and padding for the sizing; when using `content-box`, we consider only the content for the sizing. + +![after display contents](../static/blog/assets/0.77-border-box.png) + +#### CSS mixBlendMode + +The `mixBlendMode` prop lets you control how an element blends its colors with the other elements in its **stacking context**. Check out the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) for a full overview of each blending function. + +To help have more granular control about what is blending together, we also added the `isolation` property. Setting `isolation: isolate` on a `View` will force it to form a **stacking context**. So, you can set this on some ancestor `View` to ensure that some descendent `View` with `mixBlendMode` does not blend beyond the **isolated** `View`. + +##### mixBlendMode Values + +- `normal`: The element is drawn on top of its background without blending. +- `multiply`: The source color is multiplied by the destination color and replaces the destination. +- `screen`: Multiplies the complements of the backdrop and source color values, then complements the result. +- `overlay`: Multiplies or screens the colors, depending on the backdrop color value. +- `darken`: Selects the darker of the backdrop and source colors. +- `lighten`: Selects the lighter of the backdrop and source colors. + +- `color-dodge`: Brightens the backdrop color to reflect the source color. Painting with black produces no changes. + +- `color-burn`: Darkens the backdrop color to reflect the source color. Painting with white produces no change. +- `hard-light`: Multiplies or screens the colors, depending on the source color value. The effect is similar to shining a harsh spotlight on the backdrop. +- `soft-light`: Darkens or lightens the colors, depending on the source color value. The effect is similar to shining a diffused spotlight on the backdrop. +- `difference`: Subtracts the darker of the two constituent colors from the lighter color. +- `exclusion`: Produces an effect similar to that of the Difference mode but lower in contrast. +- `hue`: Creates a color with the hue of the source color and the saturation and luminosity of the backdrop color. +- `saturation`: Creates a color with the saturation of the source color and the hue and luminosity of the backdrop color. +- `color`: Creates a color with the hue and saturation of the source color and the luminosity of the backdrop color. This preserves the gray levels of the backdrop and is useful for coloring monochrome images or tinting color images. +- `luminosity`: Creates a color with the luminosity of the source color and the hue and saturation of the backdrop color. This produces an inverse effect to that of the Color mode. + +![blend mode](../static/blog/assets/0.77-blend-mode.png) + +#### Outline props + +We’ve also introduced `outlineWidth`, `outlineStyle`, `outlineSpread` and `outlineColor`. These outline props work very similar to the respective `border` props, but it is rendered around the **border box** as opposed to around the **padding box**. These props allow to highlight elements by drawing their outline without affecting their layout. + +Check out the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/outline) for more details. + +![outline props](../static/blog/assets/0.77-outline-props.png) + +### Android version 15 support & 16KB page support + +#### Forced edge-to-edge on Android 15 + +We’ve already done some work to support Android 15 on the prior release. One of the noticeable changes in Android 15 is forced edge-to-edge display when you build apps with `targetSdk` 35. + +If you have not looked into this yet, please refer to our prior [recommendation](https://github.com/react-native-community/discussions-and-proposals/discussions/827) on how this should be handled as ignoring this can potentially break your UI in the app. + +:::note +If you are using the [`react-native-safe-area-context`](https://www.npmjs.com/package/react-native-safe-area-context) in your app, the library is already handling the forced edge-to-edge for you. +::: + +#### 16 KB page size support for Android + +Android 15 introduces support for 16KB memory page size enabling [performance improvements](https://developer.android.com/guide/practices/page-sizes#benefits) for apps and more, but making previous 4KB-based apps potentially incompatible on future devices; it's currently an opt-in feature for developers to test on select devices to prepare for 16 KB page size being the OS default. + +With the 0.77 release, React Native is ready to fully support 16 KB page size and developers will be able to test and ship apps for 16 KB devices using it. + +Please refer to [the official Android Developers site](https://developer.android.com/guide/practices/page-sizes) for further information on 16 KB support. + +### Community CLI and Template Updates + +#### Community CLI: react-native init deprecation + +This version fully completes the deprecation of the `react-native init` command that was [introduced in React Native 0.75](/blog/2024/08/12/release-0.75#sunsetting-react-native-init). + +As a reminder, you won’t be able to use the `react-native init` command anymore, but you’ll have to either: + +- [Use a framework](/blog/2024/06/25/use-a-framework-to-build-react-native-apps) such as Expo, with its own dedicated command to create a new project: `npx create-expo-app` +- Invoke the Community CLI directly with `npx @react-native-community/cli init` + +#### Community CLI: Removal of "run on iOS/Android" key handlers from Metro + +In this version, we removed the ‘a’ and ‘i’ keyboard shortcuts from Metro. Those shortcuts were used to invoke the `run-android` & `run-ios` community CLI commands. +Those keyboard shortcuts provided worse developer experience and were rarely used. Moreover, we believe that frameworks are better suited to orchestrate the terminal outputs. + +You can read more about this change [in this dedicated post](https://github.com/react-native-community/discussions-and-proposals/discussions/821). + +#### Community Template: Swift as programming language for iOS apps + +:::info +Projects using Expo should not be affected by this change. +::: + +This change let us slim down the community template by replacing three files (`main.m`, `AppDelegate.h` and `AppDelegate.mm`) with a single, new [`AppDelegate.swift`](https://github.com/react-native-community/template/blob/main/template/ios/HelloWorld/AppDelegate.swift). + +This is technically a breaking change: you’ll see the change from Objective-C to Swift in the upgrade helper like this: + +![Swift Upgrade Helper](../static/blog/assets/0.77-swift-upgrade-helper.png) + +You don’t have to migrate to Swift: the Objective-C++ variant of the iOS community template is still supported (note that you still need to integrate the [`RCTAppDependencyProvider`](#rctappdependencyprovider)). New projects will be generated by using Swift as the iOS app language, although you can always migrate back to Objective-C if you need to. + +##### Limitations + +If your app has some local modules that are written in C++, you would not be able to register them in Swift as shown in [this guide](/docs/next/the-new-architecture/pure-cxx-modules#3-registering-the-cxx-turbo-native-module-in-your-app). + +If your app falls in this category, please skip the migration of the AppDelegate to Swift, and keep using Objective-C++ for your app. + +React Native core is mostly developed using C++ to encourage code sharing between iOS and Android and other platforms. The interoperability between Swift and C++ is not mature nor stable, yet. We are looking into ways to fill this gap and let you migrate to Swift too. + +##### RCTAppDependencyProvider + +React Native 0.77 slightly changes how the app loads third party dependencies. This is a new line in the community template that, if missed, can cause some runtime issues. Make sure to add it to your app. + +The equivalent Objective-C lines are the following: + +```objc title="AppDelegate.mm" +#import "AppDelegate.h" + +#import +// highlight-next-line +#import + + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @""; + // highlight-next-line + self.dependencyProvider = [RCTAppDependencyProvider new]; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = @{}; + + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +// remaining of the AppDelegate + +``` + +## Breaking Changes + +### Removal of `console.log()` streaming in Metro + +We want every aspect of React Native debugging to behave reliably and to match the functionality of modern browser tooling. To meet this quality bar, log forwarding via Metro, originally deprecated in 0.76, is removed in 0.77. + +This integration relied on a custom approach to communicate with the debugging target on device. With this change, we are moving exclusively to the Chrome DevTools Protocol (CDP). + +- To view JS logs, please use [React Native DevTools](/docs/react-native-devtools) and its fully featured Console panel — supporting log filtering, rich object inspection, Live Expressions, and more. +- You can also connect VS Code as a CDP debugger, via third party extensions such as [Expo Tools](https://github.com/expo/vscode-expo) and [Radon IDE](https://ide.swmansion.com/). + - Please note that these integrations are not directly supported by the React team. However, we are working on first party VS Code support in 2025. +- Expo continues to offer log streaming in Expo CLI. + +For more info, see [_Why are JavaScript logs leaving Metro?_](https://github.com/react-native-community/discussions-and-proposals/discussions/819#:~:text=Why%20are%20JavaScript%20logs%20leaving%20Metro%3F) + +### Other Breaking Changes + +#### General + +- Animation + - Native looping animation do not send a React state update every time the loop ends. +- Layout + - `position` of sticky headers on `ScrollView` will now be taken into account. + - Absolute positioning is now behaving in a more compliant way +- JS Modules: + - Remove `ReactFabricInternals` module + - This is not going to be accessible anymore +- Native Modules + - `NativeModules` object can now be used to load turbomodules in JS . + - This improves compatibility between Native Modules and Turbo Native Modules +- Packages + - dev-middleware: Frameworks should specify `serverBaseUrl` relative to the middleware host +- API Changes: + - Removed type for `useConcurrentRoot` from `AppRegistry`, as it was already ignored + - Removed `refs` property from `NativeMethods` TypeScript definition. +- UX Changes: + - Remove "run on iOS" and "run on Android" from the dev server key commands + +#### Android + +- Kotlin + - This is the first version of React Native that builds against Kotlin 2.0.21. You can read more about the changes coming with Kotlin 2.0 on the [language release notes](https://kotlinlang.org/docs/whatsnew2020.html). +- API Changes: + - Nullability: + - Non-primitive getters in `ReadableArray` are now correctly typed as optional + - Make `ReactHost.createSurface()` method non nullable + - Renamed: + - `DevSupportManagerBase.getCurrentContext()` to `DevSupportManagerBase.getCurrentReactContext()` + +Additionally, several APIs have been removed or restricted in visibility, so they can’t be accessed anymore. Those APIs were internal and not needed to React Native developers directly. You can find the full list below: + +
+List of Removed Android APIs: + +The following packages are now internal and can’t be accessed anymore: + +- `com.facebook.react.views.progressbar` +- `com.facebook.react.views.safeareaview` +- `com.facebook.react.modules.accessibilityinfo` +- `com.facebook.react.modules.appstate` +- `com.facebook.react.modules.clipboard` +- `com.facebook.react.modules.devmodule` +- `com.facebook.react.modules.reactdevtoolssettings` +- `com.facebook.react.views.unimplementedview` + +The following classes are now either internal or have been removed, so can’t be accessed anymore: + +- `BackHandler.removeEventListener` +- `BaseViewManagerInterface` +- `BindingImpl` +- `CompositeReactPackage` +- `DebugOverlayTags` +- Method `create()` from `DefaultDevSupportManagerFactory` +- `DevToolsReactPerfLogger` +- `FabricComponents` +- `ImageStoreManager` +- `InteropModuleRegistry` +- `NativeModulePerfLogger` +- `NoopPrinter` +- `NotThreadSafeViewHierarchyUpdateDebugListener` +- `OkHttpCallUtil` +- `PrinterHolder` +- `Printer` +- `ReactDebugOverlayTags` +- `ReactNativeFlipper` +- `ReactViewBackgroundManager` +- `ReactViewGroup.getBackgroundColor()` +- `ReactVirtualTextShadowNode` +- `ReactVirtualTextViewManager` +- `SimpleSettableFuture` +- `SwipeRefreshLayoutManager` +- `TaskCompletionSource` +- Parameter `jsBundleLoader` from DefaultReactHost.getDefaultReactHost() +
+ +#### iOS + +- API Changes + - Removed + - `RCTConstants.RCTGetMemoryPressureUnloadLevel` + - `partialBatchDidFlush` + - `RCTRuntimeExecutor` + - `UseNativeViewConfigsInBridgelessMode` + - Replaced by a proper feature flag + - `UseTurboModuleInteropForAllTurboModules` + - Interop layer is always on for TMs + - Changed + - Replace uses of `CGColorRef` with `UIColor` +- `RCTAppDelegate` now requires to use the `RCTDependencyProvider` to load third party dependencies +- CocoaPods sets C++ version for all the 3rd party dependencies to avoid compilation issues. + +
+**React 19?** + +React 19 was released the 6th of December 2024. +At the time, we already cut the branch for React Native 0.77 and we already released three RCs for React Native 0.77. +It was too late in the release of React Native 0.77 to introduce React 19 in this release. + +React 19 will be shipped in React Native 0.78, and we already cut the branch for this version. You can try it by creating a new app with the command: + +```no-syntax +npx @react-native-community/cli init YourReact19App --version 0.78.0-rc.0 +``` + +
+ +## Acknowledgements + +React Native 0.77 contains over **1061** commits from **161** contributors. Thanks for all your hard work! + +Thanks to all the additional authors that worked on documenting features in this release post: + +- [Jakub Piasecki](https://github.com/j-piasecki) for contributing to the `display: contents` feature +- [Nick Gerleman](https://github.com/NickGerleman), [Joe Vilches](https://github.com/joevilches) and [Jorge Cabiedes Acosta](https://github.com/jorge-cab) for releasing the new styling features +- [Alan Lee](https://github.com/alanleedev) for the Android 16Kb page support content +- [Riccardo Cipolleschi](https://github.com/cipolleschi) and [Oskar Kwaśniewski](https://github.com/okwasniewski) for supporting the migration of the template to Swift +- [Nicola Corti](https://github.com/cortinico) for the `react-native init` deprecation cycle content +- [Alex Hunt](https://github.com/huntie) for the content on the removal of `console.log` from metro + +### Upgrade to 0.77 + +Please use the [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) to view code changes between React Native versions for existing projects, in addition to the Upgrading docs. + +To create a new project: + +```sh +npx @react-native-community/cli@latest init MyProject --version latest +``` + +If you use Expo, React Native 0.77 will be supported in Expo SDK 52 (instructions on how to update React Native inside your Expo project to 0.77.0 will be available in a separate Expo blog post in the near future). + +:::info +0.77 is now the latest stable version of React Native and 0.74.x moves to unsupported. For more information see [React Native's support policy](https://github.com/reactwg/react-native-releases/blob/main/docs/support.md#releases-support-policy). We aim to publish a final end-of-life update of 0.74 in the near future. +::: diff --git a/website/blog/authors.yml b/website/blog/authors.yml index 8034baea675..f1cdfd0b22a 100644 --- a/website/blog/authors.yml +++ b/website/blog/authors.yml @@ -238,6 +238,37 @@ grabbou: x: grabbou image_url: https://avatars0.githubusercontent.com/u/2464966?s=460&v=4 +vonovak: + name: Vojtech Novak + title: Software Engineer @ Expo + socials: + x: vonovak + github: vonovak + image_url: https://avatars.githubusercontent.com/u/1566403?v=4 + +mazen: + name: Mazen Chami + title: Software Engineer @ InfiniteRed + socials: + x: mazenchami + github: mazenchami + image_url: https://avatars.githubusercontent.com/u/9324607?v=4 + +robhogan: + name: Rob Hogan + title: Software Engineer @ Meta + socials: + x: robjhogan + github: robhogan + image_url: https://avatars.githubusercontent.com/u/2590098?v=4 + +fabriziocucci: + name: Fabrizio Cucci + title: Software Engineer @ Meta + socials: + x: fabriziocucci + image_url: https://avatars.githubusercontent.com/u/8156463?v=4 + reactteam: name: The React Team title: "@reactjs / @reactnative" diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index b09d6d71a10..537bf29bc78 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -5,9 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -import type {Config} from '@docusaurus/types'; -import type * as Preset from '@docusaurus/preset-classic'; import type * as PluginContentDocs from '@docusaurus/plugin-content-docs'; +import type * as Preset from '@docusaurus/preset-classic'; +import type {Config} from '@docusaurus/types'; +import path from 'path'; import users from './showcase.json'; import versions from './versions.json'; @@ -15,12 +16,43 @@ import versions from './versions.json'; const lastVersion = versions[0]; const copyright = `Copyright © ${new Date().getFullYear()} Meta Platforms, Inc.`; +export interface EditUrlButton { + label: string; + href: string; +} + const commonDocsOptions = { breadcrumbs: false, showLastUpdateAuthor: false, showLastUpdateTime: true, - editUrl: - 'https://github.com/facebook/react-native-website/blob/main/website/', + editUrl: (options => { + const baseUrl = + 'https://github.com/facebook/react-native-website/edit/main'; + const nextReleasePath = `docs/${options.docPath}`; + const isNextRelease = options.version === 'current'; + const buttons: EditUrlButton[] = [ + { + label: isNextRelease ? 'Edit this page' : 'Edit page for next release', + href: `${baseUrl}/${nextReleasePath}`, + }, + ]; + if (!isNextRelease) { + const label = + options.version === lastVersion + ? 'Edit page for current release' + : `Edit page for ${options.version} release`; + const thisVersionPath = path.posix.join( + 'website', + options.versionDocsDirPath, + options.docPath + ); + buttons.push({ + label, + href: `${baseUrl}/${thisVersionPath}`, + }); + } + return JSON.stringify(buttons); + }) as PluginContentDocs.EditUrlFunction, remarkPlugins: [ require('@react-native-website/remark-snackplayer'), require('@react-native-website/remark-codeblock-language-as-title'), @@ -71,7 +103,7 @@ const config: Config = { defaultLocale: 'en', locales: ['en'], }, - onBrokenLinks: 'throw', + onBrokenLinks: 'warn', presets: [ [ '@docusaurus/preset-classic', diff --git a/website/package.json b/website/package.json index 9c8bdc2de1c..d4725b41624 100644 --- a/website/package.json +++ b/website/package.json @@ -26,7 +26,7 @@ "format:style": "prettier --write src/**/*.{scss,css}", "format:examples": "eslint-examples-js --fix && eslint-examples-tsx --fix", "prettier": "yarn format:source && yarn format:markdown && yarn format:style", - "lint": "eslint ../docs/** blog/** '{core,src}/**/*.{js,jsx,ts,tsx}'", + "lint": "eslint ../docs/** blog/** \"{core,src}/**/*.{js,jsx,ts,tsx}\"", "lint:examples": "eslint-examples-js && eslint-examples-tsx && tsc-examples", "lint:versioned": "eslint versioned_docs/**", "lint:markdown": "remark ../docs --quiet -r .remarkrc.mjs", diff --git a/website/sidebars.ts b/website/sidebars.ts index 2ac73e5c991..14e618fd6ea 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -298,6 +298,8 @@ export default { 'view-style-props', ], 'Object Types': [ + 'boxshadowvalue', + 'dropshadowvalue', 'layoutevent', 'pressevent', 'react-node', diff --git a/website/src/css/customTheme.scss b/website/src/css/customTheme.scss index ff1cc45c82b..d7ee5e21418 100644 --- a/website/src/css/customTheme.scss +++ b/website/src/css/customTheme.scss @@ -318,14 +318,14 @@ hr { text-transform: uppercase; padding: 6px 10px; font-size: 0.7rem; - text-align: left; + text-align: start; } tr td { font-size: 90%; line-height: 1.3em; padding: 10px; - text-align: left; + text-align: start; code { display: inline-block; @@ -1184,7 +1184,7 @@ button[class*="tocCollapsibleButton"] { .lastUpdated { font-size: 13px; - text-align: right; + text-align: end; } time, diff --git a/website/src/css/showcase.scss b/website/src/css/showcase.scss index df18c693cad..2397ef498a2 100644 --- a/website/src/css/showcase.scss +++ b/website/src/css/showcase.scss @@ -67,7 +67,7 @@ html[data-theme="dark"] { h2 { margin: 4px -20px 12px; padding: 0 40px 0; - text-align: left; + text-align: start; img { margin: 16px 0 8px; @@ -80,7 +80,7 @@ html[data-theme="dark"] { } .showcaseSectionDescription { - text-align: left; + text-align: start; color: var(--subtle); padding: 0 20px; margin-bottom: 8px; diff --git a/website/src/pages/Home/Framework/styles.module.css b/website/src/pages/Home/Framework/styles.module.css index 8a8e57c9d1d..90170878480 100644 --- a/website/src/pages/Home/Framework/styles.module.css +++ b/website/src/pages/Home/Framework/styles.module.css @@ -48,7 +48,7 @@ .card { flex-direction: row; - text-align: left; + text-align: start; } .cardImage { diff --git a/website/src/theme/DocItem/Footer/index.tsx b/website/src/theme/DocItem/Footer/index.tsx index 8284c1e589f..c5a226154a4 100644 --- a/website/src/theme/DocItem/Footer/index.tsx +++ b/website/src/theme/DocItem/Footer/index.tsx @@ -2,14 +2,19 @@ import React from 'react'; import clsx from 'clsx'; import {ThemeClassNames} from '@docusaurus/theme-common'; import {useDoc} from '@docusaurus/plugin-content-docs/client'; +import Translate from '@docusaurus/Translate'; +import IconEdit from '@theme/Icon/Edit'; import LastUpdated from '@theme/LastUpdated'; -import EditThisPage from '@theme/EditThisPage'; -import TagsListInline from '@theme/TagsListInline'; +import Link from '@docusaurus/Link'; +import TagsListInline, { + Props as TagsListInlineProps, +} from '@theme/TagsListInline'; +import type {EditUrlButton} from '../../../../docusaurus.config'; import styles from './styles.module.css'; import DocsRating from '../../../../core/DocsRating'; -function TagsRow(props) { +function TagsRow(props: TagsListInlineProps) { return (
); } +function EditPage({label, href}: {label: string; href: string}) { + return ( + + + + {label} + + + ); +} function EditMetaRow({editUrl, lastUpdatedAt, lastUpdatedBy}) { + const buttons = React.useMemo((): EditUrlButton[] => { + try { + return JSON.parse(editUrl); + } catch (e) { + console.error(e); + return [{href: editUrl, label: 'Edit this page'}]; + } + }, [editUrl]); return (
-
{editUrl && }
-
+
+ {buttons.map(({label, href}, index) => ( + + ))} +
+
{(lastUpdatedAt || lastUpdatedBy) && ( get() { + public Map getReactModuleInfos() { Map map = new HashMap<>(); map.put(ReactWebViewManager.REACT_CLASS, new ReactModuleInfo( ReactWebViewManager.REACT_CLASS, // name diff --git a/website/versioned_docs/version-0.76/modal.md b/website/versioned_docs/version-0.76/modal.md index 3b438154771..e299f480436 100644 --- a/website/versioned_docs/version-0.76/modal.md +++ b/website/versioned_docs/version-0.76/modal.md @@ -126,16 +126,6 @@ Possible values: --- -### `backdropColor` - -The `backdropColor` of the modal (or background color of the modal's container.) Defaults to `white` if not provided and transparent is `false`. Ignored if `transparent` is `true`. - -| Type | Default | -| --------------- | ------- | -| [color](colors) | white | - ---- - ### `hardwareAccelerated`
Android
The `hardwareAccelerated` prop controls whether to force hardware acceleration for the underlying window. diff --git a/website/versioned_docs/version-0.76/shadow-props.md b/website/versioned_docs/version-0.76/shadow-props.md index 768d190e058..cbff04e435c 100644 --- a/website/versioned_docs/version-0.76/shadow-props.md +++ b/website/versioned_docs/version-0.76/shadow-props.md @@ -218,8 +218,32 @@ export default App; # Reference +There are 3 sets of shadow APIs in React Native: + +- `boxShadow`: A View style prop and a spec-compliant implementation of the [web style prop of the same name](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow). +- `dropShadow`: A specific filter function available as part of the [`filter`](./view-style-props#filter) View style prop. +- Various `shadow` props (`shadowColor`, `shadowOffset`, `shadowOpacity`, `shadowRadius`): These map directly to their native counterparts exposed by the platform-level APIs. + +The difference between `dropShadow` and `boxShadow` are as follows: + +- `dropShadow` exists as part of `filter`, whereas `boxShadow` is a standalone style prop. +- `dropShadow` is an alpha mask, so only pixels with a positive alpha value will "cast" a shadow. `boxShadow` will cast around the border box of the element no matter it's contents (unless it is inset). +- `dropShadow` is only available on Android, `boxShadow` is available on iOS and Android. +- `dropShadow` cannot be inset like `boxShadow`. +- `dropShadow` does not have the `spreadDistance` argument like `boxShadow`. + +Both `boxShadow` and `dropShadow` are generally more capable than the `shadow` props. The `shadow` props, however, map to native platform-level APIs, so if you only need a straightforward shadow these props are recommended. Note that only `shadowColor` works on both Android and iOS, all other `shadow` props only work on iOS. + ## Props +### `boxShadow` + +See [View Style Props](./view-style-props#boxshadow) for documentation. + +### `dropShadow`
Android
+ +See [View Style Props](./view-style-props#filter) for documentation. + ### `shadowColor` Sets the drop shadow color. diff --git a/website/versioned_docs/version-0.76/the-new-architecture/pure-cxx-modules.md b/website/versioned_docs/version-0.76/the-new-architecture/pure-cxx-modules.md index 3f0e7783f93..6bdc2126060 100644 --- a/website/versioned_docs/version-0.76/the-new-architecture/pure-cxx-modules.md +++ b/website/versioned_docs/version-0.76/the-new-architecture/pure-cxx-modules.md @@ -18,15 +18,6 @@ The rest of this guide assume that you have created your application running the npx @react-native-community/cli@latest init SampleApp --version 0.76.0 ``` -:::danger -We are aware of some issues that are preventing pure C++ Modules to work well on Android, when developed locally in the app. -Pure C++ modules consumed as external libraries works well on Android. - -These issues started from version 0.76.2 and are still persisting in version 0.76.5. - -We found the root cause for the issue (see [#48298](https://github.com/facebook/react-native/issues/48298) and [#48340](https://github.com/facebook/react-native/pull/48340)), and we are aiming to fix in 0.76.6. -::: - ## 1. Create the JS specs Pure C++ Turbo Native Modules are Turbo Native Modules. They needs a specification file (also called spec file) so that Codegen can create the scaffolding code for us. The specification file is also what we use to access the Turbo Native Module in JS. diff --git a/website/versioned_docs/version-0.76/turbo-native-modules-android.md b/website/versioned_docs/version-0.76/turbo-native-modules-android.md index 281eb200399..aff7440feaa 100644 --- a/website/versioned_docs/version-0.76/turbo-native-modules-android.md +++ b/website/versioned_docs/version-0.76/turbo-native-modules-android.md @@ -139,7 +139,7 @@ public class NativeLocalStoragePackage extends TurboReactPackage { public ReactModuleInfoProvider getReactModuleInfoProvider() { return new ReactModuleInfoProvider() { @Override - public Map get() { + public Map getReactModuleInfos() { Map map = new HashMap<>(); map.put(NativeLocalStorageModule.NAME, new ReactModuleInfo( NativeLocalStorageModule.NAME, // name diff --git a/website/versioned_docs/version-0.76/view-style-props.md b/website/versioned_docs/version-0.76/view-style-props.md index 7e3ea0f8dee..e292e3e6e5c 100644 --- a/website/versioned_docs/version-0.76/view-style-props.md +++ b/website/versioned_docs/version-0.76/view-style-props.md @@ -289,6 +289,21 @@ If the rounded border is not visible, try applying `overflow: 'hidden'` as well. | ------ | | number | +### `boxShadow` + +:::note +`boxShadow` is only available on the [New Architecture](/architecture/landing-page). Outset shadows are only supported on **Android 9+**. Inset shadows are only supported on **Android 10+**. +::: + +Adds a shadow effect to an element, with the ability to control the position, color, size, and blurriness of the shadow. This shadow either appears around the outside or inside of the border box of the element, depending on whether or not the shadow is _inset_. This is a spec-compliant implementation of the [web style prop of the same name](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow). Read more about all the arguments available in the [BoxShadowValue](./boxshadowvalue) documentation. + +These shadows can be composed together so that a single `boxShadow` can be comprised of multiple different shadows. + +`boxShadow` takes either a string which mimics the [web syntax](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow#syntax) or an array of [BoxShadowValue](./boxshadowvalue) objects. +| Type | +| --------------------------- | +| array of BoxShadowValue ojects \| string | + ### `cursor`
iOS
On iOS 17+, Setting to `pointer` allows hover effects when a pointer (such as a trackpad or stylus on iOS, or the users' gaze on visionOS) is over the view. @@ -309,6 +324,47 @@ Sets the elevation of a view, using Android's underlying [elevation API](https:/ --- +### `filter` + +:::note +`filter` is only available on the [New Architecture](/architecture/landing-page) +::: + +Adds a graphical filter to the `View`. This filter is comprised of any number of _filter functions_, which each represent some atomic change to the graphical composition of the `View`. The complete list of valid filter functions is defined below. `filter` will apply to descendants of the `View` as well as the `View` itself. `filter` implies `overflow: hidden`, so descendants will be clipped to fit the bounds of the `View`. + +The following filter functions work across all platforms: + +- `brightness`: Changes the brightness of the `View`. Takes a non-negative number or percentage. +- `opacity`: Changes the opacity, or alpha, of the `View`. Takes a non-negative number or percentage. + +:::note +Due to issues with performance and spec compliance, these are the only two filter functions available on iOS. There are plans to explore some potential workarounds using SwiftUI instead of UIKit for this implementation. +::: + +
Android
+ +The following filter functions work on Android only: + +- `blur`: Blurs the `View` with a [Guassian blur](https://en.wikipedia.org/wiki/Gaussian_blur), where the specified length represents the radius used in the blurring algorithm. Any non-negative DIP value is valid (no percents). The larger the value, the blurrier the result. +- `contrast`: Changes the contrast of the `View`. Takes a non-negative number or percentage. +- `dropShadow`: Adds a shadow around the alpha mask of the `View` (only non-zero alpha pixels in the `View` will cast a shadow). Takes an optional color representing the shadow color, and 2 or 3 lengths. If 2 lengths are specified they are interperted as `offsetX` and `offsetY` which will translate the shadow in the X and Y dimensions respectfully. If a 3rd length is given it is interpreted as the standard deviation of the Guassian blur used on the shadow - so a larger value will blur the shadow more. Read more about the arguments in [DropShadowValue](./dropshadowvalue.md). +- `grayscale`: Converts the `View` to [grayscale](https://en.wikipedia.org/wiki/Grayscale) by the specified amount. Takes a non-negative number or percentage, where `1` or `100%` represents complete grayscale. +- `hueRotate`: Changes the [hue](https://en.wikipedia.org/wiki/Hue) of the View. The argument of this function defines the angle of a color wheel around which the hue will be rotated, so e.g., `360deg` would have no effect. This angle can have either `deg` or `rad` units. +- `invert`: Inverts the colors in the `View`. Takes a non-negative number or percentage, where `1` or `100%` represents complete inversion. +- `sepia`: Converts the `View` to [sepia](). Takes a non-negative number or percentage, where `1` or `100%` represents complete sepia. +- `saturate`: Changes the [saturation](https://en.wikipedia.org/wiki/Colorfulness) of the `View`. Takes a non-negative number or percentage. + +:::note +`blur` and `dropShadow` are only supported on **Android 12+** +::: + +`filter` takes either an array of objects comprising of the above filter functions or a string which mimics the [web syntax](https://developer.mozilla.org/en-US/docs/Web/CSS/filter#syntax). +| Type | +| ------ | +| array of objects: `{brightness: number\|string}`, `{opacity: number\|string}`, `{blur: number\|string}`, `{contrast: number\|string}`, `{dropShadow: DropShadowValue\|string}`, `{grayscale: number\|string}`, `{hueRotate: number\|string}`, `{invert: number\|string}`, `{sepia: number\|string}`, `{saturate: number\|string}` or string| + +--- + ### `opacity` | Type | diff --git a/website/versioned_docs/version-0.76/view.md b/website/versioned_docs/version-0.76/view.md index 099c0080e87..e39540d43e0 100644 --- a/website/versioned_docs/version-0.76/view.md +++ b/website/versioned_docs/version-0.76/view.md @@ -674,23 +674,23 @@ Controls whether the `View` can be the target of touch events. - `'none'`: The View is never the target of touch events. - `'box-none'`: The View is never the target of touch events but its subviews can be. It behaves like if the view had the following classes in CSS: -``` +```css .box-none { - pointer-events: none; + pointer-events: none; } .box-none * { - pointer-events: auto; + pointer-events: auto; } ``` - `'box-only'`: The view can be the target of touch events but its subviews cannot be. It behaves like if the view had the following classes in CSS: -``` +```css .box-only { - pointer-events: auto; + pointer-events: auto; } .box-only * { - pointer-events: none; + pointer-events: none; } ``` diff --git a/website/versioned_docs/version-0.77/_fabric-native-components.jsx b/website/versioned_docs/version-0.77/_fabric-native-components.jsx new file mode 100644 index 00000000000..fc6a3171a4f --- /dev/null +++ b/website/versioned_docs/version-0.77/_fabric-native-components.jsx @@ -0,0 +1,11 @@ +import React from 'react'; +import IOSContent from './fabric-native-components-ios.md'; +import AndroidContent from './fabric-native-components-android.md'; + +export function FabricNativeComponentsIOS() { + return ; +} + +export function FabricNativeComponentsAndroid() { + return ; +} diff --git a/website/versioned_docs/version-0.77/_getting-started-linux-android.md b/website/versioned_docs/version-0.77/_getting-started-linux-android.md new file mode 100644 index 00000000000..410a33de479 --- /dev/null +++ b/website/versioned_docs/version-0.77/_getting-started-linux-android.md @@ -0,0 +1,105 @@ +## Installing dependencies + +You will need Node, the React Native command line interface, a JDK, and Android Studio. + +While you can use any editor of your choice to develop your app, you will need to install Android Studio in order to set up the necessary tooling to build your React Native app for Android. + +

Node

+ +Follow the [installation instructions for your Linux distribution](https://nodejs.org/en/download/package-manager/) to install Node 18.18 or newer. + +

Java Development Kit

+ +React Native currently recommends version 17 of the Java SE Development Kit (JDK). You may encounter problems using higher JDK versions. You may download and install [OpenJDK](https://openjdk.java.net) from [AdoptOpenJDK](https://adoptopenjdk.net/) or your system packager. + +

Android development environment

+ +Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. + +

1. Install Android Studio

+ +[Download and install Android Studio](https://developer.android.com/studio/index.html). While on Android Studio installation wizard, make sure the boxes next to all of the following items are checked: + +- `Android SDK` +- `Android SDK Platform` +- `Android Virtual Device` + +Then, click "Next" to install all of these components. + +> If the checkboxes are grayed out, you will have a chance to install these components later on. + +Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. + +

2. Install the Android SDK

+ +Android Studio installs the latest Android SDK by default. Building a React Native app with native code, however, requires the `Android 15 (VanillaIceCream)` SDK in particular. Additional Android SDKs can be installed through the SDK Manager in Android Studio. + +To do that, open Android Studio, click on "Configure" button and select "SDK Manager". + +> The SDK Manager can also be found within the Android Studio "Settings" dialog, under **Languages & Frameworks** → **Android SDK**. + +Select the "SDK Platforms" tab from within the SDK Manager, then check the box next to "Show Package Details" in the bottom right corner. Look for and expand the `Android 15 (VanillaIceCream)` entry, then make sure the following items are checked: + +- `Android SDK Platform 35` +- `Intel x86 Atom_64 System Image` or `Google APIs Intel x86 Atom System Image` + +Next, select the "SDK Tools" tab and check the box next to "Show Package Details" here as well. Look for and expand the "Android SDK Build-Tools" entry, then make sure that `35.0.0` is selected. + +Finally, click "Apply" to download and install the Android SDK and related build tools. + +

3. Configure the ANDROID_HOME environment variable

+ +The React Native tools require some environment variables to be set up in order to build apps with native code. + +Add the following lines to your `$HOME/.bash_profile` or `$HOME/.bashrc` (if you are using `zsh` then `~/.zprofile` or `~/.zshrc`) config file: + +```shell +export ANDROID_HOME=$HOME/Android/Sdk +export PATH=$PATH:$ANDROID_HOME/emulator +export PATH=$PATH:$ANDROID_HOME/platform-tools +``` + +> `.bash_profile` is specific to `bash`. If you're using another shell, you will need to edit the appropriate shell-specific config file. + +Type `source $HOME/.bash_profile` for `bash` or `source $HOME/.zprofile` to load the config into your current shell. Verify that ANDROID_HOME has been set by running `echo $ANDROID_HOME` and the appropriate directories have been added to your path by running `echo $PATH`. + +> Please make sure you use the correct Android SDK path. You can find the actual location of the SDK in the Android Studio "Settings" dialog, under **Languages & Frameworks** → **Android SDK**. + +

Watchman

+ +Follow the [Watchman installation guide](https://facebook.github.io/watchman/docs/install#buildinstall) to compile and install Watchman from source. + +> [Watchman](https://facebook.github.io/watchman/docs/install) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance and increased compatibility in certain edge cases (translation: you may be able to get by without installing this, but your mileage may vary; installing this now may save you from a headache later). + +

Preparing the Android device

+ +You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. + +Either way, you will need to prepare the device to run Android apps for development. + +

Using a physical device

+ +If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable and following the instructions [here](running-on-device.md). + +

Using a virtual device

+ +If you use Android Studio to open `./AwesomeProject/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: + +![Android Studio AVD Manager](/docs/assets/GettingStartedAndroidStudioAVD.png) + +If you have recently installed Android Studio, you will likely need to [create a new AVD](https://developer.android.com/studio/run/managing-avds.html). Select "Create Virtual Device...", then pick any Phone from the list and click "Next", then select the **VanillaIceCream** API Level 35 image. + +> We recommend configuring [VM acceleration](https://developer.android.com/studio/run/emulator-acceleration.html#vm-linux) on your system to improve performance. Once you've followed those instructions, go back to the AVD Manager. + +Click "Next" then "Finish" to create your AVD. At this point you should be able to click on the green triangle button next to your AVD to launch it. + +

That's it!

+ +Congratulations! You successfully set up your development environment. + +
+ +

Now what?

+ +- If you want to add this new React Native code to an existing application, check out the [Integration guide](integration-with-existing-apps.md). +- If you're curious to learn more about React Native, check out the [Introduction to React Native](getting-started). diff --git a/website/versioned_docs/version-0.77/_getting-started-macos-android.md b/website/versioned_docs/version-0.77/_getting-started-macos-android.md new file mode 100644 index 00000000000..16d45441ac7 --- /dev/null +++ b/website/versioned_docs/version-0.77/_getting-started-macos-android.md @@ -0,0 +1,136 @@ +## Installing dependencies + +You will need Node, Watchman, the React Native command line interface, a JDK, and Android Studio. + +While you can use any editor of your choice to develop your app, you will need to install Android Studio in order to set up the necessary tooling to build your React Native app for Android. + +

Node & Watchman

+ +We recommend installing Node and Watchman using [Homebrew](https://brew.sh/). Run the following commands in a Terminal after installing Homebrew: + +```shell +brew install node +brew install watchman +``` + +If you have already installed Node on your system, make sure it is Node 18.18 or newer. + +[Watchman](https://facebook.github.io/watchman) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance. + +

Java Development Kit

+ +We recommend installing the OpenJDK distribution called Azul **Zulu** using [Homebrew](https://brew.sh/). Run the following commands in a Terminal after installing Homebrew: + +```shell +brew install --cask zulu@17 + +# Get path to where cask was installed to find the JDK installer +brew info --cask zulu@17 + +# ==> zulu@17: +# https://www.azul.com/downloads/ +# Installed +# /opt/homebrew/Caskroom/zulu@17/ (185.8MB) (note that the path is /usr/local/Caskroom on non-Apple Silicon Macs) +# Installed using the formulae.brew.sh API on 2024-06-06 at 10:00:00 + +# Navigate to the folder +open /opt/homebrew/Caskroom/zulu@17/ # or /usr/local/Caskroom/zulu@17/ +``` + +After opening Finder, double click the `Double-Click to Install Azul Zulu JDK 17.pkg` package to install the JDK. + +After the JDK installation, add or update your `JAVA_HOME` environment variable in `~/.zshrc` (or in `~/.bash_profile`). + +If you used above steps, JDK will likely be located at `/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home`: + +```shell +export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home +``` + +The Zulu OpenJDK distribution offers JDKs for **both Intel and M1 Macs**. This will make sure your builds are faster on M1 Macs compared to using an Intel-based JDK. + +If you have already installed JDK on your system, we recommend JDK 17. You may encounter problems using higher JDK versions. + +

Android development environment

+ +Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. + +

1. Install Android Studio

+ +[Download and install Android Studio](https://developer.android.com/studio/index.html). While on Android Studio installation wizard, make sure the boxes next to all of the following items are checked: + +- `Android SDK` +- `Android SDK Platform` +- `Android Virtual Device` + +Then, click "Next" to install all of these components. + +> If the checkboxes are grayed out, you will have a chance to install these components later on. + +Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. + +

2. Install the Android SDK

+ +Android Studio installs the latest Android SDK by default. Building a React Native app with native code, however, requires the `Android 15 (VanillaIceCream)` SDK in particular. Additional Android SDKs can be installed through the SDK Manager in Android Studio. + +To do that, open Android Studio, click on "More Actions" button and select "SDK Manager". + +![Android Studio Welcome](/docs/assets/GettingStartedAndroidStudioWelcomeMacOS.png) + +> The SDK Manager can also be found within the Android Studio "Settings" dialog, under **Languages & Frameworks** → **Android SDK**. + +Select the "SDK Platforms" tab from within the SDK Manager, then check the box next to "Show Package Details" in the bottom right corner. Look for and expand the `Android 15 (VanillaIceCream)` entry, then make sure the following items are checked: + +- `Android SDK Platform 35` +- `Intel x86 Atom_64 System Image` or `Google APIs Intel x86 Atom System Image` or (for Apple M1 Silicon) `Google APIs ARM 64 v8a System Image` + +Next, select the "SDK Tools" tab and check the box next to "Show Package Details" here as well. Look for and expand the "Android SDK Build-Tools" entry, then make sure that `35.0.0` is selected. + +Finally, click "Apply" to download and install the Android SDK and related build tools. + +

3. Configure the ANDROID_HOME environment variable

+ +The React Native tools require some environment variables to be set up in order to build apps with native code. + +Add the following lines to your `~/.zprofile` or `~/.zshrc` (if you are using `bash`, then `~/.bash_profile` or `~/.bashrc`) config file: + +```shell +export ANDROID_HOME=$HOME/Library/Android/sdk +export PATH=$PATH:$ANDROID_HOME/emulator +export PATH=$PATH:$ANDROID_HOME/platform-tools +``` + +Run `source ~/.zprofile` (or `source ~/.bash_profile` for `bash`) to load the config into your current shell. Verify that ANDROID_HOME has been set by running `echo $ANDROID_HOME` and the appropriate directories have been added to your path by running `echo $PATH`. + +> Please make sure you use the correct Android SDK path. You can find the actual location of the SDK in the Android Studio "Settings" dialog, under **Languages & Frameworks** → **Android SDK**. + +

Preparing the Android device

+ +You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. + +Either way, you will need to prepare the device to run Android apps for development. + +

Using a physical device

+ +If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable and following the instructions [here](running-on-device.md). + +

Using a virtual device

+ +If you use Android Studio to open `./AwesomeProject/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: + +![Android Studio AVD Manager](/docs/assets/GettingStartedAndroidStudioAVD.png) + +If you have recently installed Android Studio, you will likely need to [create a new AVD](https://developer.android.com/studio/run/managing-avds.html). Select "Create Virtual Device...", then pick any Phone from the list and click "Next", then select the **VanillaIceCream** API Level 35 image. + +Click "Next" then "Finish" to create your AVD. At this point you should be able to click on the green triangle button next to your AVD to launch it. + +

That's it!

+ +Congratulations! You successfully set up your development environment. + +
+ +

Now what?

+ +- If you want to add this new React Native code to an existing application, check out the [Integration guide](integration-with-existing-apps.md). +- If you're curious to learn more about React Native, check out the [Introduction to React Native](getting-started). diff --git a/website/versioned_docs/version-0.77/_getting-started-macos-ios.md b/website/versioned_docs/version-0.77/_getting-started-macos-ios.md new file mode 100644 index 00000000000..6b366fb64f4 --- /dev/null +++ b/website/versioned_docs/version-0.77/_getting-started-macos-ios.md @@ -0,0 +1,73 @@ +## Installing dependencies + +You will need Node, Watchman, the React Native command line interface, Xcode and CocoaPods. + +While you can use any editor of your choice to develop your app, you will need to install Xcode in order to set up the necessary tooling to build your React Native app for iOS. + +### Node & Watchman + +We recommend installing Node and Watchman using [Homebrew](https://brew.sh/). Run the following commands in a Terminal after installing Homebrew: + +```shell +brew install node +brew install watchman +``` + +If you have already installed Node on your system, make sure it is Node 18.18 or newer. + +[Watchman](https://facebook.github.io/watchman) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance. + +### Xcode + +Please use the **latest version** of Xcode. + +The easiest way to install Xcode is via the [Mac App Store](https://itunes.apple.com/us/app/xcode/id497799835?mt=12). Installing Xcode will also install the iOS Simulator and all the necessary tools to build your iOS app. + +#### Command Line Tools + +You will also need to install the Xcode Command Line Tools. Open Xcode, then choose **Settings... (or Preferences...)** from the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown. + +![Xcode Command Line Tools](/docs/assets/GettingStartedXcodeCommandLineTools.png) + +#### Installing an iOS Simulator in Xcode + +To install a simulator, open **Xcode > Settings... (or Preferences...)** and select the **Platforms (or Components)** tab. Select a simulator with the corresponding version of iOS you wish to use. + +If you are using Xcode version 14.0 or greater to install a simulator, open **Xcode > Settings > Platforms** tab, then click "+" icon and select **iOS…** option. + +#### CocoaPods + +[CocoaPods](https://cocoapods.org/) is one of the dependency management system available for iOS. CocoaPods is a Ruby [gem](https://en.wikipedia.org/wiki/RubyGems). You can install CocoaPods using the version of Ruby that ships with the latest version of macOS. + +For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html). + +### [Optional] Configuring your environment + +Starting from React Native version 0.69, it is possible to configure the Xcode environment using the `.xcode.env` file provided by the template. + +The `.xcode.env` file contains an environment variable to export the path to the `node` executable in the `NODE_BINARY` variable. +This is the **suggested approach** to decouple the build infrastructure from the system version of `node`. You should customize this variable with your own path or your own `node` version manager, if it differs from the default. + +On top of this, it's possible to add any other environment variable and to source the `.xcode.env` file in your build script phases. If you need to run script that requires some specific environment, this is the **suggested approach**: it allows to decouple the build phases from a specific environment. + +:::info +If you are already using [NVM](https://nvm.sh/) (a command which helps you install and switch between versions of Node.js) and [zsh](https://ohmyz.sh/), you might want to move the code that initialize NVM from your `~/.zshrc` into a `~/.zshenv` file to help Xcode find your Node executable: + +```zsh +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm +``` + +You might also want to ensure that all "shell script build phase" of your Xcode project, is using `/bin/zsh` as its shell. +::: + +

That's it!

+ +Congratulations! You successfully set up your development environment. + +
+ +

Now what?

+ +- If you want to add this new React Native code to an existing application, check out the [Integration guide](integration-with-existing-apps.md). +- If you're curious to learn more about React Native, check out the [Introduction to React Native](getting-started). diff --git a/website/versioned_docs/version-0.77/_getting-started-windows-android.md b/website/versioned_docs/version-0.77/_getting-started-windows-android.md new file mode 100644 index 00000000000..0ded094e8fc --- /dev/null +++ b/website/versioned_docs/version-0.77/_getting-started-windows-android.md @@ -0,0 +1,136 @@ +

Installing dependencies

+ +You will need Node, the React Native command line interface, a JDK, and Android Studio. + +While you can use any editor of your choice to develop your app, you will need to install Android Studio in order to set up the necessary tooling to build your React Native app for Android. + +

Node, JDK

+ +We recommend installing Node via [Chocolatey](https://chocolatey.org/install), a popular package manager for Windows. + +It is recommended to use an LTS version of Node. If you want to be able to switch between different versions, you might want to install Node via [nvm-windows](https://github.com/coreybutler/nvm-windows), a Node version manager for Windows. + +React Native also requires [Java SE Development Kit (JDK)](https://openjdk.java.net/projects/jdk/17/), which can be installed using Chocolatey as well. + +Open an Administrator Command Prompt (right click Command Prompt and select "Run as Administrator"), then run the following command: + +```powershell +choco install -y nodejs-lts microsoft-openjdk17 +``` + +If you have already installed Node on your system, make sure it is Node 18 or newer. If you already have a JDK on your system, we recommend JDK17. You may encounter problems using higher JDK versions. + +> You can find additional installation options on [Node's Downloads page](https://nodejs.org/en/download/). + +> If you're using the latest version of Java Development Kit, you'll need to change the Gradle version of your project so it can recognize the JDK. You can do that by going to `{project root folder}\android\gradle\wrapper\gradle-wrapper.properties` and changing the `distributionUrl` value to upgrade the Gradle version. You can check out [here the latest releases of Gradle](https://gradle.org/releases/). + +

Android development environment

+ +Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. + +

1. Install Android Studio

+ +[Download and install Android Studio](https://developer.android.com/studio/index.html). While on Android Studio installation wizard, make sure the boxes next to all of the following items are checked: + +- `Android SDK` +- `Android SDK Platform` +- `Android Virtual Device` +- If you are not already using Hyper-V: `Performance (Intel ® HAXM)` ([See here for AMD or Hyper-V](https://android-developers.googleblog.com/2018/07/android-emulator-amd-processor-hyper-v.html)) + +Then, click "Next" to install all of these components. + +> If the checkboxes are grayed out, you will have a chance to install these components later on. + +Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. + +

2. Install the Android SDK

+ +Android Studio installs the latest Android SDK by default. Building a React Native app with native code, however, requires the `Android 15 (VanillaIceCream)` SDK in particular. Additional Android SDKs can be installed through the SDK Manager in Android Studio. + +To do that, open Android Studio, click on "More Actions" button and select "SDK Manager". + +![Android Studio Welcome](/docs/assets/GettingStartedAndroidStudioWelcomeWindows.png) + +> The SDK Manager can also be found within the Android Studio "Settings" dialog, under **Languages & Frameworks** → **Android SDK**. + +Select the "SDK Platforms" tab from within the SDK Manager, then check the box next to "Show Package Details" in the bottom right corner. Look for and expand the `Android 15 (VanillaIceCream)` entry, then make sure the following items are checked: + +- `Android SDK Platform 35` +- `Intel x86 Atom_64 System Image` or `Google APIs Intel x86 Atom System Image` + +Next, select the "SDK Tools" tab and check the box next to "Show Package Details" here as well. Look for and expand the `Android SDK Build-Tools` entry, then make sure that `35.0.0` is selected. + +Finally, click "Apply" to download and install the Android SDK and related build tools. + +

3. Configure the ANDROID_HOME environment variable

+ +The React Native tools require some environment variables to be set up in order to build apps with native code. + +1. Open the **Windows Control Panel.** +2. Click on **User Accounts,** then click **User Accounts** again +3. Click on **Change my environment variables** +4. Click on **New...** to create a new `ANDROID_HOME` user variable that points to the path to your Android SDK: + +![ANDROID_HOME Environment Variable](/docs/assets/GettingStartedAndroidEnvironmentVariableANDROID_HOME.png) + +The SDK is installed, by default, at the following location: + +```powershell +%LOCALAPPDATA%\Android\Sdk +``` + +You can find the actual location of the SDK in the Android Studio "Settings" dialog, under **Languages & Frameworks** → **Android SDK**. + +Open a new Command Prompt window to ensure the new environment variable is loaded before proceeding to the next step. + +1. Open powershell +2. Copy and paste **Get-ChildItem -Path Env:\\** into powershell +3. Verify `ANDROID_HOME` has been added + +

4. Add platform-tools to Path

+ +1. Open the **Windows Control Panel.** +2. Click on **User Accounts,** then click **User Accounts** again +3. Click on **Change my environment variables** +4. Select the **Path** variable. +5. Click **Edit.** +6. Click **New** and add the path to platform-tools to the list. + +The default location for this folder is: + +```powershell +%LOCALAPPDATA%\Android\Sdk\platform-tools +``` + +

Preparing the Android device

+ +You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. + +Either way, you will need to prepare the device to run Android apps for development. + +

Using a physical device

+ +If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable and following the instructions [here](running-on-device.md). + +

Using a virtual device

+ +If you use Android Studio to open `./AwesomeProject/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: + +![Android Studio AVD Manager](/docs/assets/GettingStartedAndroidStudioAVD.png) + +If you have recently installed Android Studio, you will likely need to [create a new AVD](https://developer.android.com/studio/run/managing-avds.html). Select "Create Virtual Device...", then pick any Phone from the list and click "Next", then select the **VanillaIceCream** API Level 35 image. + +> If you don't have HAXM installed, click on "Install HAXM" or follow [these instructions](https://github.com/intel/haxm/wiki/Installation-Instructions-on-Windows) to set it up, then go back to the AVD Manager. + +Click "Next" then "Finish" to create your AVD. At this point you should be able to click on the green triangle button next to your AVD to launch it. + +

That's it!

+ +Congratulations! You successfully set up your development environment. + +
+ +

Now what?

+ +- If you want to add this new React Native code to an existing application, check out the [Integration guide](integration-with-existing-apps.md). +- If you're curious to learn more about React Native, check out the [Introduction to React Native](getting-started). diff --git a/website/versioned_docs/version-0.77/_integration-with-existing-apps-ios.md b/website/versioned_docs/version-0.77/_integration-with-existing-apps-ios.md new file mode 100644 index 00000000000..e822392efbe --- /dev/null +++ b/website/versioned_docs/version-0.77/_integration-with-existing-apps-ios.md @@ -0,0 +1,605 @@ +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; + +## Key Concepts + +The keys to integrating React Native components into your iOS application are to: + +1. Set up the correct directory structure. +2. Install the necessary NPM dependencies. +3. Adding React Native to your Podfile configuration. +4. Writing the TypeScript code for your first React Native screen. +5. Integrate React Native with your iOS code using a `RCTRootView`. +6. Testing your integration by running the bundler and seeing your app in action. + +## Using the Community Template + +While you follow this guide, we suggest you to use the [React Native Community Template](https://github.com/react-native-community/template/) as reference. The template contains a **minimal iOS app** and will help you understanding how to integrate React Native into an existing iOS app. + +## Prerequisites + +Follow the guide on [setting up your development environment](set-up-your-environment) and using [React Native without a framework](getting-started-without-a-framework) to configure your development environment for building React Native apps for iOS. +This guide also assumes you're familiar with the basics of iOS development such as creating a `UIViewController` and editing the `Podfile` file. + +### 1. Set up directory structure + +To ensure a smooth experience, create a new folder for your integrated React Native project, then **move your existing iOS project** to the `/ios` subfolder. + +## 2. Install NPM dependencies + +Go to the root directory and run the following command: + +```shell +curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.77-stable/template/package.json +``` + +This will copy the `package.json` [file from the Community template](https://github.com/react-native-community/template/blob/0.77-stable/template/package.json) to your project. + +Next, install the NPM packages by running: + + + + +```shell +npm install +``` + + + + +```shell +yarn install +``` + + + + +Installation process has created a new `node_modules` folder. This folder stores all the JavaScript dependencies required to build your project. + +Add `node_modules/` to your `.gitignore` file (here the [Community default one](https://github.com/react-native-community/template/blob/0.77-stable/template/_gitignore)). + +### 3. Install Development tools + +### Command Line Tools for Xcode + +Install the Command Line Tools. Choose **Settings... (or Preferences...)** in the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown. + +![Xcode Command Line Tools](/docs/assets/GettingStartedXcodeCommandLineTools.png) + +### CocoaPods + +[CocoaPods](https://cocoapods.org) is a package management tool for iOS and macOS development. We use it to add the actual React Native framework code locally into your current project. + +We recommend installing CocoaPods using [Homebrew](https://brew.sh/): + +```shell +brew install cocoapods +``` + +## 4. Adding React Native to your app + +### Configuring CocoaPods + +To configure CocoaPods, we need two files: + +- A **Gemfile** that defines which Ruby dependencies we need. +- A **Podfile** that defines how to properly install our dependencies. + +For the **Gemfile**, go to the root directory of your project and run this command + +```sh +curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.77-stable/template/Gemfile +``` + +This will download the Gemfile from the template. +Similarly, for the **Podfile**, go to the `ios` folder of your project and run + +```sh +curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.77-stable/template/ios/Podfile +``` + +Please use the Community Template as a reference point for the [Gemfile](https://github.com/react-native-community/template/blob/0.77-stable/template/Gemfile) and for the [Podfile](https://github.com/react-native-community/template/blob/0.77-stable/template/ios/Podfile). + +:::note +Remember to change [this line](https://github.com/react-native-community/template/blob/0.77-stable/template/ios/Podfile#L17) and [this line](https://github.com/react-native-community/template/blob/0.77-stable/template/ios/Podfile#L26) of the Podfile to match the name of your app. + +If your app don't have tests, remember to remove [this block](https://github.com/react-native-community/template/blob/0.77-stable/template/ios/Podfile#L26-L29). +::: + +Now, we need to run a couple of extra commands to install the Ruby gems and the Pods. +Navigate to the `ios` folder and run the following commands: + +```sh +bundle install +bundle exec pod install +``` + +The first command will install the Ruby dependencies and the second command will actually integrate the React Native code in your application so that your iOS files can import the React Native headers. + +## 5. Writing the TypeScript Code + +Now we will actually modify the native iOS application to integrate React Native. + +The first bit of code we will write is the actual React Native code for the new screen that will be integrated into our application. + +### Create a `index.js` file + +First, create an empty `index.js` file in the root of your React Native project. + +`index.js` is the starting point for React Native applications, and it is always required. It can be a small file that `import`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. + +Our `index.js` should look as follows (here the [Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/index.js)): + +```js +import {AppRegistry} from 'react-native'; +import App from './App'; + +AppRegistry.registerComponent('HelloWorld', () => App); +``` + +### Create a `App.tsx` file + +Let's create an `App.tsx` file. This is a [TypeScript](https://www.typescriptlang.org/) file that can have [JSX]() expressions. It contains the root React Native component that we will integrate into our iOS application ([link](https://github.com/react-native-community/template/blob/0.77-stable/template/App.tsx)): + +```tsx +import React from 'react'; +import { + SafeAreaView, + ScrollView, + StatusBar, + StyleSheet, + Text, + useColorScheme, + View, +} from 'react-native'; + +import { + Colors, + DebugInstructions, + Header, + ReloadInstructions, +} from 'react-native/Libraries/NewAppScreen'; + +function App(): React.JSX.Element { + const isDarkMode = useColorScheme() === 'dark'; + + const backgroundStyle = { + backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, + }; + + return ( + + + +
+ + Step One + + Edit App.tsx to + change this screen and see your edits. + + See your changes + + Debug + + + + + ); +} + +const styles = StyleSheet.create({ + title: { + fontSize: 24, + fontWeight: '600', + }, + bold: { + fontWeight: '700', + }, +}); + +export default App; +``` + +Here the [Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/App.tsx) + +## 5. Integrating with your iOS code + +We now need to add some native code in order to start the React Native runtime and tell it to render our React components. + +### Requirements + +React Native is supposed to work with the `AppDelegate`. The following part assumes that your `AppDelegate` looks like this: + + + + +```objc title="AppDelegate.m" +#import "AppDelegate.h" +#import "ViewController.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate { + UIWindow *window; +} + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + window = [UIWindow new]; + window.rootViewController = [ViewController new]; + [window makeKeyAndVisible]; + return YES; +} + +@end +``` + + + + +```swift title="AppDelegate.swift" +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + window = UIWindow() + window?.rootViewController = ViewController() + window?.makeKeyAndVisible() + return true + } +} +``` + + + + +### Update the `AppDelegate` class + +First, we need to extends the `AppDelegate` to inherit from one of the classes provided by React Native: `RCTAppDelegate`. + + + + +To achieve this, we have to modify the `AppDelegate.h` file and the `AppDelegate.m` files: + +1. Open the `AppDelegate.h` files and modify it as it follows (See the official template's [AppDelegate.h](https://github.com/react-native-community/template/blob/0.76-stable/template/ios/HelloWorld/AppDelegate.h) as reference): + +```diff title="AppDelegate.h changes" +#import ++#import + +-@interface AppDelegate : UIResponder ++@interface AppDelegate : RCTAppDelegate + + +@end +``` + +2. Open the `AppDelegate.mm` file and modify it as it follows (See the official template's [AppDelegate.mm](https://github.com/react-native-community/template/blob/0.76-stable/template/ios/HelloWorld/AppDelegate.mm) as reference + +```diff title="AppDelegate.mm" +#import "AppDelegate.h" +#import "ViewController.h" ++#import + +@interface AppDelegate () + +@end + +@implementation AppDelegate { + UIWindow *window; +} + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ++ self.automaticallyLoadReactNativeWindow = NO; ++ return [super application:application didFinishLaunchingWithOptions:launchOptions]; + window = [UIWindow new]; + window.rootViewController = [ViewController new]; + [window makeKeyAndVisible]; + return YES; + + } + ++- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge ++{ ++ return [self bundleURL]; ++} + ++- (NSURL *)bundleURL ++{ ++#if DEBUG ++ return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; ++#else ++ return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; ++#endif ++} + @end +``` + +Let's have a look at the code above: + +1. We are inheriting from the `RCTAppDelegate` and we are calling the `application:didFinishLaunchingWithOptions` of the `RCTAppDelegate`. This delegates all the React Native initialization processes to the base class. +2. We are customizing the `RCTAppDelegate` by setting the `automaticallyLoadReactNativeWindow` to `NO`. This step instruct React Native that the app is handling the `UIWindow` and React Native should not worry about that. +3. The methods `sourceURLForBridge:` and `bundleURL` are used by the App to tell to React Native where it can find the JS bundle that needs to be rendered. The `sourceURLForBridge:` is from the Old Architecture and you can see that it is deferring the decision to the `bundleURL` method, required by the New Architecture. + + + + +To achieve this, we have to modify the `AppDelegate.swift` + +1. Open the `AppDelegate.swift` files and modify it as it follows (See the official template's [AppDelegate.swift](https://github.com/react-native-community/template/blob/main/template/ios/HelloWorld/AppDelegate.swift) as reference): + +```diff title="AppDelegate.swift" +import UIKit ++import React_RCTAppDelegate + +@main +-class AppDelegate: UIResponder, UIApplicationDelegate { ++class AppDelegate: RCTAppDelegate { + +- var window: UIWindow? + +- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { ++ override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. ++ self.automaticallyLoadReactNativeWindow = false ++ super.application(application, didFinishLaunchingWithOptions: launchOptions) + window = UIWindow() +- window?.rootViewController = ViewController() +- window?.makeKeyAndVisible() ++ window.rootViewController = ViewController() ++ window.makeKeyAndVisible() + return true + } + ++ override func sourceURL(for bridge: RCTBridge) -> URL? { ++ self.bundleURL() ++ } + ++ override func bundleURL() -> URL? { ++#if DEBUG ++ RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") ++#else ++ Bundle.main.url(forResource: "main", withExtension: "jsbundle") ++#endif ++ } +} +``` + +Let's have a look at the code above: + +1. We are inheriting from the `RCTAppDelegate` and we are calling the `application(_:didFinishLaunchingWithOptions:)` of the `RCTAppDelegate`. This delegates all the React Native initialization processes to the base class. +2. We are customizing the `RCTAppDelegate` by setting the `automaticallyLoadReactNativeWindow` to `false`. This step instruct React Native that the app is handling the `UIWindow` and React Native should not worry about that. +3. The methods `sourceURLForBridge(for:)` and `bundleURL()` are used by the App to tell to React Native where it can find the JS bundle that needs to be rendered. The `sourceURLForBridge(for:)` is from the Old Architecture and you can see that it is deferring the decision to the `bundleURL()` method, required by the New Architecture. + + + + +#### Presenting a React Native view in a rootViewController + +Finally, we can present our React Native view. To do so, we need a new View Controller that can host a view in which we can load the JS content. + +1. From Xcode, let's create a new `UIViewController` (Let's call it `ReactViewController`). +2. Have the Initial `ViewController` present the `ReactViewController`. There are several ways to do so, depending on your app. For this example, we assume that you have a button that presents React Native Modally. + + + + +```diff title="ViewController.m" +#import "ViewController.h" ++#import "ReactViewController.h" + +@interface ViewController () + +@end + +- @implementation ViewController ++@implementation ViewController { ++ ReactViewController *reactViewController; ++} + + - (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.view.backgroundColor = UIColor.systemBackgroundColor; ++ UIButton *button = [UIButton new]; ++ [button setTitle:@"Open React Native" forState:UIControlStateNormal]; ++ [button setTitleColor:UIColor.systemBlueColor forState:UIControlStateNormal]; ++ [button setTitleColor:UIColor.blueColor forState:UIControlStateHighlighted]; ++ [button addTarget:self action:@selector(presentReactNative) forControlEvents:UIControlEventTouchUpInside]; ++ [self.view addSubview:button]; + ++ button.translatesAutoresizingMaskIntoConstraints = NO; ++ [NSLayoutConstraint activateConstraints:@[ ++ [button.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], ++ [button.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], ++ [button.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor], ++ [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], ++ ]]; + } + ++- (void)presentReactNative ++{ ++ if (reactViewController == NULL) { ++ reactViewController = [ReactViewController new]; ++ } ++ [self presentViewController:reactViewController animated:YES completion:nil]; ++} + +@end +``` + + + + +```diff title="ViewController.swift" +import UIKit + +class ViewController: UIViewController { + ++ var reactViewController: ReactViewController? + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + self.view.backgroundColor = .systemBackground + ++ let button = UIButton() ++ button.setTitle("Open React Native", for: .normal) ++ button.setTitleColor(.systemBlue, for: .normal) ++ button.setTitleColor(.blue, for: .highlighted) ++ button.addAction(UIAction { [weak self] _ in ++ guard let self else { return } ++ if reactViewController == nil { ++ reactViewController = ReactViewController() ++ } ++ present(reactViewController!, animated: true) ++ }, for: .touchUpInside) ++ self.view.addSubview(button) ++ ++ button.translatesAutoresizingMaskIntoConstraints = false ++ NSLayoutConstraint.activate([ ++ button.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), ++ button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), ++ button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), ++ button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor), ++ ]) + } +} +``` + + + + +3. Update the `ReactViewController` code as it follows: + + + + +```diff title="ReactViewController.m" +#import "ReactViewController.h" ++#import ++#import + +@interface ReactViewController () + +@end + +@implementation ReactViewController + + - (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. ++ RCTRootViewFactory *factory = ((RCTAppDelegate *)RCTSharedApplication().delegate).rootViewFactory; ++ self.view = [factory viewWithModuleName:@"HelloWorld"]; + } + +@end +``` + + + + +```diff title="ReactViewController.swift" +import UIKit ++import React_RCTAppDelegate + +class ReactViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + ++ let factory = (RCTSharedApplication()?.delegate as? RCTAppDelegate)?.rootViewFactory ++ self.view = factory?.view(withModuleName: "HelloWorld") + } +} +``` + + + + +4. Make sure to disable the Sandbox scripting. To achieve this, in Xcode, click on your app, then on build settings. Filter for script and set the `User Script Sandboxing` to `NO`. This step is needed to properly switch between the Debug and Release version of the [Hermes engine](https://github.com/facebook/hermes/blob/main/README.md) that we ship with React Native. + +![Disable Sandboxing](/docs/assets/disable-sandboxing.png); + +## 6. Test your integration + +You have completed all the basic steps to integrate React Native with your application. Now we will start the [Metro bundler](https://metrobundler.dev/) to build your TypeScript application code into a bundle. Metro's HTTP server shares the bundle from `localhost` on your developer environment to a simulator or device. This allows for [hot reloading](https://reactnative.dev/blog/2016/03/24/introducing-hot-reloading). + +First, you need to create a `metro.config.js` file in the root of your project as follows: + +```js +const {getDefaultConfig} = require('@react-native/metro-config'); +module.exports = getDefaultConfig(__dirname); +``` + +You can checkout the [metro.config.js file](https://github.com/react-native-community/template/blob/0.77-stable/template/metro.config.js) from the Community template file as reference. + +Once you have the config file in place, you can run the bundler. Run the following command in the root directory of your project: + + + + +```shell +npm start +``` + + + + +```shell +yarn start +``` + + + + +Now build and run your iOS app as normal. + +Once you reach your React-powered Activity inside the app, it should load the JavaScript code from the development server and display: + +
+ +### Creating a release build in Xcode + +You can use Xcode to create your release builds too! The only additional step is to add a script that is executed when the app is built to package your JS and images into the iOS application. + +1. In Xcode, select your application +2. Click on `Build Phases` +3. Click on the `+` in the top left corner and select `New Run Script Phase` +4. Click on the `Run Script` line and rename the Script to `Bundle React Native code and images` +5. Paste in the text box the following script + +```sh title="Build React Native code and image" +set -e + +WITH_ENVIRONMENT="$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh" +REACT_NATIVE_XCODE="$REACT_NATIVE_PATH/scripts/react-native-xcode.sh" + +/bin/sh -c "$WITH_ENVIRONMENT $REACT_NATIVE_XCODE" +``` + +6. Drag and drop the script before the one called `[CP] Embed Pods Frameworks`. + +Now, if you build your app for Release, it will work as expected. + +### Now what? + +At this point you can continue developing your app as usual. Refer to our [debugging](debugging) and [deployment](running-on-device) docs to learn more about working with React Native. diff --git a/website/versioned_docs/version-0.77/_integration-with-existing-apps-kotlin.md b/website/versioned_docs/version-0.77/_integration-with-existing-apps-kotlin.md new file mode 100644 index 00000000000..e39fd640b5b --- /dev/null +++ b/website/versioned_docs/version-0.77/_integration-with-existing-apps-kotlin.md @@ -0,0 +1,506 @@ +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; + +## Key Concepts + +The keys to integrating React Native components into your Android application are to: + +1. Set up the correct directory structure. +2. Install the necessary NPM dependencies. +3. Adding React Native to your Gradle configuration. +4. Writing the TypeScript code for your first React Native screen. +5. Integrate React Native with your Android code using a ReactActivity. +6. Testing your integration by running the bundler and seeing your app in action. + +## Using the Community Template + +While you follow this guide, we suggest you to use the [React Native Community Template](https://github.com/react-native-community/template/) as reference. The template contains a **minimal Android app** and will help you understanding how to integrate React Native into an existing Android app. + +## Prerequisites + +Follow the guide on [setting up your development environment](set-up-your-environment) and using [React Native without a framework](getting-started-without-a-framework) to configure your development environment for building React Native apps for Android. +This guide also assumes you're familiar with the basics of Android development such as creating Activities and editing the `AndroidManifest.xml` file. + +## 1. Set up directory structure + +To ensure a smooth experience, create a new folder for your integrated React Native project, then **move your existing Android project** to the `/android` subfolder. + +## 2. Install NPM dependencies + +Go to the root directory and run the following command: + +```shell +curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.75-stable/template/package.json +``` + +This will copy the `package.json` [file from the Community template](https://github.com/react-native-community/template/blob/0.75-stable/template/package.json) to your project. + +Next, install the NPM packages by running: + + + + +```shell +npm install +``` + + + + +```shell +yarn install +``` + + + + +Installation process has created a new `node_modules` folder. This folder stores all the JavaScript dependencies required to build your project. + +Add `node_modules/` to your `.gitignore` file (here the [Community default one](https://github.com/react-native-community/template/blob/0.75-stable/template/_gitignore)). + +## 3. Adding React Native to your app + +### Configuring Gradle + +React Native uses the React Native Gradle Plugin to configure your dependencies and project setup. + +First, let's edit your `settings.gradle` file by adding those lines (as suggested from the [Community template](https://github.com/react-native-community/template/blob/0.77-stable/template/android/settings.gradle)): + +```groovy +// Configures the React Native Gradle Settings plugin used for autolinking +pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } +plugins { id("com.facebook.react.settings") } +extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } +// If using .gradle.kts files: +// extensions.configure { autolinkLibrariesFromCommand() } +includeBuild("../node_modules/@react-native/gradle-plugin") + +// Include your existing Gradle modules here. +// include(":app") +``` + +Then you need to open your top level `build.gradle` and include this line (as suggested from the [Community template](https://github.com/react-native-community/template/blob/0.77-stable/template/android/build.gradle)): + +```diff +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:7.3.1") ++ classpath("com.facebook.react:react-native-gradle-plugin") + } +} +``` + +This makes sure the React Native Gradle Plugin (RNGP) is available inside your project. +Finally, add those lines inside your Applications's `build.gradle` file (it's a different `build.gradle` file usually inside your `app` folder - you can use the [Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/android/app/build.gradle)): + +```diff +apply plugin: "com.android.application" ++apply plugin: "com.facebook.react" + +repositories { + mavenCentral() +} + +dependencies { + // Other dependencies here ++ // Note: we intentionally don't specify the version number here as RNGP will take care of it. ++ // If you don't use the RNGP, you'll have to specify version manually. ++ implementation("com.facebook.react:react-android") ++ implementation("com.facebook.react:hermes-android") +} + ++react { ++ // Needed to enable Autolinking - https://github.com/react-native-community/cli/blob/master/docs/autolinking.md ++ autolinkLibrariesWithApp() ++} +``` + +Finally, open your application `gradle.properties` files and add the following line (here the [Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/android/gradle.properties)): + +```diff ++reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 ++newArchEnabled=true ++hermesEnabled=true +``` + +### Configuring your manifest + +First, make sure you have the Internet permission in your `AndroidManifest.xml`: + +```diff + + ++ + + + + +``` + +Then you need to enable [cleartext traffic](https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted) in your **debug** `AndroidManifest.xml`: + +```diff + + + + + +``` + +As usual, here the AndroidManifest.xml file from the Community template to use as a reference: [main](https://github.com/react-native-community/template/blob/0.77-stable/template/android/app/src/main/AndroidManifest.xml) and [debug](https://github.com/react-native-community/template/blob/0.77-stable/template/android/app/src/debug/AndroidManifest.xml) + +This is needed as your application will communicate with your local bundler, [Metro][https://metrobundler.dev/], via HTTP. + +Make sure you add this only to your **debug** manifest. + +## 4. Writing the TypeScript Code + +Now we will actually modify the native Android application to integrate React Native. + +The first bit of code we will write is the actual React Native code for the new screen that will be integrated into our application. + +### Create a `index.js` file + +First, create an empty `index.js` file in the root of your React Native project. + +`index.js` is the starting point for React Native applications, and it is always required. It can be a small file that `import`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. + +Our index.js should look as follows (here the [Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/index.js)): + +```js +import {AppRegistry} from 'react-native'; +import App from './App'; + +AppRegistry.registerComponent('HelloWorld', () => App); +``` + +### Create a `App.tsx` file + +Let's create an `App.tsx` file. This is a [TypeScript](https://www.typescriptlang.org/) file that can have [JSX]() expressions. It contains the root React Native component that we will integrate into our Android application ([link](https://github.com/react-native-community/template/blob/0.77-stable/template/App.tsx)): + +```tsx +import React from 'react'; +import { + SafeAreaView, + ScrollView, + StatusBar, + StyleSheet, + Text, + useColorScheme, + View, +} from 'react-native'; + +import { + Colors, + DebugInstructions, + Header, + ReloadInstructions, +} from 'react-native/Libraries/NewAppScreen'; + +function App(): React.JSX.Element { + const isDarkMode = useColorScheme() === 'dark'; + + const backgroundStyle = { + backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, + }; + + return ( + + + +
+ + Step One + + Edit App.tsx to + change this screen and see your edits. + + See your changes + + Debug + + + + + ); +} + +const styles = StyleSheet.create({ + title: { + fontSize: 24, + fontWeight: '600', + }, + bold: { + fontWeight: '700', + }, +}); + +export default App; +``` + +Here the [Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/App.tsx) + +## 5. Integrating with your Android code + +We now need to add some native code in order to start the React Native runtime and tell it to render our React components. + +### Updating your Application class + +First, we need to update your `Application` class to properly initialize React Native as follows: + + + + + +```diff +package ; + +import android.app.Application; ++import com.facebook.react.PackageList; ++import com.facebook.react.ReactApplication; ++import com.facebook.react.ReactHost; ++import com.facebook.react.ReactNativeHost; ++import com.facebook.react.ReactPackage; ++import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; ++import com.facebook.react.defaults.DefaultReactHost; ++import com.facebook.react.defaults.DefaultReactNativeHost; ++import com.facebook.soloader.SoLoader; ++import com.facebook.react.soloader.OpenSourceMergedSoMapping ++import java.util.List; + +-class MainApplication extends Application { ++class MainApplication extends Application implements ReactApplication { ++ @Override ++ public ReactNativeHost getReactNativeHost() { ++ return new DefaultReactNativeHost(this) { ++ @Override ++ protected List getPackages() { return new PackageList(this).getPackages(); } ++ @Override ++ protected String getJSMainModuleName() { return "index"; } ++ @Override ++ public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } ++ @Override ++ protected boolean isNewArchEnabled() { return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; } ++ @Override ++ protected Boolean isHermesEnabled() { return BuildConfig.IS_HERMES_ENABLED; } ++ }; ++ } + ++ @Override ++ public ReactHost getReactHost() { ++ return DefaultReactHost.getDefaultReactHost(getApplicationContext(), getReactNativeHost()); ++ } + + @Override + public void onCreate() { + super.onCreate(); ++ SoLoader.init(this, OpenSourceMergedSoMapping); ++ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { ++ DefaultNewArchitectureEntryPoint.load(); ++ } + } +} +``` + + + + + +```diff +// package + +import android.app.Application ++import com.facebook.react.PackageList ++import com.facebook.react.ReactApplication ++import com.facebook.react.ReactHost ++import com.facebook.react.ReactNativeHost ++import com.facebook.react.ReactPackage ++import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load ++import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost ++import com.facebook.react.defaults.DefaultReactNativeHost ++import com.facebook.soloader.SoLoader ++import com.facebook.react.soloader.OpenSourceMergedSoMapping + +-class MainApplication : Application() { ++class MainApplication : Application(), ReactApplication { + ++ override val reactNativeHost: ReactNativeHost = ++ object : DefaultReactNativeHost(this) { ++ override fun getPackages(): List = PackageList(this).packages ++ override fun getJSMainModuleName(): String = "index" ++ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG ++ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED ++ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED ++ } + ++ override val reactHost: ReactHost ++ get() = getDefaultReactHost(applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() ++ SoLoader.init(this, OpenSourceMergedSoMapping) ++ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { ++ load() ++ } + } +} +``` + + + + +As usual, here the [MainApplication.kt Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/android/app/src/main/java/com/helloworld/MainApplication.kt) + +#### Creating a `ReactActivity` + +Finally, we need to create a new `Activity` that will extend `ReactActivity` and host the React Native code. This activity will be responsible for starting the React Native runtime and rendering the React component. + + + + + +```java +// package ; + +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactActivityDelegate; + +public class MyReactActivity extends ReactActivity { + + @Override + protected String getMainComponentName() { + return "HelloWorld"; + } + + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new DefaultReactActivityDelegate(this, getMainComponentName(), DefaultNewArchitectureEntryPoint.getFabricEnabled()); + } +} +``` + + + + + +```kotlin +// package + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MyReactActivity : ReactActivity() { + + override fun getMainComponentName(): String = "HelloWorld" + + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} +``` + + + + +As usual, here the [MainActivity.kt Community template file as reference](https://github.com/react-native-community/template/blob/0.77-stable/template/android/app/src/main/java/com/helloworld/MainApplication.kt) + +Whenever you create a new Activity, you need to add it to your `AndroidManifest.xml` file. You also need set the theme of `MyReactActivity` to `Theme.AppCompat.Light.NoActionBar` (or to any non-ActionBar theme) as otherwise your application will render an ActionBar on top of your React Native screen: + +```diff + + + + + + ++ ++ + + +``` + +Now your activity is ready to run some JavaScript code. + +## 6. Test your integration + +You have completed all the basic steps to integrate React Native with your application. Now we will start the [Metro bundler](https://metrobundler.dev/) to build your TypeScript application code into a bundle. Metro's HTTP server shares the bundle from `localhost` on your developer environment to a simulator or device. This allows for [hot reloading](https://reactnative.dev/blog/2016/03/24/introducing-hot-reloading). + +First, you need to create a `metro.config.js` file in the root of your project as follows: + +```js +const {getDefaultConfig} = require('@react-native/metro-config'); +module.exports = getDefaultConfig(__dirname); +``` + +You can checkout the [metro.config.js file](https://github.com/react-native-community/template/blob/0.77-stable/template/metro.config.js) from the Community template file as reference. + +Once you have the config file in place, you can run the bundler. Run the following command in the root directory of your project: + + + + +```shell +npm start +``` + + + + +```shell +yarn start +``` + + + + +Now build and run your Android app as normal. + +Once you reach your React-powered Activity inside the app, it should load the JavaScript code from the development server and display: + +
+ +### Creating a release build in Android Studio + +You can use Android Studio to create your release builds too! It’s as quick as creating release builds of your previously-existing native Android app. + +The React Native Gradle Plugin will take care of bundling the JS code inside your APK/App Bundle. + +If you're not using Android Studio, you can create a release build with: + +``` +cd android +# For a Release APK +./gradlew :app:assembleRelease +# For a Release AAB +./gradlew :app:bundleRelease +``` + +### Now what? + +At this point you can continue developing your app as usual. Refer to our [debugging](debugging) and [deployment](running-on-device) docs to learn more about working with React Native. diff --git a/website/versioned_docs/version-0.77/_markdown-new-architecture-warning.mdx b/website/versioned_docs/version-0.77/_markdown-new-architecture-warning.mdx new file mode 100644 index 00000000000..d52c490153b --- /dev/null +++ b/website/versioned_docs/version-0.77/_markdown-new-architecture-warning.mdx @@ -0,0 +1,7 @@ +:::caution + +This documentation is still **experimental** and details are subject to changes as we iterate. Feel free to share your feedback on the [discussion inside the working group](https://github.com/reactwg/react-native-new-architecture/discussions/8) for this page. + +Moreover, it contains several **manual steps**. Please note that this won't be representative of the final developer experience once the New Architecture is stable. We're working on tools, templates and libraries to help you get started fast on the New Architecture, without having to go through the whole setup. + +::: diff --git a/website/versioned_docs/version-0.77/_remove-global-cli.md b/website/versioned_docs/version-0.77/_remove-global-cli.md new file mode 100644 index 00000000000..08d0d9ba3c1 --- /dev/null +++ b/website/versioned_docs/version-0.77/_remove-global-cli.md @@ -0,0 +1,5 @@ +> If you previously installed a global `react-native-cli` package, please remove it as it may cause unexpected issues: +> +> ```shell +> npm uninstall -g react-native-cli @react-native-community/cli +> ``` diff --git a/website/versioned_docs/version-0.77/_turbo-native-modules-components.jsx b/website/versioned_docs/version-0.77/_turbo-native-modules-components.jsx new file mode 100644 index 00000000000..1bb5a1b5edb --- /dev/null +++ b/website/versioned_docs/version-0.77/_turbo-native-modules-components.jsx @@ -0,0 +1,11 @@ +import React from 'react'; +import IOSContent from './turbo-native-modules-ios.md'; +import AndroidContent from './turbo-native-modules-android.md'; + +export function TurboNativeModulesIOS() { + return ; +} + +export function TurboNativeModulesAndroid() { + return ; +} diff --git a/website/versioned_docs/version-0.77/accessibility.md b/website/versioned_docs/version-0.77/accessibility.md new file mode 100644 index 00000000000..33e1708e43e --- /dev/null +++ b/website/versioned_docs/version-0.77/accessibility.md @@ -0,0 +1,508 @@ +--- +id: accessibility +title: Accessibility +description: Create mobile apps accessible to assistive technology with React Native's suite of APIs designed to work with Android and iOS. +--- + +Both Android and iOS provide APIs for integrating apps with assistive technologies like the bundled screen readers VoiceOver (iOS) and TalkBack (Android). React Native has complementary APIs that let your app accommodate all users. + +:::info +Android and iOS differ slightly in their approaches, and thus the React Native implementations may vary by platform. +::: + +## Accessibility properties + +### `accessible` + +When `true`, indicates that the view is an accessibility element. When a view is an accessibility element, it groups its children into a single selectable component. By default, all touchable elements are accessible. + +On Android, `accessible={true}` property for a react-native View will be translated into native `focusable={true}`. + +```tsx + + text one + text two + +``` + +In the above example, accessibility focus is only available on the parent view with the `accessible` property, and not individually for 'text one' and 'text two'. + +### `accessibilityLabel` + +When a view is marked as accessible, it is a good practice to set an `accessibilityLabel` on the view, so that people who use VoiceOver or TalkBack know what element they have selected. A screen reader will verbalize this string when the associated element is selected. + +To use, set the `accessibilityLabel` property to a custom string on your View, Text, or Touchable: + +```tsx + + + Press me! + + +``` + +In the above example, the `accessibilityLabel` on the TouchableOpacity element would default to "Press me!". The label is constructed by concatenating all Text node children separated by spaces. + +### `accessibilityLabelledBy`
Android
+ +A reference to another element [nativeID](view.md#nativeid) used to build complex forms. +The value of `accessibilityLabelledBy` should match the `nativeID` of the related element: + +```tsx + + Label for Input Field + + +``` + +In the above example, the screen reader announces `Input, Edit Box for Label for Input Field` when focusing on the TextInput. + +### `accessibilityHint` + +An accessibility hint can be used to provide additional context to the user on the result of the action when it is not clear from the accessibility label alone. + +Provide the `accessibilityHint` property a custom string on your View, Text, or Touchable: + +```tsx + + + Back + + +``` + +
iOS
+ +In the above example, VoiceOver will read the hint after the label, if the user has hints enabled in the device's VoiceOver settings. Read more about guidelines for `accessibilityHint` in the [iOS Developer Docs](https://developer.apple.com/documentation/objectivec/nsobject/1615093-accessibilityhint) + +
Android
+ +In the above example, TalkBack will read the hint after the label. At this time, hints cannot be turned off on Android. + +### `accessibilityLanguage`
iOS
+ +By using the `accessibilityLanguage` property, the screen reader will understand which language to use while reading the element's **label**, **value**, and **hint**. The provided string value must follow the [BCP 47 specification](https://www.rfc-editor.org/info/bcp47). + +```tsx + + 🍕 + +``` + +### `accessibilityIgnoresInvertColors`
iOS
+ +Inverting screen colors is an accessibility feature available in iOS and iPadOS for people with color blindness, low vision, or vision impairment. If there's a view you don't want to invert when this setting is on, possibly a photo, set this property to `true`. + +### `accessibilityLiveRegion`
Android
+ +When components dynamically change, we want TalkBack to alert the end user. This is made possible by the `accessibilityLiveRegion` property. It can be set to `none`, `polite`, and `assertive`: + +- **none** Accessibility services should not announce changes to this view. +- **polite** Accessibility services should announce changes to this view. +- **assertive** Accessibility services should interrupt ongoing speech to immediately announce changes to this view. + +```tsx + + + Click me + + + + Clicked {count} times + +``` + +In the above example method `addOne` changes the state variable `count`. When the TouchableWithoutFeedback is triggered, TalkBack reads the text in the Text view because of its `accessibilityLiveRegion="polite"` property. + +### `accessibilityRole` + +`accessibilityRole` communicates the purpose of a component to the user of assistive technology. + +`accessibilityRole` can be one of the following: + +- **adjustable** Used when an element can be "adjusted" (e.g. a slider). +- **alert** Used when an element contains important text to be presented to the user. +- **button** Used when the element should be treated as a button. +- **checkbox** Used when an element represents a checkbox that can be checked, unchecked, or have a mixed checked state. +- **combobox** Used when an element represents a combo box, which allows the user to select among several choices. +- **header** Used when an element acts as a header for a content section (e.g. the title of a navigation bar). +- **image** Used when the element should be treated as an image. Can be combined with a button or link. +- **imagebutton** Used when the element should be treated as a button and is also an image. +- **keyboardkey** Used when the element acts as a keyboard key. +- **link** Used when the element should be treated as a link. +- **menu** Used when the component is a menu of choices. +- **menubar** Used when a component is a container of multiple menus. +- **menuitem** Used to represent an item within a menu. +- **none** Used when the element has no role. +- **progressbar** Used to represent a component that indicates the progress of a task. +- **radio** Used to represent a radio button. +- **radiogroup** Used to represent a group of radio buttons. +- **scrollbar** Used to represent a scroll bar. +- **search** Used when a text field element should also be treated as a search field. +- **spinbutton** Used to represent a button that opens a list of choices. +- **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. +- **switch** Used to represent a switch that can be turned on and off. +- **tab** Used to represent a tab. +- **tablist** Used to represent a list of tabs. +- **text** Used when the element should be treated as static text that cannot change. +- **timer** Used to represent a timer. +- **togglebutton** Used to represent a toggle button. Should be used with accessibilityState checked to indicate if the button is toggled on or off. +- **toolbar** Used to represent a toolbar (a container of action buttons or components). +- **grid** Used with ScrollView, VirtualizedList, FlatList, or SectionList to represent a grid. Adds the in/out of grid announcements to Android's GridView. + +### `accessibilityShowsLargeContentViewer`
iOS
+ +A boolean value that determines whether the large content viewer is shown when the user performs a long press on the element. + +Available in iOS 13.0 and later. + +### `accessibilityLargeContentTitle`
iOS
+ +A string that will be used as the title of the large content viewer when it is shown. + +Requires `accessibilityShowsLargeContentViewer` to be set to `true`. + +```tsx + + Home + +``` + +### `accessibilityState` + +Describes the current state of a component to the assistive technology user. + +`accessibilityState` is an object. It contains the following fields: + +| Name | Description | Type | Required | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- | +| disabled | Indicates whether the element is disabled or not. | boolean | No | +| selected | Indicates whether a selectable element is currently selected or not. | boolean | No | +| checked | Indicates the state of a checkable element. This field can either take a boolean or the "mixed" string to represent mixed checkboxes. | boolean or 'mixed' | No | +| busy | Indicates whether an element is currently busy or not. | boolean | No | +| expanded | Indicates whether an expandable element is currently expanded or collapsed. | boolean | No | + +To use, set the `accessibilityState` to an object with a specific definition. + +### `accessibilityValue` + +Represents the current value of a component. It can be a textual description of a component's value, or for range-based components, such as sliders and progress bars, it contains range information (minimum, current, and maximum). + +`accessibilityValue` is an object. It contains the following fields: + +| Name | Description | Type | Required | +| ---- | ---------------------------------------------------------------------------------------------- | ------- | ------------------------- | +| min | The minimum value of this component's range. | integer | Required if `now` is set. | +| max | The maximum value of this component's range. | integer | Required if `now` is set. | +| now | The current value of this component's range. | integer | No | +| text | A textual description of this component's value. Will override `min`, `now`, and `max` if set. | string | No | + +### `accessibilityViewIsModal`
iOS
+ +A boolean value that indicates whether VoiceOver should ignore the elements within views that are siblings of the receiver. + +For example, in a window that contains sibling views `A` and `B`, setting `accessibilityViewIsModal` to `true` on view `B` causes VoiceOver to ignore the elements in view `A`. On the other hand, if view `B` contains a child view `C` and you set `accessibilityViewIsModal` to `true` on view `C`, VoiceOver does not ignore the elements in view `A`. + +### `accessibilityElementsHidden`
iOS
+ +A boolean value indicating whether the accessibility elements contained within this accessibility element are hidden. + +For example, in a window that contains sibling views `A` and `B`, setting `accessibilityElementsHidden` to `true` on view `B` causes VoiceOver to ignore the elements in view `B`. This is similar to the Android property `importantForAccessibility="no-hide-descendants"`. + +### `aria-valuemax` + +Represents the maximum value for range-based components, such as sliders and progress bars. + +### `aria-valuemin` + +Represents the minimum value for range-based components, such as sliders and progress bars. + +### `aria-valuenow` + +Represents the current value for range-based components, such as sliders and progress bars. + +### `aria-valuetext` + +Represents the textual description of the component. + +### `aria-busy` + +Indicates an element is being modified and that assistive technologies may want to wait until the changes are complete before informing the user about the update. + +| Type | Default | +| ------- | ------- | +| boolean | false | + +### `aria-checked` + +Indicates the state of a checkable element. This field can either take a boolean or the "mixed" string to represent mixed checkboxes. + +| Type | Default | +| ---------------- | ------- | +| boolean, 'mixed' | false | + +### `aria-disabled` + +Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable. + +| Type | Default | +| ------- | ------- | +| boolean | false | + +### `aria-expanded` + +Indicates whether an expandable element is currently expanded or collapsed. + +| Type | Default | +| ------- | ------- | +| boolean | false | + +### `aria-hidden` + +Indicates whether the accessibility elements contained within this accessibility element are hidden. + +For example, in a window that contains sibling views `A` and `B`, setting `aria-hidden` to `true` on view `B` causes VoiceOver to ignore the elements in view `B`. + +| Type | Default | +| ------- | ------- | +| boolean | false | + +### `aria-label` + +Defines a string value that labels an interactive element. + +| Type | +| ------ | +| string | + +### `aria-labelledby`
Android
+ +Identifies the element that labels the element it is applied to. The value of `aria-labelledby` should match the [`nativeID`](view.md#nativeid) of the related element: + +```tsx + + Label for Input Field + + +``` + +| Type | +| ------ | +| string | + +### `aria-live`
Android
+ +Indicates that an element will be updated and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. + +- **off** Accessibility services should not announce changes to this view. +- **polite** Accessibility services should announce changes to this view. +- **assertive** Accessibility services should interrupt ongoing speech to immediately announce changes to this view. + +| Type | Default | +| ---------------------------------------- | ------- | +| enum(`'assertive'`, `'off'`, `'polite'`) | `'off'` | + +--- + +### `aria-modal`
iOS
+ +Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver. + +| Type | Default | +| ------- | ------- | +| boolean | false | + +### `aria-selected` + +Indicates whether a selectable element is currently selected or not. + +| Type | +| ------- | +| boolean | + +### `importantForAccessibility`
Android
+ +In the case of two overlapping UI components with the same parent, default accessibility focus can have unpredictable behavior. The `importantForAccessibility` property will resolve this by controlling if a view fires accessibility events and if it is reported to accessibility services. It can be set to `auto`, `yes`, `no` and `no-hide-descendants` (the last value will force accessibility services to ignore the component and all of its children). + +```tsx + + + First layout + + + Second layout + + +``` + +In the above example, the `yellow` layout and its descendants are completely invisible to TalkBack and all other accessibility services. So we can use overlapping views with the same parent without confusing TalkBack. + +### `onAccessibilityEscape`
iOS
+ +Assign this property to a custom function which will be called when someone performs the "escape" gesture, which is a two finger Z shaped gesture. An escape function should move back hierarchically in the user interface. This can mean moving up or back in a navigation hierarchy or dismissing a modal user interface. If the selected element does not have an `onAccessibilityEscape` function, the system will attempt to traverse up the view hierarchy until it finds a view that does or bonk to indicate it was unable to find one. + +### `onAccessibilityTap`
iOS
+ +Use this property to assign a custom function to be called when someone activates an accessible element by double tapping on it while it's selected. + +### `onMagicTap`
iOS
+ +Assign this property to a custom function which will be called when someone performs the "magic tap" gesture, which is a double-tap with two fingers. A magic tap function should perform the most relevant action a user could take on a component. In the Phone app on iPhone, a magic tap answers a phone call or ends the current one. If the selected element does not have an `onMagicTap` function, the system will traverse up the view hierarchy until it finds a view that does. + +### `role` + +`role` communicates the purpose of a component and has precedence over the [`accessibilityRole`](accessibility#accessibilityrole) prop. + +`role` can be one of the following: + +- **alert** Used when an element contains important text to be presented to the user. +- **button** Used when the element should be treated as a button. +- **checkbox** Used when an element represents a checkbox that can be checked, unchecked, or have a mixed checked state. +- **combobox** Used when an element represents a combo box, which allows the user to select among several choices. +- **grid** Used with ScrollView, VirtualizedList, FlatList, or SectionList to represent a grid. Adds the in/out of grid announcements to the android GridView. +- **heading** Used when an element acts as a header for a content section (e.g. the title of a navigation bar). +- **img** Used when the element should be treated as an image. Can be combined with a button or link, for example. +- **link** Used when the element should be treated as a link. +- **list** Used to identify a list of items. +- **listitem** Used to itentify an item in a list. +- **menu** Used when the component is a menu of choices. +- **menubar** Used when a component is a container of multiple menus. +- **menuitem** Used to represent an item within a menu. +- **none** Used when the element has no role. +- **presentation** Used when the element has no role. +- **progressbar** Used to represent a component that indicates the progress of a task. +- **radio** Used to represent a radio button. +- **radiogroup** Used to represent a group of radio buttons. +- **scrollbar** Used to represent a scroll bar. +- **searchbox** Used when the text field element should also be treated as a search field. +- **slider** Used when an element can be "adjusted" (e.g. a slider). +- **spinbutton** Used to represent a button that opens a list of choices. +- **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. +- **switch** Used to represent a switch that can be turned on and off. +- **tab** Used to represent a tab. +- **tablist** Used to represent a list of tabs. +- **timer** Used to represent a timer. +- **toolbar** Used to represent a toolbar (a container of action buttons or components). + +## Accessibility Actions + +Accessibility actions allow assistive technology to programmatically invoke the action(s) of a component. To support accessibility actions, a component must do two things: + +- Define the list of actions it supports via the `accessibilityActions` property. +- Implement an `onAccessibilityAction` function to handle action requests. + +The `accessibilityActions` property should contain a list of action objects. Each action object should contain the following fields: + +| Name | Type | Required | +| ----- | ------ | -------- | +| name | string | Yes | +| label | string | No | + +Actions either represent standard actions, such as clicking a button or adjusting a slider, or custom actions specific to a given component such as deleting an email message. The `name` field is required for both standard and custom actions, but `label` is optional for standard actions. + +When adding support for standard actions, `name` must be one of the following: + +- `'magicTap'` - iOS only - While VoiceOver focus is on or inside the component, the user double tapped with two fingers. +- `'escape'` - iOS only - While VoiceOver focus is on or inside the component, the user performed a two-finger scrub gesture (left, right, left). +- `'activate'` - Activate the component. This should perform the same action with, or without, assistive technology. Engaged when a screen reader user double taps the component. +- `'increment'` - Increment an adjustable component. On iOS, VoiceOver generates this action when the component has a role of `'adjustable'` and the user places focus on it and swipes upward. On Android, TalkBack generates this action when the user places accessibility focus on the component and presses the volume-up button. +- `'decrement'` - Decrement an adjustable component. On iOS, VoiceOver generates this action when the component has a role of `'adjustable'` and the user places focus on it and swipes downward. On Android, TalkBack generates this action when the user places accessibility focus on the component and presses the volume-down button. +- `'longpress'` - Android only - This action is generated when the user places accessibility focus on the component, then double-taps and holds one finger on the screen. This should perform the same action with, or without, assistive technology. + +The `label` field is optional for standard actions and is often unused by assistive technologies. For custom actions, it is a localized string containing a description of the action to be presented to the user. + +To handle action requests, a component must implement an `onAccessibilityAction` function. The only argument to this function is an event containing the name of the action to perform. The below example from RNTester shows how to create a component that defines and handles several custom actions. + +```tsx + { + switch (event.nativeEvent.actionName) { + case 'cut': + Alert.alert('Alert', 'cut action success'); + break; + case 'copy': + Alert.alert('Alert', 'copy action success'); + break; + case 'paste': + Alert.alert('Alert', 'paste action success'); + break; + } + }} +/> +``` + +## Checking if a Screen Reader is Enabled + +The `AccessibilityInfo` API allows you to determine whether or not a screen reader is currently active. See the [AccessibilityInfo documentation](accessibilityinfo) for details. + +## Sending Accessibility Events
Android
+ +Sometimes it is useful to trigger an accessibility event on a UI component (i.e. when a custom view appears on a screen or set accessibility focus to a view). Native UIManager module exposes a method ‘sendAccessibilityEvent’ for this purpose. It takes two arguments: a view tag and a type of event. The supported event types are `typeWindowStateChanged`, `typeViewFocused`, and `typeViewClicked`. + +```tsx +import {Platform, UIManager, findNodeHandle} from 'react-native'; + +if (Platform.OS === 'android') { + UIManager.sendAccessibilityEvent( + findNodeHandle(this), + UIManager.AccessibilityEventTypes.typeViewFocused, + ); +} +``` + +## Testing TalkBack Support
Android
+ +To enable TalkBack, go to the Settings app on your Android device or emulator. Tap Accessibility, then TalkBack. Toggle the "Use service" switch to enable or disable it. + +Android emulators don't have TalkBack installed by default. You can install TalkBack on your emulator via the Google Play Store. Make sure to choose an emulator with the Google Play store installed. These are available in Android Studio. + +You can use the volume key shortcut to toggle TalkBack. To turn on the volume key shortcut, go to the Settings app, then Accessibility. At the top, turn on the volume key shortcut. + +To use the volume key shortcut, press both volume keys for 3 seconds to start an accessibility tool. + +Additionally, if you prefer, you can toggle TalkBack via the command line with: + +```shell +# disable +adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService + +# enable +adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService +``` + +## Testing VoiceOver Support
iOS
+ +To enable VoiceOver on your iOS or iPadOS device, go to the Settings app, tap General, then Accessibility. There you will find many tools available for people to enable their devices to be more usable, including VoiceOver. To enable VoiceOver, tap on VoiceOver under "Vision" and toggle the switch that appears at the top. + +At the very bottom of the Accessibility settings, there is an "Accessibility Shortcut". You can use this to toggle VoiceOver by triple-clicking the Home button. + +VoiceOver isn't available via the simulator, but you can use Accessibility Inspector from Xcode to use the macOS VoiceOver through an application. Note it's always best to test with a device as macOS's VoiceOver may result in varied experiences. + +## Additional Resources + +- [Making React Native Apps Accessible](https://engineering.fb.com/ios/making-react-native-apps-accessible/) diff --git a/website/versioned_docs/version-0.77/accessibilityinfo.md b/website/versioned_docs/version-0.77/accessibilityinfo.md new file mode 100644 index 00000000000..47ad03012d1 --- /dev/null +++ b/website/versioned_docs/version-0.77/accessibilityinfo.md @@ -0,0 +1,245 @@ +--- +id: accessibilityinfo +title: AccessibilityInfo +--- + +Sometimes it's useful to know whether or not the device has a screen reader that is currently active. The `AccessibilityInfo` API is designed for this purpose. You can use it to query the current state of the screen reader as well as to register to be notified when the state of the screen reader changes. + +## Example + +```SnackPlayer name=AccessibilityInfo%20Example&supportedPlatforms=android,ios +import React, {useState, useEffect} from 'react'; +import {AccessibilityInfo, Text, StyleSheet} from 'react-native'; +import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context'; + +const App = () => { + const [reduceMotionEnabled, setReduceMotionEnabled] = useState(false); + const [screenReaderEnabled, setScreenReaderEnabled] = useState(false); + + useEffect(() => { + const reduceMotionChangedSubscription = AccessibilityInfo.addEventListener( + 'reduceMotionChanged', + isReduceMotionEnabled => { + setReduceMotionEnabled(isReduceMotionEnabled); + }, + ); + const screenReaderChangedSubscription = AccessibilityInfo.addEventListener( + 'screenReaderChanged', + isScreenReaderEnabled => { + setScreenReaderEnabled(isScreenReaderEnabled); + }, + ); + + AccessibilityInfo.isReduceMotionEnabled().then(isReduceMotionEnabled => { + setReduceMotionEnabled(isReduceMotionEnabled); + }); + AccessibilityInfo.isScreenReaderEnabled().then(isScreenReaderEnabled => { + setScreenReaderEnabled(isScreenReaderEnabled); + }); + + return () => { + reduceMotionChangedSubscription.remove(); + screenReaderChangedSubscription.remove(); + }; + }, []); + + return ( + + + + The reduce motion is {reduceMotionEnabled ? 'enabled' : 'disabled'}. + + + The screen reader is {screenReaderEnabled ? 'enabled' : 'disabled'}. + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + status: { + margin: 30, + }, +}); + +export default App; +``` + +--- + +# Reference + +## Methods + +### `addEventListener()` + +```tsx +static addEventListener( + eventName: AccessibilityChangeEventName | AccessibilityAnnouncementEventName, + handler: ( + event: AccessibilityChangeEvent | AccessibilityAnnouncementFinishedEvent, + ) => void, +): EmitterSubscription; +``` + +Add an event handler. Supported events: + +| Event name | Description | +| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `accessibilityServiceChanged`
Android
| Fires when some services such as TalkBack, other Android assistive technologies, and third-party accessibility services are enabled. The argument to the event handler is a boolean. The boolean is `true` when a some accessibility services is enabled and `false` otherwise. | +| `announcementFinished`
iOS
| Fires when the screen reader has finished making an announcement. The argument to the event handler is a dictionary with these keys:
  • `announcement`: The string announced by the screen reader.
  • `success`: A boolean indicating whether the announcement was successfully made.
| +| `boldTextChanged`
iOS
| Fires when the state of the bold text toggle changes. The argument to the event handler is a boolean. The boolean is `true` when bold text is enabled and `false` otherwise. | +| `grayscaleChanged`
iOS
| Fires when the state of the gray scale toggle changes. The argument to the event handler is a boolean. The boolean is `true` when a gray scale is enabled and `false` otherwise. | +| `invertColorsChanged`
iOS
| Fires when the state of the invert colors toggle changes. The argument to the event handler is a boolean. The boolean is `true` when invert colors is enabled and `false` otherwise. | +| `reduceMotionChanged` | Fires when the state of the reduce motion toggle changes. The argument to the event handler is a boolean. The boolean is `true` when a reduce motion is enabled (or when "Transition Animation Scale" in "Developer options" is "Animation off") and `false` otherwise. | +| `reduceTransparencyChanged`
iOS
| Fires when the state of the reduce transparency toggle changes. The argument to the event handler is a boolean. The boolean is `true` when reduce transparency is enabled and `false` otherwise. | +| `screenReaderChanged` | Fires when the state of the screen reader changes. The argument to the event handler is a boolean. The boolean is `true` when a screen reader is enabled and `false` otherwise. | + +--- + +### `announceForAccessibility()` + +```tsx +static announceForAccessibility(announcement: string); +``` + +Post a string to be announced by the screen reader. + +--- + +### `announceForAccessibilityWithOptions()` + +```tsx +static announceForAccessibilityWithOptions( + announcement: string, + options: options: {queue?: boolean}, +); +``` + +Post a string to be announced by the screen reader with modification options. By default announcements will interrupt any existing speech, but on iOS they can be queued behind existing speech by setting `queue` to `true` in the options object. + +**Parameters:** + +| Name | Type | Description | +| ------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------- | +| announcement
Required
| string | The string to be announced | +| options
Required
| object | `queue` - queue the announcement behind existing speech
iOS
| + +--- + +### `getRecommendedTimeoutMillis()`
Android
+ +```tsx +static getRecommendedTimeoutMillis(originalTimeout: number): Promise; +``` + +Gets the timeout in millisecond that the user needs. +This value is set in "Time to take action (Accessibility timeout)" of "Accessibility" settings. + +**Parameters:** + +| Name | Type | Description | +| ---------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------- | +| originalTimeout
Required
| number | The timeout to return if "Accessibility timeout" is not set. Specify in milliseconds. | + +--- + +### `isAccessibilityServiceEnabled()`
Android
+ +```tsx +static isAccessibilityServiceEnabled(): Promise; +``` + +Check whether any accessibility service is enabled. This includes TalkBack but also any third-party accessibility app that may be installed. To only check whether TalkBack is enabled, use [isScreenReaderEnabled](#isscreenreaderenabled). Returns a promise which resolves to a boolean. The result is `true` when some accessibility services is enabled and `false` otherwise. + +> **Note**: Please use [isScreenReaderEnabled](#isscreenreaderenabled) if you only want to check the status of TalkBack. + +--- + +### `isBoldTextEnabled()`
iOS
+ +```tsx +static isBoldTextEnabled(): Promise: +``` + +Query whether a bold text is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when bold text is enabled and `false` otherwise. + +--- + +### `isGrayscaleEnabled()`
iOS
+ +```tsx +static isGrayscaleEnabled(): Promise; +``` + +Query whether grayscale is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when grayscale is enabled and `false` otherwise. + +--- + +### `isInvertColorsEnabled()`
iOS
+ +```tsx +static isInvertColorsEnabled(): Promise; +``` + +Query whether invert colors is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when invert colors is enabled and `false` otherwise. + +--- + +### `isReduceMotionEnabled()` + +```tsx +static isReduceMotionEnabled(): Promise; +``` + +Query whether reduce motion is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when reduce motion is enabled and `false` otherwise. + +--- + +### `isReduceTransparencyEnabled()`
iOS
+ +```tsx +static isReduceTransparencyEnabled(): Promise; +``` + +Query whether reduce transparency is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when a reduce transparency is enabled and `false` otherwise. + +--- + +### `isScreenReaderEnabled()` + +```tsx +static isScreenReaderEnabled(): Promise; +``` + +Query whether a screen reader is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when a screen reader is enabled and `false` otherwise. + +--- + +### `prefersCrossFadeTransitions()`
iOS
+ +```tsx +static prefersCrossFadeTransitions(): Promise; +``` + +Query whether reduce motion and prefer cross-fade transitions settings are currently enabled. Returns a promise which resolves to a boolean. The result is `true` when prefer cross-fade transitions is enabled and `false` otherwise. + +--- + +### `setAccessibilityFocus()` + +```tsx +static setAccessibilityFocus(reactTag: number); +``` + +Set accessibility focus to a React component. + +On Android, this calls `UIManager.sendAccessibilityEvent` method with passed `reactTag` and `UIManager.AccessibilityEventTypes.typeViewFocused` arguments. + +> **Note**: Make sure that any `View` you want to receive the accessibility focus has `accessible={true}`. diff --git a/website/versioned_docs/version-0.77/actionsheetios.md b/website/versioned_docs/version-0.77/actionsheetios.md new file mode 100644 index 00000000000..d24bc299921 --- /dev/null +++ b/website/versioned_docs/version-0.77/actionsheetios.md @@ -0,0 +1,142 @@ +--- +id: actionsheetios +title: ActionSheetIOS +--- + +Displays native to iOS [Action Sheet](https://developer.apple.com/design/human-interface-guidelines/ios/views/action-sheets/) component. + +## Example + +```SnackPlayer name=ActionSheetIOS%20Example&supportedPlatforms=ios +import React, {useState} from 'react'; +import {ActionSheetIOS, Button, StyleSheet, Text} from 'react-native'; +import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context'; + +const App = () => { + const [result, setResult] = useState('🔮'); + + const onPress = () => + ActionSheetIOS.showActionSheetWithOptions( + { + options: ['Cancel', 'Generate number', 'Reset'], + destructiveButtonIndex: 2, + cancelButtonIndex: 0, + userInterfaceStyle: 'dark', + }, + buttonIndex => { + if (buttonIndex === 0) { + // cancel action + } else if (buttonIndex === 1) { + setResult(String(Math.floor(Math.random() * 100) + 1)); + } else if (buttonIndex === 2) { + setResult('🔮'); + } + }, + ); + + return ( + + + {result} +