Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .claude/skills/add-test/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
name: add-test
description: Scaffold a test for a react-native-css feature following the project's testing conventions.
argument-hint: [feature-or-css-property]
allowed-tools: Read, Grep, Glob, Edit, Write
---

## Context

react-native-css has three test domains in `src/__tests__/`:

- `babel/` — Babel plugin tests using `babel-plugin-tester`
- `compiler/` — CSS compilation tests verifying JSON output
- `native/` — Runtime tests for style application

## Conventions by domain

### Babel tests (`src/__tests__/babel/`)

Use `babel-plugin-tester`:

```typescript
import { pluginTester } from "babel-plugin-tester";

pluginTester({
plugin,
tests: {
"test name": {
code: `import { View } from 'react-native';`,
output: `import { View } from 'react-native-css/components';`,
},
},
});
```

### Compiler tests (`src/__tests__/compiler/`)

Verify CSS → JSON compilation output structure.

### Native tests (`src/__tests__/native/`)

Test runtime style application on native platform.

## Steps

1. **Identify the feature**: What needs testing? Use `$ARGUMENTS` as the starting point.

2. **Determine the domain**: Is this a babel transform, compiler output, or runtime behavior?

3. **Find existing tests**: Search the appropriate `src/__tests__/` subdirectory for similar tests.

4. **Write the test**: Follow the conventions of the domain.

5. **Run the test**: Execute `yarn test`. Note: ignore `ExperimentalWarning: VM Modules` warnings — they're expected.
32 changes: 32 additions & 0 deletions .claude/skills/architecture/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: architecture
description: Explain the react-native-css architecture, compiler pipeline, and key files. Use when a contributor wants to understand how the codebase works.
allowed-tools: Read, Grep, Glob
---

You are explaining the architecture of **react-native-css** to a contributor.

Start by reading `DEVELOPMENT.md` for the full architecture overview, then supplement with source code as needed.

## How to explain

1. **Start with the big picture**: react-native-css is a standalone CSS polyfill for React Native. It works independently of Tailwind — any `.css` file can be used. Nativewind v5 depends on this as its core engine.

2. **Show the compiler pipeline**: Walk through how a CSS rule becomes a React Native style:
- Metro transformer intercepts `.css` files (`src/metro/metro-transformer.ts`)
- lightningcss parses the CSS AST
- `compile()` processes rules, media queries, keyframes, variables (`src/compiler/compiler.ts`)
- Output is a `ReactNativeCssStyleSheet` (JSON)
- Injection code registers styles with the native runtime (`src/metro/injection-code.ts`)

3. **Explain the babel plugin**: It rewrites React Native imports so components get `className` support:
- `import { View } from 'react-native'` → `import { View } from 'react-native-css/components'`

4. **Explain the runtime**:
- Reactive style system (`src/native/reactivity.ts`) — observables for media queries, color scheme
- StyleCollection singleton (`src/native-internal/`) — isolated to avoid circular deps
- Platform-aware: different outputs for native (JSON) vs web (browser CSS)

5. **Show relevant code**: Read source files to illustrate. The compiler and runtime are the most complex parts.

6. **Clarify the boundary**: This repo owns compilation, runtime, babel, and Metro integration. Nativewind adds Tailwind-specific theming on top.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

## <small>3.0.5 (2026-03-15)</small>

* chore: add Claude Code skills for architecture and testing ([02bac92](https://github.com/nativewind/react-native-css/commit/02bac92))
* chore: add conventional changelog for GitHub releases (#294) ([251cdfc](https://github.com/nativewind/react-native-css/commit/251cdfc)), closes [#294](https://github.com/nativewind/react-native-css/issues/294)
* chore(deps): bump basic-ftp from 5.0.5 to 5.2.0 (#286) ([930095f](https://github.com/nativewind/react-native-css/commit/930095f)), closes [#286](https://github.com/nativewind/react-native-css/issues/286)
* chore(deps): bump minimatch from 3.1.2 to 3.1.5 (#289) ([ae42457](https://github.com/nativewind/react-native-css/commit/ae42457)), closes [#289](https://github.com/nativewind/react-native-css/issues/289)
* chore(deps): bump tar from 7.5.9 to 7.5.11 (#296) ([431852a](https://github.com/nativewind/react-native-css/commit/431852a)), closes [#296](https://github.com/nativewind/react-native-css/issues/296)
* docs: add DEVELOPMENT.md and CLAUDE.md for contributor tooling ([ed4e5b3](https://github.com/nativewind/react-native-css/commit/ed4e5b3))
* feat: add CSS @property rule support (#284) ([4ee27ab](https://github.com/nativewind/react-native-css/commit/4ee27ab)), closes [#284](https://github.com/nativewind/react-native-css/issues/284)
* feat: add inset shadow parsing support (#277) ([b0b35b1](https://github.com/nativewind/react-native-css/commit/b0b35b1)), closes [#277](https://github.com/nativewind/react-native-css/issues/277)
* fix(types): move @types/debug from devDependencies to dependencies (#290) ([43787dc](https://github.com/nativewind/react-native-css/commit/43787dc)), closes [#290](https://github.com/nativewind/react-native-css/issues/290)
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Claude Code Context

Read these files for project context:

- @DEVELOPMENT.md — architecture, directory structure, commands, testing, pitfalls
- @CONTRIBUTING.md — contribution workflow, PR process, development notes
141 changes: 141 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# react-native-css Development Guide

## Project Overview

A standalone CSS polyfill for React Native. Part of the Nativewind v5 ecosystem but can function independently of Tailwind CSS. Provides direct `.css` file support in React Native apps.

### Relationship to Nativewind

- **Nativewind** (`github.com/nativewind/nativewind`, main branch) provides the Tailwind CSS integration layer
- **This repo** provides the underlying CSS-to-React-Native engine
- Both are part of the v5 story, but this repo has no Tailwind dependency

## Architecture

```
.css file
Metro Transformer (src/metro/metro-transformer.ts)
↓ delegates to Expo's CSS transformer
lightningcss parses CSS AST
compile() in src/compiler/compiler.ts
├→ parseMediaQuery() — media query conditions
├→ parseContainerCondition() — container queries
├→ parseDeclaration() — CSS properties → RN properties
├→ extractKeyFrames() — animation extraction
└→ inlineVariables() — CSS variable optimization
ReactNativeCssStyleSheet (JSON)
getNativeInjectionCode() (src/metro/injection-code.ts)
Native runtime consumes via StyleCollection
```

### Babel Plugin

The Babel plugin (`src/babel/react-native.ts`) rewrites React Native imports:
```
import { View } from 'react-native'
→ import { View } from 'react-native-css/components'
```
This enables `className` prop support on all React Native components.

### Key Architectural Patterns

- **Reactive style system** (`src/native/reactivity.ts`) — custom observables for media queries, container queries, color scheme changes
- **StyleCollection singleton** (`src/native-internal/`) — isolated to prevent circular dependencies between native runtime and CSS file imports
- **Platform-aware compilation** — different outputs for native (JSON) vs web (browser CSS)
- **Inline variable optimization** — single-use CSS variables are inlined at compile time; multi-use preserved

## Package Entry Points

| Import | Purpose |
|--------|---------|
| `react-native-css` | Runtime API |
| `react-native-css/compiler` | CSS-to-JSON compiler |
| `react-native-css/babel` | Babel plugin for import transformation |
| `react-native-css/metro` | `withReactNativeCSS()` Metro config |
| `react-native-css/components` | Pre-wrapped RN components with className support |
| `react-native-css/jest` | Jest test utilities |
| `react-native-css/native` | Native runtime API |
| `react-native-css/web` | Web runtime API |

## Key Directories

```
src/
├── babel/ # Babel plugin (rewrites RN imports)
├── compiler/ # CSS compilation engine (lightningcss-based)
│ ├── compiler.ts # Main entry
│ ├── declarations.ts # CSS property handling
│ ├── selectors.ts # Selector parsing
│ ├── media-query.ts # Media query parsing
│ ├── container-query.ts
│ ├── keyframes.ts # Animation extraction
│ └── inline-variables.ts
├── metro/ # Metro bundler integration
│ ├── metro-transformer.ts # Custom JS/CSS transformer
│ ├── resolver.ts # Module resolution
│ └── typescript.ts # TypeScript env generation
├── native/ # Native runtime (iOS/Android)
│ ├── api.tsx # styled(), useCssElement(), hooks
│ ├── reactivity.ts # Observable/reactive system
│ ├── styles/ # Runtime style resolution
│ ├── conditions/ # Media/container query evaluation
│ └── react/ # React integration hooks
├── native-internal/ # Shared singletons (avoids circular deps)
│ ├── root.ts # Global style collection root
│ ├── style-collection.ts
│ └── variables.tsx # CSS variable context
├── web/ # Web runtime
├── components/ # Pre-wrapped RN components (View, Text, etc.)
└── utilities/ # Type utilities (dot notation)
```

## Commands

```bash
yarn # Install dependencies (npm is NOT supported)
yarn build # Build with react-native-builder-bob
yarn test # Run tests (Jest with ESM)
yarn typecheck # TypeScript validation
yarn lint --fix # ESLint + Prettier
yarn clean # Install deps, rebuild project and example app
```

### Example App

```bash
yarn example ios # Build and run on iOS
yarn example android # Build and run on Android
yarn example start # Start Metro server
yarn example start:build # Rebuild library + start Metro (clears cache)
yarn example start:debug # Rebuild + start with debug logging
```

## Testing

- **Runner:** Jest with experimental ESM support (`NODE_OPTIONS="--experimental-vm-modules"`)
- **Convention:** Tests in `src/__tests__/` organized by domain (`babel/`, `compiler/`, `native/`)
- **Babel tests** use `babel-plugin-tester`
- **Compiler tests** verify JSON output structure
- **Run specific suites:** `yarn test babel`, `yarn test compiler`
- Ignore `ExperimentalWarning: VM Modules` warnings — expected with ESM support

## Code Conventions

- TypeScript throughout
- **Yarn v4 only** — npm is not supported (enforced via `packageManager` field)
- Conventional commits required: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`, `chore:`
- Pre-commit hooks enforce linting and commit message format
- Publishing via `release-it`

## Common Pitfalls

- **No npm** — this repo uses Yarn workspaces; `npm install` will not work
- **No rebuild watch** — use `yarn example start:build` to rebuild + start in one command
- **Metro transformer / Babel plugin changes require full rebuild** — no fast refresh for these
- **native-internal exists to break circular deps** — don't import directly from `native/` in CSS file outputs; use `native-internal/`
- **Nested node_modules in example/** — can cause Metro issues; ensure dependency versions match root
Loading