Skip to main content

Overview

The CustomSelect component is a fully-featured dropdown select input that replaces native HTML select elements with a custom-styled alternative. It includes support for icons, validation states, disabled states, and dark mode. Location: ~/workspace/source/Fronted/src/components/common/CustomSelect.jsx:4

Features

  • Custom dropdown UI with smooth animations
  • Optional icon support for visual enhancement
  • Error state styling with validation feedback
  • Disabled state handling
  • Dark mode compatible
  • Click-outside to close functionality
  • Clear selection option
  • Keyboard-friendly interface

Props

name
string
required
The name attribute for the select input, used when handling form submissions
value
string
required
The currently selected value from the options array
onChange
function
required
Callback function triggered when selection changes. Receives an event object with target.name and target.value
onChange={(e) => console.log(e.target.name, e.target.value)}
options
array
required
Array of string options to display in the dropdown
options={["Opción 1", "Opción 2", "Opción 3"]}
disabled
boolean
default:"false"
When true, disables user interaction with the select component
error
boolean
default:"false"
When true, applies error styling (red border and text color)
icon
React.Component
A Lucide React icon component to display on the left side of the select button
import { User } from 'lucide-react';
icon={User}
placeholder
string
default:"Seleccione..."
Placeholder text shown when no value is selected

Import

import CustomSelect from './components/common/CustomSelect';
import { Building2, User } from 'lucide-react';

Usage Examples

import React, { useState } from 'react';
import CustomSelect from './components/common/CustomSelect';

function MyForm() {
  const [formData, setFormData] = useState({ category: '' });

  const handleChange = (e) => {
    setFormData(prev => ({
      ...prev,
      [e.target.name]: e.target.value
    }));
  };

  return (
    <CustomSelect
      name="category"
      value={formData.category}
      onChange={handleChange}
      options={["Estudiante", "Docente", "Administrativo"]}
      placeholder="Seleccione una categoría"
    />
  );
}

Visual Behavior

The CustomSelect component renders as:
  1. Closed State: A button displaying the current value or placeholder, with a chevron icon
  2. Open State: Expands to show a dropdown list with all options
  3. Selected Option: Highlighted with a check icon and colored background
  4. Clear Option: First item in the list allows clearing the selection

Styling States

Default State

  • Semi-transparent white background
  • Subtle border
  • Dark mode compatible colors

Open State

  • Ring border with indigo accent
  • Elevated dropdown with shadow
  • Rotated chevron icon

Error State

  • Red border color
  • Red text color for icon and text
  • Visual feedback for validation failures

Disabled State

  • Reduced opacity (50%)
  • Cursor not-allowed
  • Non-interactive

Implementation Details

Click Outside Detection

The component uses a ref and event listener to detect clicks outside the dropdown and automatically close it:
// From CustomSelect.jsx:8-16
useEffect(() => {
    const handleClickOutside = (event) => {
        if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
            setIsOpen(false);
        }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);

Event Handler Pattern

The onChange event mimics native select behavior by passing an event object:
// From CustomSelect.jsx:18-21
const handleSelect = (opt) => {
    onChange({ target: { name, value: opt } });
    setIsOpen(false);
};

Accessibility

  • Semantic button element for the trigger
  • Keyboard navigation support (click to open)
  • Focus management
  • Disabled state properly communicated
  • ARIA-compatible structure

Best Practices

Always integrate CustomSelect with your form state management solution (useState, React Hook Form, Formik, etc.) to ensure controlled component behavior.
Keep option text concise and descriptive. Long text will be truncated with ellipsis.
Use the error prop in combination with your validation logic to provide visual feedback to users.
Only add icons when they enhance understanding of the field’s purpose (e.g., User icon for user type selection).

Build docs developers (and LLMs) love