Skip to content

Commit 2fac7fd

Browse files
authored
Merge pull request #5 from finkef/feature/media-queries
Reimplement CSS Media Queries
2 parents 800a353 + d98a8a6 commit 2fac7fd

26 files changed

+716
-244
lines changed

README.md

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ const Status = ({ isActive, labelColor }) => {
7575

7676
`ios:bg-blue-800 android:bg-purple-800`
7777

78+
- 🖥   Web only selectors
79+
80+
`focus:bg-blue-400 active:bg-indigo-400`
81+
7882
- 🕺   Stackable selectors
7983

8084
`ios:md:font-bold android:(text-blue-800 sm:dark:text-blue-100)`
@@ -107,7 +111,7 @@ Add babel-plugin-macros to your `.babelrc` or `babel.config.js` and you're all s
107111

108112
### Using the `tw` prop
109113

110-
The best and easiest usage is to simply use the `tw` prop that is artificially added to all JSX elements. Under the hood, the macro removes the `tw` prop completely and instead applies or extends a `style` prop and also adds a web-only media id used by [react-native-media-query](https://github.com/kasinskas/react-native-media-query) to apply CSS-based media queries.
114+
The best and easiest usage is to simply use the `tw` prop that is artificially added to all JSX elements. Under the hood, the macro removes the `tw` prop completely and instead applies or extends a `style` prop and also adds a web-only data-tw id used to apply CSS-based media queries.
111115

112116
All you have to do is have _any_ import of react-native-tailwind.macro in your file, either `import "react-native-tailwind.macro"` or `import { /* whatever import you need */ } from "react-native-tailwind.macro"`.
113117

@@ -197,7 +201,7 @@ const Example = ({ rounded, backgroundColor }) => {
197201
<Animated.View
198202
style={styles.box}
199203
{/* Required for responsive styles on the web, hence it's preferred to apply all responsive styles through the `tw` prop */}
200-
dataSet={{ media: styles.box.id }}
204+
dataSet={{ tw: styles.box.id }}
201205
/>
202206
<TouchableOpacity
203207
{/* Mix and match tw prop and styles in your code */}
@@ -228,20 +232,31 @@ const styles = useTailwindStyles(
228232

229233
By default, the device's color scheme preference is used to enable dark mode. If you want to dynamically change whether dark mode is enabled, you can wrap your App with `TailwindProvider` and pass in your dark mode preference.
230234

235+
On the web, the set value will automatically be persisted in a cookie to enable SSR and SSG without flashes on load.
236+
231237
```ts
232-
import { Appearance } from "react-native"
233-
import { TailwindProvider } from "react-native-tailwind.macro"
238+
import {
239+
TailwindProvider,
240+
getInitialColorScheme,
241+
} from "react-native-tailwind.macro"
234242

235243
const App = () => {
236-
const [darkMode, setDarkMode] = useState(
237-
// Use device preference as default
238-
Appearance.getColorScheme() === "dark"
239-
)
244+
const [darkMode, setDarkMode] = useState(getInitialColorScheme() === "dark")
240245

241246
return <TailwindProvider dark={darkMode}>{/* ... */}</TailwindProvider>
242247
}
243248
```
244249

250+
### `getInitialColorScheme`
251+
252+
Returns either the cookie-persisted preference on web or falls back to the system preference.
253+
254+
```ts
255+
import { getInitialColorScheme } from "react-native-tailwind.macro"
256+
257+
getInitialColorScheme() // returns "light" or "dark"
258+
```
259+
245260
### Macro Options
246261

247262
You can apply options to the macro by adding a `babel-plugin-macros.config.js` or specifying them in your `package.json` like below:
@@ -282,9 +297,10 @@ Alternatively:
282297

283298
In order to enable SSR support via media queries on Next.js, update your [custom document](https://nextjs.org/docs/advanced-features/custom-document) as follows:
284299

285-
```ts
286-
// Add the flush import
287-
import { flush } from "react-native-tailwind.macro"
300+
```diff
301+
// pages/_document.js
302+
303+
+ import { flush } from "react-native-tailwind.macro"
288304

289305
/* ... */
290306

@@ -295,7 +311,7 @@ export class Document extends NextDocument {
295311
const page = renderPage()
296312
const styles = [
297313
getStyleElement(),
298-
flush(), // Add this call
314+
+ flush(),
299315
]
300316
return { ...page, styles: React.Children.toArray(styles) }
301317
}
@@ -314,7 +330,7 @@ Behind the scenes, `react-native-tailwind.macro` turns your _simple_ code from t
314330
import "react-native-tailwind.macro"
315331

316332
const Example = () => (
317-
<View tw="w-[100px] h-[100px] bg-purple-500 dark:ios:lg:bg-pink-500" />
333+
<View tw="w-[100px] h-[100px] bg-purple-500 dark:ios:lg:bg-pink-500 hover:bg-indigo-500" />
318334
)
319335
```
320336

@@ -330,6 +346,7 @@ const useStyles = ReactNativeTailwindMacro.createUseTailwindStyles({
330346
a7gsbs: [
331347
{
332348
dark: false,
349+
selectors: [],
333350
style: {
334351
width: 100,
335352
height: 100,
@@ -338,13 +355,22 @@ const useStyles = ReactNativeTailwindMacro.createUseTailwindStyles({
338355
},
339356
{
340357
dark: true,
341-
breakpoint: "lg",
358+
breakpoint: {
359+
label: "lg",
360+
minWidth: "1024px",
361+
},
362+
selectors: [],
342363
platform: "ios",
343364
style: {
344-
// Output for react-native-media-query
345-
"@media(min-width: 1024px)": {
346-
backgroundColor: "#ec4899",
347-
},
365+
backgroundColor: "#ec4899",
366+
},
367+
},
368+
{
369+
dark: false,
370+
// Styles on web will only be applied on web
371+
selectors: ["hover"],
372+
style: {
373+
backgroundColor: "#6366f1",
348374
},
349375
},
350376
],
@@ -359,8 +385,8 @@ const Example = () => {
359385
<View
360386
// Apply the memoized style
361387
style={tailwindStyles["a7gsbs"]}
362-
// Apply media id for CSS-based media queries using react-native-media-query
363-
dataSet={{ media: tailwindStyles["a7gsbs"].id }}
388+
// Apply data-tw id for CSS-based media queries
389+
dataSet={{ tw: tailwindStyles["a7gsbs"].id }}
364390
/>
365391
)
366392
}
@@ -380,7 +406,7 @@ For more examples and use cases, check the [macro test snapshots](packages/react
380406

381407
- [tailwind-react-native-classnames](https://github.com/jaredh159/tailwind-react-native-classnames): Used for compiling Tailwind styles
382408

383-
- [react-native-media-query](https://github.com/kasinskas/react-native-media-query): Used for applying responsive styles with CSS media queries on the web
409+
- [react-native-media-query](https://github.com/kasinskas/react-native-media-query): Provides the base implementation used to enable CSS media query support
384410

385411
- [twin.macro](https://github.com/ben-rogerson/twin.macro): Inspiration for writing a babel macro
386412

examples/expo/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"react": "16.13.1",
1919
"react-dom": "16.13.1",
2020
"react-native": "0.63.4",
21-
"react-native-media-query": "^1.0.7",
2221
"react-native-tailwind.macro": "*",
2322
"react-native-unimodules": "~0.12.0",
2423
"react-native-web": "~0.14.9"

examples/expo/src/App.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import * as React from "react"
22

33
import { View, Text } from "react-native"
4-
import { TailwindProvider } from "react-native-tailwind.macro"
4+
import {
5+
getInitialColorScheme,
6+
TailwindProvider,
7+
} from "react-native-tailwind.macro"
58
import { Button } from "./Button"
69

710
interface AppProps {
@@ -39,7 +42,7 @@ const App: React.FunctionComponent<AppProps> = ({ toggleTheme }) => {
3942
}
4043

4144
export default () => {
42-
const [dark, setDark] = React.useState(false)
45+
const [dark, setDark] = React.useState(getInitialColorScheme() === "dark")
4346

4447
return (
4548
<TailwindProvider dark={dark}>

examples/next/App.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import * as React from "react"
22

33
import { View, Text } from "react-native"
4-
import { TailwindProvider } from "react-native-tailwind.macro"
4+
import {
5+
TailwindProvider,
6+
getInitialColorScheme,
7+
} from "react-native-tailwind.macro"
58
import { Button } from "./components/Button"
69

710
interface AppProps {
@@ -25,11 +28,21 @@ const App: React.FunctionComponent<AppProps> = ({ toggleTheme }) => {
2528
</Text>
2629

2730
<Text tw="mt-16 font-bold text-xl dark:text-white">Breakpoints</Text>
28-
<Text tw="dark:text-white xs:(font-bold text-blue-500)">xs</Text>
29-
<Text tw="dark:text-white sm:(font-bold text-blue-500)">sm</Text>
30-
<Text tw="dark:text-white md:(font-bold text-blue-500)">md</Text>
31-
<Text tw="dark:text-white lg:(font-bold text-blue-500)">lg</Text>
32-
<Text tw="dark:text-white xl:(font-bold text-blue-500)">xl</Text>
31+
<Text tw="dark:text-white xs:(font-bold text-blue-500 dark:text-pink-500)">
32+
xs
33+
</Text>
34+
<Text tw="dark:text-white sm:(font-bold text-blue-500 dark:text-pink-500)">
35+
sm
36+
</Text>
37+
<Text tw="dark:text-white md:(font-bold text-blue-500 dark:text-pink-500)">
38+
md
39+
</Text>
40+
<Text tw="dark:text-white lg:(font-bold text-blue-500 dark:text-pink-500)">
41+
lg
42+
</Text>
43+
<Text tw="dark:text-white xl:(font-bold text-blue-500 dark:text-pink-500)">
44+
xl
45+
</Text>
3346

3447
<Text tw="mt-8 text-custom">
3548
Text using custom color from tailwind.config.js
@@ -39,7 +52,7 @@ const App: React.FunctionComponent<AppProps> = ({ toggleTheme }) => {
3952
}
4053

4154
export default () => {
42-
const [dark, setDark] = React.useState(false)
55+
const [dark, setDark] = React.useState(getInitialColorScheme() === "dark")
4356

4457
return (
4558
<TailwindProvider dark={dark}>

examples/next/components/Button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const Button: FunctionComponent<ButtonProps> = ({ label, onPress }) => {
1414
(tw) => ({
1515
button: [
1616
tw`px-8 py-4 rounded-3xl bg-blue-500`,
17-
pressed && tw`bg-blue-200`,
17+
pressed ? tw`bg-blue-200` : tw`hover:bg-blue-400`,
1818
],
1919
text: tw`text-white dark:text-black`,
2020
}),
@@ -27,7 +27,7 @@ export const Button: FunctionComponent<ButtonProps> = ({ label, onPress }) => {
2727
onPressOut={() => setPressed(false)}
2828
onPress={onPress}
2929
>
30-
<View style={styles.button}>
30+
<View style={styles.button} dataSet={{ tw: styles.button.id }}>
3131
<Text style={styles.text}>{label}</Text>
3232
</View>
3333
</TouchableWithoutFeedback>

examples/next/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
},
2222
"scripts": {
2323
"start": "yarn clean && yarn next dev",
24+
"build": "yarn clean && yarn next build",
25+
"serve": "yarn next start",
2426
"clean": "rimraf .expo/web/cache"
2527
},
2628
"prettier": {

packages/react-native-tailwind.macro/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
"@babel/template": "^7.15.4",
4848
"babel-plugin-macros": "^3.1.0",
4949
"nanoid": "^3.1.25",
50-
"react-native-media-query": "^1.0.9",
5150
"twrnc": "2.1.0-beta.5"
5251
},
5352
"devDependencies": {

packages/react-native-tailwind.macro/src/__tests__/__fixtures__/component-with-hook.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ const Comp = () => {
66
[isFocused]
77
)
88

9-
return <View tw="bg-blue-500" style={box} dataSet={{ media: box.id }} />
9+
return <View tw="bg-blue-500" style={box} dataSet={{ tw: box.id }} />
1010
}

packages/react-native-tailwind.macro/src/__tests__/__fixtures__/existing-data-set-prop.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import tw from "../../macro"
22

33
const Comp = () => <View tw="px-8" dataSet={{ foo: "bar" }} />
44

5-
const Comp2 = () => <View tw="px-8" dataSet={{ foo: "bar", media: "baz" }} />
5+
const Comp2 = () => <View tw="px-8" dataSet={{ foo: "bar", tw: "baz" }} />

0 commit comments

Comments
 (0)