mirror of
https://github.com/0xWheatyz/handler.git
synced 2026-09-02 01:06:25 +00:00
Implement Handler mobile app (React Native + Expo iOS)
Build the committed 2a interactive prototype from Handler Mobile.dc.html as a real Expo app: six wired screens (Fleet, Agent detail, Answer, Spawn, Log, Settings) with the exact state logic ported from the design's renderVals(). - Port Leeworks tokens (colors light/dark, typography, spacing, radii, shadows) to typed RN values in src/theme. - Reimplement the design-system components used by the screens (Button, Badge, Icon, Switch, Select, TextField, segmented control, chip, tab bar). - Shared store mirrors the prototype's single-screen navigation and the Waiting -> Running flip when agt-7a1d is answered. - Real OS status bar / home indicator (safe-area insets) replace the mock phone chrome; dark mode follows system appearance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PdF2hHVQ4UUBFPtpeMQ81o
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
StyleSheet,
|
||||
TextInput,
|
||||
View,
|
||||
type StyleProp,
|
||||
type ViewStyle,
|
||||
} from "react-native";
|
||||
import { fonts, radius } from "../theme/tokens";
|
||||
import { useTheme } from "../theme/useTheme";
|
||||
|
||||
/**
|
||||
* Text field covering both the Leeworks single-line Input (answer reply) and
|
||||
* the multiline task textarea on the spawn screen. Focus swaps the border to
|
||||
* `--border-strong` per the Input component.
|
||||
*/
|
||||
export function TextField({
|
||||
value,
|
||||
onChangeText,
|
||||
placeholder,
|
||||
multiline = false,
|
||||
height = 48,
|
||||
style,
|
||||
}: {
|
||||
value: string;
|
||||
onChangeText: (t: string) => void;
|
||||
placeholder?: string;
|
||||
multiline?: boolean;
|
||||
/** For single-line this is the control height; for multiline, the box height. */
|
||||
height?: number;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
}) {
|
||||
const { colors } = useTheme();
|
||||
const [focus, setFocus] = useState(false);
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.wrap,
|
||||
{
|
||||
height,
|
||||
backgroundColor: colors.surfaceCard,
|
||||
borderColor: focus ? colors.borderStrong : colors.borderDefault,
|
||||
alignItems: multiline ? "stretch" : "center",
|
||||
paddingVertical: multiline ? 12 : 0,
|
||||
},
|
||||
style,
|
||||
]}
|
||||
>
|
||||
<TextInput
|
||||
value={value}
|
||||
onChangeText={onChangeText}
|
||||
placeholder={placeholder}
|
||||
placeholderTextColor={colors.textMuted}
|
||||
multiline={multiline}
|
||||
onFocus={() => setFocus(true)}
|
||||
onBlur={() => setFocus(false)}
|
||||
style={[
|
||||
styles.input,
|
||||
{
|
||||
color: colors.textHeading,
|
||||
textAlignVertical: multiline ? "top" : "center",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
wrap: {
|
||||
flexDirection: "row",
|
||||
borderWidth: 1,
|
||||
borderRadius: radius.md,
|
||||
paddingHorizontal: 14,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
alignSelf: "stretch",
|
||||
fontFamily: fonts.bodyRegular,
|
||||
fontSize: 15,
|
||||
padding: 0,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user