create-react-native-library-template 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-react-native-library-template",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "Scaffold a React Native UI library monorepo: Bun workspaces, Expo, Storybook (web + native), Vitest, Biome and Changesets",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,7 +12,9 @@ Tooling: **bun** (package manager + script runner), **biome** (lint + format), *
12
12
  (strict, `verbatimModuleSyntax` — use `import type` for types), **vitest** (unit tests via
13
13
  react-native-web in jsdom; story tests via `@storybook/addon-vitest` in Chromium),
14
14
  **react-native-builder-bob** (library build), **changesets** (versioning/publishing),
15
- **husky** (git hooks — a `pre-commit` hook runs lint, typecheck, and unit tests).
15
+ **husky** (git hooks — a `pre-commit` hook runs lint, typecheck, and unit tests). Components are
16
+ styled with **[Uniwind](https://uniwind.dev)** (Tailwind CSS 4 `className` for React Native) plus
17
+ **[cva](https://cva.style)** for variants — see [Styling](#styling-uniwind).
16
18
 
17
19
  ## Commands (run from the repo root)
18
20
 
@@ -41,17 +43,21 @@ implementation. For a component named `Foo`:
41
43
 
42
44
  **No `index.ts`** — barrel files are forbidden everywhere in the library. Public entry
43
45
  points are declared in the `exports` map of `packages/ui/package.json` (step 3), and
44
- internal imports always target the concrete file (`../../theme/tokens`), never a folder.
46
+ internal imports always target the concrete file (`../../components/Button/button`), never a folder.
45
47
  2. **Write the component** (`foo.tsx`):
46
48
  - Named function export (`export function Foo(...)`), never a default export.
47
49
  - Export a `FooProps` interface with a JSDoc comment per prop; document defaults with `@default`.
48
50
  - Only import from `react`, `react-native`, and internal modules. New runtime dependencies
49
51
  need explicit approval — they become dependencies for every consumer of the library.
50
- - Use only RN APIs that exist on react-native-web (`View`, `Text`, `Pressable`,
51
- `StyleSheet`, ...), otherwise unit tests and the web Storybook will break.
52
- - Style with `StyleSheet.create` and the design tokens from `src/theme/tokens.ts` (`colors`,
53
- `spacing`, `radii`, `fontSizes`) — no hard-coded colors or magic numbers. Add new tokens
54
- to `src/theme/tokens.ts` if needed.
52
+ - Use only RN APIs that exist on react-native-web (`View`, `Text`, `Pressable`, ...),
53
+ otherwise unit tests and the web Storybook will break.
54
+ - Style with Tailwind `className` (resolved by [Uniwind](https://uniwind.dev)) no
55
+ `StyleSheet.create`, no hard-coded colors or magic numbers. Compose variants with
56
+ [`class-variance-authority`](https://cva.style) (`cva`), following `Button` as the
57
+ reference. Keep class strings as static literals so Tailwind's scanner can see them.
58
+ `View`/`Text`/`Pressable` take `className`; `ActivityIndicator` takes `colorClassName`
59
+ (see the full prop list in `uniwind/types`). Still accept a `style` prop for escape-hatch
60
+ overrides.
55
61
  - Accessibility is required: set `accessibilityRole`, `accessibilityState`, and accept an
56
62
  `accessibilityLabel` prop. Also accept `style` (as `StyleProp<...>`) and `testID`.
57
63
  3. **Export it from the library**: add a `./foo` subpath to the `exports` map in
@@ -84,6 +90,29 @@ implementation. For a component named `Foo`:
84
90
  component (`patch` for fixes, `major` for breaking changes), write a one-line summary.
85
91
  Commit the generated `.changeset/*.md` file with your change.
86
92
 
93
+ ## Styling (Uniwind)
94
+
95
+ The library styles React Native components with Tailwind classes through
96
+ [Uniwind](https://uniwind.dev), the Tailwind provider for React Native. There is no runtime
97
+ provider to mount: Uniwind rewrites `react-native` imports to className-aware components in the
98
+ **bundler**, so components just import from `react-native` and set `className`. That rewrite is
99
+ configured once per app, and the three pieces below are already wired in this repo:
100
+
101
+ - **Native (Metro)** — `storybook/native/metro.config.js` wraps the config with
102
+ `withUniwindConfig(...)` from `uniwind/metro`, as the **outermost** wrapper. `cssEntryFile`
103
+ must be a plain relative string.
104
+ - **Web (Vite)** — `storybook/web/.storybook/main.ts` adds `@tailwindcss/vite` and
105
+ `uniwind({...})` from `uniwind/vite` in `viteFinal`.
106
+ - **CSS entry** — each Storybook has a `global.css` (`@import 'tailwindcss'; @import 'uniwind';`)
107
+ imported from its `preview`. Because components live in `packages/ui`, each `global.css` has an
108
+ `@source '../../packages/ui/src'` so Tailwind's scanner finds the class strings there.
109
+
110
+ `className` typechecks via a per-workspace `uniwind-env.d.ts` (`/// <reference types="uniwind/types" />`),
111
+ which augments `react-native` to add `className`/`colorClassName`. Uniwind's generated
112
+ `uniwind-types.d.ts` (theme-aware autocomplete) is gitignored. Unit tests need none of this:
113
+ they run in jsdom on react-native-web, which passes `className` through harmlessly, and they
114
+ assert behavior by role/name — never computed styles.
115
+
87
116
  ## Releasing
88
117
 
89
118
  CI (`.github/workflows/ci.yml`) runs lint, typecheck, tests, build, and Storybook tests on
@@ -4,6 +4,7 @@ Template for building and publishing a React Native UI component library.
4
4
 
5
5
  - **[Bun](https://bun.sh)** — package manager, script runner, workspaces
6
6
  - **[TypeScript 6](https://www.typescriptlang.org)** — strict mode everywhere
7
+ - **[Uniwind](https://uniwind.dev)** — Tailwind CSS for React Native (`className` on RN components), with [`cva`](https://cva.style) for variants
7
8
  - **[Biome](https://biomejs.dev)** — linting + formatting
8
9
  - **[Vitest](https://vitest.dev)** — unit tests (react-native-web in jsdom)
9
10
  - **[Storybook 10](https://storybook.js.org)** — web (react-native-web + Vite) **and** on-device (Expo) demos from the same stories
@@ -49,6 +50,19 @@ bun run build # library build → packages/ui/lib
49
50
  See [AGENTS.md](./AGENTS.md) — it documents the full checklist (component, tests, stories,
50
51
  exports, changeset). `packages/ui/src/components/Button` is the reference implementation.
51
52
 
53
+ ## Styling
54
+
55
+ Components are styled with Tailwind classes via [Uniwind](https://uniwind.dev), which resolves
56
+ `className` on React Native components at bundle time (Metro for native, Vite for web) — there's
57
+ no runtime provider to mount. Variants are composed with [`cva`](https://cva.style); see
58
+ `packages/ui/src/components/Button/button.tsx`.
59
+
60
+ Each app has a `global.css` (`@import 'tailwindcss'; @import 'uniwind';`) that the bundler is
61
+ pointed at: `storybook/web` wires `@tailwindcss/vite` + `uniwind/vite` in `.storybook/main.ts`,
62
+ and `storybook/native` wraps its Metro config with `withUniwindConfig`. A consumer of the
63
+ published library does the same in their own app. Keep class strings as static literals so
64
+ Tailwind's scanner picks them up.
65
+
52
66
  ## Releasing
53
67
 
54
68
  1. With every user-facing change, run `bun run changeset` and commit the generated file.