jaredh159 / tailwind-react-native-classnames

simple, expressive API for tailwindcss + react-native
2.06k stars 85 forks source link

twrnc modifiers not working on expo react native project #206

Closed Teqshark closed 1 year ago

Teqshark commented 1 year ago

I have been unable to get the modifiers (screen, state, etc) to work in my expo react native project. using twrnc^3.4.1 Most of everything else seems to work fine. I configured the tailwind.config file like below and my custom colors worked fine using this config file however custom breakpoints never worked nor did the default ones at all not even when I try on a fresh tailwind integration before trying to customize it.

Also I noticed none of the state modifier have worked i.e. (hover:, ios:, android:, dark:, light: etc.) as stated none of them have worked even before i configure the config file.

I looked at the tailwindcss docs and stackoverlfow for example config files and while the custom colors and classes work fine the screens/breakpoints and default modifiers never do.

here is my tailwind.config.js :

`/* @type {import('tailwindcss').Config} / // tailwind.config.js const { plugin } = require('twrnc'); const defaultTheme = require('tailwindcss/defaultTheme') // or, you can use tailwinds plugin function: // const plugin = require('tailwindcss/plugin');

module.exports = { important: true, // purge: [], content: ["./src/*/.{js,jsx,ts,tsx}", "./app.js"], // this line is important to use tailwind CSS. theme: { screens: { 'sm': '640px', // => @media (min-width: 640px) { ... }

  'md': '768px',
  // => @media (min-width: 768px) { ... }

  'lg': '1024px',
  // => @media (min-width: 1024px) { ... }

  'xl': '1280px',
  // => @media (min-width: 1280px) { ... }

  '2xl': '1536px',
  // => @media (min-width: 1536px) { ... }
},
extend: {
  colors: {
    darklogo: '#00216e',
    lightlogo: '#0c54ff',
    gold:
    { 
      '50': '#FFCE5C',
      100: '#FFC233',
      // 100: '#b98b41',
      // 75: '#c29752',
      200: '#ffb70c',
      300: '#c29752',
      '400': '#c9a265',
      // 500: '#cfae78',
      // 600: '#d6b98b',
    },
    transparent: 'transparent',
    blacklogo:{
      100:'#000',
      200: '#090C08'
    },
    whitelogo: {
      50: '#e5e5e5',
      100:'#fff',
      200: '#FFF5FF',
      300: '#FFE8F7',
      400: '#F2ECFF',
    },
    redlogo: {
      50: '#fff1f3',
      100: '#ffdfe4',
      200: '#ffc4cd',
      300: '#ff9baa',
      400: '#ff6179',
      500: '#ff304f',
      600: '#f21032',
      700: '#c20925',
      800: '#a80c24',
      900: '#8b1123',
    },
    greenlogo: {
      '50': '#eefbf5',
      '100': '#d5f6e5',
      '200': '#afebcf',
      '300': '#7adbb4',
      '400': '#44c395',
      '500': '#21a87b',
      '600': '#148763',
      '700': '#106c52',
      '800': '#0f5642',
      '900': '#0d4738',
    },
    bluelogo: {
      '50': '#e6f9ff',
      '100': '#d1f4ff',
      '200': '#ade9ff',
      '300': '#7cd5ff',
      '400': '#49b2ff',
      '500': '#218cff',
      '550': '#117AFF',
      '580': '#0068ff',
      '590': '#006Aff',
      '600': '#006Cff',
      '650': '#0064ec',
      '660': '#0060E3',
      // '68': '#005BD9',
      '700': '#006cff',
      '800': '#005bd9',
      '850': '#024396',
      '900': '#042a5e',
    },
    bahamablue: {
      '50': '#f0f7ff',
      '100': '#e0effe',
      '200': '#badffd',
      '300': '#7ec5fb',
      '400': '#39a7f7',
      '500': '#108de7',
      '600': '#036fc6',
      '700': '#04559b',
      '800': '#084b84',
      '900': '#0d406d',
    },
    brightsun: {
      '50': '#fffbeb',
      '100': '#fff3c6',
      '200': '#ffe588',
      '300': '#ffcf40',
      '400': '#ffbd20',
      // '500': '#f99b07',
      // '600': '#dd7302',
      // '700': '#b75006',
      // '800': '#943d0c',
      // '900': '#7a330d',
    },
    gray: {
      100: '#f7fafc',
      // ...
      900: '#1a202c',
    },
  },
  fontFamily: {
    sans: ['Nunito','Graphik', 'sans-serif'],
    serif: ['Merriweather', 'serif'],
  },
  boxShadow: {
    rainbow: '0 0 0 10px #ff0000,0 0 0 20px #ff7700,0 0 0 30px #FFDD00,0 0 0 40px #00FF00,0 0 0 50px #0000FF,0 0 0 60px #C77DF3,0 0 0 70px #8A2BE2',
  },
  spacing: {
    '8xl': '96rem',
    '9xl': '128rem',
  },
  borderRadius: {
    '4xl': '2rem',
  }
}

}, // variants: {}, plugins: [ plugin(({ addUtilities }) => { addUtilities({

    container: {
      width: '100%',
    },
    container1: {
      width: '100vw',
      // display: 'flex',
      // flex: 1,
      // width: '100vw',
      // height: 'auto',
      // display: 'flex',
      // width: '100vw',
      // height: 'auto',
      backgroundColor: 'white',
      alignItems: 'center',
      justifyContent: 'center', 
      justifyItems: 'center',
      border: '1px dashed blue'
      // justifyContent: 'center',
    },
    container2: {
      flex: 1,
      // display: 'flex',
      // width: '100vw',
      // height: 'auto',
      backgroundColor: 'white',
      alignItems: 'center',
      border: '1px dashed blue'
      // justifyContent: 'center',
    },
    btn: {
      padding: 3,
      borderRadius: 10,
      textTransform: `uppercase`,
      backgroundColor: `#333`,
    },
    'glass-border': {
      border: '1px solid white',
    },
    nav: {

      opacity: '0.4',
      display: 'flex',
      width: '87vw',
      alignSelf: 'center',
      // maxWidth: '100vw',
      overflow: 'hidden',
      borderRadius: '12px',
      fontSize:  20,
      backgroundColor: 'transparent', 
      height: '12.4%',
      minHeight: 70,
      // display: 'flex',
      flexDirection: 'row',
      padding: '2rem, 3rem',
      alignContent: 'center',
      justifyContent: 'center',
      alignItems: 'center',
      justifyItems: 'center',
    },
    btnContainer: {
      flexDirection: 'row',
    },
    navIcon: {
      // fdlkj:'Adrian Codes',
      height: '80%',
      width: 'auto',
      aspectRatio: 'maintain', 
    },
    navBtn: {
      border: 'none',
      backgroundColor: 'red',
      // padding: '2rem 3rem',
      color: 'white',
      alignSelf: 'center',
      justifySelf: 'center',
    },
    'nav-text': `text-base leading-relaxed tracking-wide font-bold text-blue-500 font-sans`,
    'resize-repeat': {
      resizeMode: `contain`,
    },
    'd-none': {
      display: 'none',
    },
    logoTagline: `py-1 px-1 text-md font-sans`,
    'text-logo': `font-sans text-large`,
    ctaButton: {
      fontSize: '26px',
      backgroundColor: 'blue-400',
    },
    dNone: {display:'none'},
    header: {
      fontSize: '42px',
      // spacing:
    },
    'resize-cover': {
      resizeMode: 'cover',
    },
    scroll: 
    {width: '100vw'},
    // 'section-mb': `flex flex-column md:flex-row justify-between align-center` ,
    section: {
      backgroundColor: 'red', border: '1px solid white',
      alignSelf: 'center',
      width: '80%',
      height: '70vh',
      marginTop: '2rem',
      marginBottom: '2rem',
      borderRadius: 20,
      // display: 'flex',
      // flexDirection: 'column'
  },
    sectionMobile: {
      height: '87vh',
      width: '96vw',
      margin: '4rem',
      padding: '4rem 6rem',
    },
    // sectionWebLg: {
    //   height: '80&vh',
    //   width: '100vw',
    //   margin: '4rem',
    //   padding: '4rem 6rem',
    // },
    sectionWeb: {

      height: '80%',
      width: '90%',
      alignSelf: 'center',
      margin: '4rem',
      padding: '4rem 6rem',
    },
    glass: {

    },
    form: `mb-4 md:flex md:flex-wrap md:justify-between`,
    formDiv: `flex flex-col mb-6 md:w-full`,
    formLabel: `mb-2 uppercase font-bold text-lg text-gray-100`,
    formInput: `border py-2 px-3 text-gray-900`,
    formButton: ` bg-teal-500 hover:bg-teal-800 text-white uppercase text-lg mx-auto p-4 rounded`,
    'resize-contain': {
      resizeMode: `contain`,
    },
    btn1: `px-4 py-1 rounded-full bg-red-800 text-white`,
    'body-text': `font-serif leading-relaxed tracking-wide text-gray-900`,
    contactForm: {
        fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI" ,Roboto, Oxygen,Ubuntu, Cantarell, "Open Sans,"Helvetica Neue", sans-serif',
    }
  });
}),

], // content: [],

}

`

package.json : { "name": "adriancodes", "version": "1.0.0", "main": "./entry.js", "scripts": { "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "@expo/webpack-config": "^0.17.2", "@react-native-community/blur": "^4.3.0", "debounce": "^1.2.1", "dom-to-image": "^2.6.0", "expo": "~47.0.6", "expo-blur": "~12.0.1", "expo-gl": "~12.0.1", "expo-image-picker": "~14.0.2", "expo-media-library": "~15.0.0", "expo-splash-screen": "~0.17.5", "expo-status-bar": "~1.4.2", "expo-three": "^7.0.0", "firebase": "^9.15.0", "hsl-to-hex-v2": "^1.0.0", "react": "18.1.0", "react-dom": "18.1.0", "react-hook-form": "^7.40.0", "react-native": "0.70.5", "react-native-canvas": "^0.1.38", "react-native-gesture-handler": "~2.8.0", "react-native-picker-select": "^8.0.4", "react-native-reanimated": "~2.12.0", "react-native-view-shot": "3.4.0", "react-native-web": "~0.18.9", "simplex-noise": "^4.0.1", "three": "^0.147.0", "twrnc": "^3.4.1" }, "devDependencies": { "@babel/core": "^7.12.9", "@babel/plugin-proposal-export-namespace-from": "^7.18.9" }, "private": true }

tailwind.js :

`import {create } from 'twrnc';

const tw = create(require('../../tailwind.config.js'));

export default tw; `

console.logging gives the expected object when not using modifiers like so: console.log('tw-', twbg-gold-400); and gives empty objects when trying to use the modifiers: console.log('tw-', twlight:bg-red-500 dark:bg-blue-500);

was really looking forward to using this package however i will have to use an alternative if i can't get the modifiers to work

please help!

jaredh159 commented 1 year ago

this is most often caused by failure to connect the tw function to the source of runtime device information as described in the readme here:

https://github.com/jaredh159/tailwind-react-native-classnames#enabling-device-context-prefixes

Did you do that step?

Teqshark commented 1 year ago

@jaredh159 Thanks so much I dont know how I missed that after looking over the docs so many times ! That is the only thing i had not done!

jaredh159 commented 1 year ago

no worries, it's easy to miss stuff like that 😄

tomh4 commented 1 year ago

@Teqshark how did you get it working with expo? I am using expo-router, and I cannot execute the hook at the root level as it is not exposed, where should I call it to make it work ? :) @jaredh159

jaredh159 commented 1 year ago

@tomh4 i would just try executing the hook at the highest point of the hierarchy that i control. you just need it higher than any of your usages of the tw fn, so it should still work. (provided you're targeting RN native, and not RN web).

tomh4 commented 1 year ago

@jaredh159 thanks, ok, I tried that but it seems not to work correctly. Basically I am using Expo Router, targeting iOS, and calling it inside the _layout.tsx directly inside the app folder, so it is the first thing that is loaded when the app starts. It stays in bright mode though :(

jaredh159 commented 1 year ago

hmmm..... have you looked at this issue? https://github.com/jaredh159/tailwind-react-native-classnames/issues/112

wondering if there is some similar memoization going on with expo router. i'm not familiar at all with that package. otherwise, is you project open source where i could look at the code in it's entirety?

tomh4 commented 1 year ago

the project is not open source, but it is basically a fresh project. I pushed it here to this public remote, take a look if you want :) https://github.com/tomh4/tailwind-expo-router

tomh4 commented 1 year ago

@jaredh159 does the project work with dark/bright mode for you ?

sapjax commented 1 year ago

same issue here, useDeviceContext only works at a single component level, no effect at root level.

jaredh159 commented 1 year ago

@tomh4 i pulled your project down, but couldn't get the dependencies installed, got an error:

CommandError: It looks like you're trying to use web support but don't have the required dependencies installed.

Please install react-dom@18.2.0 by running:

npx expo install react-dom@18.2.0

If you're not using web, please ensure you remove the "web" string from the platforms array in the project Expo config.

but i've never used expo before, and a minute or two of poking around and i couldn't find an expo config file.

edit: ran the expo install command, and i can get it building, but i'm getting errors in the ios simulator, so can't tell.

did you look into issue #112?

anirudhgray commented 1 year ago

Okay, so I had a similar problem working with an Expo app, except mine didn't get resolved even after checking if I had added useDeviceContext (I had).

Go to the app.json file in your project root, and set the following:

{
  "expo": {
    "userInterfaceStyle": "automatic"
  }
}

For some reason, Expo keeps the default as "light" which forces your app to run in light mode, regardless of system preferences. https://docs.expo.dev/develop/user-interface/color-themes/

tomh4 commented 1 year ago

thanks @anirudhgray , mine was set as light as well so that was definitely one of the issues. However, it is still not loading my dark attributes, can you tell me where you did put the useDeviceContext?

anirudhgray commented 1 year ago

@tomh4 I've put useDeviceContext in App.js since that's my root component (my navigation container and all is in there). Not sure how to go about it in your case with Expo router.

sapjax commented 1 year ago

I'm using Expo router, On every page, I need to add useDeviceContext(tw) or useColorScheme() to make the page responsive to Appearance theme changes, if I didn't add these hooks, the page will not change even tw.setColorScheme manually.

YounesKHENIFER commented 1 year ago

same , useDeviceContext(tw) not working on top app.js

JamesHemery commented 1 year ago

Same for me, with Expo Router useDeviceContext not working on top app.js

JamesHemery commented 1 year ago

A temp workaround is to change the route stack key :

// app/_layout.tsx
function useRouterKey(): string {
  const dimensions = useWindowDimensions();
  const colorScheme = useColorScheme();

  return useMemo(() => {
    return JSON.stringify({ ...dimensions, colorScheme });
  }, [dimensions, colorScheme]);
}

export function RootLayout() {
  useDeviceContext(tw);

  const routerKey = useRouterKey();

  return (
    <ReactNavigationTheme>
      <Stack key={routerKey}>
        <Stack.Screen name="(auth)" options={{ headerShown: false }} />
        <Stack.Screen name="(main)" options={{ headerShown: false }} />
      </Stack>
    </ReactNavigationTheme>
  );
}

I'll be taking a closer look in the near future to find a permanent solution.