Documentation

Complete guide to using Pickle in your projects. From basic setup to advanced theming and programmatic control.

Introduction

What is Pickle?

Pickle is a lightweight, dependency-free JavaScript library that transforms native HTML select elements into beautiful, accessible, and feature-rich custom dropdowns. Built with modern web standards and accessibility in mind.

Key Features

  • Zero Dependencies: Pure JavaScript with no external libraries required
  • Fully Accessible: Complete ARIA support and keyboard navigation
  • Multi-select Support: Single and multiple selection modes
  • Search & Filter: Built-in search with fuzzy matching
  • Themeable: Customizable themes and CSS variables
  • Performance Optimized: Virtual scrolling for large datasets
  • Mobile Friendly: Touch-optimized for mobile devices
  • Framework Agnostic: Works with any framework or vanilla JavaScript

Installation

Via CDN

The fastest way to get started is using a CDN. Add these lines to your HTML:

<!-- CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pickle-select@1.1.0/dist/pickle.min.css">

<!-- JavaScript (ES Module) -->
<script type="module">
    import Pickle from 'https://cdn.jsdelivr.net/npm/pickle-select@1.1.0/dist/pickle.esm.min.js';
</script>
<!-- OR -->
<!-- JavaScript (UMD Loader) -->
<script src="https://cdn.jsdelivr.net/npm/pickle-select@1.1.0/dist/pickle.umd.min.js"></script>
                                    

Via npm

Install Pickle using your favorite package manager:

# npm
npm install pickle-select

# yarn
yarn add pickle-select

# pnpm
pnpm add pickle-select

Then import in your JavaScript:

// ES6 import
import Pickle from 'pickle-select';
import 'pickle-select/dist/pickle.css';

// CommonJS
const Pickle = require('pickle-select');
require('pickle-select/dist/pickle.css');

Download

Download the latest release from GitHub and include the files manually:

<link rel="stylesheet" href="path/to/pickle.min.css">
<script src="path/to/pickle.umd.min.js"></script>

Quick Start

Basic HTML Setup

Start with a standard HTML select element:

<label for="fruit-select">Choose a fruit:</label>
<select id="fruit-select" name="fruit">
    <option value="">Select a fruit...</option>
    <option value="apple">Apple</option>
    <option value="banana">Banana</option>
    <option value="cherry">Cherry</option>
    <option value="grape">Grape</option>
</select>

Initialize Pickle

Transform your select element with just one line of JavaScript:

// Initialize with element ID
const picker = new Pickle('#fruit-select');

// Or with element reference
const selectElement = document.getElementById('fruit-select');
const picker = new Pickle(selectElement);

Complete Example

Here's a complete working example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pickle Example</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pickle-select@1.1.0/dist/pickle.min.css">
</head>
<body>
    <label for="demo-select">Choose an option:</label>
    <select id="demo-select">
        <option value="">Select an option...</option>
        <option value="option1">Option 1</option>
        <option value="option2">Option 2</option>
        <option value="option3">Option 3</option>
    </select>

    <script type="module">
        import Pickle from 'https://cdn.jsdelivr.net/npm/pickle-select@1.1.0/dist/pickle.esm.min.js';
        
        const picker = new Pickle('#demo-select', {
            onChange: (value, { text }) => {
                console.log('Selected:', value, text);
            }
        });
    </script>
</body>
</html>

Browser Support

Supported Browsers

Pickle works in all modern browsers that support ES6 modules:

Browser Minimum Version Notes
Chrome 61+ Full support
Firefox 60+ Full support
Safari 10.1+ Full support
Edge 16+ Full support
iOS Safari 10.3+ Full support with touch optimizations
Android Chrome 61+ Full support with touch optimizations

Legacy Browser Support

For older browsers, you can use a transpiled version with polyfills. We recommend using Babel with the following presets:

{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "ie >= 11"]
      }
    }]
  ]
}

Basic Usage

Simple Select

The most basic implementation with default settings:

const picker = new Pickle('#my-select');

With Options

Customize behavior with configuration options:

const picker = new Pickle('#my-select', {
    searchable: true,
    theme: 'modern',
    width: '300px',
    onChange: (value, { text, element }) => {
        console.log('Selected:', value, text);
    }
});

Multi-select

Enable multiple selection mode:

<select id="multi-select" multiple>
    <option value="option1">Option 1</option>
    <option value="option2">Option 2</option>
    <option value="option3">Option 3</option>
</select>
const multiPicker = new Pickle('#multi-select', {
    multiple: true, // Optional: auto-detected from HTML
    searchable: true
});

Option Groups

Organize options with `<optgroup>` elements:

<select id="grouped-select">
    <optgroup label="Fruits">
        <option value="apple">Apple</option>
        <option value="banana">Banana</option>
        <option value="cherry">Cherry</option>
    </optgroup>
    <optgroup label="Vegetables">
        <option value="carrot">Carrot</option>
        <option value="lettuce">Lettuce</option>
        <option value="tomato">Tomato</option>
    </optgroup>
</select>

Configuration Options

Available Options

Configure Pickle behavior with these options:

Option Type Default Description
onChange Function null Callback function called when selection changes
defaultValue string | string[] null Initial value(s) to select
theme string 'default' Theme name to apply
width string '100%' CSS width value
height string null CSS height value for trigger
disabled boolean false Whether the select is disabled
required boolean false Whether the select is required
searchable boolean false Enable search functionality
fuzzySearch boolean false Enable fuzzy search matching
multiple boolean false Enable multiple selection (auto-detected from HTML)
debug boolean false Enable debug logging
l10n Object null Localization strings object

Localization (l10n)

Customize text strings for internationalization:

const picker = new Pickle('#my-select', {
    l10n: {
        placeholder: 'Choose an option',
        searchPlaceholder: 'Type to search...',
        selectionCleared: 'Selection cleared',
        selected: 'Selected: {text}',
        multipleSelection: '{count} items selected',
        ariaLabel: 'Select dropdown'
    }
});

Events

Event System

Pickle emits custom events that you can listen to for advanced functionality:

Event When Triggered Detail Properties
pickle:beforeOpen Before dropdown opens instance
pickle:open After dropdown opens instance
pickle:beforeClose Before dropdown closes instance
pickle:close After dropdown closes instance
pickle:change When selection changes instance, value, text
pickle:search When search input changes instance, term, visibleCount
pickle:optionAdded When option is added instance, value, text, index, disabled
pickle:optionRemoved When option is removed instance, value
pickle:optionsUpdated When options are updated instance, options
pickle:destroyed When instance is destroyed instance

Listening to Events

Add event listeners to the wrapper element:

const picker = new Pickle('#my-select');

// Listen to specific events
picker.wrapper.addEventListener('pickle:open', (event) => {
    console.log('Dropdown opened', event.detail.instance);
});

picker.wrapper.addEventListener('pickle:change', (event) => {
    const { value, text, instance } = event.detail;
    console.log('Selection changed:', value, text);
});

// Prevent dropdown from opening
picker.wrapper.addEventListener('pickle:beforeOpen', (event) => {
    if (someCondition) {
        event.preventDefault(); // Cancels the open action
    }
});

Callbacks

onChange Callback

The primary callback for handling selection changes:

const picker = new Pickle('#my-select', {
    onChange: (value, context) => {
        // value: current selection (string for single, array for multiple)
        // context: additional information object
        
        console.log('Current value:', value);
        console.log('Display text:', context.text);
        console.log('Original event:', context.originalEvent);
        console.log('Picker instance:', context.element);
        
        // Handle single select
        if (!Array.isArray(value)) {
            if (value) {
                console.log('Selected:', value, context.text);
            } else {
                console.log('Selection cleared');
            }
        }
        
        // Handle multi-select
        else {
            console.log('Selected items:', value.length);
            console.log('All selected values:', value);
            console.log('All selected texts:', context.text);
        }
    }
});

Native Change Events

Pickle also triggers native `change` events on the original select element:

// Listen to native change event
document.getElementById('my-select').addEventListener('change', (event) => {
    console.log('Native change event:', event.target.value);
    
    // This works with form libraries and frameworks
    // that listen for native change events
});

Constructor

new Pickle(elementOrID, options)

Constructor

Creates a new Pickle instance and transforms the specified select element.

Parameters

Name Type Description
elementOrID HTMLSelectElement | string The select element or its ID (with or without '#')
options Object Configuration options (optional)

Examples

// Basic initialization
const picker = new Pickle('#my-select');

// With element reference
const element = document.querySelector('#my-select');
const picker = new Pickle(element);

// With options
const picker = new Pickle('#my-select', {
    searchable: true,
    theme: 'modern',
    onChange: (value) => console.log(value)
});

Instance Methods

get()

Returns: string | string[]

Retrieves the current value(s) of the select. Returns an array for multi-select.

Example

const picker = new Pickle('#my-select');
const value = picker.get();
console.log(value); // 'option1' or ['option1', 'option2'] for multi-select

set(value)

Param: string | string[]

Sets the selected option by its value. For multi-select, accepts an array of values.

Parameters

Name Type Description
value string | string[] The value or array of values to select

Examples

// Single select
picker.set('option2');

// Multi-select
picker.set(['option1', 'option3']);

// Clear selection
picker.set(''); // or picker.set([]) for multi-select

clear(silent)

Param: boolean

Clears the current selection. Optionally suppress change events.

Parameters

Name Type Default Description
silent boolean false If true, change events will not be fired

open()

Opens the dropdown menu programmatically.

close()

Closes the dropdown menu programmatically.

toggle()

Toggles the dropdown open/closed state.

getText()

Returns: string | string[]

Retrieves the display text of the currently selected option(s).

getOption()

Returns: HTMLElement | HTMLElement[] | null

Returns the currently selected option element(s).

getOptions()

Returns: Array<Object>

Retrieves all available options with their values, text, and state information.

Example

const options = picker.getOptions();
// Returns: [
//   { value: 'opt1', text: 'Option 1', disabled: false, selected: true },
//   { value: 'opt2', text: 'Option 2', disabled: false, selected: false }
// ]

addOption(value, text, index, disabled)

Adds a new option to the select.

Parameters

Name Type Default Description
value string - The option value
text string - The option display text
index number -1 Position to insert (end if -1)
disabled boolean false Whether the option is disabled

Example

// Add to end
picker.addOption('new-value', 'New Option');

// Add at specific position
picker.addOption('another-value', 'Another Option', 2);

// Add disabled option
picker.addOption('disabled-value', 'Disabled Option', -1, true);

removeOption(value)

Removes an option by its value.

Parameters

Name Type Description
value string The value of the option to remove

updateOptions(optionsArray)

Replaces all options with a new array of options.

Parameters

Name Type Description
optionsArray Array<Object> Array of {value, text, disabled} objects

Example

picker.updateOptions([
    { value: 'opt1', text: 'Option 1', disabled: false },
    { value: 'opt2', text: 'Option 2', disabled: false },
    { value: 'opt3', text: 'Option 3', disabled: true }
]);

setDisabled(disabled)

Enables or disables the select component.

setSearchable(searchable)

Enables or disables search functionality.

setTheme(theme)

Changes the theme at runtime.

setRequired(required)

Sets the required state of the select.

getValidationState()

Returns: Object

Gets the current validation state of the select.

Example

const validation = picker.getValidationState();
// Returns: {
//   valid: true,
//   valueMissing: false,
//   customError: false,
//   validationMessage: ''
// }

setCustomValidity(message)

Sets a custom validation message.

destroy()

Destroys the Pickle instance and cleans up all resources.

Example

// Cleanup when component is no longer needed
picker.destroy();

// Original select element is restored
// All event listeners are removed
// Memory is freed

Properties

Instance Properties

Read-only properties available on Pickle instances:

Property Type Description
originalSelect HTMLSelectElement Reference to the original select element
wrapper HTMLElement The main wrapper element containing the custom select
trigger HTMLElement The clickable trigger element
dropdown HTMLElement The dropdown container element
searchInput HTMLInputElement | null The search input element (if searchable)
isOpen boolean Whether the dropdown is currently open
isMultiple boolean Whether multi-select is enabled
disabled boolean Whether the select is disabled
required boolean Whether the select is required
searchable boolean Whether search is enabled
fuzzySearch boolean Whether fuzzy search is enabled
theme string Current theme name
id string Unique identifier for this instance

Usage Example

const picker = new Pickle('#my-select');

// Access properties
console.log('Is open:', picker.isOpen);
console.log('Is multiple:', picker.isMultiple);
console.log('Current theme:', picker.theme);

// Access DOM elements
picker.wrapper.classList.add('custom-class');
picker.trigger.style.fontSize = '16px';

Static Methods

Class Methods

Static methods available on the Pickle class:

Pickle.instances

Returns: Set

A Set containing all active Pickle instances. Useful for global operations.

Example

// Get all instances
console.log('Active instances:', Pickle.instances.size);

// Close all dropdowns
Pickle.instances.forEach(instance => {
    if (instance.isOpen) {
        instance.close();
    }
});

// Destroy all instances
Pickle.instances.forEach(instance => instance.destroy());

Pickle.defaultStrings

Returns: Object

Default localization strings used by all instances unless overridden.

Example

// Customize default strings globally
Pickle.defaultStrings.placeholder = 'Choose an option...';
Pickle.defaultStrings.searchPlaceholder = 'Type to search...';

// All new instances will use these defaults
const picker1 = new Pickle('#select1'); // Uses new defaults
const picker2 = new Pickle('#select2'); // Uses new defaults

Examples

Basic Select

Live Demo

HTML

<label for="basic-example">Choose a fruit:</label>
<select id="basic-example">
    <option value="">Select a fruit...</option>
    <option value="apple">Apple</option>
    <option value="banana">Banana</option>
    <option value="cherry">Cherry</option>
    <option value="grape">Grape</option>
    <option value="orange">Orange</option>
</select>

JavaScript

const basicPicker = new Pickle('#basic-example');

Searchable Select

Live Demo

JavaScript

const searchablePicker = new Pickle('#searchable-example', {
    searchable: true,
    onChange: (value, { text }) => {
        console.log('Selected country:', value, text);
    }
});

Multi-Select

Live Demo

HTML

<select id="multi-example" multiple>
    <option value="js">JavaScript</option>
    <option value="py">Python</option>
    <option value="java">Java</option>
    <!-- more options... -->
</select>

JavaScript

const multiPicker = new Pickle('#multi-example', {
    searchable: true,
    onChange: (values, { text }) => {
        console.log('Selected languages:', values);
        console.log('Selected texts:', text);
    }
});

Grouped Options

Live Demo

HTML

<select id="grouped-example">
    <option value="">Select an item...</option>
    <optgroup label="Fruits">
        <option value="apple">Apple</option>
        <option value="banana">Banana</option>
        <option value="cherry">Cherry</option>
        <option value="grape">Grape</option>
    </optgroup>
    <optgroup label="Vegetables">
        <option value="carrot">Carrot</option>
        <option value="lettuce">Lettuce</option>
        <option value="tomato">Tomato</option>
        <option value="cucumber">Cucumber</option>
    </optgroup>
    <!-- more optgroups... -->
</select>

Dynamic Options

Live Demo

JavaScript

const dynamicPicker = new Pickle('#dynamic-example');
let optionCounter = 3;

function addOption() {
    const value = `opt${optionCounter}`;
    const text = `Option ${optionCounter}`;
    dynamicPicker.addOption(value, text);
    optionCounter++;
}

function removeOption() {
    const options = dynamicPicker.getOptions();
    if (options.length > 0) {
        const lastOption = options[options.length - 1];
        dynamicPicker.removeOption(lastOption.value);
    }
}

function updateAllOptions() {
    const newOptions = [
        { value: 'new1', text: 'New Option 1' },
        { value: 'new2', text: 'New Option 2' },
        { value: 'new3', text: 'New Option 3' }
    ];
    dynamicPicker.updateOptions(newOptions);
}

Theming

Built-in Themes

Default Theme

The default theme provides a clean, modern appearance with automatic light/dark mode support:

// Default theme (no configuration needed)
const picker = new Pickle('#my-select');

Features

  • Respects system color scheme preferences
  • Smooth transitions and animations
  • Focus indicators for accessibility
  • Hover and active states
  • Responsive design for mobile devices

Applying Themes

Set a theme during initialization or change it at runtime:

// Set theme during initialization
const picker = new Pickle('#my-select', {
    theme: 'modern'
});

// Change theme at runtime
picker.setTheme('compact');

Creating Custom Themes

Theme Structure

Themes are CSS classes that modify the appearance of Pickle components. Each theme class follows the pattern `pickle-select--theme-{name}`:

/* Custom theme: "modern" */
.pickle-select--theme-modern {
    /* Container styles */
}

.pickle-select--theme-modern .pickle-select__trigger {
    /* Trigger button styles */
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: none;
    color: white;
    border-radius: 8px;
}

.pickle-select--theme-modern .pickle-select__dropdown {
    /* Dropdown styles */
    border-radius: 8px;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}

.pickle-select--theme-modern .pickle-select__option {
    /* Option styles */
    padding: 12px 16px;
}

.pickle-select--theme-modern .pickle-select__option:hover {
    background: #667eea;
    color: white;
}

Theme Components

Key CSS classes you can style in your custom theme:

Class Element Description
.pickle-select Container Main wrapper element
.pickle-select__trigger Button Clickable trigger button
.pickle-select__value Span Selected value display
.pickle-select__arrow Span Dropdown arrow icon
.pickle-select__dropdown Div Dropdown container
.pickle-select__search Input Search input field
.pickle-select__option Div Individual option
.pickle-select__optgroup-label Div Option group label
.pickle-select__tag Span Multi-select value tag

State Modifiers

Style different states of the component:

/* State modifiers */
.pickle-select--theme-modern .pickle-select__trigger[aria-expanded="true"] {
    /* Open state */
    transform: scale(1.02);
}

.pickle-select--theme-modern .pickle-select__option--focused {
    /* Keyboard focused option */
    background: rgba(102, 126, 234, 0.1);
    outline: 2px solid #667eea;
}

.pickle-select--theme-modern .pickle-select__option--selected {
    /* Selected option */
    background: #667eea;
    color: white;
    font-weight: 600;
}

.pickle-select--theme-modern .pickle-select__option--disabled {
    /* Disabled option */
    opacity: 0.5;
    cursor: not-allowed;
}

.pickle-select--theme-modern.pickle-select--disabled {
    /* Disabled select */
    opacity: 0.6;
    pointer-events: none;
}

CSS Custom Properties

Available CSS Variables

The default theme uses CSS custom properties (variables) that you can override:

Variable Default Value Description
--pickle-bg-primary #ffffff Primary background color
--pickle-bg-secondary #f8fafc Secondary background color
--pickle-bg-hover #f1f5f9 Hover background color
--pickle-border-color #d1d5db Default border color
--pickle-border-focus #3b82f6 Focus border color
--pickle-text-primary #1f2937 Primary text color
--pickle-text-secondary #6b7280 Secondary text color
--pickle-border-radius 0.375rem Border radius
--pickle-transition all 0.15s cubic-bezier(0.4, 0, 0.2, 1) Transition timing

Customizing Variables

Override CSS variables to quickly customize the appearance:

/* Global customization */
:root {
    --pickle-border-radius: 12px;
    --pickle-border-focus: #10b981;
    --pickle-bg-hover: #ecfdf5;
}

/* Per-instance customization */
.my-custom-select {
    --pickle-bg-primary: #f3f4f6;
    --pickle-text-primary: #374151;
    --pickle-border-color: #d1d5db;
}

/* Dark theme override */
[data-theme="dark"] {
    --pickle-bg-primary: #1f2937;
    --pickle-bg-secondary: #374151;
    --pickle-text-primary: #f9fafb;
    --pickle-border-color: #4b5563;
}

Theme Examples

Minimal Theme

A clean, borderless design:

.pickle-select--theme-minimal .pickle-select__trigger {
    border: none;
    background: #f8fafc;
    border-radius: 0;
    border-bottom: 2px solid #e2e8f0;
    transition: border-color 0.2s ease;
}

.pickle-select--theme-minimal .pickle-select__trigger:focus {
    border-bottom-color: #3b82f6;
    box-shadow: none;
}

.pickle-select--theme-minimal .pickle-select__dropdown {
    border: none;
    border-radius: 0;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.pickle-select--theme-minimal .pickle-select__option {
    border-bottom: 1px solid #f1f5f9;
    padding: 16px;
}

.pickle-select--theme-minimal .pickle-select__option:last-child {
    border-bottom: none;
}

Rounded Theme

A playful theme with rounded corners:

.pickle-select--theme-rounded .pickle-select__trigger {
    border-radius: 25px;
    padding: 12px 20px;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: none;
    color: white;
}

.pickle-select--theme-rounded .pickle-select__dropdown {
    border-radius: 20px;
    border: none;
    overflow: hidden;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}

.pickle-select--theme-rounded .pickle-select__option {
    padding: 15px 20px;
    transition: all 0.2s ease;
}

.pickle-select--theme-rounded .pickle-select__option:hover {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    transform: translateX(5px);
}

.pickle-select--theme-rounded .pickle-select__search {
    border-radius: 20px 20px 0 0;
    background: #f8fafc;
    border: none;
    padding: 15px 20px;
}

Corporate Theme

A professional theme for business applications:

.pickle-select--theme-corporate {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.pickle-select--theme-corporate .pickle-select__trigger {
    background: white;
    border: 2px solid #0066cc;
    border-radius: 4px;
    color: #333;
    font-weight: 500;
    min-height: 44px;
}

.pickle-select--theme-corporate .pickle-select__trigger:focus {
    border-color: #004499;
    box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);
}

.pickle-select--theme-corporate .pickle-select__dropdown {
    border: 2px solid #0066cc;
    border-radius: 4px;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}

.pickle-select--theme-corporate .pickle-select__option {
    padding: 12px 16px;
    color: #333;
    font-weight: 500;
}

.pickle-select--theme-corporate .pickle-select__option:hover {
    background: #e6f3ff;
}

.pickle-select--theme-corporate .pickle-select__option--selected {
    background: #0066cc;
    color: white;
}

.pickle-select--theme-corporate .pickle-select__optgroup-label {
    background: #f5f5f5;
    color: #666;
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.8em;
    letter-spacing: 0.5px;
    padding: 8px 16px;
}

Accessibility

ARIA Support

Pickle implements comprehensive ARIA (Accessible Rich Internet Applications) support:

Roles and Attributes

  • role="combobox" - Applied to the trigger element
  • role="listbox" - Applied to the dropdown container
  • role="option" - Applied to each option element
  • aria-expanded - Indicates whether dropdown is open
  • aria-selected - Indicates selected options
  • aria-disabled - Indicates disabled options
  • aria-activedescendant - Tracks keyboard focus
  • aria-labelledby or aria-label - Accessible labeling

Screen Reader Support

Pickle includes a live region for announcing selection changes:

// Live announcements are automatic
const picker = new Pickle('#my-select', {
    l10n: {
        selected: 'Selected: {text}',
        selectionCleared: 'Selection cleared',
        multipleSelection: '{count} items selected'
    }
});

Keyboard Navigation

Full keyboard support for users who cannot use a mouse:

Key Action
Tab Focus the select trigger
Enter / Space Open dropdown or select focused option
Escape Close dropdown
/ Navigate between options
Home / End Jump to first/last option
A-Z Type-ahead search (when searchable)

Focus Management

Proper focus management ensures keyboard users can navigate efficiently:

  • Focus is trapped within the dropdown when open
  • Focus returns to trigger when dropdown closes
  • Currently focused option is clearly indicated
  • Focus follows keyboard navigation
  • Focus is managed when options are dynamically added/removed

High Contrast Support

Pickle supports high contrast mode preferences:

/* High contrast support built-in */
@media (prefers-contrast: high) {
    .pickle-select__trigger {
        border-width: 2px;
    }
    
    .pickle-select__option--focused {
        outline-width: 3px;
    }
}

Reduced Motion Support

Respects user preferences for reduced motion:

/* Animations disabled for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
    .pickle-select__trigger,
    .pickle-select__dropdown,
    .pickle-select__option,
    .pickle-select__arrow {
        transition: none;
    }
}

Performance

Virtual Scrolling

Pickle uses virtual scrolling to handle large datasets efficiently:

  • Only renders visible options in the DOM
  • Loads additional options as user scrolls
  • Maintains smooth performance with thousands of options
  • Configurable chunk size for rendering
// Virtual scrolling is automatic
// Handles large datasets efficiently
const largeDataPicker = new Pickle('#large-select', {
    searchable: true // Recommended for large datasets
});

// Options are rendered in chunks of 100 by default
// This ensures smooth scrolling performance

Memory Management

Proper cleanup prevents memory leaks:

  • Event listeners are properly removed on destroy
  • DOM references are cleared
  • Instance tracking prevents memory accumulation
// Always destroy instances when no longer needed
const picker = new Pickle('#temp-select');

// Later, when component is removed
picker.destroy();

// For SPAs, destroy on route change or component unmount
// React example:
useEffect(() => {
    const picker = new Pickle('#my-select');
    return () => picker.destroy(); // Cleanup
}, []);

Bundle Size

Pickle is designed to be lightweight:

  • Zero dependencies
  • Minified size: ~15KB JavaScript + ~8KB CSS
  • Gzipped size: ~5KB JavaScript + ~2KB CSS
  • ES modules for better tree shaking

Optimization Tips

  • Use search for large datasets: Enable search to help users find options quickly
  • Avoid frequent option updates: Batch option changes when possible
  • Destroy unused instances: Clean up instances in SPAs
  • Debounce search input: For external data sources, debounce search queries
  • Use CSS containment: Add contain: layout style to wrapper for better rendering performance

Troubleshooting

Common Issues

Dropdown doesn't appear

Possible causes:

  • CSS not loaded or path incorrect
  • Z-index conflicts with other elements
  • Parent container has overflow: hidden

Solutions:

/* Increase z-index if needed */
.pickle-select__dropdown {
    z-index: 9999 !important;
}

/* Ensure parent allows overflow */
.parent-container {
    overflow: visible;
}

Events not firing

Check:

  • Event listener is attached to correct element
  • Event name includes 'pickle:' prefix
  • Instance isn't destroyed before event fires
// Correct event listening
picker.wrapper.addEventListener('pickle:change', (event) => {
    console.log('Change event:', event.detail);
});

// Check if instance exists
if (picker && picker.wrapper) {
    // Safe to add listeners
}

Styling not applied

Verify:

  • CSS is loaded after Pickle CSS
  • Specificity is sufficient
  • Theme class is correctly applied

Search not working

Ensure:

  • Search is enabled: searchable: true
  • Options have text content to search
  • Search input is not being interfered with by other scripts

Debug Mode

Enable debug mode for detailed logging:

const picker = new Pickle('#my-select', {
    debug: true // Enables console logging
});

// Check instance state
console.log('Picker state:', {
    isOpen: picker.isOpen,
    isMultiple: picker.isMultiple,
    disabled: picker.disabled,
    selectedValues: picker.get()
});

// Check DOM elements
console.log('DOM elements:', {
    wrapper: picker.wrapper,
    trigger: picker.trigger,
    dropdown: picker.dropdown
});

Browser DevTools

Use browser developer tools to diagnose issues:

  • Elements tab: Inspect the generated DOM structure
  • Console tab: Check for JavaScript errors
  • Network tab: Verify CSS and JS files are loading
  • Accessibility tab: Test ARIA implementation

Useful Console Commands

// Get all Pickle instances
console.log('All instances:', Pickle.instances);

// Find instance by element
const element = document.getElementById('my-select');
const instance = Array.from(Pickle.instances)
    .find(p => p.originalSelect === element);

// Check computed styles
const trigger = document.querySelector('.pickle-select__trigger');
console.log('Computed styles:', getComputedStyle(trigger));

Getting Help

If you're still experiencing issues:

  • Check the examples: Compare your implementation with working examples
  • Review the API: Ensure you're using methods correctly
  • Check browser compatibility: Verify your target browsers are supported
  • Open an issue: Report bugs on the GitHub repository with a minimal reproduction case

Migration Guide

From Native Select

Migrating from native HTML select elements to Pickle is straightforward:

Before (Native Select)

<select id="my-select" onchange="handleChange(this.value)">
    <option value="">Choose...</option>
    <option value="opt1">Option 1</option>
    <option value="opt2">Option 2</option>
</select>

After (Pickle)

<select id="my-select">
    <option value="">Choose...</option>
    <option value="opt1">Option 1</option>
    <option value="opt2">Option 2</option>
</select>
// Replace inline onchange with Pickle
const picker = new Pickle('#my-select', {
    onChange: (value) => handleChange(value)
});

// Or use native change events (works with existing code)
document.getElementById('my-select').addEventListener('change', (e) => {
    handleChange(e.target.value);
});

From Other Libraries

From Select2

// Select2
$('#my-select').select2({
    placeholder: 'Choose an option',
    allowClear: true,
    width: '100%'
});

// Pickle equivalent
const picker = new Pickle('#my-select', {
    l10n: { placeholder: 'Choose an option' },
    width: '100%'
});
// Note: Clear functionality is built-in for empty value options

From Choices.js

// Choices.js
const choices = new Choices('#my-select', {
    searchEnabled: true,
    removeItemButton: true,
    placeholderValue: 'Choose options'
});

// Pickle equivalent
const picker = new Pickle('#my-select', {
    searchable: true,
    multiple: true, // For remove buttons on tags
    l10n: { placeholder: 'Choose options' }
});

Breaking Changes From 1.0.0

None. Public API remains unchanged from v1.0.0.