nextui-org / nextui

🚀 Beautiful, fast and modern React UI library.
https://nextui.org
MIT License
20.45k stars 1.24k forks source link

[BUG] - RTL Support for Modals #2414

Open tareq96 opened 4 months ago

tareq96 commented 4 months ago

NextUI Version

2.2.9

Describe the bug

The Modal title overlaps with the close icon when using RTL

image

I believe it should look like this: image

Your Example Website or App

No response

Steps to Reproduce the Bug or Issue

Use RTL layout, put the direction: rtl for the HTML or the body tag. Then Open any modal

Expected behavior

image

Screenshots or Videos

No response

Operating System Version

macOS

Browser

Chrome

linear[bot] commented 4 months ago

ENG-416 [BUG] - RTL Support for Modals

kuri-sun commented 4 months ago

Hi @tareq96! Could you provide me with the code and also its CSS, please? Thank you!

tareq96 commented 4 months ago

Hi @kuri-sun

`import { useEffect, useState } from 'react' import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, useDisclosure, Input } from "@nextui-org/react"; import { GoPlus } from "react-icons/go"; import toast from 'react-hot-toast'; import { ResponseModel } from '../../services/apiModels'; import { api } from '../../services/apis'; import { useForm } from 'react-hook-form'; import { EyeSlashFilledIcon } from '../../icons/EyeSlashFilledIcon'; import { EyeFilledIcon } from '../../icons/EyeFilledIcon';

interface Props { getAdminUsers: () => void; }

const AddUserModal = ({ getAdminUsers }: Props) => { const { isOpen, onOpen, onOpenChange } = useDisclosure(); const [isVisible, setIsVisible] = useState(false); const { register, handleSubmit, reset, formState: { errors } } = useForm(); const [isLoading, setIsLoading] = useState(false);

const handleCreateUser = async (userParams: any) => {
    const postData = {
        username: userParams.username,
        email: userParams.email,
        password: userParams.password,
    };

    setIsLoading(true);

    const response = await api.createAdminUser(postData) as ResponseModel;

    if (response?.status === 'success') {
        onOpenChange();
        getAdminUsers();
        response?.message && toast.success(response?.message);
    } else {
        toast.error(response?.error?.message)
    }

    setIsLoading(false);
}

const toggleVisibility = () => setIsVisible(!isVisible);

useEffect(() => {
    if (!isOpen) {
        reset();
    }
}, [isOpen]);

return (
    <>
        <Button
            onPress={onOpen}
            color='primary'
            endContent={<GoPlus size={20} />}
            size="sm"
            className='w-3/6 xs:w-auto'
        >
            Add User
        </Button>
        <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
            <ModalContent>
                {(onClose) => (
                    <form className="" onSubmit={handleSubmit(handleCreateUser)}>
                        <ModalHeader>Add New User</ModalHeader>
                        <ModalBody>
                            <div>
                                <Input
                                    type="username"
                                    label="Username"
                                    labelPlacement="outside"
                                    className='mb-0'
                                    isInvalid={!!errors.username}
                                    errorMessage={errors.username?.message as string}
                                    {...register('username', {
                                        required: 'This field is required'
                                    })}
                                />
                            </div>

                            <div>
                                <Input
                                    type="email"
                                    label="Email"
                                    labelPlacement="outside"
                                    className='mb-0'
                                    isInvalid={!!errors.email}
                                    errorMessage={errors.email?.message as string}
                                    {...register('email', {
                                        required: 'This field is required',
                                        pattern: {
                                            value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                                            message: "Invalid email address"
                                        }
                                    })}
                                />
                            </div>

                            <div>
                                <Input
                                    type={isVisible ? "text" : "password"}
                                    label="Password"
                                    labelPlacement='outside'
                                    className='mb-0'
                                    isInvalid={!!errors.password}
                                    errorMessage={errors.password?.message as string}
                                    {
                                    ...register('password', {
                                        required: 'This field is required',
                                        minLength: {
                                            value: 8,
                                            message: 'Length must be 8 or more'
                                        }
                                    })
                                    }
                                    endContent={
                                        <button className="focus:outline-none" type="button" onClick={toggleVisibility}>
                                            {isVisible ? (
                                                <EyeSlashFilledIcon className="text-2xl text-primary pointer-events-none" />
                                            ) : (
                                                <EyeFilledIcon className="text-2xl text-primary pointer-events-none" />
                                            )}
                                        </button>
                                    }
                                />
                            </div>
                        </ModalBody>
                        <ModalFooter>
                            <Button variant="light" color='danger' onPress={onClose}>
                                Close
                            </Button>
                            <Button type='submit' color="primary" isLoading={isLoading}>
                                Add User
                            </Button>
                        </ModalFooter>
                    </form>
                )}
            </ModalContent>
        </Modal>
    </>
)

}

export default AddUserModal`

kuri-sun commented 4 months ago

Hi @tareq96, I took a look at it, however, I could not reproduce the same bug as yours. For me, it looks like this(pic below)

In the example that you provided, I believe the passing type is primary however the button color seems like RED in the bug picture. So, could you take a look at the code and if there are any other CSS or not, please? Thank you 😊

Screenshot 2024-03-03 at 6 49 30 AM
tareq96 commented 4 months ago

Hi @kuri-sun

I'm able to reproduce it in the doc. site: https://nextui.org/docs/components/modal Just change the direction of the HTML tag to "rtl" and you can re-create it for any modal.

image image

mrbadri commented 3 months ago

Hi @jrgarciadev , I resolved this issue