Skip to content

Commit

Permalink
cleanup + standardize text inputs (#4317)
Browse files Browse the repository at this point in the history
  • Loading branch information
dnbrwstr authored Jan 14, 2025
1 parent 1b9c46a commit e6a5387
Show file tree
Hide file tree
Showing 19 changed files with 515 additions and 317 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
import { useBranch, useLureMetadata } from '@tloncorp/app/contexts/branch';
import { trackError, trackOnboardingAction } from '@tloncorp/app/utils/posthog';
import {
DeepLinkData,
createInviteLinkRegex,
extractNormalizedInviteLink,
getInviteLinkMeta,
Expand All @@ -17,7 +16,7 @@ import {
Field,
Pressable,
ScreenHeader,
TextInputWithButton,
TextInput,
TlonText,
View,
YStack,
Expand Down Expand Up @@ -159,16 +158,20 @@ export const PasteInviteLinkScreen = ({ navigation }: Props) => {
error={metadataError ?? errors.inviteLink?.message}
paddingTop="$l"
>
<TextInputWithButton
<TextInput
placeholder="join.tlon.io/0v4.pca0n.evapv..."
onBlur={onBlur}
onChangeText={onChange}
value={value}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
buttonText="Paste"
onButtonPress={onHandlePasteClick}
rightControls={
<TextInput.InnerButton
label="Paste"
onPress={onHandlePasteClick}
/>
}
/>
</Field>
)}
Expand Down
11 changes: 7 additions & 4 deletions apps/tlon-mobile/src/screens/Onboarding/ShipLoginScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
OnboardingTextBlock,
ScreenHeader,
TextInput,
TextInputWithButton,
TlonText,
View,
YStack,
Expand Down Expand Up @@ -211,7 +210,7 @@ export const ShipLoginScreen = ({ navigation }: Props) => {
}}
render={({ field: { onChange, onBlur, value } }) => (
<Field label="Access Code" error={errors.accessCode?.message}>
<TextInputWithButton
<TextInput
testID="textInput accessCode"
placeholder="xxxxxx-xxxxxx-xxxxxx-xxxxxx"
onBlur={() => {
Expand All @@ -226,8 +225,12 @@ export const ShipLoginScreen = ({ navigation }: Props) => {
autoCorrect={false}
returnKeyType="send"
enablesReturnKeyAutomatically
buttonText={codevisible ? 'Hide' : 'Show'}
onButtonPress={() => setCodeVisible(!codevisible)}
rightControls={
<TextInput.InnerButton
label={codevisible ? 'Hide' : 'Show'}
onPress={() => setCodeVisible(!codevisible)}
/>
}
/>
</Field>
)}
Expand Down
11 changes: 7 additions & 4 deletions apps/tlon-mobile/src/screens/Onboarding/TlonLoginLegacy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
OnboardingTextBlock,
ScreenHeader,
TextInput,
TextInputWithButton,
TlonText,
View,
YStack,
Expand Down Expand Up @@ -229,7 +228,7 @@ export const TlonLoginLegacy = ({ navigation }: Props) => {
}}
render={({ field: { onChange, onBlur, value } }) => (
<Field label="Password" error={errors.password?.message}>
<TextInputWithButton
<TextInput
placeholder="Password"
onBlur={() => {
onBlur();
Expand All @@ -243,8 +242,12 @@ export const TlonLoginLegacy = ({ navigation }: Props) => {
autoCorrect={false}
returnKeyType="send"
enablesReturnKeyAutomatically
buttonText={passwordVisible ? 'Hide' : 'Show'}
onButtonPress={() => setPasswordVisible(!passwordVisible)}
rightControls={
<TextInput.InnerButton
label={passwordVisible ? 'Hide' : 'Show'}
onPress={() => setPasswordVisible(!passwordVisible)}
/>
}
/>
</Field>
)}
Expand Down
157 changes: 131 additions & 26 deletions packages/app/fixtures/Form.fixture.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Button, ScrollView } from '@tloncorp/ui';
import { Button, IconType, ScrollView, View } from '@tloncorp/ui';
import * as Form from '@tloncorp/ui/src/components/Form';
import { useMemo } from 'react';
import React, { useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

Expand All @@ -16,6 +16,7 @@ const FormFixture = () => {
number: 'one',
listItem: 'chat',
image: undefined,
textarea: undefined,
},
});

Expand All @@ -25,7 +26,12 @@ const FormFixture = () => {

const options: Form.RadioInputOption<string>[] = [
{ title: 'One', value: 'one', description: 'This is one things' },
{ title: 'Two', value: 'two', description: 'This is two things' },
{
title: 'Two',
value: 'two',
description: 'This is two things',
disabled: true,
},
{ title: 'Three', value: 'three', description: 'This is three things' },
];

Expand All @@ -51,10 +57,21 @@ const FormFixture = () => {
icon: 'ChannelGalleries',
},
];
const [selectedToggleGroupOption, setSelectedToggleGroupOptions] =
useState('chat');

const toggleGroupOptions: { label: string; value: string }[] = [
{ label: 'Chat', value: 'chat' },
{ label: 'Notebook', value: 'notebook' },
{ label: 'Gallery', value: 'gallery' },
{ label: 'And', value: '0' },
{ label: 'More', value: '1' },
{ label: 'Items', value: '2' },
];

return (
<ScrollView flex={1} contentContainerStyle={{ paddingTop: insets.top }}>
<Form.FormFrame>
<Form.FormFrame backgroundType="secondary">
<Form.ControlledImageField
name={'image'}
label="Image"
Expand All @@ -66,6 +83,7 @@ const FormFixture = () => {
label="Title"
control={control}
rules={formRules}
inputProps={{ icon: 'Search', placeholder: 'Type here' }}
/>
<Form.ControlledRadioField
options={options}
Expand All @@ -79,37 +97,124 @@ const FormFixture = () => {
label="List input"
control={control}
/>
<Form.RadioControl disabled={true} />
<Form.RadioControl checked={false} />
<Form.RadioControl checked={true} />
<Form.ListItemInput options={listOptions} />

<Form.ControlledTextareaField
name="textarea"
label="Textarea"
control={control}
inputProps={{
placeholder: 'Put some text here',
numberOfLines: 5,
multiline: true,
}}
rules={{
maxLength: {
value: 300,
message: 'Bug report notes are limited to 300 characters',
},
}}
/>

<Form.Field label="Toggle group">
<Form.ToggleGroupInput
value={selectedToggleGroupOption}
onChange={setSelectedToggleGroupOptions}
options={toggleGroupOptions}
/>
</Form.Field>
<Form.Field required error="Bad thing happen" label="My label">
<Form.TextInput placeholder="Type here" />
</Form.Field>
<Button
onPress={() =>
reset({
title: 'monk',
description: '',
})
}
>
<Button.Text>Reseet</Button.Text>
</Button>

<Form.Field label="Button input">
<Button
secondary
onPress={() =>
reset({
title: 'monk',
description: '',
})
}
>
<Button.Text>Reseet</Button.Text>
</Button>
</Form.Field>

<Form.Field label="Find Friends">
<Form.TextInputWithIconAndButton
<Form.TextInput
icon="Search"
buttonText="Clear"
onButtonPress={() => {}}
rightControls={
<Form.TextInput.InnerButton label="Clear" onPress={() => {}} />
}
/>
</Form.Field>
</Form.FormFrame>
</ScrollView>
);
};

export default (
<FixtureWrapper fillWidth fillHeight>
<FormFixture />
</FixtureWrapper>
);
const accents: Form.Accent[] = ['neutral', 'positive', 'negative'];
const icons: (IconType | undefined)[] = [undefined, 'Search'];
const buttonLabels: (string | undefined)[] = [undefined, 'Clear'];
const backgroundTypes = ['primary', 'secondary'] as const;

export default {
textInput: (
<FixtureWrapper fillWidth fillHeight safeArea={true}>
<ScrollView flex={1}>
{backgroundTypes.map((backgroundType) => (
<Form.FormFrame backgroundType={backgroundType} key={backgroundType}>
{buttonLabels.map((buttonLabel) => (
<React.Fragment key={buttonLabel ?? 'no-label'}>
{icons.map((icon) => (
<React.Fragment key={icon ?? 'no-icon'}>
<Form.FieldLabel paddingVertical="$2xl" margin={0}>
{!icon && !buttonLabel
? 'Default'
: icon && !buttonLabel
? 'Icon, no button'
: !icon && buttonLabel
? 'Button, no icon'
: 'Icon and button'}
</Form.FieldLabel>
<React.Fragment>
{accents.map((accent) => (
<Form.Field
label={`Accent: ${accent}`}
accent={accent}
error={
accent === 'negative'
? 'Bad thing happen'
: undefined
}
key={accent + icon + buttonLabel}
>
<Form.TextInput
icon={icon}
placeholder="Type here"
rightControls={
buttonLabel ? (
<Form.TextInput.InnerButton
label={buttonLabel}
/>
) : undefined
}
/>
</Form.Field>
))}
</React.Fragment>
</React.Fragment>
))}
</React.Fragment>
))}
</Form.FormFrame>
))}
</ScrollView>
</FixtureWrapper>
),
full: (
<FixtureWrapper fillWidth fillHeight>
<FormFixture />
</FixtureWrapper>
),
};
12 changes: 12 additions & 0 deletions packages/app/tamagui.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { config } from '../ui/src/tamagui.config';

export type Conf = typeof config;

// Sets up typing for tamagui so that theme variables autocomplete
declare module 'tamagui' {
interface TamaguiCustomConfig extends Conf {}

interface TypeOverride {
groupNames(): 'button';
}
}
2 changes: 1 addition & 1 deletion packages/app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "../../tsconfig",
"include": ["**/*.ts", "**/*.tsx", "window.ts"],
"include": ["**/*.ts", "**/*.tsx", "window.ts", "tamagui.d.ts"],
"compilerOptions": {
"composite": true,
"jsx": "react-jsx",
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/ActionList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import ListFrame from './ListFrame';
const ActionFrame = styled(ListItem, {
borderRadius: 'unset',
borderBottomWidth: 0.5,
borderBottomColor: '$secondaryBorder',
borderBottomColor: '$border',
backgroundColor: 'transparent',
pressStyle: {
backgroundColor: '$secondaryBorder',
backgroundColor: '$border',
},
variants: {
last: {
Expand Down
12 changes: 8 additions & 4 deletions packages/ui/src/components/ChatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { Text, View, YStack, getTokenValue, useTheme } from 'tamagui';
import { useCalm, useChatOptions } from '../contexts';
import { getChannelTitle, getGroupTitle } from '../utils';
import { interactionWithTiming } from '../utils/animation';
import { TextInputWithIconAndButton } from './Form';
import { TextInput } from './Form';
import { ChatListItem, InteractableChatListItem } from './ListItem';
import Pressable from './Pressable';
import { SectionListHeader } from './SectionList';
Expand Down Expand Up @@ -292,16 +292,20 @@ const ChatListSearch = React.memo(function ChatListSearchComponent({
right={0}
>
<View paddingHorizontal="$l" paddingTop="$xl">
<TextInputWithIconAndButton
<TextInput
icon="Search"
placeholder="Find by name"
value={query}
onChangeText={onQueryChange}
spellCheck={false}
autoCorrect={false}
autoCapitalize="none"
buttonText={query !== '' ? 'Clear' : 'Close'}
onButtonPress={query !== '' ? onPressClear : onPressClose}
rightControls={
<TextInput.InnerButton
label={query !== '' ? 'Clear' : 'Close'}
onPress={query !== '' ? onPressClear : onPressClose}
/>
}
/>
</View>
</YStack>
Expand Down
Loading

0 comments on commit e6a5387

Please sign in to comment.