lodev09 / react-native-true-sheet

The true native bottom sheet experience 💩
https://sheet.lodev09.com
MIT License
394 stars 12 forks source link

Bottom Sheet Floats on Android #92

Open Code-Victor opened 2 weeks ago

Code-Victor commented 2 weeks ago

First off, I want to thank you for building such an amazing project. You're Godsent! I noticed an issue with my button sheet when it hangs in the air and's dismissed when the Keyboard is still active(visible). Take a look

https://github.com/user-attachments/assets/21bd7f0f-1b8e-425c-9554-462ba486ed56

Here's the code I have:

const editNameSchema = z.object({
  name: z.string({ required_error: "Name is required" }).min(1, {
    message: "Name is required",
  }),
});
type EditNameSchema = z.infer<typeof editNameSchema>;
function EditNameForm() {
  const user = useStore((s) => s.user);
  const { control, handleSubmit } = useForm<EditNameSchema>({
    defaultValues: {
      name: user?.type === "user" ? user.name : undefined,
    },
    resolver: zodResolver(editNameSchema),
  });
  const onSubmit = (data: EditNameSchema) => {
    console.log(data);
  };
  return (
    <TrueSheet
      sizes={["auto"]}
      name="edit-name-sheet"
      cornerRadius={16}
    >
      <RNView style={{ padding: 24, gap: 24 }}>
        <Controller
          name="name"
          control={control}
          render={({ field, formState }) => (
            <Input size="md" mt="$4" minWidth="100%">
              <Input.Label htmlFor="input" mb="$1.5">
                Full Name
              </Input.Label>
              <Input.Box>
                <Input.Area
                  id="input"
                  onBlur={field.onBlur}
                  value={field.value}
                  onChangeText={field.onChange}
                />
              </Input.Box>
              {formState.errors.name ? (
                <Input.SubText error>
                  {formState.errors.name.message}
                </Input.SubText>
              ) : null}
            </Input>
          )}
        />
        <Button rounded="pill" onPress={handleSubmit(onSubmit)}>
          <Button.Text>Save</Button.Text>
        </Button>
      </RNView>
    </TrueSheet>
  );
}

Then I present it in another component

<ListItem
    // other props...
    onPress={() => {
      TrueSheet.present("edit-name-sheet");
     }}
/>

After hours of debugging, I found a nice little trick that works for me though. I change the key of the Sheet to trigger a render on dismiss.


function EditNameForm() {
// same code ...
+  const [key, setKey] = React.useState(0);
// same code...
  return (
    <TrueSheet
      sizes={["auto"]}
      name="edit-name-sheet"
      cornerRadius={16}
+    key={`edit-name-sheet${key}`}
+     onDismiss={() => {
+       setKey((prev) => prev + 1);
+     }}
    >
// same code
        );
}

This may not be the best approach but it works.
https://github.com/user-attachments/assets/50a14fcc-b5ec-43bc-b242-221ccda7efb7

I tried changing the keyboardMode to "pan" and it worked well but it was covering the button. I'd appreciate knowing if there's a better way to handle this.

lodev09 commented 2 weeks ago

Thanks for the feedback!

Actually, I think this might be a good solution, for now. I'm having headache with android at the moment with all the size changes. Force rendering should do the trick with all this edge-case.

Code-Victor commented 2 weeks ago

Alright, thanks for your help🫡