Skip to content

Commit

Permalink
fix: correct ModalHeaderSubmitButton naming and enhance UI components
Browse files Browse the repository at this point in the history
- Renamed `ModalHeaderShubmitButton` to `ModalHeaderSubmitButton` for consistency.
- Updated `SwipeableItem` to include animated text for action labels.
- Refactored `TextField` to support an input postfix element and improved styling.
- Enhanced `GroupedInsetListCard` to conditionally show separators between children.
- Adjusted `MarkdownWeb` to prevent vertical overflow.
- Updated `FollowFeed`, `FollowList`, and `rsshub-form` to use the corrected `ModalHeaderSubmitButton`.
- Added navigation functionality to the `AddListButton` in `ListsScreen`.
- Improved color validation in utility functions.

These changes improve code consistency and enhance the user interface across various components.

Signed-off-by: Innei <tukon479@gmail.com>
  • Loading branch information
Innei committed Jan 23, 2025
1 parent a084c2b commit 55dcfb0
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 62 deletions.
9 changes: 5 additions & 4 deletions apps/mobile/src/components/common/ModalSharedComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,26 @@ const ModalHeaderCloseButtonImpl = () => {
)
}

export interface ModalHeaderShubmitButtonProps {
export interface ModalHeaderSubmitButtonProps {
isValid: boolean
onPress: () => void
isLoading?: boolean
}
export const ModalHeaderShubmitButton = ({
export const ModalHeaderSubmitButton = ({
isValid,
onPress,
isLoading,
}: ModalHeaderShubmitButtonProps) => {
}: ModalHeaderSubmitButtonProps) => {
return <ModalHeaderShubmitButtonImpl isValid={isValid} onPress={onPress} isLoading={isLoading} />
}

const ModalHeaderShubmitButtonImpl = ({
isValid,
onPress,
isLoading,
}: ModalHeaderShubmitButtonProps) => {
}: ModalHeaderSubmitButtonProps) => {
const label = useColor("label")

return (
<TouchableOpacity onPress={onPress} disabled={!isValid || isLoading}>
{isLoading ? (
Expand Down
14 changes: 13 additions & 1 deletion apps/mobile/src/components/common/SwipeableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ export const SwipeableItem: React.FC<SwipeableItemProps> = ({
const renderRightActions = (progress: Animated.AnimatedInterpolation<number>) => {
const width = rightActions?.length ? rightActions.length * 74 : 74

const parallaxX = progress.interpolate({
inputRange: [0, 1, 1.2],
outputRange: [0, 0, 10],
})
return (
<>
<View
Expand Down Expand Up @@ -167,7 +171,15 @@ export const SwipeableItem: React.FC<SwipeableItemProps> = ({
onPress={action.onPress}
>
{action.icon}
<Text style={styles.actionText}>{action.label}</Text>
<Animated.Text
style={[
styles.actionText,
{ color: action.color ?? "#fff" },
{ transform: [{ translateX: parallaxX }] },
]}
>
{action.label}
</Animated.Text>
</RectButton>
</Animated.View>
)
Expand Down
55 changes: 46 additions & 9 deletions apps/mobile/src/components/ui/form/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,36 @@ import { accentColor } from "@/src/theme/colors"

import { FormLabel } from "./Label"

interface TextFieldProps {
interface BaseFieldProps {
wrapperClassName?: string
wrapperStyle?: StyleProp<ViewStyle>

label?: string
description?: string
required?: boolean

inputPostfixElement?: React.ReactNode
}

export const TextField = forwardRef<TextInput, TextInputProps & TextFieldProps>(
const BaseField = forwardRef<TextInput, TextInputProps & BaseFieldProps>(
(
{ className, style, wrapperClassName, wrapperStyle, label, description, required, ...rest },
{
className,
style,
wrapperClassName,
wrapperStyle,
label,
description,
required,
inputPostfixElement,
...rest
},
ref,
) => {
return (
<>
{!!label && <FormLabel className="pl-1" label={label} optional={!required} />}
<View className="flex-1">
{!!label && <FormLabel className="pl-2.5" label={label} optional={!required} />}
{!!description && (
<Text className="text-secondary-label mb-1 pl-1 text-sm">{description}</Text>
<Text className="text-secondary-label mb-1 pl-2.5 text-sm">{description}</Text>
)}
<View
className={cn(
Expand All @@ -37,16 +48,42 @@ export const TextField = forwardRef<TextInput, TextInputProps & TextFieldProps>(
<TextInput
selectionColor={accentColor}
ref={ref}
className={cn("text-text placeholder:text-secondary-label w-full flex-1", className)}
className={cn("text-label placeholder:text-secondary-label w-full flex-1", className)}
style={StyleSheet.flatten([styles.textField, style])}
{...rest}
/>
{inputPostfixElement}
</View>
</>
</View>
)
},
)

export const TextField = forwardRef<TextInput, TextInputProps & BaseFieldProps>((props, ref) => (
<BaseField {...props} ref={ref} />
))

interface NumberFieldProps extends BaseFieldProps {
value?: number
onChangeNumber?: (value: number) => void
defaultValue?: number
}

export const NumberField = forwardRef<
TextInput,
Omit<TextInputProps, "keyboardType" | "value" | "onChangeText" | "defaultValue"> &
NumberFieldProps
>(({ value, onChangeNumber, defaultValue, ...rest }, ref) => (
<BaseField
{...rest}
ref={ref}
keyboardType="number-pad"
value={value?.toString()}
onChangeText={(text) => onChangeNumber?.(Math.min(Number(text), Number.MAX_SAFE_INTEGER))}
defaultValue={defaultValue?.toString()}
/>
))

const styles = StyleSheet.create({
textField: {
fontSize: 16,
Expand Down
50 changes: 27 additions & 23 deletions apps/mobile/src/components/ui/grouped/GroupedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import { MingcuteRightLine } from "@/src/icons/mingcute_right_line"
import { RightCuteReIcon } from "@/src/icons/right_cute_re"
import { useColor } from "@/src/theme/colors"

export const GroupedInsetListCard: FC<PropsWithChildren & ViewProps> = ({
children,
className,
...props
}) => {
type GroupedInsetListCardProps = {
showSeparator?: boolean
}

export const GroupedInsetListCard: FC<
PropsWithChildren & ViewProps & GroupedInsetListCardProps
> = ({ children, className, showSeparator = true, ...props }) => {
return (
<View
{...props}
Expand All @@ -22,26 +24,28 @@ export const GroupedInsetListCard: FC<PropsWithChildren & ViewProps> = ({
className,
)}
>
{React.Children.map(children, (child, index) => {
const isLast = index === React.Children.count(children) - 1
{showSeparator
? React.Children.map(children, (child, index) => {
const isLast = index === React.Children.count(children) - 1

const isNavigationLink =
React.isValidElement(child) &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
(child.type as Function).name === GroupedInsetListNavigationLink.name
const isNavigationLink =
React.isValidElement(child) &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
(child.type as Function).name === GroupedInsetListNavigationLink.name

return (
<Fragment key={index}>
{child}
{!isLast && (
<View
className={cn("bg-opaque-separator", isNavigationLink ? "ml-16" : "mx-4")}
style={{ height: StyleSheet.hairlineWidth }}
/>
)}
</Fragment>
)
})}
return (
<Fragment key={index}>
{child}
{!isLast && (
<View
className={cn("bg-opaque-separator", isNavigationLink ? "ml-16" : "mx-4")}
style={{ height: StyleSheet.hairlineWidth }}
/>
)}
</Fragment>
)
})
: children}
</View>
)
}
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/components/ui/typography/MarkdownWeb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const MarkdownWeb: WebComponent<{
overscroll-behavior: none;
}
body, html {
overflow: hidden;
overflow-y: hidden;
}
`,
}}
Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/src/modules/feed/FollowFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { z } from "zod"

import {
ModalHeaderCloseButton,
ModalHeaderShubmitButton,
ModalHeaderSubmitButton,
} from "@/src/components/common/ModalSharedComponents"
import { FormProvider } from "@/src/components/ui/form/FormProvider"
import { FormLabel } from "@/src/components/ui/form/Label"
Expand Down Expand Up @@ -108,7 +108,7 @@ function FollowImpl() {
headerLeft: ModalHeaderCloseButton,
gestureEnabled: !isDirty,
headerRight: () => (
<ModalHeaderShubmitButton
<ModalHeaderSubmitButton
isValid={isValid}
onPress={form.handleSubmit(submit)}
isLoading={isLoading}
Expand Down
9 changes: 4 additions & 5 deletions apps/mobile/src/modules/feed/view-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { FeedViewType } from "@follow/constants"
import { cn } from "@follow/utils"
import { Text, TouchableOpacity, View } from "react-native"

import { Grid } from "@/src/components/ui/grid"
Expand Down Expand Up @@ -34,10 +33,10 @@ export const FeedViewSelector = ({ value, onChange, className, readOnly }: Props
width={18}
/>
<Text
className={cn(
"mt-1 whitespace-nowrap text-[8px] font-medium",
isSelected ? "text-accent" : "text-secondary-label",
)}
className={"mt-1 whitespace-nowrap text-[8px] font-medium"}
style={{
color: isSelected ? view.activeColor : secondaryLabelColor,
}}
>
{view.name}
</Text>
Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/src/modules/list/FollowList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { z } from "zod"

import {
ModalHeaderCloseButton,
ModalHeaderShubmitButton,
ModalHeaderSubmitButton,
} from "@/src/components/common/ModalSharedComponents"
import { FormProvider } from "@/src/components/ui/form/FormProvider"
import { FormLabel } from "@/src/components/ui/form/Label"
Expand Down Expand Up @@ -118,7 +118,7 @@ const Impl = (props: { id: string }) => {
headerLeft: ModalHeaderCloseButton,
gestureEnabled: !isDirty,
headerRight: () => (
<ModalHeaderShubmitButton
<ModalHeaderSubmitButton
isValid={isValid}
onPress={form.handleSubmit(submit)}
isLoading={isLoading}
Expand Down
5 changes: 3 additions & 2 deletions apps/mobile/src/modules/settings/routes/Lists.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useQuery } from "@tanstack/react-query"
import { router } from "expo-router"
import { createElement, useCallback } from "react"
import type { ListRenderItem } from "react-native"
import { Image, StyleSheet, Text, TouchableOpacity, View } from "react-native"
Expand Down Expand Up @@ -84,7 +85,7 @@ export const ListsScreen = () => {
const AddListButton = () => {
const labelColor = useColor("label")
return (
<TouchableOpacity hitSlop={10}>
<TouchableOpacity hitSlop={10} onPress={() => router.push("/list")}>
<AddCuteReIcon height={20} width={20} color={labelColor} />
</TouchableOpacity>
)
Expand All @@ -109,7 +110,7 @@ const ListItemCell: ListRenderItem<HonoApiClient.List_List_Get> = ({ item: list
{
label: "Edit",
onPress: () => {
// TODO
router.push(`/list?id=${list.id}`)
},
backgroundColor: "#0ea5e9",
},
Expand Down
6 changes: 6 additions & 0 deletions apps/mobile/src/screens/(modal)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export default function ModalLayout() {
title: "Follow",
}}
/>
<Stack.Screen
name="list"
options={{
title: "List",
}}
/>
</Stack>
)
}
Loading

0 comments on commit 55dcfb0

Please sign in to comment.