@mgcrea/react-native-tailwind 0.9.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +386 -43
- package/dist/babel/config-loader.d.ts +12 -3
- package/dist/babel/config-loader.test.ts +154 -0
- package/dist/babel/config-loader.ts +41 -9
- package/dist/babel/index.cjs +592 -69
- package/dist/babel/plugin.d.ts +23 -1
- package/dist/babel/plugin.test.ts +331 -0
- package/dist/babel/plugin.ts +268 -37
- package/dist/babel/utils/colorSchemeModifierProcessing.d.ts +34 -0
- package/dist/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/dist/babel/utils/dynamicProcessing.d.ts +34 -3
- package/dist/babel/utils/dynamicProcessing.ts +358 -39
- package/dist/babel/utils/modifierProcessing.d.ts +3 -3
- package/dist/babel/utils/modifierProcessing.ts +5 -5
- package/dist/babel/utils/platformModifierProcessing.d.ts +3 -3
- package/dist/babel/utils/platformModifierProcessing.ts +4 -4
- package/dist/babel/utils/styleInjection.d.ts +13 -0
- package/dist/babel/utils/styleInjection.ts +101 -0
- package/dist/babel/utils/styleTransforms.test.ts +56 -0
- package/dist/babel/utils/twProcessing.d.ts +5 -3
- package/dist/babel/utils/twProcessing.ts +27 -6
- package/dist/parser/index.d.ts +13 -6
- package/dist/parser/index.js +1 -1
- package/dist/parser/modifiers.d.ts +48 -2
- package/dist/parser/modifiers.js +1 -1
- package/dist/parser/modifiers.test.js +1 -1
- package/dist/parser/typography.d.ts +3 -1
- package/dist/parser/typography.js +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +3 -3
- package/dist/runtime.d.ts +8 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +3 -3
- package/dist/runtime.test.js +1 -1
- package/dist/types/config.d.ts +7 -0
- package/dist/types/config.js +0 -0
- package/package.json +3 -2
- package/src/babel/config-loader.test.ts +154 -0
- package/src/babel/config-loader.ts +41 -9
- package/src/babel/plugin.test.ts +331 -0
- package/src/babel/plugin.ts +268 -37
- package/src/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/src/babel/utils/dynamicProcessing.ts +358 -39
- package/src/babel/utils/modifierProcessing.ts +5 -5
- package/src/babel/utils/platformModifierProcessing.ts +4 -4
- package/src/babel/utils/styleInjection.ts +101 -0
- package/src/babel/utils/styleTransforms.test.ts +56 -0
- package/src/babel/utils/twProcessing.ts +27 -6
- package/src/parser/index.ts +28 -9
- package/src/parser/modifiers.test.ts +151 -1
- package/src/parser/modifiers.ts +139 -4
- package/src/parser/typography.ts +14 -2
- package/src/runtime.test.ts +7 -7
- package/src/runtime.ts +37 -14
- package/src/types/config.ts +7 -0
package/README.md
CHANGED
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
<a href="https://github.com/mgcrea/react-native-tailwind/actions/workflows/main.yaml">
|
|
24
24
|
<img src="https://img.shields.io/github/actions/workflow/status/mgcrea/react-native-tailwind/main.yaml?style=for-the-badge&branch=main" alt="build status" />
|
|
25
25
|
</a>
|
|
26
|
+
<a href="https://codecov.io/gh/mgcrea/react-native-tailwind">
|
|
27
|
+
<img src="https://img.shields.io/codecov/c/github/mgcrea/react-native-tailwind?style=for-the-badge" alt="coverage" />
|
|
28
|
+
</a>
|
|
26
29
|
<a href="https://depfu.com/github/mgcrea/react-native-tailwind">
|
|
27
30
|
<img src="https://img.shields.io/depfu/dependencies/github/mgcrea/react-native-tailwind?style=for-the-badge" alt="dependencies status" />
|
|
28
31
|
</a>
|
|
@@ -46,6 +49,8 @@ Compile-time Tailwind CSS for React Native with zero runtime overhead. Transform
|
|
|
46
49
|
- 🏃 **Runtime option** — Optional `tw` template tag for fully dynamic styling (~25KB)
|
|
47
50
|
- 🎯 **State modifiers** — `active:`, `hover:`, `focus:`, and `disabled:` modifiers for interactive components
|
|
48
51
|
- 📱 **Platform modifiers** — `ios:`, `android:`, and `web:` modifiers for platform-specific styling
|
|
52
|
+
- 🌓 **Color scheme modifiers** — `dark:` and `light:` modifiers for automatic theme adaptation
|
|
53
|
+
- 🎨 **Scheme modifier** — `scheme:` convenience modifier that expands to both `dark:` and `light:` variants
|
|
49
54
|
- 📜 **Special style props** — Support for `contentContainerClassName`, `columnWrapperClassName`, and more
|
|
50
55
|
- 🎛️ **Custom attributes** — Configure which props to transform with exact matching or glob patterns
|
|
51
56
|
|
|
@@ -78,28 +83,6 @@ module.exports = {
|
|
|
78
83
|
};
|
|
79
84
|
```
|
|
80
85
|
|
|
81
|
-
**Advanced:** You can customize which attributes are transformed and the generated styles identifier:
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
module.exports = {
|
|
85
|
-
presets: ["module:@react-native/babel-preset"],
|
|
86
|
-
plugins: [
|
|
87
|
-
[
|
|
88
|
-
"@mgcrea/react-native-tailwind/babel",
|
|
89
|
-
{
|
|
90
|
-
// Specify which attributes to transform
|
|
91
|
-
// Default: ['className', 'contentContainerClassName', 'columnWrapperClassName', 'ListHeaderComponentClassName', 'ListFooterComponentClassName']
|
|
92
|
-
attributes: ["className", "buttonClassName", "containerClassName"],
|
|
93
|
-
|
|
94
|
-
// Custom identifier for the generated StyleSheet constant
|
|
95
|
-
// Default: '_twStyles'
|
|
96
|
-
stylesIdentifier: "styles",
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
],
|
|
100
|
-
};
|
|
101
|
-
```
|
|
102
|
-
|
|
103
86
|
### 2. Enable TypeScript Support (TypeScript)
|
|
104
87
|
|
|
105
88
|
Create a type declaration file in your project to enable `className` prop autocomplete:
|
|
@@ -442,7 +425,7 @@ export function RuntimeExample() {
|
|
|
442
425
|
|
|
443
426
|
#### Configuration
|
|
444
427
|
|
|
445
|
-
Configure custom colors and
|
|
428
|
+
Configure custom colors and font families using `setConfig()`:
|
|
446
429
|
|
|
447
430
|
```typescript
|
|
448
431
|
import { setConfig } from '@mgcrea/react-native-tailwind/runtime';
|
|
@@ -459,13 +442,17 @@ setConfig({
|
|
|
459
442
|
dark: '#CC0000',
|
|
460
443
|
},
|
|
461
444
|
},
|
|
445
|
+
fontFamily: {
|
|
446
|
+
sans: ['"SF Pro Rounded"'],
|
|
447
|
+
custom: ['"My Custom Font"'],
|
|
448
|
+
},
|
|
462
449
|
},
|
|
463
450
|
},
|
|
464
451
|
});
|
|
465
452
|
|
|
466
|
-
// Now you can use custom
|
|
453
|
+
// Now you can use custom theme
|
|
467
454
|
<View style={tw`bg-primary p-4`} />
|
|
468
|
-
<Text style={tw`text-brand-light`}>Custom
|
|
455
|
+
<Text style={tw`text-brand-light font-custom`}>Custom styling</Text>
|
|
469
456
|
```
|
|
470
457
|
|
|
471
458
|
#### API Reference
|
|
@@ -722,9 +709,7 @@ import { View, Text } from "react-native";
|
|
|
722
709
|
export function PlatformCard() {
|
|
723
710
|
return (
|
|
724
711
|
<View className="p-4 ios:p-6 android:p-8 bg-white rounded-lg">
|
|
725
|
-
<Text className="text-base ios:text-blue-600 android:text-green-600">
|
|
726
|
-
Platform-specific styles
|
|
727
|
-
</Text>
|
|
712
|
+
<Text className="text-base ios:text-blue-600 android:text-green-600">Platform-specific styles</Text>
|
|
728
713
|
</View>
|
|
729
714
|
);
|
|
730
715
|
}
|
|
@@ -844,15 +829,16 @@ import { Pressable } from "@mgcrea/react-native-tailwind";
|
|
|
844
829
|
|
|
845
830
|
**Supported Platforms:**
|
|
846
831
|
|
|
847
|
-
| Modifier
|
|
848
|
-
|
|
|
849
|
-
| `ios:`
|
|
850
|
-
| `android:` | Android
|
|
851
|
-
| `web:`
|
|
832
|
+
| Modifier | Platform | Description |
|
|
833
|
+
| ---------- | ---------------- | -------------------------- |
|
|
834
|
+
| `ios:` | iOS | Styles specific to iOS |
|
|
835
|
+
| `android:` | Android | Styles specific to Android |
|
|
836
|
+
| `web:` | React Native Web | Styles for web platform |
|
|
852
837
|
|
|
853
838
|
**How it works:**
|
|
854
839
|
|
|
855
840
|
The Babel plugin:
|
|
841
|
+
|
|
856
842
|
1. Detects platform modifiers during compilation
|
|
857
843
|
2. Parses all platform-specific classes at compile-time
|
|
858
844
|
3. Generates `Platform.select()` expressions with references to pre-compiled styles
|
|
@@ -861,6 +847,350 @@ The Babel plugin:
|
|
|
861
847
|
|
|
862
848
|
This approach provides the best of both worlds: compile-time optimization for all styles, with minimal runtime platform detection only for the conditional selection logic.
|
|
863
849
|
|
|
850
|
+
### Color Scheme Modifiers
|
|
851
|
+
|
|
852
|
+
Apply color scheme-specific styles using `dark:` and `light:` modifiers that automatically react to the device's appearance settings. These work on **all components in functional components** and compile to conditional expressions that use React Native's `useColorScheme()` hook.
|
|
853
|
+
|
|
854
|
+
**Basic Example:**
|
|
855
|
+
|
|
856
|
+
```tsx
|
|
857
|
+
import { View, Text } from "react-native";
|
|
858
|
+
|
|
859
|
+
export function ThemeCard() {
|
|
860
|
+
return (
|
|
861
|
+
<View className="bg-white dark:bg-gray-900 p-4 rounded-lg">
|
|
862
|
+
<Text className="text-gray-900 dark:text-white">Adapts to device theme</Text>
|
|
863
|
+
</View>
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
**Transforms to:**
|
|
869
|
+
|
|
870
|
+
```tsx
|
|
871
|
+
import { useColorScheme, StyleSheet } from "react-native";
|
|
872
|
+
|
|
873
|
+
export function ThemeCard() {
|
|
874
|
+
const _twColorScheme = useColorScheme();
|
|
875
|
+
|
|
876
|
+
return (
|
|
877
|
+
<View
|
|
878
|
+
style={[
|
|
879
|
+
_twStyles._bg_white_p_4_rounded_lg,
|
|
880
|
+
_twColorScheme === "dark" && _twStyles._dark_bg_gray_900,
|
|
881
|
+
]}
|
|
882
|
+
>
|
|
883
|
+
<Text style={[_twStyles._text_gray_900, _twColorScheme === "dark" && _twStyles._dark_text_white]}>
|
|
884
|
+
Adapts to device theme
|
|
885
|
+
</Text>
|
|
886
|
+
</View>
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// Generated styles:
|
|
891
|
+
const _twStyles = StyleSheet.create({
|
|
892
|
+
_bg_white_p_4_rounded_lg: {
|
|
893
|
+
backgroundColor: "#FFFFFF",
|
|
894
|
+
padding: 16,
|
|
895
|
+
borderRadius: 8,
|
|
896
|
+
},
|
|
897
|
+
_dark_bg_gray_900: { backgroundColor: "#111827" },
|
|
898
|
+
_text_gray_900: { color: "#111827" },
|
|
899
|
+
_dark_text_white: { color: "#FFFFFF" },
|
|
900
|
+
});
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
**Common Use Cases:**
|
|
904
|
+
|
|
905
|
+
**Dark mode support:**
|
|
906
|
+
|
|
907
|
+
```tsx
|
|
908
|
+
// Automatically switches between light and dark themes
|
|
909
|
+
<View className="bg-white dark:bg-gray-900">
|
|
910
|
+
<Text className="text-gray-900 dark:text-white">Theme-aware text</Text>
|
|
911
|
+
</View>
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
**Both light and dark overrides:**
|
|
915
|
+
|
|
916
|
+
```tsx
|
|
917
|
+
// Specify both light and dark mode styles explicitly
|
|
918
|
+
<View className="bg-gray-100 light:bg-white dark:bg-gray-900">
|
|
919
|
+
<Text className="text-gray-600 light:text-gray-900 dark:text-gray-100">Custom light & dark styles</Text>
|
|
920
|
+
</View>
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
**Mixed color scheme and platform modifiers:**
|
|
924
|
+
|
|
925
|
+
```tsx
|
|
926
|
+
// Combine color scheme with platform-specific styles
|
|
927
|
+
<View className="p-4 ios:p-6 dark:bg-gray-900 android:rounded-xl">
|
|
928
|
+
<Text className="text-base dark:text-white ios:text-blue-600">Platform + theme aware</Text>
|
|
929
|
+
</View>
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
**Theme-aware cards:**
|
|
933
|
+
|
|
934
|
+
```tsx
|
|
935
|
+
// Card that looks great in both light and dark mode
|
|
936
|
+
<View className="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 p-4 rounded-lg">
|
|
937
|
+
<Text className="text-lg font-bold text-gray-900 dark:text-white mb-2">Card Title</Text>
|
|
938
|
+
<Text className="text-gray-600 dark:text-gray-300">Card description text</Text>
|
|
939
|
+
</View>
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
**Key Features:**
|
|
943
|
+
|
|
944
|
+
- ✅ **Reactive** — Automatically updates when user changes system appearance
|
|
945
|
+
- ✅ **Zero runtime parsing** — All styles compiled at build time
|
|
946
|
+
- ✅ **Auto-injected hook** — `useColorScheme()` automatically added to components
|
|
947
|
+
- ✅ **Works with all modifiers** — Combine with platform and state modifiers
|
|
948
|
+
- ✅ **Type-safe** — Full TypeScript autocomplete
|
|
949
|
+
- ✅ **Optimized** — Minimal runtime overhead (just conditional checks)
|
|
950
|
+
|
|
951
|
+
**Supported Modifiers:**
|
|
952
|
+
|
|
953
|
+
| Modifier | Color Scheme | Description |
|
|
954
|
+
| -------- | ------------ | ------------------------------ |
|
|
955
|
+
| `dark:` | Dark mode | Styles when dark mode is active |
|
|
956
|
+
| `light:` | Light mode | Styles when light mode is active |
|
|
957
|
+
|
|
958
|
+
**How it works:**
|
|
959
|
+
|
|
960
|
+
The Babel plugin:
|
|
961
|
+
|
|
962
|
+
1. Detects color scheme modifiers during compilation
|
|
963
|
+
2. Finds the parent function component
|
|
964
|
+
3. Auto-injects `const _twColorScheme = useColorScheme();` at the top of the component
|
|
965
|
+
4. Parses all color scheme-specific classes at compile-time
|
|
966
|
+
5. Generates conditional expressions: `_twColorScheme === 'dark' && styles._dark_bg_gray_900`
|
|
967
|
+
6. Auto-imports `useColorScheme` from `react-native` when needed
|
|
968
|
+
7. Reuses the same hook variable for multiple elements in the same component
|
|
969
|
+
|
|
970
|
+
**Requirements:**
|
|
971
|
+
|
|
972
|
+
- ⚠️ **Functional components only** — Color scheme modifiers require hooks (React Native's `useColorScheme()`)
|
|
973
|
+
- ✅ Works with function declarations: `function Component() { ... }`
|
|
974
|
+
- ✅ Works with arrow functions: `const Component = () => { ... }`
|
|
975
|
+
- ✅ Works with concise arrow functions: `const Component = () => <View className="dark:..." />`
|
|
976
|
+
- ✅ Works in nested callbacks: Hook injected at component level, not in callbacks
|
|
977
|
+
- ❌ **Not supported in class components** — Will show a warning
|
|
978
|
+
- ⚠️ **React Native 0.62+** — Requires the `useColorScheme` API
|
|
979
|
+
- ✅ **Dynamic expressions supported** — Works in template literals and conditional expressions:
|
|
980
|
+
|
|
981
|
+
```tsx
|
|
982
|
+
<View className={`p-4 ${isActive ? "dark:bg-blue-500" : "dark:bg-gray-900"}`} />
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
**Performance:**
|
|
986
|
+
|
|
987
|
+
- **Compile-time**: All styles parsed and registered during build
|
|
988
|
+
- **Runtime**: One `useColorScheme()` hook call per component + minimal conditional checks
|
|
989
|
+
- **Bundle size**: Only includes styles actually used in your code
|
|
990
|
+
|
|
991
|
+
#### Scheme Modifier (Convenience)
|
|
992
|
+
|
|
993
|
+
The `scheme:` modifier is a convenience feature that automatically expands to both `dark:` and `light:` modifiers for color classes. This is useful when you have custom colors with separate dark and light variants.
|
|
994
|
+
|
|
995
|
+
**Basic Usage:**
|
|
996
|
+
|
|
997
|
+
```tsx
|
|
998
|
+
import { View, Text } from "react-native";
|
|
999
|
+
|
|
1000
|
+
export function ThemedCard() {
|
|
1001
|
+
return (
|
|
1002
|
+
<View className="scheme:bg-systemGray p-4 rounded-lg">
|
|
1003
|
+
<Text className="scheme:text-systemLabel">Adaptive system colors</Text>
|
|
1004
|
+
</View>
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
**Transforms to:**
|
|
1010
|
+
|
|
1011
|
+
```tsx
|
|
1012
|
+
// Automatically expands to both dark: and light: modifiers
|
|
1013
|
+
<View className="dark:bg-systemGray-dark light:bg-systemGray-light p-4 rounded-lg">
|
|
1014
|
+
<Text className="dark:text-systemLabel-dark light:text-systemLabel-light">
|
|
1015
|
+
Adaptive system colors
|
|
1016
|
+
</Text>
|
|
1017
|
+
</View>
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
**Requirements:**
|
|
1021
|
+
|
|
1022
|
+
To use the `scheme:` modifier, you must define both color variants in your `tailwind.config.*`:
|
|
1023
|
+
|
|
1024
|
+
```javascript
|
|
1025
|
+
// tailwind.config.mjs
|
|
1026
|
+
export default {
|
|
1027
|
+
theme: {
|
|
1028
|
+
extend: {
|
|
1029
|
+
colors: {
|
|
1030
|
+
// Option 1: Nested structure
|
|
1031
|
+
systemGray: {
|
|
1032
|
+
light: "#8e8e93",
|
|
1033
|
+
dark: "#8e8e93",
|
|
1034
|
+
},
|
|
1035
|
+
systemLabel: {
|
|
1036
|
+
light: "#000000",
|
|
1037
|
+
dark: "#ffffff",
|
|
1038
|
+
},
|
|
1039
|
+
|
|
1040
|
+
// Option 2: Flat structure with suffixes
|
|
1041
|
+
"primary-light": "#bfdbfe",
|
|
1042
|
+
"primary-dark": "#1e40af",
|
|
1043
|
+
},
|
|
1044
|
+
},
|
|
1045
|
+
},
|
|
1046
|
+
};
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
**Configuring Suffixes:**
|
|
1050
|
+
|
|
1051
|
+
By default, the plugin looks for `-dark` and `-light` suffixes. You can customize these in your Babel configuration:
|
|
1052
|
+
|
|
1053
|
+
```javascript
|
|
1054
|
+
// babel.config.js
|
|
1055
|
+
module.exports = {
|
|
1056
|
+
plugins: [
|
|
1057
|
+
[
|
|
1058
|
+
"@mgcrea/react-native-tailwind/babel",
|
|
1059
|
+
{
|
|
1060
|
+
schemeModifier: {
|
|
1061
|
+
darkSuffix: "-dark", // default
|
|
1062
|
+
lightSuffix: "-light", // default
|
|
1063
|
+
},
|
|
1064
|
+
},
|
|
1065
|
+
],
|
|
1066
|
+
],
|
|
1067
|
+
};
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
**Custom Suffixes Example:**
|
|
1071
|
+
|
|
1072
|
+
```javascript
|
|
1073
|
+
// babel.config.js with custom suffixes
|
|
1074
|
+
module.exports = {
|
|
1075
|
+
plugins: [
|
|
1076
|
+
[
|
|
1077
|
+
"@mgcrea/react-native-tailwind/babel",
|
|
1078
|
+
{
|
|
1079
|
+
schemeModifier: {
|
|
1080
|
+
darkSuffix: "Dark",
|
|
1081
|
+
lightSuffix: "Light",
|
|
1082
|
+
},
|
|
1083
|
+
},
|
|
1084
|
+
],
|
|
1085
|
+
],
|
|
1086
|
+
};
|
|
1087
|
+
|
|
1088
|
+
// tailwind.config.mjs
|
|
1089
|
+
export default {
|
|
1090
|
+
theme: {
|
|
1091
|
+
extend: {
|
|
1092
|
+
colors: {
|
|
1093
|
+
systemGrayDark: "#8e8e93",
|
|
1094
|
+
systemGrayLight: "#8e8e93",
|
|
1095
|
+
},
|
|
1096
|
+
},
|
|
1097
|
+
},
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
// Usage (same as before)
|
|
1101
|
+
<View className="scheme:bg-systemGray" />
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1104
|
+
**Validation:**
|
|
1105
|
+
|
|
1106
|
+
The plugin validates that both color variants exist at compile time:
|
|
1107
|
+
|
|
1108
|
+
```tsx
|
|
1109
|
+
// ✅ Works - both variants exist
|
|
1110
|
+
<View className="scheme:bg-systemGray" />
|
|
1111
|
+
// Expands to: dark:bg-systemGray-dark light:bg-systemGray-light
|
|
1112
|
+
|
|
1113
|
+
// ⚠️ Warning (development only) - missing light variant
|
|
1114
|
+
<View className="scheme:bg-incomplete" />
|
|
1115
|
+
// Only has: incomplete-dark
|
|
1116
|
+
// Warning: "Missing: incomplete-light. This modifier will be ignored."
|
|
1117
|
+
|
|
1118
|
+
// ⚠️ Warning - non-color class
|
|
1119
|
+
<View className="scheme:p-4" />
|
|
1120
|
+
// Warning: "scheme: modifier only supports color classes (text-*, bg-*, border-*)"
|
|
1121
|
+
```
|
|
1122
|
+
|
|
1123
|
+
**Supported Color Classes:**
|
|
1124
|
+
|
|
1125
|
+
The `scheme:` modifier only works with color utilities:
|
|
1126
|
+
|
|
1127
|
+
- ✅ `scheme:text-{color}` — Text colors
|
|
1128
|
+
- ✅ `scheme:bg-{color}` — Background colors
|
|
1129
|
+
- ✅ `scheme:border-{color}` — Border colors
|
|
1130
|
+
- ❌ Other utilities — Ignored with development warning
|
|
1131
|
+
|
|
1132
|
+
**Use Cases:**
|
|
1133
|
+
|
|
1134
|
+
**Semantic color names:**
|
|
1135
|
+
|
|
1136
|
+
```tsx
|
|
1137
|
+
// Define semantic system colors that adapt to appearance
|
|
1138
|
+
<View className="scheme:bg-systemBackground p-4">
|
|
1139
|
+
<Text className="scheme:text-systemLabel">System-native appearance</Text>
|
|
1140
|
+
<View className="scheme:border-systemSeparator border-t mt-2 pt-2">
|
|
1141
|
+
<Text className="scheme:text-systemSecondaryLabel">Secondary text</Text>
|
|
1142
|
+
</View>
|
|
1143
|
+
</View>
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
**Brand colors with theme variants:**
|
|
1147
|
+
|
|
1148
|
+
```tsx
|
|
1149
|
+
// Brand colors that look good in both themes
|
|
1150
|
+
<View className="scheme:bg-brand p-6 rounded-xl">
|
|
1151
|
+
<Text className="scheme:text-brandContrast text-xl font-bold">
|
|
1152
|
+
Branded Card
|
|
1153
|
+
</Text>
|
|
1154
|
+
<Text className="scheme:text-brandSubtle mt-2">
|
|
1155
|
+
Automatically adapts to user's theme preference
|
|
1156
|
+
</Text>
|
|
1157
|
+
</View>
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
**Mixed with other modifiers:**
|
|
1161
|
+
|
|
1162
|
+
```tsx
|
|
1163
|
+
import { Pressable } from "@mgcrea/react-native-tailwind";
|
|
1164
|
+
|
|
1165
|
+
// Combine with state and platform modifiers
|
|
1166
|
+
<Pressable className="scheme:bg-interactive active:opacity-80 ios:p-6 android:p-4 rounded-lg">
|
|
1167
|
+
<Text className="scheme:text-interactiveText font-semibold">
|
|
1168
|
+
Press Me
|
|
1169
|
+
</Text>
|
|
1170
|
+
</Pressable>
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
**Key Features:**
|
|
1174
|
+
|
|
1175
|
+
- ✅ **DRY principle** — Define color pairs once, use everywhere with `scheme:`
|
|
1176
|
+
- ✅ **Compile-time expansion** — Expands to `dark:` and `light:` during build
|
|
1177
|
+
- ✅ **Type-safe** — Full TypeScript autocomplete
|
|
1178
|
+
- ✅ **Validates at compile-time** — Ensures both variants exist
|
|
1179
|
+
- ✅ **Zero runtime overhead** — Same performance as writing `dark:` and `light:` manually
|
|
1180
|
+
- ✅ **Configurable suffixes** — Adapt to your naming convention
|
|
1181
|
+
|
|
1182
|
+
**How it works:**
|
|
1183
|
+
|
|
1184
|
+
The Babel plugin:
|
|
1185
|
+
|
|
1186
|
+
1. Detects `scheme:` modifiers during compilation
|
|
1187
|
+
2. Validates that the class is a color utility (`text-*`, `bg-*`, `border-*`)
|
|
1188
|
+
3. Checks that both color variants exist in your custom colors (e.g., `systemGray-dark` and `systemGray-light`)
|
|
1189
|
+
4. Expands to both `dark:` and `light:` modifiers before further processing
|
|
1190
|
+
5. Processes the expanded modifiers using the standard color scheme logic (injects `useColorScheme()` hook)
|
|
1191
|
+
|
|
1192
|
+
This means `scheme:bg-systemGray` is functionally identical to writing `dark:bg-systemGray-dark light:bg-systemGray-light`, but more concise and maintainable.
|
|
1193
|
+
|
|
864
1194
|
### ScrollView Content Container
|
|
865
1195
|
|
|
866
1196
|
Use `contentContainerClassName` to style the ScrollView's content container:
|
|
@@ -1039,7 +1369,7 @@ This pattern allows you to build component libraries with optimized default styl
|
|
|
1039
1369
|
|
|
1040
1370
|
**Available shades:** `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`
|
|
1041
1371
|
|
|
1042
|
-
> **Note:** You can extend the color palette with custom colors via `tailwind.config.*` — see [Custom
|
|
1372
|
+
> **Note:** You can extend the color palette with custom colors via `tailwind.config.*` — see [Custom Theme Extensions](#custom-theme-extensions)
|
|
1043
1373
|
|
|
1044
1374
|
**Opacity Modifiers:**
|
|
1045
1375
|
|
|
@@ -1585,9 +1915,9 @@ Use arbitrary values for custom sizes, spacing, and borders not in the preset sc
|
|
|
1585
1915
|
|
|
1586
1916
|
> **Note:** CSS units (`rem`, `em`, `vh`, `vw`) are not supported by React Native.
|
|
1587
1917
|
|
|
1588
|
-
### Custom
|
|
1918
|
+
### Custom Theme Extensions
|
|
1589
1919
|
|
|
1590
|
-
Extend the default color palette via `tailwind.config.*` in your project root:
|
|
1920
|
+
Extend the default color palette and font families via `tailwind.config.*` in your project root:
|
|
1591
1921
|
|
|
1592
1922
|
```javascript
|
|
1593
1923
|
// tailwind.config.mjs
|
|
@@ -1603,16 +1933,21 @@ export default {
|
|
|
1603
1933
|
dark: "#0c4a6e",
|
|
1604
1934
|
},
|
|
1605
1935
|
},
|
|
1936
|
+
fontFamily: {
|
|
1937
|
+
sans: ['"SF Pro Rounded"'],
|
|
1938
|
+
custom: ['"My Custom Font"'],
|
|
1939
|
+
},
|
|
1606
1940
|
},
|
|
1607
1941
|
},
|
|
1608
1942
|
};
|
|
1609
1943
|
```
|
|
1610
1944
|
|
|
1611
|
-
Then use your custom
|
|
1945
|
+
Then use your custom theme:
|
|
1612
1946
|
|
|
1613
1947
|
```tsx
|
|
1614
1948
|
<View className="bg-primary p-4">
|
|
1615
|
-
<Text className="text-brand">Custom branded text</Text>
|
|
1949
|
+
<Text className="text-brand font-custom">Custom branded text</Text>
|
|
1950
|
+
<Text className="font-sans">SF Pro Rounded text</Text>
|
|
1616
1951
|
<View className="bg-brand-light rounded-lg" />
|
|
1617
1952
|
</View>
|
|
1618
1953
|
```
|
|
@@ -1620,13 +1955,14 @@ Then use your custom colors:
|
|
|
1620
1955
|
**How it works:**
|
|
1621
1956
|
|
|
1622
1957
|
- Babel plugin discovers config by traversing up from source files
|
|
1623
|
-
- Custom
|
|
1624
|
-
- Nested objects flattened with dash notation: `brand.light` → `brand-light`
|
|
1958
|
+
- Custom theme merged with defaults at build time (custom takes precedence)
|
|
1959
|
+
- Nested color objects flattened with dash notation: `brand.light` → `brand-light`
|
|
1960
|
+
- Font families use first font in array (React Native doesn't support font stacks)
|
|
1625
1961
|
- Zero runtime overhead — all loading happens during compilation
|
|
1626
1962
|
|
|
1627
1963
|
**Supported formats:** `.js`, `.mjs`, `.cjs`, `.ts`
|
|
1628
1964
|
|
|
1629
|
-
> **Tip:** Use `theme.extend
|
|
1965
|
+
> **Tip:** Use `theme.extend.*` to keep defaults. Using `theme.colors` or `theme.fontFamily` directly will override all defaults.
|
|
1630
1966
|
|
|
1631
1967
|
### Programmatic API
|
|
1632
1968
|
|
|
@@ -1635,10 +1971,17 @@ Access the parser and constants programmatically:
|
|
|
1635
1971
|
```typescript
|
|
1636
1972
|
import { parseClassName, COLORS, SPACING_SCALE } from "@mgcrea/react-native-tailwind";
|
|
1637
1973
|
|
|
1638
|
-
// Parse className strings
|
|
1639
|
-
const
|
|
1974
|
+
// Parse className strings (no custom theme)
|
|
1975
|
+
const styles = parseClassName("m-4 p-2 bg-blue-500");
|
|
1640
1976
|
// Returns: { margin: 16, padding: 8, backgroundColor: '#3B82F6' }
|
|
1641
1977
|
|
|
1978
|
+
// Parse with custom theme
|
|
1979
|
+
const customStyles = parseClassName("m-4 bg-primary font-custom", {
|
|
1980
|
+
colors: { primary: "#1d4ed8" },
|
|
1981
|
+
fontFamily: { custom: "My Custom Font" },
|
|
1982
|
+
});
|
|
1983
|
+
// Returns: { margin: 16, backgroundColor: '#1d4ed8', fontFamily: 'My Custom Font' }
|
|
1984
|
+
|
|
1642
1985
|
// Access default scales
|
|
1643
1986
|
const blueColor = COLORS["blue-500"]; // '#3B82F6'
|
|
1644
1987
|
const spacing = SPACING_SCALE[4]; // 16
|
|
@@ -6,8 +6,10 @@ export type TailwindConfig = {
|
|
|
6
6
|
theme?: {
|
|
7
7
|
extend?: {
|
|
8
8
|
colors?: Record<string, string | Record<string, string>>;
|
|
9
|
+
fontFamily?: Record<string, string | string[]>;
|
|
9
10
|
};
|
|
10
11
|
colors?: Record<string, string | Record<string, string>>;
|
|
12
|
+
fontFamily?: Record<string, string | string[]>;
|
|
11
13
|
};
|
|
12
14
|
};
|
|
13
15
|
/**
|
|
@@ -19,7 +21,14 @@ export declare function findTailwindConfig(startDir: string): string | null;
|
|
|
19
21
|
*/
|
|
20
22
|
export declare function loadTailwindConfig(configPath: string): TailwindConfig | null;
|
|
21
23
|
/**
|
|
22
|
-
*
|
|
23
|
-
* Prefers theme.extend.colors over theme.colors to avoid overriding defaults
|
|
24
|
+
* Custom theme configuration extracted from tailwind.config
|
|
24
25
|
*/
|
|
25
|
-
export
|
|
26
|
+
export type CustomTheme = {
|
|
27
|
+
colors: Record<string, string>;
|
|
28
|
+
fontFamily: Record<string, string>;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Extract all custom theme extensions from tailwind config
|
|
32
|
+
* Prefers theme.extend.* over theme.* to avoid overriding defaults
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractCustomTheme(filename: string): CustomTheme;
|