# Screens, elements and masking A report is only as useful as its location. The component cannot see which element was tapped by itself, so you (or your agent) give names to the screens and the elements that matter. ## Screens A screen name is stored in the `screen` field of every report made on that screen. Keep names short and stable: `Home`, `Settings`, `Checkout`. - SwiftUI: `.nitpickScreen("Home")` on the root view of the screen. - Expo Router: not automatic. Put `useNitpickScreen(usePathname())` in a small component inside the provider in the root layout, so the route path becomes the screen name (see [Install for Expo](/docs/install-expo)). - React Navigation: use `useNitpickScreen` with the navigation container's current route name. - Tabs or a stack: also pass the focus of the screen, see the next section. ## Tabs and stacks: pass the focus A tab bar or a stack keeps the screens that are not shown. Their marked elements still exist, so a tap on the screen could be matched to a hidden element, even a smaller one on the same place. Pass the focus of each screen: elements inside a screen with `focused` set to false never count when the user points, and that screen does not set the screen name. Without the option nothing changes. Expo Router: wrap each tab or stack screen in `` and pass `useIsFocused()`. The name is up to you; the route path is a good one. ```tsx // app/(tabs)/settings.tsx import { useIsFocused } from "expo-router"; import { NitpickElement, NitpickScreen } from "@nitpickhq/react-native"; export default function Settings() { const focused = useIsFocused(); return ( {/* ... */} ); } ``` React Navigation without Expo Router: the same, with `useIsFocused` from `@react-navigation/native`. If you only want the screen name and not the elements, use `useNitpickScreen("/settings", { focused })`; the elements below it then still count, so wrap the screen in `` when it has marked elements. SwiftUI: give each screen of a `TabView` its own `.nitpickScreen` and pass whether its tab is selected. ```swift TabView(selection: $selection) { HomeView() .nitpickScreen("Home", focused: selection == .home) .tabItem { Label("Home", systemImage: "house") } .tag(Tab.home) SettingsView() .nitpickScreen("Settings", focused: selection == .settings) .tabItem { Label("Settings", systemImage: "gear") } .tag(Tab.settings) } ``` The `focused` parameter is optional and defaults to true. A screen inside a screen without focus has no focus either. ## Elements An element name goes into the `element` field. Mark the buttons, fields and cards that users are likely to point at. Prefer names that lead to the file: `Home/StartButton`, `Checkout/PayButton`. - SwiftUI: `.nitpickElement("Home/StartButton")`. - React Native: `` or a `testID`. ### SwiftUI: elements inside a List In a `List` or `Section`, a `Button` is often the row itself. A marker on such a `Button` is not found when the user points at it: the report gets `element_match: none` and no frame. Put the marker on the content of the row instead, for example a `VStack` or `HStack` inside the button's label: ```swift List { // Not found: the marker sits on the Button that is the row Button("Mark all done", action: markAll) .nitpickElement("Home/MarkAllDoneButton") // Found: the marker sits on the content of the row Button(action: markAll) { HStack { Text("Mark all done") Spacer() } .nitpickElement("Home/MarkAllDoneButton") } } ``` If a marked element in a list is still not found, mark a view that is not itself the row (a `VStack` with the card inside works), and check with `nitpick feedback list` that `element_match` is `exact`. ## How a tap is matched When the user points at something, the component looks at the tap and sets `element_match`: | `element_match` | Meaning | |---|---| | `exact` | The tap was inside a marked element. The smallest marked element that contains the tap wins. | | `nearest` | No marked element contains the tap, but one is within 44 points. That one is used. | | `none` | Nothing marked nearby. The report still has the screen, the screenshot and the tap position. | The report also carries `element_frame` (the element's box in points) and `tap`, so your agent can see exactly where on the screenshot the user pointed. ## Masking Masked parts show up as a black box on the screenshot. The user sees the preview before sending and can also remove the screenshot completely. - Password fields are masked where the platform allows it. - Everything else is up to you: card numbers, addresses, health data, anything personal. Mark it with `.nitpickMask()` or ``. - Automatic masking in SwiftUI is only partial, so do not rely on it. Mark sensitive views yourself. Your agent does this during install. - Screens that you flag as secure by the platform's own means are not captured. ## What the component never does It captures nothing before the user opens it. The only thing it does earlier is ask Nitpick for your settings when the app starts. It records no screen, reads no photo library, collects no device name and uses no private APIs. See [Privacy and store forms](/docs/privacy).