Getting started
Install @terratcg/ui, mount ThemeProvider and OverlayHost once at the root, and press your first Button.
Install
npm install @terratcg/ui react-native-screensTerraUI runs on plain React Native for iOS and Android, with or without Expo. Its peers are React, React Native and react-native-screens; only the overlay layer (Dialogs, Menus and toasts) uses Screens. The supported versions are on Compatibility.
Set up
Mount one ThemeProvider and one OverlayHost at the root of your app:
import { Button, ButtonText, OverlayHost, ThemeProvider, defaultDark, defaultLight, showDialog } from "@terratcg/ui";
import { useColorScheme } from "react-native";
export function App() {
const dark = useColorScheme() === "dark";
return (
<ThemeProvider theme={dark ? defaultDark : defaultLight}>
<Button onPress={() => showDialog({ title: "Saved", body: "Your changes are saved.", confirm: "OK", tone: "info" })}>
<ButtonText>Save</ButtonText>
</Button>
<OverlayHost failureText="Something went wrong. Try again." />
</ThemeProvider>
);
}ThemeProvidergives every component its theme, and your feedback handler if you have one. Without a provider, components fall back todefaultLight. See ThemeProvider and feedback.OverlayHostdraws the Dialogs, Menus and toasts thatshowDialog,showMenuandshowToastopen from anywhere. Put it after your navigator, insideThemeProvider. See OverlayHost.
To match your brand, start from the default theme and override a few tokens with createTheme: see Theming.
React Native rules
TerraUI is React Native for iOS and Android, not web React. Follow these rules before writing code with it:
- Versions:
react ~19.3.0,react-native ~0.88.0andreact-native-screens ~4.30.0. Expo is optional. - Style props, not
className: style through each component's props and React Native'sstyleprop. There is no CSS and no class name. onPress, notonClick: every pressable control takesonPress.- Text inside text components: put every string inside a text component, such as
ButtonText,Text,RowTitleorNoticeTitle. A bare string inside aButtonor aViewdoes not render. - One
ThemeProvider, oneOverlayHost: mount each once, at the root of the app, withOverlayHostinsideThemeProviderand after your navigator. Dialogs, menus and toasts open through them, from anywhere. - Native first: import from
@terratcg/ui, never a web component library. Haptics, sounds, icons and navigation stay in your app.
Imports
Import everything from the root, or one family from its subpath:
import { Button, ButtonText } from "@terratcg/ui";
import { Switch } from "@terratcg/ui/switch";Both resolve to the same modules. Anything not listed in the package's exports is internal and may change in any release.
Docs for coding agents
The package carries these docs as Markdown, in the version you installed, at node_modules/@terratcg/ui/docs/. index.md there opens with the rules above and lists every page.
AGENTS.md
Paste this section into your project's AGENTS.md (or CLAUDE.md), so coding agents read the installed docs and the rules before writing TerraUI code:
## TerraUI
This project uses TerraUI (`@terratcg/ui`). Its docs, for the version installed here, are Markdown files in `node_modules/@terratcg/ui/docs/`. Read `index.md` there first, then the page of every component you use, and trust them over what you remember.
TerraUI is React Native for iOS and Android, not web React. Follow these rules before writing code with it:
- **Versions:** `react ~19.3.0`, `react-native ~0.88.0` and `react-native-screens ~4.30.0`. Expo is optional.
- **Style props, not `className`:** style through each component's props and React Native's `style` prop. There is no CSS and no class name.
- **`onPress`, not `onClick`:** every pressable control takes `onPress`.
- **Text inside text components:** put every string inside a text component, such as `ButtonText`, `Text`, `RowTitle` or `NoticeTitle`. A bare string inside a `Button` or a `View` does not render.
- **One `ThemeProvider`, one `OverlayHost`:** mount each once, at the root of the app, with `OverlayHost` inside `ThemeProvider` and after your navigator. Dialogs, menus and toasts open through them, from anywhere.
- **Native first:** import from `@terratcg/ui`, never a web component library. Haptics, sounds, icons and navigation stay in your app.On the site
Every page is also Markdown: append .md to its URL, such as /docs/button.md. llms.txt lists every page and opens with the rules above; llms-full.txt holds every page in full. Each page's actions copy its Markdown or open it in ChatGPT, Claude or Cursor.