skip to Main Content

I am developing a react website and I am trying to customize select option based on my own Figma design.

enter image description here

This is my Figma design and I made it like this :

const CustomDatePicker = ({ birthdate, handle }) => {
    const selectRef = useRef(null);

    const [month, setMonth] = useState('0');
    const [day, setDay] = useState('0');
    const [year, setYear] = useState('0');

    const months = [
        { value: '01', label: 'January' },
        { value: '02', label: 'February' },
        { value: '03', label: 'March' },
        { value: '04', label: 'April' },
        { value: '05', label: 'May' },
        { value: '06', label: 'June' },
        { value: '07', label: 'July' },
        { value: '08', label: 'August' },
        { value: '09', label: 'September' },
        { value: '10', label: 'Octorber' },
        { value: '11', label: 'November' },
        { value: '12', label: 'December' },
    ];

    const days = Array.from({ length: 31 }, (_, i) => i + 1).map((day) => ({
        value: day < 10 ? `0${day}` : `${day}`,
        label: day.toString(),
    }));

    const years = Array.from({ length: 125 }, (_, i) => 2024 - i).map((year) => ({
        value: year.toString(),
        label: year.toString(),
    }));

    const handleMonthChange = (event: any) => {
        setMonth(event.target.value);
        handle({ ...birthdate, month: parseInt(event.target.value) });
    };

    const handleDayChange = (event: any) => {
        setDay(event.target.value);
        handle({ ...birthdate, day: parseInt(event.target.value) });
    };

    const handleYearChange = (event: any) => {
        setYear(event.target.value);
        handle({ ...birthdate, year: parseInt(event.target.value) });
    };

    const handleIconClick = () => {
        // Trigger click event on select element
        selectRef.current.click();
    };

    return (
        <div style={{ display: 'flex', gap: '8px' }}>
            <div style={{ flex: 1, position: 'relative' }}>
                <select ref={selectRef} value={month} onChange={handleMonthChange} className={month == '0' ? styles.date_selector_placeholder : styles.date_selector}>
                    <option value="0" disabled className={styles.date_selector_option_item_placeholder}>Month</option>
                    {months.map((month) => (
                        <option key={month.value} value={month.value} className={styles.date_selector_option_item}>
                            {month.label}
                        </option>
                    ))}
                </select>
                <CustomIcon onClick={handleIconClick} name='arrowDownGrey' width={23} height={17} style={{ position: 'absolute', top: '14px', right: '12px' }} />
            </div>
            <div style={{ flex: 0.5, position: 'relative' }}>
                <select value={day} onChange={handleDayChange} className={day == '0' ? styles.date_selector_placeholder : styles.date_selector} style={{ flex: 0.5 }}>
                    <option value="0" disabled className={styles.date_selector_option_item_placeholder}>Day</option>
                    {days.map((day) => (
                        <option key={day.value} value={day.value} className={styles.date_selector_option_item}>
                            {day.label}
                        </option>
                    ))}
                </select>
                <CustomIcon onClick={handleIconClick} name='arrowDownGrey' width={23} height={17} style={{ position: 'absolute', top: '14px', right: '12px' }} />
            </div>
            <div style={{ flex: 0.5, position: 'relative' }}>
                <select value={year} onChange={handleYearChange} className={year == '0' ? styles.date_selector_placeholder : styles.date_selector} style={{ flex: 0.5 }}>
                    <option value="0" disabled className={styles.date_selector_option_item_placeholder}>Year</option>
                    {years.map((year) => (
                        <option key={year.value} value={year.value} className={styles.date_selector_option_item}>
                            {year.label}
                        </option>
                    ))}
                </select>
                <CustomIcon onClick={handleIconClick} name='arrowDownGrey' width={23} height={17} style={{ position: 'absolute', top: '14px', right: '12px' }} />
            </div>
        </div>
    );
};

As you can see, when I click CustomIcon, I want to open select option menu but it’s not working. I tried to find solutions but there is no results yet. Please help me, Thanks all.

To solve the issue, I used useRef and it’s not working. Any other methods?

2

Answers


  1. Try to assign a ref (selectRefs.month, selectRefs.day, selectRefs.year) each select element. When the custom icon is clicked, it triggers a click on the corresponding select element using its ref.
    Check the code below:

    const CustomDatePicker = ({ birthdate, handle }) => {
        const selectRefs = {
            month: useRef(null),
            day: useRef(null),
            year: useRef(null)
        };
    
        const [month, setMonth] = useState('0');
        const [day, setDay] = useState('0');
        const [year, setYear] = useState('0');
    
        const months = [
            { value: '01', label: 'January' },
            { value: '02', label: 'February' },
            { value: '03', label: 'March' },
            { value: '04', label: 'April' },
            { value: '05', label: 'May' },
            { value: '06', label: 'June' },
            { value: '07', label: 'July' },
            { value: '08', label: 'August' },
            { value: '09', label: 'September' },
            { value: '10', label: 'Octorber' },
            { value: '11', label: 'November' },
            { value: '12', label: 'December' },
        ];
    
        const days = Array.from({ length: 31 }, (_, i) => i + 1).map((day) => ({
            value: day < 10 ? `0${day}` : `${day}`,
            label: day.toString(),
        }));
    
        const years = Array.from({ length: 125 }, (_, i) => 2024 - i).map((year) => ({
            value: year.toString(),
            label: year.toString(),
        }));
    
        const handleMonthChange = (event: any) => {
            setMonth(event.target.value);
            handle({ ...birthdate, month: parseInt(event.target.value) });
        };
    
        const handleDayChange = (event: any) => {
            setDay(event.target.value);
            handle({ ...birthdate, day: parseInt(event.target.value) });
        };
    
        const handleYearChange = (event: any) => {
            setYear(event.target.value);
            handle({ ...birthdate, year: parseInt(event.target.value) });
        };
    
        const handleIconClick = (ref) => {
            ref.current.click();
        };
    
        return (
            <div style={{ display: 'flex', gap: '8px' }}>
                <div style={{ flex: 1, position: 'relative' }}>
                    <select ref={selectRefs.month} value={month} onChange={handleMonthChange} className={month == '0' ? styles.date_selector_placeholder : styles.date_selector}>
                        <option value="0" disabled className={styles.date_selector_option_item_placeholder}>Month</option>
                        {months.map((month) => (
                            <option key={month.value} value={month.value} className={styles.date_selector_option_item}>
                                {month.label}
                            </option>
                        ))}
                    </select>
                    <CustomIcon onClick={() => handleIconClick(selectRefs.month)} name='arrowDownGrey' width={23} height={17} style={{ position: 'absolute', top: '14px', right: '12px' }} />
                </div>
                <div style={{ flex: 0.5, position: 'relative' }}>
                    <select ref={selectRefs.day} value={day} onChange={handleDayChange} className={day == '0' ? styles.date_selector_placeholder : styles.date_selector} style={{ flex: 0.5 }}>
                        <option value="0" disabled className={styles.date_selector_option_item_placeholder}>Day</option>
                        {days.map((day) => (
                            <option key={day.value} value={day.value} className={styles.date_selector_option_item}>
                                {day.label}
                            </option>
                        ))}
                    </select>
                    <CustomIcon onClick={() => handleIconClick(selectRefs.day)} name='arrowDownGrey' width={23} height={17} style={{ position: 'absolute', top: '14px', right: '12px' }} />
                </div>
                <div style={{ flex: 0.5, position: 'relative' }}>
                    <select ref={selectRefs.year} value={year} onChange={handleYearChange} className={year == '0' ? styles.date_selector_placeholder : styles.date_selector} style={{ flex: 0.5 }}>
                        <option value="0" disabled className={styles.date_selector_option_item_placeholder}>Year</option>
                        {years.map((year) => (
                            <option key={year.value} value={year.value} className={styles.date_selector_option_item}>
                                {year.label}
                            </option>
                        ))}
                    </select>
                    <CustomIcon onClick={() => handleIconClick(selectRefs.year)} name='arrowDownGrey' width={23} height={17} style={{ position: 'absolute', top: '14px', right: '12px' }} />
                </div>
            </div>
        );
    };
    
    Login or Signup to reply.
  2. Please reference this repository.
    https://github.com/santiagourregobotero/customized-select

    To achieve a customized appearance for a select element, a common technique involves setting the select’s opacity to 0, effectively hiding it, and then customizing its appearance using alternative elements. This method allows for a more professional and tailored look and feel for the select element.

    By setting the opacity of the select element to 0, it becomes visually hidden while still retaining its functionality. Subsequently, custom styling can be applied to other elements, such as a div or span, to create a visually appealing and personalized representation of the select element. This approach provides greater flexibility in terms of design and allows for a more seamless integration with the overall look and feel of the web page or application.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search