What happened?
On native platforms, Uniwind stops applying className styles to every component that comes from node_modules (e.g. all of HeroUI Native's Card, Surface, Button, etc. render with no background, padding, radius or fill) whenever the app's absolute path contains a directory named react-native, e.g. ~/Developer/react-native/my-app. The same class strings work on Views in the app's own source.
Root cause: nativeResolver in packages/uniwind/src/bundler/adapters/metro/resolvers.ts decides whether a module is React Native internals with a substring match on the whole absolute path:
const isFromNodeModules = context.originModulePath.includes(`${sep}node_modules${sep}`)
const isFromReactNative = context.originModulePath.includes(`${sep}react-native${sep}`)
|| context.originModulePath.includes(`${sep}@react-native${sep}`)
// ...
|| (isFromReactNative && isFromNodeModules && !isReactNativeAnimated) // Is from react-native but not Animated
For /Users/me/Developer/react-native/my-app/node_modules/heroui-native/lib/module/components/surface/surface.js, both flags are true (because of the parent react-native/ folder), so the react-native → uniwind/components rewrite is skipped for every dependency. App files don't contain /node_modules/, so they keep working, which makes this look like a component-library bug.
Quick check:
const p = '/Users/me/Developer/react-native/my-app/node_modules/heroui-native/lib/module/components/surface/surface.js'
p.includes('/node_modules/') && p.includes('/react-native/') // true → resolver skips the swap
Suggested fix (only look at the path after the last node_modules segment). We're running this as a local pnpm patch, and it fixes the problem while keeping the React Native internals and the Animated exception behaving as before:
const afterNodeModules = context.originModulePath.split(`${sep}node_modules${sep}`).at(-1) ?? ''
const isFromReactNative = afterNodeModules.startsWith(`react-native${sep}`)
|| afterNodeModules.startsWith(`@react-native${sep}`)
(startsWith('react-native' + sep) also avoids matching sibling packages like react-native-svg.)
Steps to Reproduce
- Headless:
mkdir -p /tmp/react-native && cd /tmp/react-native && git clone https://github.com/musab-olurode/uniwind-rn-path-repro && cd uniwind-rn-path-repro && npm install && node scripts/check-resolver.js prints BUG. The same steps under /tmp/rn-ok/ print OK.
Or manually:
mkdir -p /tmp/react-native && cd /tmp/react-native. The parent folder name is what matters.
- Create an Expo app there and set up Uniwind + HeroUI Native per their quick-starts (
withUniwindConfig in metro.config.js, global.css importing tailwindcss, uniwind, heroui-native/styles, app wrapped in GestureHandlerRootView + HeroUINativeProvider).
- Render
<Card><Card.Body><Card.Title>Hi</Card.Title></Card.Body></Card> and <Button>Press</Button>.
- Run on Android. The Card and Button have no background, radius, padding or fill.
- Move the same project to a path without a
react-native segment (e.g. /tmp/rn/…), clear the Metro cache, and run again. The components are styled correctly.
Snack or Repository Link
https://github.com/musab-olurode/uniwind-rn-path-repro
It includes a headless check, node scripts/check-resolver.js. The script runs expo export --platform android --dev through the real metro.config.js and inspects what heroui-native's surface.js react-native import resolved to. Clone it into a folder named react-native and it prints BUG: heroui-native's react-native import resolved to node_modules/react-native/index.js (not rewritten). Clone it anywhere else and it prints OK: heroui-native's react-native import is rewritten to uniwind/components.
Uniwind version
1.12.0 (the same code is on main)
React Native Version
0.86.3 (Expo SDK 57; heroui-native 1.0.9 and 1.0.10)
Platforms
Android (the code path is the native resolver, so iOS should be affected the same way)
Expo
Yes
Additional information 〰
(Re-filed from #684, which the template bot auto-closed because it was submitted outside the issue form.)
What happened?
On native platforms, Uniwind stops applying
classNamestyles to every component that comes fromnode_modules(e.g. all of HeroUI Native'sCard,Surface,Button, etc. render with no background, padding, radius or fill) whenever the app's absolute path contains a directory namedreact-native, e.g.~/Developer/react-native/my-app. The same class strings work onViews in the app's own source.Root cause:
nativeResolverinpackages/uniwind/src/bundler/adapters/metro/resolvers.tsdecides whether a module is React Native internals with a substring match on the whole absolute path:For
/Users/me/Developer/react-native/my-app/node_modules/heroui-native/lib/module/components/surface/surface.js, both flags aretrue(because of the parentreact-native/folder), so thereact-native→uniwind/componentsrewrite is skipped for every dependency. App files don't contain/node_modules/, so they keep working, which makes this look like a component-library bug.Quick check:
Suggested fix (only look at the path after the last
node_modulessegment). We're running this as a localpnpm patch, and it fixes the problem while keeping the React Native internals and the Animated exception behaving as before:(
startsWith('react-native' + sep)also avoids matching sibling packages likereact-native-svg.)Steps to Reproduce
mkdir -p /tmp/react-native && cd /tmp/react-native && git clone https://github.com/musab-olurode/uniwind-rn-path-repro && cd uniwind-rn-path-repro && npm install && node scripts/check-resolver.jsprints BUG. The same steps under/tmp/rn-ok/print OK.Or manually:
mkdir -p /tmp/react-native && cd /tmp/react-native. The parent folder name is what matters.withUniwindConfiginmetro.config.js,global.cssimportingtailwindcss,uniwind,heroui-native/styles, app wrapped inGestureHandlerRootView+HeroUINativeProvider).<Card><Card.Body><Card.Title>Hi</Card.Title></Card.Body></Card>and<Button>Press</Button>.react-nativesegment (e.g./tmp/rn/…), clear the Metro cache, and run again. The components are styled correctly.Snack or Repository Link
https://github.com/musab-olurode/uniwind-rn-path-repro
It includes a headless check,
node scripts/check-resolver.js. The script runsexpo export --platform android --devthrough the realmetro.config.jsand inspects what heroui-native'ssurface.jsreact-nativeimport resolved to. Clone it into a folder namedreact-nativeand it printsBUG: heroui-native's react-native import resolved to node_modules/react-native/index.js (not rewritten). Clone it anywhere else and it printsOK: heroui-native's react-native import is rewritten to uniwind/components.Uniwind version
1.12.0 (the same code is on
main)React Native Version
0.86.3 (Expo SDK 57; heroui-native 1.0.9 and 1.0.10)
Platforms
Android (the code path is the native resolver, so iOS should be affected the same way)
Expo
Yes
Additional information 〰
isInternalpath-classification bug in the same resolver)(Re-filed from #684, which the template bot auto-closed because it was submitted outside the issue form.)