Skip to content

Commit 12cef37

Browse files
authored
Merge pull request #126 from flexbox/feature/ui-tier-list-e04
NativeWind initial commit
2 parents aef9efc + fb30be6 commit 12cef37

34 files changed

+600
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "react-native-wcandillon",
3+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
node_modules/
2+
.expo/
3+
dist/
4+
npm-debug.*
5+
*.jks
6+
*.p8
7+
*.p12
8+
*.key
9+
*.mobileprovision
10+
*.orig.*
11+
web-build/
12+
13+
# macOS
14+
.DS_Store
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { SafeAreaProvider } from "react-native-safe-area-context";
2+
import { StatusBar } from "expo-status-bar";
3+
import { StyleSheet, View } from "react-native";
4+
5+
import { LoginScreen } from "./LoginScreen";
6+
7+
// eslint-disable-next-line import/no-default-export
8+
export default function App() {
9+
return (
10+
<SafeAreaProvider>
11+
<StatusBar style="auto" />
12+
<View style={styles.container}>
13+
<LoginScreen />
14+
</View>
15+
</SafeAreaProvider>
16+
);
17+
}
18+
19+
const styles = StyleSheet.create({
20+
container: {
21+
flex: 1,
22+
},
23+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { View, Text, TouchableOpacity } from "react-native";
2+
import React, { useState } from "react";
3+
import { SafeAreaView } from "react-native-safe-area-context";
4+
5+
import { Input } from "./components/Input";
6+
import { Button } from "./components/Button";
7+
8+
export const LoginScreen = () => {
9+
const [hidePassword, setHidePassword] = useState(true);
10+
11+
const togglePassword = () => {
12+
setHidePassword((prev) => !prev);
13+
};
14+
15+
return (
16+
<View className="flex-1">
17+
<View className="bg-blue-500 justify-center items-center py-12 mb-6">
18+
<SafeAreaView>
19+
<Text className="text-white font-bold text-3xl text-center">
20+
Hello
21+
</Text>
22+
<Text className="text-white text-xl">Sign in to your account</Text>
23+
</SafeAreaView>
24+
</View>
25+
<View className="px-4">
26+
<Input label="Email" className="mb-4" />
27+
<Input label="Password" secureTextEntry={hidePassword} />
28+
<TouchableOpacity onPress={togglePassword}>
29+
<Text className="text-blue-500 text-right">
30+
{hidePassword ? "show" : "hide"} password?
31+
</Text>
32+
</TouchableOpacity>
33+
</View>
34+
<View className="px-4 mt-12">
35+
<Button variant="filled">Sign In</Button>
36+
<Button variant="ghost">Don't have an account? Create</Button>
37+
</View>
38+
</View>
39+
);
40+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Getting started
2+
3+
```bash
4+
yarn
5+
yarn ios
6+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="nativewind/types" />
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"expo": {
3+
"name": "template",
4+
"slug": "template",
5+
"version": "1.0.0",
6+
"orientation": "portrait",
7+
"icon": "./assets/icon.png",
8+
"userInterfaceStyle": "light",
9+
"splash": {
10+
"image": "./assets/splash.png",
11+
"resizeMode": "contain",
12+
"backgroundColor": "#ffffff"
13+
},
14+
"updates": {
15+
"fallbackToCacheTimeout": 0
16+
},
17+
"assetBundlePatterns": [
18+
"**/*"
19+
],
20+
"ios": {
21+
"supportsTablet": true
22+
},
23+
"android": {
24+
"adaptiveIcon": {
25+
"foregroundImage": "./assets/adaptive-icon.png",
26+
"backgroundColor": "#FFFFFF"
27+
}
28+
},
29+
"web": {
30+
"favicon": "./assets/favicon.png"
31+
}
32+
}
33+
}
Loading
Loading
Loading
Loading
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = function (api) {
2+
api.cache(true);
3+
return {
4+
presets: ["babel-preset-expo"],
5+
plugins: ["nativewind/babel"],
6+
};
7+
};
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import type { PressableProps } from "react-native";
2+
import { View, Text, Pressable } from "react-native";
3+
import type { ReactNode } from "react";
4+
import React from "react";
5+
6+
interface Props extends PressableProps {
7+
variant?: "dark" | "light" | "filled" | "outline" | "ghost";
8+
styles?: string;
9+
children: ReactNode;
10+
}
11+
12+
export const Button = ({
13+
variant = "filled",
14+
children,
15+
styles = "",
16+
...props
17+
}: Props) => {
18+
let style = "";
19+
let textStyle = "text-base font-bold px-10 py-3";
20+
let textColorVariant = "";
21+
22+
switch (variant) {
23+
case "dark":
24+
style = "bg-black";
25+
textColorVariant = "text-white";
26+
break;
27+
case "light":
28+
style = "bg-white";
29+
textColorVariant = "text-black";
30+
break;
31+
case "filled":
32+
style = "bg-blue-500 hover:bg-blue-700";
33+
textColorVariant = "text-white";
34+
break;
35+
case "outline":
36+
style = "bg-blue-100 hover:bg-blue-700";
37+
textColorVariant = "text-blue-500";
38+
break;
39+
case "light":
40+
style = "bg-white";
41+
textStyle = "text-black";
42+
break;
43+
}
44+
45+
const box =
46+
"inline-flex items-center border border-transparent rounded-xl shadow-sm";
47+
const classNames = `${styles} ${box} ${style}`;
48+
const textClassNames = `${textStyle} ${textColorVariant}`;
49+
50+
return (
51+
<Pressable {...props}>
52+
{({ pressed }) => {
53+
let activeClassNames = "";
54+
if (pressed) {
55+
switch (variant) {
56+
case "dark":
57+
activeClassNames = "bg-neutral-700";
58+
break;
59+
case "light":
60+
activeClassNames = "bg-neutral-100";
61+
break;
62+
case "filled":
63+
activeClassNames = "bg-blue-600 hover:bg-blue-700";
64+
break;
65+
case "outline":
66+
activeClassNames = "bg-blue-200 hover:bg-blue-700";
67+
break;
68+
case "ghost":
69+
activeClassNames = "opacity-3";
70+
break;
71+
}
72+
}
73+
74+
const pressedClassNames = `${classNames} ${activeClassNames}`;
75+
76+
return (
77+
<View className={pressedClassNames}>
78+
<Text className={textClassNames}>{children}</Text>
79+
</View>
80+
);
81+
}}
82+
</Pressable>
83+
);
84+
};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import * as React from "react";
2+
import type { TextInput, TextInputProps } from "react-native";
3+
import { View, TextInput as NTextInput, Text } from "react-native";
4+
import colors from "tailwindcss/colors";
5+
6+
export interface NInputProps extends TextInputProps {
7+
label?: string;
8+
disabled?: boolean;
9+
error?: string;
10+
}
11+
12+
export const Input = React.forwardRef<TextInput, NInputProps>((props, ref) => {
13+
const { label, error, ...inputProps } = props;
14+
15+
const [isFocussed, setIsFocussed] = React.useState(false);
16+
const onBlur = React.useCallback(() => setIsFocussed(false), []);
17+
const onFocus = React.useCallback(() => setIsFocussed(true), []);
18+
19+
// eslint-disable-next-line no-nested-ternary
20+
const borderColor = error
21+
? "border-danger-600"
22+
: isFocussed
23+
? "border-neutral-400"
24+
: "border-neutral-200";
25+
26+
const bgColor = error ? "bg-danger-50" : "bg-neutral-200";
27+
28+
return (
29+
<View className="mb-4">
30+
{label && (
31+
<Text className={error ? "text-danger-600" : "text-black"}>
32+
{label}
33+
</Text>
34+
)}
35+
<NTextInput
36+
testID="STextInput"
37+
ref={ref}
38+
placeholderTextColor={colors.neutral[400]}
39+
className={`mt-0 border-[3px] py-4 px-2 ${borderColor} rounded-md ${bgColor} text-[16px] text-left`}
40+
onBlur={onBlur}
41+
onFocus={onFocus}
42+
{...inputProps}
43+
/>
44+
{error && <Text>{error}</Text>}
45+
</View>
46+
);
47+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name": "template",
3+
"version": "1.0.0",
4+
"main": "node_modules/expo/AppEntry.js",
5+
"scripts": {
6+
"start": "expo start",
7+
"android": "expo start --android",
8+
"ios": "expo start --ios",
9+
"web": "expo start --web"
10+
},
11+
"dependencies": {
12+
"class-variance-authority": "^0.4.0",
13+
"expo": "~47.0.6",
14+
"expo-status-bar": "~1.4.2",
15+
"nativewind": "^2.0.11",
16+
"react": "18.1.0",
17+
"react-dom": "18.1.0",
18+
"react-native": "0.70.5",
19+
"react-native-safe-area-context": "^4.4.1",
20+
"react-native-web": "~0.18.9"
21+
},
22+
"devDependencies": {
23+
"@babel/core": "^7.12.9",
24+
"@types/react": "~18.0.14",
25+
"@types/react-native": "~0.70.6",
26+
"eslint": "^8.27.0",
27+
"eslint-config-react-native-wcandillon": "^3.9.0",
28+
"tailwindcss": "^3.2.4",
29+
"typescript": "^4.6.3"
30+
},
31+
"private": true
32+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
content: ["./*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
3+
// ...
4+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": "eslint-config-react-native-wcandillon/tsconfig.base",
3+
"compilerOptions": {
4+
"strict": true
5+
}
6+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "react-native-wcandillon",
3+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
node_modules/
2+
.expo/
3+
dist/
4+
npm-debug.*
5+
*.jks
6+
*.p8
7+
*.p12
8+
*.key
9+
*.mobileprovision
10+
*.orig.*
11+
web-build/
12+
13+
# macOS
14+
.DS_Store
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { SafeAreaProvider } from "react-native-safe-area-context";
2+
import { StatusBar } from "expo-status-bar";
3+
import { StyleSheet, View } from "react-native";
4+
import { ThemeProvider } from "@shopify/restyle";
5+
6+
import { LoginScreen } from "./LoginScreen";
7+
import theme from "./theme";
8+
9+
// eslint-disable-next-line import/no-default-export
10+
export default function App() {
11+
return (
12+
<ThemeProvider theme={theme}>
13+
<SafeAreaProvider>
14+
<StatusBar style="auto" />
15+
<View style={styles.container}>
16+
<LoginScreen />
17+
</View>
18+
</SafeAreaProvider>
19+
</ThemeProvider>
20+
);
21+
}
22+
23+
const styles = StyleSheet.create({
24+
container: {
25+
flex: 1,
26+
},
27+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from "react";
2+
import { Alert } from "react-native";
3+
4+
import { Box } from "./components/Box";
5+
import { Button } from "./components/Button";
6+
import { Text } from "./components/Text";
7+
8+
interface Props {}
9+
10+
export const LoginScreen = (props: Props) => {
11+
return (
12+
<Box flex={1}>
13+
<Box
14+
alignItems="center"
15+
justifyContent="center"
16+
backgroundColor="cardPrimaryBackground"
17+
minHeight={250}
18+
>
19+
<Text variant="h2" color="textOnDark">
20+
LoginScreen
21+
</Text>
22+
<Text variant="p1" color="textOnDark">
23+
LoginScreen
24+
</Text>
25+
</Box>
26+
<Box p="m">
27+
<Button label="Sign In" onPress={() => Alert.alert("Pressed")} />
28+
<Button
29+
mt="xl"
30+
borderRadius="m"
31+
backgroundColor="cardPrimaryBackground"
32+
padding="m"
33+
label="Don't have an account? Create"
34+
onPress={() => Alert.alert("Pressed")}
35+
/>
36+
</Box>
37+
</Box>
38+
);
39+
};

0 commit comments

Comments
 (0)