diff --git a/.claude/skills/expo-skill-eval/SKILL.md b/.claude/skills/expo-skill-eval/SKILL.md index 763c48c..10caea7 100644 --- a/.claude/skills/expo-skill-eval/SKILL.md +++ b/.claude/skills/expo-skill-eval/SKILL.md @@ -72,7 +72,7 @@ Read `references/runtime-matrix.md` to find the skill's default mode before sugg Pass the choice to the snapshot scripts via the `EXPO_SKILL_EVAL_RUNNER` env var (`expo-go` default, or `dev-build`), and reflect it in each eval case's `runtime.mode` (`expo-go` or `dev-build`). See step 5. -**Pick the platforms — always ask, regardless of skill.** Offer iOS / Android / web (multi-select) with `AskUserQuestion`; default to iOS + Android, but always present web as an option — don't pre-filter by skill. **Web is a valid choice for most skills**: `@expo/ui`'s *universal* components (`Host`, `Row`, `Column`, `Button`, `List`, …) render on web, as do `use-dom`, NativeWind/Tailwind, API routes, and plain React Native. The only thing that won't show on web is a *platform-specific* native tree (`@expo/ui/swift-ui` or `@expo/ui/jetpack-compose`), which renders blank there — and that blank is itself a useful signal, so it's still the user's call. Web runs via `snapshot-web.sh` (`expo start --web` + Playwright/Chromium) **regardless of the runner** (`expo run` is native-only; there's no web dev build), and it's the least-exercised path. Write the chosen set into each eval case's `runtime.platforms` and have `run_snapshots.py` loop them. +**Pick the platforms — always ask, regardless of skill.** Offer iOS / Android / web (multi-select) with `AskUserQuestion`; default to iOS + Android, but always present web as an option — don't pre-filter by skill. **Web is a valid choice for most skills**: `@expo/ui`'s *universal* components (`Host`, `Row`, `Column`, `Button`, `List`, …) render on web, as do `use-dom`, Nativewind/Tailwind, API routes, and plain React Native. The only thing that won't show on web is a *platform-specific* native tree (`@expo/ui/swift-ui` or `@expo/ui/jetpack-compose`), which renders blank there — and that blank is itself a useful signal, so it's still the user's call. Web runs via `snapshot-web.sh` (`expo start --web` + Playwright/Chromium) **regardless of the runner** (`expo run` is native-only; there's no web dev build), and it's the least-exercised path. Write the chosen set into each eval case's `runtime.platforms` and have `run_snapshots.py` loop them. **Confirm how `claude -p` subprocesses run — once, before starting.** Ask with `AskUserQuestion` whether they may run with `--dangerously-skip-permissions`, then apply the same answer to every subprocess this run (never re-prompt mid-run): diff --git a/.claude/skills/expo-skill-eval/references/runtime-matrix.md b/.claude/skills/expo-skill-eval/references/runtime-matrix.md index edcc9b3..517a107 100644 --- a/.claude/skills/expo-skill-eval/references/runtime-matrix.md +++ b/.claude/skills/expo-skill-eval/references/runtime-matrix.md @@ -11,7 +11,7 @@ Modes: | Skill | Mode | Platforms | Notes | |-------|------|-----------|-------| | building-native-ui | expo-go | ios, android | Core target for visual evals. Expo Router + RN primitives all work in Expo Go. Native tabs sections may need a dev build — verify per case. | -| expo-tailwind-setup | expo-go | ios, android, web | NativeWind v5 / react-native-css are JS-level; works in Expo Go. Good web candidate too. | +| expo-tailwind-setup | expo-go | ios, android, web | Nativewind v5 / react-native-css are JS-level; works in Expo Go. Good web candidate too. | | native-data-fetching | expo-go | ios, android | Fetch/React Query/SWR are pure JS. Mock or use stable public endpoints so evals are deterministic. | | use-dom | expo-go | ios, android, web | DOM components run in a webview on native (Expo Go, SDK 52+) and as-is on web. Allow extra settle time for the webview to paint. | | expo-api-routes | static-only + HTTP | — | No screenshot: while Metro runs, `curl` the route and save the response as an output file for grading. | diff --git a/README.md b/README.md index bfcb79d..7db9f3e 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ npx skills@latest update building-native-ui After installing, ask your agent Expo-specific questions like: - "Build a native-feeling Expo Router screen with tabs, modals, and animations." -- "Set up Tailwind CSS v4 and NativeWind v5 in this Expo app." +- "Set up Tailwind CSS v4 and Nativewind v5 in this Expo app." - "Create an EAS workflow that builds previews on pull requests." - "Help me upgrade this app to the latest Expo SDK." - "Check whether this EAS Update rollout is healthy." @@ -98,7 +98,7 @@ Agents choose the right skill from the task context and each skill's description | `building-native-ui` | Expo Router screens, navigation, styling, animations, native tabs, and app UI patterns. | | `native-data-fetching` | API calls, React Query, SWR, caching, offline support, and Expo Router data loaders. | | `expo-api-routes` | Expo Router API routes with EAS Hosting. | -| `expo-tailwind-setup` | Tailwind CSS v4, `react-native-css`, and NativeWind v5 setup. | +| `expo-tailwind-setup` | Tailwind CSS v4, `react-native-css`, and Nativewind v5 setup. | | `use-dom` | Expo DOM components for gradually using web code in native apps. | | `expo-dev-client` | Local and TestFlight development client builds. | diff --git a/plugins/expo/README.md b/plugins/expo/README.md index 9093104..4bb9d11 100644 --- a/plugins/expo/README.md +++ b/plugins/expo/README.md @@ -11,7 +11,7 @@ Official AI agent skills from the Expo team for building, deploying, upgrading, - Explains native iOS controls, SF Symbols, animations, and visual effects - Guides API route creation with EAS Hosting - Covers data fetching patterns with React Query, offline support, and Expo Router loaders -- Helps set up Tailwind CSS v4 with NativeWind v5 +- Helps set up Tailwind CSS v4 with Nativewind v5 - Explains DOM components for running web code in native apps - Covers iOS App Clips and brownfield Expo integration into existing native apps - Wires Expo projects into the Codex app Run button and action terminal @@ -69,7 +69,7 @@ Official AI agent skills from the Expo team for building, deploying, upgrading, - **expo-api-routes** — Create API routes in Expo Router with EAS Hosting - **expo-brownfield** — Integrate Expo and React Native into existing native iOS or Android apps - **expo-dev-client** — Build and distribute Expo development clients locally or via TestFlight -- **expo-tailwind-setup** — Set up Tailwind CSS v4 in Expo with NativeWind v5 +- **expo-tailwind-setup** — Set up Tailwind CSS v4 in Expo with Nativewind v5 - **expo-ui** — Native UI with @expo/ui: universal cross-platform components first, with SwiftUI and Jetpack Compose for platform-specific needs - **native-data-fetching** — Network requests, API calls, caching, and offline support - **use-dom** — Run web code in a webview on native using DOM components diff --git a/plugins/expo/skills/expo-examples/SKILL.md b/plugins/expo/skills/expo-examples/SKILL.md index 8b1cebc..01b3a61 100644 --- a/plugins/expo/skills/expo-examples/SKILL.md +++ b/plugins/expo/skills/expo-examples/SKILL.md @@ -1,6 +1,6 @@ --- name: expo-examples -description: Expo's official example projects — the expo/examples repo of ~70 `with-*` integrations (Stripe, Clerk, Supabase, OpenAI, maps, Reanimated, SQLite, Skia, NativeWind, and more). Use when integrating a third-party library or service into an existing Expo app and you want the canonical, version-matched pattern to adapt, or when scaffolding a new project from one with `npx create-expo --example`. +description: Expo's official example projects — the expo/examples repo of ~70 `with-*` integrations (Stripe, Clerk, Supabase, OpenAI, maps, Reanimated, SQLite, Skia, Nativewind, and more). Use when integrating a third-party library or service into an existing Expo app and you want the canonical, version-matched pattern to adapt, or when scaffolding a new project from one with `npx create-expo --example`. allowed-tools: "Read,Bash(gh api:*),Bash(git clone:*),Bash(npx create-expo:*),Bash(npx degit:*),Bash(bun create:*)" version: 1.0.0 license: MIT @@ -87,7 +87,7 @@ When the user already has an app, **add only what the example introduces; never ## Related skills -- Tailwind / NativeWind styling → `expo-tailwind-setup` +- Tailwind / Nativewind styling → `expo-tailwind-setup` - Native UI components → `building-native-ui` - Authoring a native module → `expo-module` - Upgrade the SDK before adopting a latest-SDK example → `upgrading-expo` diff --git a/plugins/expo/skills/expo-examples/references/catalog.md b/plugins/expo/skills/expo-examples/references/catalog.md index 3582ca6..0fad348 100644 --- a/plugins/expo/skills/expo-examples/references/catalog.md +++ b/plugins/expo/skills/expo-examples/references/catalog.md @@ -46,7 +46,7 @@ Most are single-screen integrations; a few differ: - `with-react-router` — React Router (web) ## Styling & UI -- `with-tailwindcss` — Tailwind / NativeWind (see also `expo-tailwind-setup` skill) +- `with-tailwindcss` — Tailwind / Nativewind (see also `expo-tailwind-setup` skill) - `with-styled-components` — styled-components - `with-shadcn` — shadcn-style components - `with-moti` — Moti animations diff --git a/plugins/expo/skills/expo-tailwind-setup/SKILL.md b/plugins/expo/skills/expo-tailwind-setup/SKILL.md index d37fe32..e92289e 100644 --- a/plugins/expo/skills/expo-tailwind-setup/SKILL.md +++ b/plugins/expo/skills/expo-tailwind-setup/SKILL.md @@ -1,13 +1,13 @@ --- name: expo-tailwind-setup -description: Set up Tailwind CSS v4 in Expo with react-native-css and NativeWind v5 for universal styling -version: 1.0.0 +description: Set up Tailwind CSS v4 in Expo with react-native-css and Nativewind v5 for universal styling +version: 1.1.0 license: MIT --- # Tailwind CSS Setup for Expo with react-native-css -This guide covers setting up Tailwind CSS v4 in Expo using react-native-css and NativeWind v5 for universal styling across iOS, Android, and Web. +This guide covers setting up Tailwind CSS v4 in Expo using react-native-css and Nativewind v5 for universal styling across iOS, Android, and Web. It follows the official Nativewind v5 installation instructions. ## Overview @@ -15,20 +15,39 @@ This setup uses: - **Tailwind CSS v4** - Modern CSS-first configuration - **react-native-css** - CSS runtime for React Native -- **NativeWind v5** - Metro transformer for Tailwind in React Native +- **Nativewind v5** - Metro transformer for Tailwind in React Native - **@tailwindcss/postcss** - PostCSS plugin for Tailwind v4 ## Installation +Install `nativewind` and its peer dependencies, then Tailwind CSS as dev dependencies: + ```bash -# Install dependencies -npx expo install tailwindcss@^4 nativewind@5.0.0-preview.2 react-native-css@0.0.0-nightly.5ce6396 @tailwindcss/postcss tailwind-merge clsx +npx expo install nativewind@preview react-native-css@latest react-native-reanimated react-native-safe-area-context +npx expo install --dev tailwindcss @tailwindcss/postcss postcss ``` -Add resolutions for lightningcss compatibility: +Optionally add `tailwind-merge` and `clsx` for class composition, and `prettier-plugin-tailwindcss` (dev) for class sorting. + +- Do NOT pin `react-native-css` to a specific nightly build. Use `@latest`. +- Do NOT pin `nativewind` to a specific preview build. Use the `preview` dist-tag. +- autoprefixer is not needed in Expo because of lightningcss + +### Override the lightningcss version + +Force `lightningcss` to a specific version in your `package.json`. Without this you may hit deserialization errors on `global.css` when building. + +```json +// package.json (npm / bun) +{ + "overrides": { + "lightningcss": "1.30.1" + } +} +``` ```json -// package.json +// package.json (yarn) { "resolutions": { "lightningcss": "1.30.1" @@ -36,14 +55,22 @@ Add resolutions for lightningcss compatibility: } ``` -- autoprefixer is not needed in Expo because of lightningcss -- postcss is included in expo by default +```json +// package.json (pnpm) +{ + "pnpm": { + "overrides": { + "lightningcss": "1.30.1" + } + } +} +``` ## Configuration Files ### Metro Config -Create or update `metro.config.js`: +Run `npx expo customize metro.config.js` if you don't have one, then wrap the default config with `withNativewind`: ```js // metro.config.js @@ -53,14 +80,11 @@ const { withNativewind } = require("nativewind/metro"); /** @type {import('expo/metro-config').MetroConfig} */ const config = getDefaultConfig(__dirname); -module.exports = withNativewind(config, { - // inline variables break PlatformColor in CSS variables - inlineVariables: false, - // We add className support manually - globalClassNamePolyfill: false, -}); +module.exports = withNativewind(config); ``` +No options are needed for the standard setup. `withNativewind` defaults to `globalClassNamePolyfill: true`, which adds `className` support to all React Native components, and generates TypeScript types at `nativewind-env.d.ts`. In v4 this function was called `withNativeWind` (capital W); both spellings work in v5, but `withNativewind` is preferred. + ### PostCSS Config Create `postcss.config.mjs`: @@ -76,39 +100,39 @@ export default { ### Global CSS -Create `src/global.css`: +Create `global.css` and add the Tailwind directives plus the Nativewind theme: ```css @import "tailwindcss/theme.css" layer(theme); @import "tailwindcss/preflight.css" layer(base); @import "tailwindcss/utilities.css"; -/* Platform-specific font families */ -@media android { - :root { - --font-mono: monospace; - --font-rounded: normal; - --font-serif: serif; - --font-sans: normal; - } -} +@import "nativewind/theme"; +``` -@media ios { - :root { - --font-mono: ui-monospace; - --font-serif: ui-serif; - --font-sans: system-ui; - --font-rounded: ui-rounded; - } +Use these at-rules instead of the standard `@tailwind` directives; they provide better compatibility with `react-native-web`. + +### Import your CSS file + +Import the CSS file in the same file as the top-most component of your app: + +```tsx +// App.tsx +import "./global.css"; + +export default function App() { + /* Your App */ } ``` +Do NOT import it in the same file that calls `AppRegistry.registerComponent` or the app will not Fast Refresh properly. In Expo Router projects, import it in the root `app/_layout.tsx`. + ## IMPORTANT: No Babel Config Needed -With Tailwind v4 and NativeWind v5, you do NOT need a babel.config.js for Tailwind. Remove any NativeWind babel presets if present: +With Tailwind v4 and Nativewind v5, you do NOT need a babel.config.js for Tailwind. Remove any Nativewind babel presets if present: ```js -// DELETE babel.config.js if it only contains NativeWind config +// DELETE babel.config.js if it only contains Nativewind config // The following is NO LONGER needed: // module.exports = function (api) { // api.cache(true); @@ -121,9 +145,184 @@ With Tailwind v4 and NativeWind v5, you do NOT need a babel.config.js for Tailwi // }; ``` -## CSS Component Wrappers +## TypeScript Setup + +Nativewind extends the React Native types via declaration merging. Metro generates a `nativewind-env.d.ts` file automatically; running `npx expo start --clear` creates it. To create it manually, add a triple-slash directive referencing the types: + +```tsx +// nativewind-env.d.ts +/// +``` + +Commit this file with your source code. Do NOT name it `nativewind.d.ts`, the same name as a sibling file or folder (e.g. `app.d.ts` next to an `/app` folder), or the same name as a folder in `node_modules` (e.g. `react.d.ts`), or TypeScript will not pick up the types. + +## Usage + +`className` works directly on React Native components: + +```tsx +import "./global.css"; +import { Text, View } from "react-native"; + +export default function App() { + return ( + + + Welcome to Nativewind! + + + ); +} +``` + +## Custom Theme Variables + +Add custom theme variables in your global.css using `@theme`: + +```css +@layer theme { + @theme { + /* Custom fonts */ + --font-rounded: "SF Pro Rounded", sans-serif; + + /* Custom line heights */ + --text-xs--line-height: calc(1em / 0.75); + --text-sm--line-height: calc(1.25em / 0.875); + --text-base--line-height: calc(1.5em / 1); + + /* Custom leading scales */ + --leading-tight: 1.25em; + --leading-snug: 1.375em; + --leading-normal: 1.5em; + } +} +``` + +## Platform-Specific Styles + +Use platform media queries for platform-specific styling: + +```css +@media ios { + :root { + --font-mono: ui-monospace; + --font-serif: ui-serif; + --font-sans: system-ui; + --font-rounded: ui-rounded; + } +} + +@media android { + :root { + --font-mono: monospace; + --font-serif: serif; + --font-sans: normal; + --font-rounded: normal; + } +} +``` + +## Apple System Colors with CSS Variables + +Create a CSS file for Apple semantic colors: + +```css +/* src/css/sf.css */ +@layer base { + html { + color-scheme: light; + } +} + +:root { + /* Accent colors with light/dark mode */ + --sf-blue: light-dark(rgb(0 122 255), rgb(10 132 255)); + --sf-green: light-dark(rgb(52 199 89), rgb(48 209 89)); + --sf-red: light-dark(rgb(255 59 48), rgb(255 69 58)); + + /* Gray scales */ + --sf-gray: light-dark(rgb(142 142 147), rgb(142 142 147)); + --sf-gray-2: light-dark(rgb(174 174 178), rgb(99 99 102)); + + /* Text colors */ + --sf-text: light-dark(rgb(0 0 0), rgb(255 255 255)); + --sf-text-2: light-dark(rgb(60 60 67 / 0.6), rgb(235 235 245 / 0.6)); + + /* Background colors */ + --sf-bg: light-dark(rgb(255 255 255), rgb(0 0 0)); + --sf-bg-2: light-dark(rgb(242 242 247), rgb(28 28 30)); +} + +/* iOS native colors via platformColor */ +@media ios { + :root { + --sf-blue: platformColor(systemBlue); + --sf-green: platformColor(systemGreen); + --sf-red: platformColor(systemRed); + --sf-gray: platformColor(systemGray); + --sf-text: platformColor(label); + --sf-text-2: platformColor(secondaryLabel); + --sf-bg: platformColor(systemBackground); + --sf-bg-2: platformColor(secondarySystemBackground); + } +} + +/* Register as Tailwind theme colors */ +@layer theme { + @theme { + --color-sf-blue: var(--sf-blue); + --color-sf-green: var(--sf-green); + --color-sf-red: var(--sf-red); + --color-sf-gray: var(--sf-gray); + --color-sf-text: var(--sf-text); + --color-sf-text-2: var(--sf-text-2); + --color-sf-bg: var(--sf-bg); + --color-sf-bg-2: var(--sf-bg-2); + } +} +``` + +Then use in components: + +```tsx +Primary text +Secondary text +... +``` + +## Using CSS Variables in JavaScript + +react-native-css exposes a hook for reading CSS variables at runtime: + +```tsx +import { useNativeVariable } from "react-native-css"; + +// On web, CSS variables resolve natively: +export const useCSSVariable = + process.env.EXPO_OS !== "web" + ? useNativeVariable + : (variable: string) => `var(${variable})`; + +function MyComponent() { + const blue = useCSSVariable("--sf-blue"); + + return ; +} +``` + +## Optional: Explicit CSS Component Wrappers -Since react-native-css requires explicit CSS element wrapping, create reusable components: +The default setup adds `className` support to all React Native components via a babel transform (`globalClassNamePolyfill: true`). If you prefer explicit control over which components accept CSS, disable the polyfill and wrap components manually with `useCssElement`: + +```js +// metro.config.js +module.exports = withNativewind(config, { + // inline variables break PlatformColor in CSS variables + inlineVariables: false, + // We add className support manually + globalClassNamePolyfill: false, +}); +``` ### Main Components (`src/tw/index.tsx`) @@ -302,179 +501,37 @@ export const Animated = { }; ``` -## Usage - -Import CSS-wrapped components from your tw directory: - -```tsx -import { View, Text, ScrollView, Image } from "@/tw"; - -export default function MyScreen() { - return ( - - - Hello Tailwind! - - - - ); -} -``` - -## Custom Theme Variables - -Add custom theme variables in your global.css using `@theme`: - -```css -@layer theme { - @theme { - /* Custom fonts */ - --font-rounded: "SF Pro Rounded", sans-serif; - - /* Custom line heights */ - --text-xs--line-height: calc(1em / 0.75); - --text-sm--line-height: calc(1.25em / 0.875); - --text-base--line-height: calc(1.5em / 1); - - /* Custom leading scales */ - --leading-tight: 1.25em; - --leading-snug: 1.375em; - --leading-normal: 1.5em; - } -} -``` - -## Platform-Specific Styles - -Use platform media queries for platform-specific styling: - -```css -@media ios { - :root { - --font-sans: system-ui; - --font-rounded: ui-rounded; - } -} - -@media android { - :root { - --font-sans: normal; - --font-rounded: normal; - } -} -``` - -## Apple System Colors with CSS Variables - -Create a CSS file for Apple semantic colors: - -```css -/* src/css/sf.css */ -@layer base { - html { - color-scheme: light; - } -} - -:root { - /* Accent colors with light/dark mode */ - --sf-blue: light-dark(rgb(0 122 255), rgb(10 132 255)); - --sf-green: light-dark(rgb(52 199 89), rgb(48 209 89)); - --sf-red: light-dark(rgb(255 59 48), rgb(255 69 58)); - - /* Gray scales */ - --sf-gray: light-dark(rgb(142 142 147), rgb(142 142 147)); - --sf-gray-2: light-dark(rgb(174 174 178), rgb(99 99 102)); - - /* Text colors */ - --sf-text: light-dark(rgb(0 0 0), rgb(255 255 255)); - --sf-text-2: light-dark(rgb(60 60 67 / 0.6), rgb(235 235 245 / 0.6)); - - /* Background colors */ - --sf-bg: light-dark(rgb(255 255 255), rgb(0 0 0)); - --sf-bg-2: light-dark(rgb(242 242 247), rgb(28 28 30)); -} - -/* iOS native colors via platformColor */ -@media ios { - :root { - --sf-blue: platformColor(systemBlue); - --sf-green: platformColor(systemGreen); - --sf-red: platformColor(systemRed); - --sf-gray: platformColor(systemGray); - --sf-text: platformColor(label); - --sf-text-2: platformColor(secondaryLabel); - --sf-bg: platformColor(systemBackground); - --sf-bg-2: platformColor(secondarySystemBackground); - } -} - -/* Register as Tailwind theme colors */ -@layer theme { - @theme { - --color-sf-blue: var(--sf-blue); - --color-sf-green: var(--sf-green); - --color-sf-red: var(--sf-red); - --color-sf-gray: var(--sf-gray); - --color-sf-text: var(--sf-text); - --color-sf-text-2: var(--sf-text-2); - --color-sf-bg: var(--sf-bg); - --color-sf-bg-2: var(--sf-bg-2); - } -} -``` - -Then use in components: - -```tsx -Primary text -Secondary text -... -``` - -## Using CSS Variables in JavaScript - -Use the `useCSSVariable` hook: - -```tsx -import { useCSSVariable } from "@/tw"; - -function MyComponent() { - const blue = useCSSVariable("--sf-blue"); - - return ; -} -``` - -## Key Differences from NativeWind v4 / Tailwind v3 +## Key Differences from Nativewind v4 / Tailwind v3 1. **No babel.config.js** - Configuration is now CSS-first 2. **PostCSS plugin** - Uses `@tailwindcss/postcss` instead of `tailwindcss` -3. **CSS imports** - Use `@import "tailwindcss/..."` instead of `@tailwind` directives +3. **CSS imports** - Use `@import "tailwindcss/..."` plus `@import "nativewind/theme"` instead of `@tailwind` directives 4. **Theme config** - Use `@theme` in CSS instead of `tailwind.config.js` -5. **Component wrappers** - Must wrap components with `useCssElement` for className support -6. **Metro config** - Use `withNativewind` with different options (`inlineVariables: false`) +5. **className everywhere** - The default `globalClassNamePolyfill` adds `className` support to all React Native components; no wrappers needed +6. **Metro config** - `withNativewind` (lowercase w) with no required options ## Troubleshooting +### Install fails with ERESOLVE errors + +Do not pin `react-native-css` to a specific nightly build. Stale nightlies fall behind the React Native peer dependency range and cause npm ERESOLVE failures on newer Expo SDKs. Use `react-native-css@latest` instead. + ### Styles not applying -1. Ensure you have the CSS file imported in your app entry -2. Check that components are wrapped with `useCssElement` -3. Verify Metro config has `withNativewind` applied +1. Ensure `global.css` is imported in the file with your top-most component +2. Verify Metro config has `withNativewind` applied +3. Restart the bundler with `npx expo start --clear` +4. If you disabled `globalClassNamePolyfill`, check that components are wrapped with `useCssElement` + +### Build fails with lightningcss deserialization errors + +Pin `lightningcss` to `1.30.1` via `overrides` (npm/bun), `resolutions` (yarn), or `pnpm.overrides` (pnpm). ### Platform colors not working 1. Use `platformColor()` in `@media ios` blocks 2. Fall back to `light-dark()` for web/Android -### TypeScript errors - -Add className to component props: +### TypeScript errors on className -```tsx -type Props = React.ComponentProps & { className?: string }; -``` +Ensure `nativewind-env.d.ts` exists with `/// ` and is not named after a sibling file, folder, or `node_modules` package. diff --git a/plugins/expo/skills/expo-tailwind-setup/agents/openai.yaml b/plugins/expo/skills/expo-tailwind-setup/agents/openai.yaml index b72cc60..7a6227e 100644 --- a/plugins/expo/skills/expo-tailwind-setup/agents/openai.yaml +++ b/plugins/expo/skills/expo-tailwind-setup/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "Expo Tailwind Setup" - short_description: "Set up Tailwind CSS v4, react-native-css, NativeWind v5, and CSS wrappers in Expo" - default_prompt: "Use $expo-tailwind-setup to install and configure Tailwind CSS v4 with Expo, NativeWind v5, react-native-css, Metro, PostCSS, global CSS, typed component wrappers, and theme variables." + short_description: "Set up Tailwind CSS v4, react-native-css, and Nativewind v5 in Expo" + default_prompt: "Use $expo-tailwind-setup to install and configure Tailwind CSS v4 with Expo, Nativewind v5, react-native-css, Metro, PostCSS, global CSS, TypeScript types, and theme variables." diff --git a/plugins/expo/skills/web-to-native/references/false-friends.md b/plugins/expo/skills/web-to-native/references/false-friends.md index 22f1292..6871f56 100644 --- a/plugins/expo/skills/web-to-native/references/false-friends.md +++ b/plugins/expo/skills/web-to-native/references/false-friends.md @@ -29,7 +29,7 @@ This is the single source of truth for the mapping; the SKILL.md steps name a fe | Web | Native | Gotcha | |---|---|---| -| `className` / CSS files | `StyleSheet.create` or NativeWind | Plain RN has no className. For Tailwind muscle memory use NativeWind (`expo-tailwind-setup`). | +| `className` / CSS files | `StyleSheet.create` or Nativewind | Plain RN has no className. For Tailwind muscle memory use Nativewind (`expo-tailwind-setup`). | | CSS cascade & inheritance | none | Styles don't inherit (except a few `Text` props like `color`/`fontSize` to nested `Text`). Style each node. | | `display: flex` opt-in, default `row` | flex always on, default **`column`** | Biggest layout surprise: flex is the only layout model and the main axis is vertical by default. | | `px`, `rem`, `%` | unitless numbers (dp) | `padding: 16` = density-independent pixels. `%` works in some props; no `rem`/`em`/`vh`. |