Skip to content

Commit 20a646a

Browse files
authored
More nativewind friendly (#1037)
* Add nativwind to example app * `className` support for more components
1 parent fcbba18 commit 20a646a

25 files changed

Lines changed: 644 additions & 68 deletions

eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ module.exports = [
5151
"@typescript-eslint/no-unnecessary-type-constraint": "off",
5252
"react-native/no-inline-styles": "off",
5353
"react-native/no-color-literals": "off",
54+
"react-native/no-raw-text": "off",
5455

5556
// ignore unused vars that start with underscore
5657
"@typescript-eslint/no-unused-vars": [

example/global.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import "tailwindcss/theme.css" layer(theme);
2+
@import "tailwindcss/preflight.css" layer(base);
3+
@import "tailwindcss/utilities.css";
4+
5+
@import "nativewind/theme";

example/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import "react-native-get-random-values";
2+
import "./global.css";
23
import { registerRootComponent } from "expo";
34
import App from "./src/App";
45

example/metro.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { getDefaultConfig } = require("expo/metro-config");
2+
const { withNativewind } = require("nativewind/metro");
23
const path = require("path");
34

45
// Follows https://docs.expo.dev/guides/monorepos/
@@ -20,4 +21,4 @@ config.resolver.nodeModulesPaths = [
2021
// 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
2122
config.resolver.disableHierarchicalLookup = true;
2223

23-
module.exports = config;
24+
module.exports = withNativewind(config);

example/nativewind-env.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/// <reference types="react-native-css/types" />
2+
3+
// NOTE: This file should not be edited and should be committed with your source code. It is generated by react-native-css. If you need to move or disable this file, please see the documentation.

example/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@
2727
"expo-font": "~14.0.11",
2828
"expo-splash-screen": "~31.0.13",
2929
"expo-status-bar": "~3.0.9",
30+
"nativewind": "^5.0.0-preview.4",
3031
"react": "19.1.0",
3132
"react-dom": "19.1.0",
3233
"react-native": "0.81.5",
34+
"react-native-css": "^3.0.7",
3335
"react-native-gesture-handler": "~2.28.0",
3436
"react-native-get-random-values": "~1.11.0",
3537
"react-native-reanimated": "~4.1.1",
@@ -41,9 +43,15 @@
4143
},
4244
"devDependencies": {
4345
"@babel/core": "^7.24.0",
46+
"@tailwindcss/postcss": "^4.3.0",
4447
"@types/react": "~19.1.10",
4548
"@types/react-native": "~0.70.6",
4649
"babel-loader": "8.1.0",
47-
"sharp-cli": "2.1.0"
50+
"postcss": "^8.5.15",
51+
"sharp-cli": "2.1.0",
52+
"tailwindcss": "^4.3.0"
53+
},
54+
"resolutions": {
55+
"lightningcss": "1.30.1"
4856
}
4957
}

example/postcss.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
plugins: {
3+
"@tailwindcss/postcss": {},
4+
},
5+
};

example/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,10 @@ import LoadingIndicatorExample from "./LoadingIndicatorExample";
7777
import TimerExample from "./TimerExample";
7878
import LottieAnimationExample from "./LottieAnimationExample";
7979
import ExpoImageExample from "./ExpoImageExample";
80+
import NativeWindExample from "./NativeWindExample";
8081

8182
const ROUTES = {
83+
NativeWind: NativeWindExample,
8284
LottieAnimationExample: LottieAnimationExample,
8385
Timer: TimerExample,
8486
LoadingIndicator: LoadingIndicatorExample,

example/src/NativeWindExample.tsx

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
import React from "react";
2+
import { View, Text } from "react-native";
3+
import {
4+
AudioPlayer,
5+
CircularProgress,
6+
CustomPinInputCell,
7+
CustomPinInputText,
8+
DeckSwiper,
9+
DeckSwiperCard,
10+
LinearProgress,
11+
LoadingIndicator,
12+
LottieAnimation,
13+
Markdown,
14+
PinInput,
15+
Swiper,
16+
SwiperItem,
17+
Timer,
18+
VideoPlayer,
19+
WebView,
20+
} from "@draftbit/ui";
21+
import { LoadingIndicatorType } from "@draftbit/core/lib/typescript/src/components/LoadingIndicator";
22+
import Section, { Container } from "./Section";
23+
24+
const PROGRESS_VALUE = 65;
25+
26+
const NativeWindExample: React.FC<{ theme?: any }> = () => {
27+
const [pinValue, setPinValue] = React.useState("");
28+
const timerRef = React.useRef<any>(null);
29+
30+
return (
31+
<Container style={{}}>
32+
<Section title="AudioPlayer" style={{}}>
33+
<AudioPlayer
34+
className="rounded-2xl bg-gray-100 h-12 border-0 w-100"
35+
source={{
36+
uri: "https://static.draftbit.com/audio/intro-to-draftbit-audio.mp3",
37+
}}
38+
/>
39+
</Section>
40+
41+
<Section title="CircularProgress" style={{}}>
42+
<View className="items-center flex-row">
43+
<CircularProgress className="w-60" value={PROGRESS_VALUE} />
44+
<CircularProgress
45+
className="w-40 ml-20"
46+
color="rgb(99,102,241)"
47+
trackColor="rgb(224,231,255)"
48+
value={PROGRESS_VALUE}
49+
/>
50+
</View>
51+
</Section>
52+
53+
<Section
54+
title="DeckSwiper + DeckSwiperCard"
55+
style={{ paddingBottom: 30 }}
56+
>
57+
<DeckSwiper className="w-100" visibleCardCount={2}>
58+
<DeckSwiperCard className="bg-red-100 p-10 items-center justify-center rounded-xl">
59+
<Text className="text-base font-semibold text-red-700">Card 1</Text>
60+
</DeckSwiperCard>
61+
<DeckSwiperCard className="bg-blue-100 p-10 items-center justify-center rounded-xl">
62+
<Text className="text-base font-semibold text-blue-700">
63+
Card 2
64+
</Text>
65+
</DeckSwiperCard>
66+
<DeckSwiperCard className="bg-green-100 p-10 items-center justify-center rounded-xl">
67+
<Text className="text-base font-semibold text-green-700">
68+
Card 3
69+
</Text>
70+
</DeckSwiperCard>
71+
</DeckSwiper>
72+
</Section>
73+
74+
<Section title="LinearProgress" style={{}}>
75+
<LinearProgress className="w-100" value={PROGRESS_VALUE} />
76+
<LinearProgress
77+
className="w-100 mt-3"
78+
color="rgb(99,102,241)"
79+
trackColor="rgb(224,231,255)"
80+
thickness={12}
81+
value={PROGRESS_VALUE}
82+
/>
83+
<LinearProgress
84+
className="w-150 mt-10"
85+
thickness={8}
86+
trackThickness={8}
87+
dashWidth={12}
88+
dashGap={8}
89+
value={PROGRESS_VALUE}
90+
/>
91+
</Section>
92+
93+
<Section title="LoadingIndicator" style={{}}>
94+
<View className="flex-row">
95+
<LoadingIndicator
96+
className="m-2 border-2 p-4"
97+
type={LoadingIndicatorType.circle}
98+
/>
99+
<LoadingIndicator className="m-2" type={LoadingIndicatorType.wave} />
100+
101+
<LoadingIndicator
102+
className="m-2"
103+
type={LoadingIndicatorType.bounce}
104+
/>
105+
106+
<LoadingIndicator className="m-2" type={LoadingIndicatorType.pulse} />
107+
</View>
108+
</Section>
109+
110+
<Section title="LottieAnimation" style={{}}>
111+
<LottieAnimation
112+
className="w-48 h-48 border-2"
113+
source={require("./assets/lottie_animation_example.json")}
114+
/>
115+
</Section>
116+
117+
<Section title="Markdown" style={{}}>
118+
<Markdown className="w-200">
119+
{
120+
"## NativeWind\n\nThis is **bold** and _italic_ text styled via `className`.\n\n- Item one\n- Item two\n- Item three"
121+
}
122+
</Markdown>
123+
</Section>
124+
125+
<Section title="PinInput (default)" style={{}}>
126+
<PinInput
127+
className="border-2 w-100"
128+
value={pinValue}
129+
onChangeText={setPinValue}
130+
/>
131+
</Section>
132+
133+
<Section
134+
title="PinInput (CustomPinInputCell + CustomPinInputText)"
135+
style={{}}
136+
>
137+
<PinInput
138+
value={pinValue}
139+
onChangeText={setPinValue}
140+
className="w-100"
141+
renderItem={({ cellValue, isFocused }) => (
142+
<CustomPinInputCell
143+
className={`w-14 h-14 mx-1.5 rounded-xl bg-white items-center justify-center ${
144+
isFocused ? "border-2 border-red-500" : "border border-gray-300"
145+
}`}
146+
>
147+
<CustomPinInputText
148+
className={`text-xl font-bold ${
149+
isFocused ? "text-indigo-500" : "text-gray-800"
150+
}`}
151+
isFocused={isFocused}
152+
>
153+
{cellValue}
154+
</CustomPinInputText>
155+
</CustomPinInputCell>
156+
)}
157+
/>
158+
</Section>
159+
160+
<Section title="Swiper + SwiperItem" style={{}}>
161+
<Swiper
162+
keyExtractor={(key) => key}
163+
className="w-100 h-48"
164+
vertical={false}
165+
loop
166+
>
167+
<SwiperItem className="items-center justify-center bg-red-100">
168+
<Text className="text-lg font-semibold text-red-700">Slide 1</Text>
169+
</SwiperItem>
170+
<SwiperItem className="items-center justify-center bg-indigo-100">
171+
<Text className="text-lg font-semibold text-indigo-700">
172+
Slide 2
173+
</Text>
174+
</SwiperItem>
175+
<SwiperItem className="items-center justify-center bg-green-100">
176+
<Text className="text-lg font-semibold text-green-700">
177+
Slide 3
178+
</Text>
179+
</SwiperItem>
180+
</Swiper>
181+
</Section>
182+
183+
<Section title="Timer" style={{}}>
184+
<Timer
185+
ref={timerRef}
186+
className="text-5xl text-red-800"
187+
initialTime={0}
188+
format="mm:ss"
189+
countDirection="up"
190+
/>
191+
</Section>
192+
193+
<Section title="VideoPlayer" style={{}}>
194+
<VideoPlayer
195+
className="w-100 h-56 rounded-xl overflow-hidden"
196+
source={{
197+
uri: "http://static.draftbit.com/videos/intro-to-draftbit.mp4",
198+
}}
199+
useNativeControls
200+
resizeMode="cover"
201+
/>
202+
</Section>
203+
204+
<Section title="WebView" style={{}}>
205+
<WebView
206+
className="w-200 h-100 rounded-xl overflow-hidden"
207+
source={{ uri: "https://docs.expo.io/" }}
208+
/>
209+
</Section>
210+
</Container>
211+
);
212+
};
213+
214+
export default NativeWindExample;

packages/core/src/components/DeckSwiper/DeckSwiperCard.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,24 @@ import { withTheme } from "@draftbit/theme";
1212
export interface DeckSwiperCardProps
1313
extends Omit<ViewProps, "style" | "children"> {
1414
style?: StyleProp<ViewStyle>;
15+
className?: string;
1516
theme: ReadTheme;
1617
}
1718

1819
const DeckSwiperCard: React.FC<
1920
React.PropsWithChildren<DeckSwiperCardProps>
20-
> = ({ style, children, theme, ...rest }) => (
21+
> = ({ style, className, children, theme, ...rest }) => (
2122
<View
2223
style={[
2324
styles.card,
24-
{
25+
!className && {
2526
backgroundColor: theme.colors.background.base,
2627
borderColor: theme.colors.border.base,
2728
},
2829
style,
2930
]}
31+
// @ts-ignore
32+
className={className}
3033
{...rest}
3134
>
3235
{children}

0 commit comments

Comments
 (0)