diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/Collapsible.tsx | 33 | ||||
-rw-r--r-- | components/ParallaxScrollView.tsx | 33 | ||||
-rw-r--r-- | components/PrimaryButton.tsx | 1 | ||||
-rw-r--r-- | components/ThemedText.tsx | 29 | ||||
-rw-r--r-- | components/ThemedView.tsx | 17 | ||||
-rw-r--r-- | components/login/ShipCredsForm.tsx | 105 |
6 files changed, 173 insertions, 45 deletions
diff --git a/components/Collapsible.tsx b/components/Collapsible.tsx index 55bff2f..5820251 100644 --- a/components/Collapsible.tsx +++ b/components/Collapsible.tsx @@ -1,28 +1,33 @@ -import { PropsWithChildren, useState } from 'react'; -import { StyleSheet, TouchableOpacity } from 'react-native'; +"use client"; +import { PropsWithChildren, useState } from "react"; +import { StyleSheet, TouchableOpacity } from "react-native"; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; -import { IconSymbol } from '@/components/ui/IconSymbol'; -import { Colors } from '@/constants/Colors'; -import { useColorScheme } from '@/hooks/useColorScheme'; +import { ThemedText } from "@/components/ThemedText"; +import { ThemedView } from "@/components/ThemedView"; +import { IconSymbol } from "@/components/ui/IconSymbol"; +import { Colors } from "@/constants/Colors"; +import { useColorScheme } from "@/hooks/useColorScheme"; -export function Collapsible({ children, title }: PropsWithChildren & { title: string }) { +export function Collapsible({ + children, + title, +}: PropsWithChildren & { title: string }) { const [isOpen, setIsOpen] = useState(false); - const theme = useColorScheme() ?? 'light'; + const theme = useColorScheme() ?? "light"; return ( <ThemedView> <TouchableOpacity style={styles.heading} onPress={() => setIsOpen((value) => !value)} - activeOpacity={0.8}> + activeOpacity={0.8} + > <IconSymbol name="chevron.right" size={18} weight="medium" - color={theme === 'light' ? Colors.light.icon : Colors.dark.icon} - style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }} + color={theme === "light" ? Colors.light.icon : Colors.dark.icon} + style={{ transform: [{ rotate: isOpen ? "90deg" : "0deg" }] }} /> <ThemedText type="defaultSemiBold">{title}</ThemedText> @@ -34,8 +39,8 @@ export function Collapsible({ children, title }: PropsWithChildren & { title: st const styles = StyleSheet.create({ heading: { - flexDirection: 'row', - alignItems: 'center', + flexDirection: "row", + alignItems: "center", gap: 6, }, content: { diff --git a/components/ParallaxScrollView.tsx b/components/ParallaxScrollView.tsx index 5df1d75..46ed68e 100644 --- a/components/ParallaxScrollView.tsx +++ b/components/ParallaxScrollView.tsx @@ -1,15 +1,16 @@ -import type { PropsWithChildren, ReactElement } from 'react'; -import { StyleSheet } from 'react-native'; +"use client"; +import type { PropsWithChildren, ReactElement } from "react"; +import { StyleSheet } from "react-native"; import Animated, { interpolate, useAnimatedRef, useAnimatedStyle, useScrollViewOffset, -} from 'react-native-reanimated'; +} from "react-native-reanimated"; -import { ThemedView } from '@/components/ThemedView'; -import { useBottomTabOverflow } from '@/components/ui/TabBarBackground'; -import { useColorScheme } from '@/hooks/useColorScheme'; +import { ThemedView } from "@/components/ThemedView"; +import { useBottomTabOverflow } from "@/components/ui/TabBarBackground"; +import { useColorScheme } from "@/hooks/useColorScheme"; const HEADER_HEIGHT = 250; @@ -23,7 +24,7 @@ export default function ParallaxScrollView({ headerImage, headerBackgroundColor, }: Props) { - const colorScheme = useColorScheme() ?? 'light'; + const colorScheme = useColorScheme() ?? "light"; const scrollRef = useAnimatedRef<Animated.ScrollView>(); const scrollOffset = useScrollViewOffset(scrollRef); const bottom = useBottomTabOverflow(); @@ -34,11 +35,15 @@ export default function ParallaxScrollView({ translateY: interpolate( scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], - [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75] + [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75], ), }, { - scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]), + scale: interpolate( + scrollOffset.value, + [-HEADER_HEIGHT, 0, HEADER_HEIGHT], + [2, 1, 1], + ), }, ], }; @@ -50,13 +55,15 @@ export default function ParallaxScrollView({ ref={scrollRef} scrollEventThrottle={16} scrollIndicatorInsets={{ bottom }} - contentContainerStyle={{ paddingBottom: bottom }}> + contentContainerStyle={{ paddingBottom: bottom }} + > <Animated.View style={[ styles.header, { backgroundColor: headerBackgroundColor[colorScheme] }, headerAnimatedStyle, - ]}> + ]} + > {headerImage} </Animated.View> <ThemedView style={styles.content}>{children}</ThemedView> @@ -71,12 +78,12 @@ const styles = StyleSheet.create({ }, header: { height: HEADER_HEIGHT, - overflow: 'hidden', + overflow: "hidden", }, content: { flex: 1, padding: 32, gap: 16, - overflow: 'hidden', + overflow: "hidden", }, }); diff --git a/components/PrimaryButton.tsx b/components/PrimaryButton.tsx index 94bd8ce..b515818 100644 --- a/components/PrimaryButton.tsx +++ b/components/PrimaryButton.tsx @@ -1,3 +1,4 @@ +"use client"; import React from "react"; import { TouchableOpacity, diff --git a/components/ThemedText.tsx b/components/ThemedText.tsx index 9d214a2..c545b1c 100644 --- a/components/ThemedText.tsx +++ b/components/ThemedText.tsx @@ -1,31 +1,32 @@ -import { StyleSheet, Text, type TextProps } from 'react-native'; +"use client"; +import { StyleSheet, Text, type TextProps } from "react-native"; -import { useThemeColor } from '@/hooks/useThemeColor'; +import { useThemeColor } from "@/hooks/useThemeColor"; export type ThemedTextProps = TextProps & { lightColor?: string; darkColor?: string; - type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link'; + type?: "default" | "title" | "defaultSemiBold" | "subtitle" | "link"; }; export function ThemedText({ style, lightColor, darkColor, - type = 'default', + type = "default", ...rest }: ThemedTextProps) { - const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text'); + const color = useThemeColor({ light: lightColor, dark: darkColor }, "text"); return ( <Text style={[ { color }, - type === 'default' ? styles.default : undefined, - type === 'title' ? styles.title : undefined, - type === 'defaultSemiBold' ? styles.defaultSemiBold : undefined, - type === 'subtitle' ? styles.subtitle : undefined, - type === 'link' ? styles.link : undefined, + type === "default" ? styles.default : undefined, + type === "title" ? styles.title : undefined, + type === "defaultSemiBold" ? styles.defaultSemiBold : undefined, + type === "subtitle" ? styles.subtitle : undefined, + type === "link" ? styles.link : undefined, style, ]} {...rest} @@ -41,20 +42,20 @@ const styles = StyleSheet.create({ defaultSemiBold: { fontSize: 16, lineHeight: 24, - fontWeight: '600', + fontWeight: "600", }, title: { fontSize: 32, - fontWeight: 'bold', + fontWeight: "bold", lineHeight: 32, }, subtitle: { fontSize: 20, - fontWeight: 'bold', + fontWeight: "bold", }, link: { lineHeight: 30, fontSize: 16, - color: '#0a7ea4', + color: "#0a7ea4", }, }); diff --git a/components/ThemedView.tsx b/components/ThemedView.tsx index 4d2cb09..fe06be6 100644 --- a/components/ThemedView.tsx +++ b/components/ThemedView.tsx @@ -1,14 +1,23 @@ -import { View, type ViewProps } from 'react-native'; +"use client"; +import { View, type ViewProps } from "react-native"; -import { useThemeColor } from '@/hooks/useThemeColor'; +import { useThemeColor } from "@/hooks/useThemeColor"; export type ThemedViewProps = ViewProps & { lightColor?: string; darkColor?: string; }; -export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) { - const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background'); +export function ThemedView({ + style, + lightColor, + darkColor, + ...otherProps +}: ThemedViewProps) { + const backgroundColor = useThemeColor( + { light: lightColor, dark: darkColor }, + "background", + ); return <View style={[{ backgroundColor }, style]} {...otherProps} />; } diff --git a/components/login/ShipCredsForm.tsx b/components/login/ShipCredsForm.tsx new file mode 100644 index 0000000..15712c2 --- /dev/null +++ b/components/login/ShipCredsForm.tsx @@ -0,0 +1,105 @@ +"use client"; +import { ColorScheme, lightColors } from "@/constants"; +import { BottomTabBarButtonProps } from "@react-navigation/bottom-tabs"; +import { + StyleSheet, + TextInput, + TouchableOpacity, + View, + Text, +} from "react-native"; +import PrimaryButton from "../PrimaryButton"; +import { useState } from "react"; + +export function ShipForm() { + const colors = lightColors; + const styles = getStyles(colors); + const [patp, setPatp] = useState("~mirtyl-wacdec"); + const [ticket, setTicket] = useState("~posseg-winnub-fogluc-dirmes"); + const [isLoading, setIsLoading] = useState(false); + async function onSubmit() { + console.log({ patp, ticket }); + } + return ( + <View style={styles.bottomSection}> + <TextInput + style={styles.input} + placeholder="~sampel-palnet" + placeholderTextColor={colors.secondary} + value={patp} + onChangeText={setPatp} + autoCapitalize="none" + autoCorrect={false} + /> + <TextInput + style={styles.input} + placeholder="~sampel-ticlyt-migfun-falmel" + placeholderTextColor={colors.secondary} + value={ticket} + onChangeText={setTicket} + autoCapitalize="none" + autoCorrect={false} + secureTextEntry + /> + + <PrimaryButton + label="Log in" + onPress={onSubmit} + style={{ marginTop: 0 }} + isLoading={isLoading} + /> + + <TouchableOpacity style={styles.footer}> + <Text style={styles.footerText}>No Urbit ID? Get yours.</Text> + </TouchableOpacity> + </View> + ); +} +export const getStyles = (colors: ColorScheme) => + StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background, + justifyContent: "space-between", + padding: 20, + }, + topSection: { + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + walletIcon: { + width: 64, + height: 64, + marginBottom: 12, + }, + logoText: { + fontSize: 18, + color: colors.text, + fontWeight: "400", + }, + bottomSection: { + gap: 8, + marginBottom: 40, + }, + input: { + height: 48, + backgroundColor: colors.card, + borderColor: colors.border, + borderWidth: 1, + borderRadius: 8, + paddingHorizontal: 16, + paddingVertical: 12, + color: colors.text, + fontWeight: "500", + fontSize: 16, + }, + footer: { + marginTop: 50, + alignItems: "center", + }, + footerText: { + color: colors.text, + fontSize: 16, + }, + }); |