Knit UI
GitHub

Installation

Knit UI is two packages: @knitui/core (tokens, themes, Provider) and @knitui/components (the components). Everything else is optional.

Four steps, about five minutes. Pick your framework in any tab below — every tab on this page stays in sync, and so does your package manager, so you only choose once.

What you need first

RequirementVersion
Node20 or newer
React19.2.x
Native appReact Native 0.86.x — easiest via Expo SDK 57
Web appNext.js 16 (built with --webpack) or Vite

Anything else is checked for you: if a peer dependency is missing, the kit throws a named error the first time a component renders instead of failing somewhere deep inside a gesture handler. Full matrix in Compatibility.

1. Install the packages

npx expo install @knitui/core @knitui/components react-native-gesture-handler react-native-reanimated react-native-svg react-native-teleport react-native-worklets

Note the expo install: it picks the native module versions your Expo SDK was built against. Installing those peers by hand is the single most common cause of a red screen on first launch. (npx expo install --check audits a project later.)

No app yet? npx create-expo-app@latest my-app first.

2. Point your bundler at the kit

The kit source-shipsmain points at ./src/index.ts, so platform-split files stay resolvable and the Tamagui compiler can see real source. Your bundler needs to know that, which is the one job of @knitui/plugins.

babel.config.js
module.exports = (api) => {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
    plugins: [require("@knitui/plugins/babel-plugin")],
  };
};
metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withKnitui } = require("@knitui/plugins/metro");

module.exports = withKnitui(getDefaultConfig(__dirname));

Restart with a cleared cache the first time: npx expo start --clear.

Details on what each plugin does: Bundler setup.

3. Wrap your app in one Provider

app/_layout.tsx
import { Provider } from "@knitui/core";
import { Stack } from "expo-router";

export default function RootLayout() {
  return (
    <Provider defaultColorScheme="system">
      <Stack />
    </Provider>
  );
}

Provider is more than a theme context. It mounts the token and theme config, the color-scheme controller ("system" follows the OS), GestureHandlerRootView — so you don't add one — and the portal host that Modal, Drawer, Popover and Tooltip teleport into.

Deeper per-framework detail — dev builds, static export, Storybook, the pitfalls specific to each: Expo · Next.js · Vite.

4. Check it works

Drop this anywhere inside the Provider and run the app:

import { Button, Card, Group, Text, TextInput } from "@knitui/components";

export function SignIn() {
  return (
    <Card padding="lg" gap="$md">
      <Text fontWeight="600">Sign in</Text>
      <TextInput label="Email" placeholder="you@example.com" />
      <Group>
        <Button variant="light">Cancel</Button>
        <Button>Continue</Button>
      </Group>
    </Card>
  );
}

You should see a bordered card with a labelled input and two buttons, themed to your OS light/dark setting, on iOS, Android and the web from that one file. If it renders, you're installed — and the buttons below are the same components, running live in this page:

Rendered by the docs site with the setup you just did.

Loading example…

VariantsSourceStorybook

Add only what you need

The core two packages cover 100+ components. Each satellite package is installed on its own, and only @knitui/map, @knitui/media and @knitui/graphics bring native modules with them.

On Expo, install a satellite package's native module through expo install too:

npx expo install @knitui/media expo-audio expo-video

Which package needs which peer, straight from each package.json:

PackageRequired peersOptional peers
@knitui/corereact react-native react-native-gesture-handler react-native-reanimated react-native-web
@knitui/componentsreact react-native react-native-svg react-native-teleport react-native-web react-native-reanimated react-native-worklets react-native-gesture-handler
@knitui/hooksreact react-native react-native-reanimated
@knitui/iconsreact react-native react-native-svg
@knitui/emojireact react-native react-native-svg
@knitui/datesreact react-native react-native-teleport react-native-web react-native-reanimated
@knitui/carouselreact react-native react-native-gesture-handler react-native-reanimated react-native-worklets
@knitui/map@maplibre/maplibre-gl-style-spec @types/geojson react @maplibre/maplibre-react-native maplibre-gl react-dom react-native react-native-svg
@knitui/mediareact react-native react-native-reanimated
@knitui/graphics@shopify/react-native-skia react react-native react-native-reanimated
@knitui/sheetreact react-native react-native-gesture-handler react-native-reanimated react-native-worklets
@knitui/mediaqueryreact react-native
@knitui/pluginsreact react-native next

If something went wrong

What you seeAlmost always
Red screen, "property is not writable" on HermesTwo copies of react-native
"Another instance of Reanimated was detected"Two copies of reanimated
Styles land a frame late on Next.jsNextTamaguiProvider missing or too deep
A modal or dropdown renders behind everythingMore than one Provider
Warning: Tamagui skipped loading N modulesHarmless — src-shipped packages
Sliders or sheets don't respond to dragsSomething is mounted above Provider, so there's no GestureHandlerRootView

Every symptom, with fixes: Troubleshooting.

Next steps