deskripsi:
- fix styles Text input & Text area
This commit is contained in:
2025-07-09 10:58:47 +08:00
parent 16559b94fe
commit 6ac122c631
6 changed files with 133 additions and 142 deletions

View File

@@ -1,14 +1,14 @@
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
import { import {
ButtonCustom, ButtonCustom,
Grid, Grid,
SelectCustom, SelectCustom,
Spacing, Spacing,
StackCustom, StackCustom,
TextAreaCustom, TextAreaCustom,
TextCustom, TextCustom,
TextInputCustom, TextInputCustom,
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter"; import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter";
import InformationBox from "@/components/Box/InformationBox"; import InformationBox from "@/components/Box/InformationBox";
@@ -100,11 +100,7 @@ export default function PortofolioCreate() {
Tambah Pilihan Tambah Pilihan
</ButtonCenteredOnly> </ButtonCenteredOnly>
<Spacing /> <Spacing />
<TextInputCustom
required
label="Alamat Bisnis"
placeholder="Masukkan alamat bisnis"
/>
<View> <View>
<View style={{ flexDirection: "row", alignItems: "center" }}> <View style={{ flexDirection: "row", alignItems: "center" }}>
<TextCustom semiBold style={{ color: MainColor.white_gray }}> <TextCustom semiBold style={{ color: MainColor.white_gray }}>
@@ -123,6 +119,13 @@ export default function PortofolioCreate() {
/> />
</View> </View>
<Spacing /> <Spacing />
<TextInputCustom
required
label="Alamat Bisnis"
placeholder="Masukkan alamat bisnis"
/>
<TextAreaCustom <TextAreaCustom
label="Deskripsi Bisnis" label="Deskripsi Bisnis"
placeholder="Masukkan deskripsi bisnis" placeholder="Masukkan deskripsi bisnis"

View File

@@ -142,7 +142,7 @@ const styles = StyleSheet.create({
option: { option: {
padding: 16, padding: 16,
borderBottomWidth: 1, borderBottomWidth: 1,
borderBottomColor: "#eee", borderBottomColor: MainColor.white_gray,
}, },
errorMessage: { errorMessage: {
marginTop: 4, marginTop: 4,

View File

@@ -1,13 +1,12 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { import {
TextInput as RNTextInput, TextInput as RNTextInput,
StyleProp, StyleProp,
Text, Text,
View, View,
ViewStyle, ViewStyle,
} from "react-native"; } from "react-native";
import { GStyles } from "@/styles/global-styles";
import { textInputStyles } from "../TextInput/textInputStyles";
type IconType = React.ReactNode | string; type IconType = React.ReactNode | string;
@@ -71,31 +70,31 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
const renderIcon = (icon: IconType) => { const renderIcon = (icon: IconType) => {
if (!icon) return null; if (!icon) return null;
return typeof icon === "string" ? ( return typeof icon === "string" ? (
<Text style={textInputStyles.iconText}>{icon}</Text> <Text style={GStyles.iconTextInput}>{icon}</Text>
) : ( ) : (
icon icon
); );
}; };
return ( return (
<View style={textInputStyles.container}> <View style={GStyles.containerAreaInput}>
{label && ( {label && (
<Text style={textInputStyles.label}> <Text style={GStyles.labelInput}>
{label} {label}
{required && <Text style={textInputStyles.required}> *</Text>} {required && <Text style={GStyles.requiredInput}> *</Text>}
</Text> </Text>
)} )}
<View <View
style={[ style={[
textInputStyles.inputContainer, GStyles.inputContainerInput,
disabled && textInputStyles.disabled, disabled && GStyles.disabledInput,
hasError ? textInputStyles.errorBorder : {}, hasError ? GStyles.errorBorderInput : {},
{ borderRadius }, { borderRadius },
style, style,
]} ]}
> >
{iconLeft && ( {iconLeft && (
<View style={textInputStyles.icon}>{renderIcon(iconLeft)}</View> <View style={GStyles.iconInput}>{renderIcon(iconLeft)}</View>
)} )}
<RNTextInput <RNTextInput
@@ -103,8 +102,8 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
multiline multiline
numberOfLines={numberOfLines} numberOfLines={numberOfLines}
style={[ style={[
textInputStyles.input, GStyles.inputInput,
textInputStyles.textArea, GStyles.textAreaInput,
{ color: fontColor }, { color: fontColor },
]} ]}
editable={!disabled} editable={!disabled}
@@ -114,7 +113,7 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
/> />
{iconRight && ( {iconRight && (
<View style={textInputStyles.icon}>{renderIcon(iconRight)}</View> <View style={GStyles.iconInput}>{renderIcon(iconRight)}</View>
)} )}
</View> </View>
@@ -128,11 +127,11 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
}} }}
> >
{hasError ? ( {hasError ? (
<Text style={textInputStyles.errorMessage}>{error}</Text> <Text style={GStyles.errorMessageInput}>{error}</Text>
) : null} ) : null}
{showCount && maxLength ? ( {showCount && maxLength ? (
<Text style={textInputStyles.inputLength}> <Text style={GStyles.inputMaxLength}>
{(value as string)?.length || 0}/{maxLength} {(value as string)?.length || 0}/{maxLength}
</Text> </Text>
) : null} ) : null}

View File

@@ -1,3 +1,4 @@
import { GStyles } from "@/styles/global-styles";
import Ionicons from "@expo/vector-icons/Ionicons"; import Ionicons from "@expo/vector-icons/Ionicons";
import React, { useState } from "react"; import React, { useState } from "react";
import { import {
@@ -8,7 +9,7 @@ import {
View, View,
ViewStyle, ViewStyle,
} from "react-native"; } from "react-native";
import { textInputStyles } from "./textInputStyles";
type IconType = React.ReactNode | string; type IconType = React.ReactNode | string;
@@ -49,7 +50,7 @@ export const TextInputCustom = ({
const renderIcon = (icon: IconType) => { const renderIcon = (icon: IconType) => {
if (!icon) return null; if (!icon) return null;
return typeof icon === "string" ? ( return typeof icon === "string" ? (
<Text style={textInputStyles.iconText}>{icon}</Text> <Text style={GStyles.iconTextInput}>{icon}</Text>
) : ( ) : (
icon icon
); );
@@ -73,27 +74,27 @@ export const TextInputCustom = ({
}; };
return ( return (
<View style={textInputStyles.container}> <View style={GStyles.containerAreaInput}>
{label && ( {label && (
<Text style={textInputStyles.label}> <Text style={GStyles.labelInput}>
{label} {label}
{required && <Text style={textInputStyles.required}> *</Text>} {required && <Text style={GStyles.requiredInput}> *</Text>}
</Text> </Text>
)} )}
<View <View
style={[ style={[
textInputStyles.inputContainer, GStyles.inputContainerInput,
disabled && textInputStyles.disabled, disabled && GStyles.disabledInput,
{ borderRadius }, { borderRadius },
externalError || internalError ? textInputStyles.errorBorder : null, externalError || internalError ? GStyles.errorBorderInput : null,
style, style,
]} ]}
> >
{iconLeft && ( {iconLeft && (
<View style={textInputStyles.icon}>{renderIcon(iconLeft)}</View> <View style={GStyles.iconInput}>{renderIcon(iconLeft)}</View>
)} )}
<RNTextInput <RNTextInput
style={[textInputStyles.input, { color: fontColor }]} style={[GStyles.inputInput, { color: fontColor }]}
editable={!disabled} editable={!disabled}
secureTextEntry={secureTextEntry && !isPasswordVisible} secureTextEntry={secureTextEntry && !isPasswordVisible}
keyboardType={keyboardType} keyboardType={keyboardType}
@@ -104,7 +105,7 @@ export const TextInputCustom = ({
{secureTextEntry && ( {secureTextEntry && (
<TouchableOpacity <TouchableOpacity
onPress={() => setIsPasswordVisible((prev) => !prev)} onPress={() => setIsPasswordVisible((prev) => !prev)}
style={textInputStyles.icon} style={GStyles.iconInput}
> >
<Ionicons <Ionicons
name={isPasswordVisible ? "eye-off" : "eye"} name={isPasswordVisible ? "eye-off" : "eye"}
@@ -114,12 +115,12 @@ export const TextInputCustom = ({
</TouchableOpacity> </TouchableOpacity>
)} )}
{iconRight && ( {iconRight && (
<View style={textInputStyles.icon}>{renderIcon(iconRight)}</View> <View style={GStyles.iconInput}>{renderIcon(iconRight)}</View>
)} )}
</View> </View>
{/* Prioritaskan error eksternal */} {/* Prioritaskan error eksternal */}
{externalError || internalError ? ( {externalError || internalError ? (
<Text style={textInputStyles.errorMessage}> <Text style={GStyles.errorMessageInput}>
{externalError || internalError} {externalError || internalError}
</Text> </Text>
) : null} ) : null}

View File

@@ -1,85 +0,0 @@
// components/text-input.styles.ts
import { MainColor } from "@/constants/color-palet";
import { TEXT_SIZE_LARGE, TEXT_SIZE_MEDIUM } from "@/constants/constans-value";
import { StyleSheet } from "react-native";
export const textInputStyles = StyleSheet.create({
// Container utama input (View luar)
container: {
marginBottom: 16,
},
// Label di atas input
label: {
fontSize: 14,
marginBottom: 6,
fontWeight: "500",
color: MainColor.white_gray,
},
// Tanda bintang merah untuk required
required: {
color: "red",
},
// Pesan error di bawah input
errorMessage: {
marginTop: 4,
fontSize: 12,
color: MainColor.red,
},
// Input Length
inputLength: {
fontSize: 12,
color: MainColor.white_gray,
},
// Wrapper input (View pembungkus TextInput)
inputContainer: {
flexDirection: "row",
alignItems: "center",
borderWidth: 1,
borderColor: MainColor.white_gray,
backgroundColor: MainColor.white,
paddingHorizontal: 12,
height: 50,
},
// Style saat disabled
disabled: {
backgroundColor: "#f9f9f9",
borderColor: "#e0e0e0",
},
// Input utama (TextInput)
input: {
flex: 1,
fontSize: TEXT_SIZE_MEDIUM,
paddingVertical: 0,
},
// Ikon di kiri/kanan
icon: {
marginHorizontal: 4,
justifyContent: "center",
},
// Teks ikon jika berupa string
iconText: {
fontSize: TEXT_SIZE_LARGE,
color: "#000",
},
// Border merah jika ada error
errorBorder: {
borderColor: "red",
},
// Untuk TextArea tambahan
textArea: {
textAlignVertical: "top",
padding: 12,
height: undefined, // biar multiline bebas tinggi
},
});

View File

@@ -1,4 +1,4 @@
import { TEXT_SIZE_MEDIUM } from "@/constants/constans-value"; import { TEXT_SIZE_LARGE, TEXT_SIZE_MEDIUM, TEXT_SIZE_SMALL } from "@/constants/constans-value";
import { Dimensions, StyleSheet } from "react-native"; import { Dimensions, StyleSheet } from "react-native";
import { AccentColor, MainColor } from "../constants/color-palet"; import { AccentColor, MainColor } from "../constants/color-palet";
@@ -141,14 +141,6 @@ export const GStyles = StyleSheet.create({
backgroundColor: MainColor.darkblue, backgroundColor: MainColor.darkblue,
borderTopColor: AccentColor.blue, borderTopColor: AccentColor.blue,
borderTopWidth: 1, borderTopWidth: 1,
// shadowColor: AccentColor.blue,
// shadowOffset: {
// width: 0,
// height: -1,
// },
// shadowOpacity: 0.9,
// shadowRadius: 5,
// elevation: 5,
}, },
bottomBarContainer: { bottomBarContainer: {
paddingHorizontal: 15, paddingHorizontal: 15,
@@ -161,4 +153,85 @@ export const GStyles = StyleSheet.create({
width: "50%", width: "50%",
alignSelf: "center", alignSelf: "center",
}, },
// =============== BUTTON =============== //
// =============== TEXT INPUT =============== //
// Container utama input (View luar)
containerAreaInput: {
marginBottom: 16,
},
// Label di atas input
labelInput: {
fontSize: TEXT_SIZE_MEDIUM,
marginBottom: 6,
fontWeight: "500",
color: MainColor.white_gray,
},
// Tanda bintang merah untuk required
requiredInput: {
color: "red",
},
// Pesan error di bawah input
errorMessageInput: {
marginTop: 4,
fontSize: TEXT_SIZE_SMALL,
color: MainColor.red,
},
// Input Length
inputMaxLength: {
fontSize: TEXT_SIZE_SMALL,
color: MainColor.white_gray,
},
// Wrapper input (View pembungkus TextInput)
inputContainerInput: {
flexDirection: "row",
alignItems: "center",
borderWidth: 1,
borderColor: MainColor.white_gray,
backgroundColor: MainColor.white,
paddingHorizontal: 10,
height: 50,
},
// Style saat disabled
disabledInput: {
backgroundColor: "#f9f9f9",
borderColor: "#e0e0e0",
},
// Input utama (TextInput)
inputInput: {
flex: 1,
fontSize: TEXT_SIZE_MEDIUM,
paddingVertical: 0,
},
// Ikon di kiri/kanan
iconInput: {
marginHorizontal: 4,
justifyContent: "center",
},
// Teks ikon jika berupa string
iconTextInput: {
fontSize: TEXT_SIZE_LARGE,
color: "#000",
},
// Border merah jika ada error
errorBorderInput: {
borderColor: "red",
},
// Untuk TextArea tambahan
textAreaInput: {
textAlignVertical: "top",
padding: 5,
height: undefined, // biar multiline bebas tinggi
},
}); });