Dropdown
The Dropdown component is a wrapper around PrimeReact’s Dropdown with automatic z-index management for proper overlay behavior.
Purpose
Section titled “Purpose”Dropdown provides a select component that correctly appears above dialogs and other overlays without z-index conflicts.
Key Features
Section titled “Key Features”- Full PrimeReact Dropdown functionality
- Automatic z-index management
- Works inside dialogs
- Appends to document body by default
- All PrimeReact Dropdown props supported
Quick Start
Section titled “Quick Start”import { Dropdown } from '@cratis/components/Dropdown';
function MyForm() { const [selectedCity, setSelectedCity] = useState(null);
const cities = [ { label: 'Oslo', value: 'oslo' }, { label: 'Bergen', value: 'bergen' }, { label: 'Trondheim', value: 'trondheim' } ];
return ( <Dropdown value={selectedCity} options={cities} onChange={(e) => setSelectedCity(e.value)} placeholder="Select a City" /> );}All PrimeReact Dropdown props are supported. See PrimeReact Dropdown Documentation for complete list.
Common Props
Section titled “Common Props”interface DropdownProps { value?: unknown; options: Array<{ label: string; value: unknown }>; onChange?: (e: { value: unknown }) => void; placeholder?: string; disabled?: boolean; filter?: boolean; filterPlaceholder?: string; showClear?: boolean; optionLabel?: string; optionValue?: string; // ... all other PrimeReact Dropdown props}Basic Examples
Section titled “Basic Examples”Simple String Options
Section titled “Simple String Options”const options = ['React', 'Angular', 'Vue', 'Svelte'];
<Dropdown value={selectedFramework} options={options} onChange={(e) => setSelectedFramework(e.value)} placeholder="Select Framework"/>Object Options
Section titled “Object Options”const countries = [ { name: 'Norway', code: 'NO' }, { name: 'Sweden', code: 'SE' }, { name: 'Denmark', code: 'DK' }];
<Dropdown value={selectedCountry} options={countries} onChange={(e) => setSelectedCountry(e.value)} optionLabel="name" placeholder="Select Country"/>With Filtering
Section titled “With Filtering”<Dropdown value={selected} options={longListOfOptions} onChange={(e) => setSelected(e.value)} filter filterPlaceholder="Search..." placeholder="Select Option"/>Clearable Selection
Section titled “Clearable Selection”<Dropdown value={selected} options={options} onChange={(e) => setSelected(e.value)} showClear placeholder="Select (optional)"/>Grouped Options
Section titled “Grouped Options”const groupedCities = [ { label: 'Norway', items: [ { label: 'Oslo', value: 'oslo' }, { label: 'Bergen', value: 'bergen' } ] }, { label: 'Sweden', items: [ { label: 'Stockholm', value: 'stockholm' }, { label: 'Gothenburg', value: 'gothenburg' } ] }];
<Dropdown value={selected} options={groupedCities} onChange={(e) => setSelected(e.value)} optionLabel="label" optionGroupLabel="label" optionGroupChildren="items" placeholder="Select City"/>Custom Item Template
Section titled “Custom Item Template”const countryTemplate = (option: Country) => { return ( <div className="flex align-items-center"> <img src={`/flags/${option.code}.png`} width="20" alt={option.name} /> <span className="ml-2">{option.name}</span> </div> );};
<Dropdown value={selectedCountry} options={countries} onChange={(e) => setSelectedCountry(e.value)} itemTemplate={countryTemplate} optionLabel="name" placeholder="Select Country"/>Inside Dialogs
Section titled “Inside Dialogs”Dropdown automatically works correctly inside dialogs:
<Dialog visible={visible} onHide={() => setVisible(false)}> <div className="field"> <label>Category</label> <Dropdown value={category} options={categories} onChange={(e) => setCategory(e.value)} placeholder="Select Category" /> </div></Dialog>The dropdown panel will appear above the dialog without z-index issues.
Z-Index Management
Section titled “Z-Index Management”The component uses useOverlayZIndex hook to ensure proper layering:
- Dropdown panel automatically gets correct z-index
- Works with multiple layered dialogs
- Appends to document body by default
- Prevents overlay conflicts
Disabled State
Section titled “Disabled State”<Dropdown value={selected} options={options} disabled={isLoading} placeholder="Loading..."/>Validation and Errors
Section titled “Validation and Errors”Integrate with form validation:
<div className="field"> <label htmlFor="status">Status</label> <Dropdown id="status" value={formData.status} options={statusOptions} onChange={(e) => setFormData({ ...formData, status: e.value })} className={errors.status ? 'p-invalid' : ''} /> {errors.status && <small className="p-error">{errors.status}</small>}</div>Complete Form Example
Section titled “Complete Form Example”import { Dropdown } from '@cratis/components/Dropdown';import { useState } from 'react';
interface FormData { category: string; priority: string; assignee: string;}
function IssueForm() { const [formData, setFormData] = useState<FormData>({ category: '', priority: '', assignee: '' });
const categories = [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Improvement', value: 'improvement' } ];
const priorities = [ { label: 'Low', value: 'low' }, { label: 'Medium', value: 'medium' }, { label: 'High', value: 'high' }, { label: 'Critical', value: 'critical' } ];
const assignees = [ { label: 'Alice', value: 'alice' }, { label: 'Bob', value: 'bob' }, { label: 'Charlie', value: 'charlie' } ];
return ( <form> <div className="field"> <label htmlFor="category">Category</label> <Dropdown id="category" value={formData.category} options={categories} onChange={(e) => setFormData({ ...formData, category: e.value })} placeholder="Select Category" /> </div>
<div className="field"> <label htmlFor="priority">Priority</label> <Dropdown id="priority" value={formData.priority} options={priorities} onChange={(e) => setFormData({ ...formData, priority: e.value })} placeholder="Select Priority" /> </div>
<div className="field"> <label htmlFor="assignee">Assignee</label> <Dropdown id="assignee" value={formData.assignee} options={assignees} onChange={(e) => setFormData({ ...formData, assignee: e.value })} placeholder="Assign to..." showClear filter /> </div> </form> );}Use Cases
Section titled “Use Cases”- Form fields: Select inputs in forms
- Filters: Filtering data by category, status, etc.
- Preferences: User settings selection
- Navigation: Menu-style navigation options
- Status selection: Workflow state transitions
- Type selection: Choose item types in editors
Differences from PrimeReact Dropdown
Section titled “Differences from PrimeReact Dropdown”This component extends PrimeReact Dropdown with:
- Automatic z-index management: Works correctly in dialogs without manual configuration
- Default appendTo: Automatically appends to document.body
- Consistent behavior: Same overlay behavior across all usage contexts
Otherwise, it’s identical to PrimeReact Dropdown.
Best Practices
Section titled “Best Practices”- Provide clear labels: Always label dropdowns
- Use placeholders: Guide users with meaningful placeholders
- Enable filtering for long lists: Use
filterprop for 10+ options - Show clear button: Use
showClearfor optional selections - Validate selections: Provide error feedback
- Disable when appropriate: Disable during loading or when unavailable
- Use object options: For complex data with multiple properties
- Group related options: Use grouped options for better organization
- Provide feedback: Show loading states, error states clearly
Accessibility
Section titled “Accessibility”Inherits PrimeReact Dropdown accessibility features:
- Keyboard navigation (Arrow keys, Enter, Escape)
- ARIA labels and roles
- Focus management
- Screen reader support
Enhance with:
<label htmlFor="dropdown-id"> Selection Label</label><Dropdown id="dropdown-id" aria-label="Selection Label" // ... other props/>Styling
Section titled “Styling”Style via className or custom CSS:
<Dropdown className="w-full" panelClassName="custom-dropdown-panel" // .../>Or global CSS:
.p-dropdown { /* Custom dropdown styles */}
.p-dropdown-panel { /* Custom panel styles */}