seo-select
v4.3.7
Published
Customizable, high-performance select dropdown Web Component with search, virtual scroll, multiple selection, i18n, and framework compatibility (React, Vue, Svelte, Angular, Qwik). Accessible, SSR-safe, and zero dependencies.
Maintainers
Keywords
Readme
SeoSelect
A lightweight and extensible select component built with pure Web Components (no dependencies), designed to work seamlessly across frameworks. Supports search, virtual scrolling, multiple selection, i18n, and flexible theming.
🌟 Support with a
GitHub star— your encouragement means the world to me!
Features
- 🎨 Multiple Themes: Basic, float themes with dark mode support
- 🌍 Internationalization: Built-in support for multiple languages (EN, KO, JA, ZH)
- 🔍 Search Functionality: Advanced multilingual search with fuzzy matching
- ♿ Accessibility: Full keyboard navigation and screen reader support
- 🚀 Virtual Scrolling: High performance with large datasets
- 📏 Auto Width: Automatic width calculation based on content
- 🎯 Multiple Selection: Tag-based multi-select with individual remove buttons
- 💡 Zero Dependencies: Built with native Web Components (no Lit, no external libraries) for minimal bundle size and maximum compatibility.
- ⚡ Modern Event System: Standard addEventListener with type-safe helpers
Why SeoSelect?
SeoSelect is designed to solve the real-world pain points of select components across modern web projects. Here’s how it stands out compared to popular alternatives:
| Feature | SeoSelect | react-select | headlessui | antd / prime | | ------------------ | ----------------------------- | ---------------- | -------------- | --------------- | | Framework Agnostic | ✅ Web Component | ❌ React only | ❌ React/Vue | ❌ Framework-bound | | Bundle Size | ✅ Ultra-small (0 deps) | ❌ Large (~700KB+) | △ | ❌ Large | | Dependencies | ✅ Zero | ❌ Many | △ | ❌ Many | | Virtual Scroll | ✅ Built-in | ❌ Extra setup | ❌ None | △ Limited | | Multilingual Search| ✅ Korean/JP/Chinese support | ❌ None | ❌ None | ❌ None | | Search Accuracy | ✅ Fuzzy + Multilingual | △ Simple filter | ❌ | △ | | Keyboard Access | ✅ Full support | △ | △ | △ | | Type Safety | ✅ Global type extension | △ | △ | ❌ Complex | | Event Design | ✅ Standard + type helpers | ❌ React props | ❌ | ❌ | | Multi-Framework | ✅ React/Vue/Angular/Qwik/Solid| ❌ | ❌ | ❌ | | Customization | ✅ CSS Variables | △ | △ | ❌ Theme-locked | | SSR Safe | ✅ | ❌ | △ | ❌ |
Why choose SeoSelect?
- Framework Independence: Use anywhere—React, Vue, Angular, Svelte, Qwik, or plain HTML. No lock-in.
- Tiny & Dependency-Free: No runtime dependencies, minimal bundle size, and lightning-fast load times.
- Advanced Search: Out-of-the-box support for Korean initial consonant, Japanese romaji, and Chinese pinyin search. Fuzzy matching for all languages.
- Virtual Scrolling: Handles thousands of options smoothly without extra setup.
- Accessibility: Full keyboard navigation and screen reader support.
- TypeScript First: Global type extensions for safe, ergonomic event handling in any environment.
- Customizable: Style every aspect with CSS variables—no theme lock-in.
- SSR Safe: Works seamlessly in SSR (Next.js, Nuxt, SvelteKit, etc.) and browser environments.
- Modern Event System: Standard
addEventListenerwith type-safe helpers for best DX.
SeoSelect is the only select component you need for modern, scalable, and framework-agnostic web apps.
Installation
For Modern Bundlers (Recommended)
npm install seo-select// Import basic select component
import 'seo-select';
// Import search-enabled select component
import 'seo-select/components/seo-select-search';
// Import Style
import 'seo-select/styles'
// Import Types
import 'seo-select/types';For Direct Browser Usage
<!-- Import both JavaScript and CSS files -->
<link rel="stylesheet" href="./min/index.css">
<script type="module" src="./min/index.js"></script>Alternative: Download pre-built files from GitHub Releases
Components Overview
seo-select - Basic Select Component
Standard dropdown functionality with virtual scrolling, multiple selection, themes, and form integration.
seo-select-search - Search-Enhanced Select Component
Extended component with real-time multilingual search including Korean initial consonant search (ㅎㄱㅇ → 한국어), Japanese romaji search (nihongo → 日本語), and Chinese pinyin search (beijing → 北京).
Basic Usage Examples
Simple Select
<!DOCTYPE html>
<html>
<head>
<script type="module">
import 'seo-select';
</script>
</head>
<body>
<seo-select name="country" required>
<option value="us">United States</option>
<option value="kr">South Korea</option>
<option value="jp">Japan</option>
</seo-select>
</body>
</html>Search-enabled Select
<script type="module">
import 'seo-select/components/seo-select-search';
</script>
<seo-select-search
name="city"
theme="float"
language="en"
show-reset>
<option value="seoul">Seoul</option>
<option value="tokyo">Tokyo</option>
<option value="beijing">Beijing</option>
</seo-select-search>Multiple Selection
<seo-select-search
multiple
name="skills"
theme="float"
show-reset>
<option value="js">JavaScript</option>
<option value="ts">TypeScript</option>
<option value="python">Python</option>
</seo-select-search>Event System
Standard addEventListener (Recommended)
// Works in any framework — listen to custom events emitted by the component.
// All event payloads are provided in `event.detail`.
searchSelect.addEventListener('onSelect', (event: CustomEvent<{ label: string; value: string }>) => {
console.log('Selected:', event.detail.label, event.detail.value);
});
searchSelect.addEventListener('onDeselect', (event: CustomEvent<{ label: string; value: string }>) => {
console.log('Deselected:', event.detail.label, event.detail.value);
});
searchSelect.addEventListener(
'onReset',
( event: CustomEvent<{ value: string; label: string } | { values: string[]; labels: string[] } >) => {
if ('values' in event.detail) {
console.log('Reset multiple:', event.detail.values, event.detail.labels);
} else {
console.log('Reset single:', event.detail.value, event.detail.label);
}
}
);
searchSelect.addEventListener('onChange', () => {
console.log('Value changed');
});
searchSelect.addEventListener('onOpen', (event: CustomEvent<{ selectInstance?: any }>) => {
console.log('Dropdown opened', event.detail);
});
// Search-specific events (seo-select-search only)
searchSelect.addEventListener(
'onSearchChange',
( event: CustomEvent<{ searchText: string } | { searchText: string; previousSearchText: string } > ) => {
console.log('Search text changed:', event.detail.searchText);
}
);
searchSelect.addEventListener(
'onSearchFilter',
(
event: CustomEvent<{
filteredOptions: VirtualSelectOption[];
searchText: string;
hasResults: boolean;
}>
) => {
console.log(
`Search filtered: ${event.detail.filteredOptions.length} results for "${event.detail.searchText}"`
);
}
);Type-Safe Helper Methods (Built-in)
// These helper methods wrap `addEventListener` for better DX (Developer Experience).
// They provide typed callbacks and cleaner syntax.
searchSelect.onSelect(({ label, value }) => {
console.log('Selected:', label, value);
});
searchSelect.onDeselect(({ label, value }) => {
console.log('Deselected:', label, value);
});
searchSelect.onReset((detail) => {
console.log('Reset event:', detail);
});
searchSelect.onChange(() => {
console.log('Value changed');
});
searchSelect.onOpen(() => {
console.log('Dropdown opened');
});
// Search-specific helpers
searchSelect.onSearchChange((searchText) => {
console.log('Search text changed:', searchText);
});
searchSelect.onSearchFilter((filteredOptions) => {
console.log('Filtered results count:', filteredOptions.length);
});
JavaScript/TypeScript Usage
import 'seo-select/components/seo-select-search';
// Create the element programmatically
const select = document.createElement('seo-select-search');
select.optionItems = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' }
];
select.multiple = true;
select.theme = 'float';
select.language = 'ko';
// Append to the DOM
document.body.appendChild(select);
// Handle events using addEventListener
select.addEventListener('onSelect', (event: CustomEvent<{ label: string; value: string }>) => {
console.log('Selected:', event.detail.label, event.detail.value);
});
// Or use the built-in helper methods
select.onSelect(({ label, value }) => {
console.log('Selected:', label, value);
});Events Reference
Common Events (Both Components)
| Event Name | Properties | Description |
|------------|------------|-------------|
| onSelect | { label, value } | User selects an option |
| onDeselect | { label, value } | User removes selected option (multiple mode) |
| onChange | - | Form value changes |
| onReset | { value, label } or { values, labels } | Component resets to default |
| onOpen | - | Dropdown opens |
Search Component Additional Events (SeoSelectSearch Only)
| Event Name | Properties | Description |
|------------|------------|-------------|
| onSearchChange | searchText: string | Search text changes in real-time |
| onSearchFilter | filteredOptions: VirtualSelectOption[] | Search results are filtered |
Component Properties
Common Properties
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| name | string | - | Form field name |
| required | boolean | false | Whether the field is required |
| multiple | boolean | false | Enable multiple selection |
| theme | 'basic' \| 'float' | 'float' | Visual theme |
| dark | boolean | false | Enable dark mode |
| language | 'en' \| 'ko' \| 'ja' \| 'zh' | 'en' | Interface language |
| showReset | boolean | true | Show reset button |
| width | string | null | Custom width (auto-calculated if not set) |
SeoSelectSearch Additional Properties
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| searchTexts | Partial<SearchLocalizedTexts> | {} | Custom search-related texts |
Methods
SeoSelect (Basic Component)
The basic seo-select component provides fundamental option management and value control methods:
Value Management
// Get/Set single value
const currentValue = select.value;
select.value = 'option1';
// Get/Set multiple values (when multiple=true)
const selectedValues = select.selectedValues; // ['opt1', 'opt2']
select.selectedValues = ['opt1', 'opt3'];
// Reset to default value
select.resetToDefaultValue();Dynamic Option Management
// Add multiple options at once (replaces existing options)
select.addOptions([
{ value: 'opt1', label: 'Option 1' },
{ value: 'opt2', label: 'Option 2' }
], preserveSelection); // preserveSelection: boolean (default: false)
// Add a single option
select.addOption({ value: 'new', label: 'New Option' }, index); // index: optional position
// Remove a specific option by value
select.clearOption('option-value-to-remove');
// Remove all options
select.clearAllOptions();
// Batch update operations (highly optimized for performance)
select.batchUpdateOptions([
{ action: 'add', option: { value: 'new1', label: 'New 1' } },
{ action: 'remove', value: 'old-option' },
{ action: 'update', value: 'existing', option: { value: 'existing', label: 'Updated Label' } }
]);Customization Methods
// Change language dynamically
select.setLanguage('ko'); // 'en' | 'ko' | 'ja' | 'zh'
// Set custom localized texts
select.setTexts({
placeholder: 'Custom placeholder...',
required: 'This field is required',
resetToDefault: 'Reset selection'
});
// Enable/disable auto-width calculation
select.setAutoWidth(true);
// Clear internal caches (useful for memory optimization)
select.clearCaches();Event Management (Type-Safe Helpers)
// Basic events (always available)
select.onSelect((event) => {
console.log('Selected:', event.label, event.value);
});
select.onDeselect((event) => {
console.log('Deselected:', event.label, event.value);
});
select.onReset((event) => {
if (select.multiple) {
console.log('Reset multiple:', event.values, event.labels);
} else {
console.log('Reset single:', event.value, event.label);
}
});
select.onChange(() => {
console.log('Form value changed');
});
select.onOpen(() => {
console.log('Dropdown opened');
});Utility Methods
// Get current option count
const optionCount = select.options.length;
// Get selected index (single mode only)
const selectedIndex = select.selectedIndex;
// Get default value
const defaultValue = select.defaultValue;
// Check if component has options
const hasOptions = !select.hasNoOptions();SeoSelectSearch (Search-Enhanced Component)
The seo-select-search component extends the basic component with advanced search functionality:
Search-Specific Methods
// ► Practical example: Auto-focus search when dropdown opens
searchSelect.onOpen(() => {
// Set initial search text to help users
searchSelect.searchText = 'Seoul';
// Or clear previous search and let user type fresh
searchSelect.clearSearchText();
});
// ► Advanced example: Set search based on previous selection
let lastSelected = '';
searchSelect.onSelect((event) => {
lastSelected = event.value;
});
searchSelect.onOpen(() => {
if (lastSelected.startsWith('kr')) {
searchSelect.searchText = 'Korean';
}
});Advanced Option Management
// Update options while preserving search state
searchSelect.updateOptionsWithSearch([
{ value: 'opt1', label: 'Searchable Option 1' },
{ value: 'opt2', label: 'Searchable Option 2' }
], preserveSearch); // preserveSearch: boolean (default: true)
// Load options dynamically based on search
await searchSelect.loadOptionsForSearch('search term', async (searchText) => {
// Custom async function to load options
const response = await fetch(`/api/search?q=${searchText}`);
return await response.json();
});Search Event Handling
// Listen to search text changes
searchSelect.onSearchChange((searchText) => {
console.log('User typed:', searchText);
// Trigger API calls, analytics, etc.
});
// Listen to search filter events
searchSelect.onSearchFilter((filteredOptions) => {
console.log(`Found ${filteredOptions.length} results`);
// Update UI indicators, show result counts, etc.
});Custom Search Texts
// Set search-specific localized texts
searchSelect.setSearchTexts({
searchPlaceholder: 'Type to search...',
noMatchText: 'No results found'
});Inherited Methods
The seo-select-search component inherits all methods from the basic seo-select component, so you can use all the value management, option management, and customization methods mentioned above.
Performance Considerations
// For large datasets, use batch operations
searchSelect.batchUpdateOptions(largeUpdateArray);
// Clear caches when dealing with frequent option updates
searchSelect.clearCaches();
// Use preserveSelection for better UX when updating options
searchSelect.addOptions(newOptions, true); // Preserves current selectionFramework Wrappers
seo-select provides official wrapper components for major frameworks. Each wrapper offers native-feeling APIs with proper event handling and TypeScript support.
Supported Frameworks
| Framework | Import Path | Version |
|-----------|-------------|---------|
| React | seo-select/react | >= 17.0.0 |
| Vue | seo-select/vue | >= 3.0.0 |
| Angular | seo-select/angular | >= 14.0.0 |
| Solid.js | seo-select/solid | >= 1.0.0 |
| Qwik | seo-select/qwik | >= 1.0.0 |
All framework dependencies are optional peer dependencies - only install what you need!
React
import { SeoSelect, SeoSelectSearch } from 'seo-select/react';
import 'seo-select/styles';
export default function MyComponent() {
const options = [
{ value: 'react', label: 'React' },
{ value: 'nextjs', label: 'Next.js' },
{ value: 'remix', label: 'Remix' }
];
return (
<SeoSelect
name="framework"
theme="float"
language="ko"
optionItems={options}
onSelect={(e) => console.log('Selected:', e.detail)}
onReset={(e) => console.log('Reset:', e.detail)}
/>
);
}With Search
import { SeoSelectSearch, type SeoSelectRef } from 'seo-select/react';
import { useRef } from 'react';
export default function SearchExample() {
const selectRef = useRef<SeoSelectRef>(null);
const handleReset = () => {
selectRef.current?.reset();
};
return (
<>
<SeoSelectSearch
ref={selectRef}
name="city"
multiple
showReset
optionItems={[
{ value: 'seoul', label: 'Seoul' },
{ value: 'tokyo', label: 'Tokyo' },
{ value: 'beijing', label: 'Beijing' }
]}
onSelect={(e) => console.log('Selected:', e.detail)}
onSearchChange={(e) => console.log('Search:', e.detail.searchText)}
/>
<button onClick={handleReset}>Reset</button>
</>
);
}Vue 3
<script setup lang="ts">
import { SeoSelect, SeoSelectSearch } from 'seo-select/vue';
import 'seo-select/styles';
const options = [
{ value: 'vue', label: 'Vue 3' },
{ value: 'nuxt', label: 'Nuxt 3' },
{ value: 'vite', label: 'Vite' }
];
const handleSelect = (detail: { label: string; value: string }) => {
console.log('Selected:', detail);
};
</script>
<template>
<SeoSelect
name="framework"
theme="float"
:optionItems="options"
@select="handleSelect"
/>
</template>With Search and Multiple Selection
<script setup lang="ts">
import { ref } from 'vue';
import { SeoSelectSearch } from 'seo-select/vue';
const selectRef = ref();
const handleReset = () => {
selectRef.value?.reset();
};
</script>
<template>
<SeoSelectSearch
ref="selectRef"
name="city"
multiple
showReset
:optionItems="[
{ value: 'seoul', label: 'Seoul' },
{ value: 'tokyo', label: 'Tokyo' }
]"
@select="(detail) => console.log('Selected:', detail)"
@searchChange="(detail) => console.log('Search:', detail.searchText)"
/>
<button @click="handleReset">Reset</button>
</template>Angular
import { Component } from '@angular/core';
import { SeoSelectComponent, SeoSelectSearchComponent } from 'seo-select/angular';
import 'seo-select/styles';
@Component({
selector: 'app-select-demo',
standalone: true,
imports: [SeoSelectComponent, SeoSelectSearchComponent],
template: `
<app-seo-select
name="framework"
theme="float"
[optionItems]="options"
(selectEvent)="onSelect($event)"
(resetEvent)="onReset($event)"
/>
`
})
export class SelectDemoComponent {
options = [
{ value: 'angular', label: 'Angular' },
{ value: 'ionic', label: 'Ionic' },
{ value: 'ngrx', label: 'NgRx' }
];
onSelect(detail: { label: string; value: string }) {
console.log('Selected:', detail);
}
onReset(detail: any) {
console.log('Reset:', detail);
}
}With Search
@Component({
selector: 'app-search-demo',
standalone: true,
imports: [SeoSelectSearchComponent],
template: `
<app-seo-select-search
name="city"
[multiple]="true"
[showReset]="true"
[optionItems]="options"
(selectEvent)="onSelect($event)"
(searchChangeEvent)="onSearchChange($event)"
/>
`
})
export class SearchDemoComponent {
options = [
{ value: 'seoul', label: 'Seoul' },
{ value: 'tokyo', label: 'Tokyo' }
];
onSelect(detail: { label: string; value: string }) {
console.log('Selected:', detail);
}
onSearchChange(detail: { searchText: string }) {
console.log('Search:', detail.searchText);
}
}Solid.js
import { SeoSelect, SeoSelectSearch } from 'seo-select/solid';
import 'seo-select/styles';
export default function MyComponent() {
const options = [
{ value: 'solid', label: 'Solid.js' },
{ value: 'start', label: 'SolidStart' }
];
return (
<SeoSelect
name="framework"
theme="float"
optionItems={options}
onSelect={(e) => console.log('Selected:', e.detail)}
/>
);
}With Ref
import { SeoSelectSearch } from 'seo-select/solid';
export default function SearchExample() {
let selectEl: HTMLElement | undefined;
const handleReset = () => {
(selectEl as any)?.reset?.();
};
return (
<>
<SeoSelectSearch
ref={(el) => { selectEl = el; }}
name="city"
multiple
optionItems={[
{ value: 'seoul', label: 'Seoul' },
{ value: 'tokyo', label: 'Tokyo' }
]}
onSelect={(e) => console.log('Selected:', e.detail)}
onSearchChange={(e) => console.log('Search:', e.detail.searchText)}
/>
<button onClick={handleReset}>Reset</button>
</>
);
}Qwik
import { component$ } from '@builder.io/qwik';
import { SeoSelect, SeoSelectSearch } from 'seo-select/qwik';
import 'seo-select/styles';
export const SelectDemo = component$(() => {
const options = [
{ value: 'qwik', label: 'Qwik' },
{ value: 'qwikcity', label: 'QwikCity' }
];
return (
<SeoSelect
name="framework"
theme="float"
optionItems={options}
onSelect$={(e) => console.log('Selected:', e.detail)}
/>
);
});With Search
import { component$ } from '@builder.io/qwik';
import { SeoSelectSearch } from 'seo-select/qwik';
export const SearchDemo = component$(() => {
return (
<SeoSelectSearch
name="city"
multiple
showReset
optionItems={[
{ value: 'seoul', label: 'Seoul' },
{ value: 'tokyo', label: 'Tokyo' }
]}
onSelect$={(e) => console.log('Selected:', e.detail)}
onSearchChange$={(e) => console.log('Search:', e.detail.searchText)}
/>
);
});Vanilla JavaScript / Web Component
For vanilla JavaScript or other frameworks, use the web component directly:
import 'seo-select/types';
import 'seo-select/styles';
import 'seo-select/components/seo-select-search';
const select = document.createElement('seo-select-search');
select.optionItems = [
{ value: 'vanilla', label: 'Vanilla JS' },
{ value: 'typescript', label: 'TypeScript' }
];
select.theme = 'float';
select.multiple = true;
select.addEventListener('onSelect', (event) => {
console.log('Selected:', event.detail);
});
document.body.appendChild(select);TypeScript Support
Type Definitions
For TypeScript projects, import the type definitions to enable full type safety and IntelliSense support for custom events and component APIs:
// Import type definitions (add this once in your project)
import 'seo-select/types';
// Import components
import 'seo-select';
import 'seo-select/components/seo-select-search';That's it! With just import 'seo-select/types';, you get:
- ✅ Full type safety for all event listeners (
addEventListener) - ✅ IntelliSense support for event properties (
event.label,event.value) - ✅ Global type extensions for
HTMLElementEventMap - ✅ Zero configuration - works immediately
Basic Usage with Type Safety
import 'seo-select/types';
import 'seo-select';
const select = document.createElement('seo-select');
// All event listeners are now fully type-safe
select.addEventListener('onSelect', (event) => {
// TypeScript knows event.label and event.value exist
console.log('Selected:', event.label, event.value);
});
select.addEventListener('onReset', (event) => {
// TypeScript automatically infers the correct event type
if (event.values) {
console.log('Multiple reset:', event.values, event.labels);
} else {
console.log('Single reset:', event.value, event.label);
}
});Advanced Usage with Specific Types
When you need specific types for your application logic, import them explicitly:
import 'seo-select/types';
import type {
VirtualSelectOption,
SeoSelectElement,
SeoSelectSearchElement,
SupportedLanguage,
BatchUpdateOption
} from 'seo-select/types';
// Type-safe option creation
const options: VirtualSelectOption[] = [
{ value: 'us', label: 'United States' },
{ value: 'kr', label: 'South Korea' }
];
// Type-safe element creation
const selectElement = document.createElement('seo-select') as SeoSelectElement;
selectElement.optionItems = options;
selectElement.language = 'ko' as SupportedLanguage;
// Type-safe batch operations
const updates: BatchUpdateOption[] = [
{ action: 'add', option: { value: 'jp', label: 'Japan' } },
{ action: 'remove', value: 'us' }
];
selectElement.batchUpdateOptions(updates);Available Types
| Category | Types |
|----------|-------|
| Component Elements | SeoSelectElement, SeoSelectSearchElement |
| Options & Data | VirtualSelectOption, OptionItem, BatchUpdateOption |
| Configuration | SupportedLanguage, SelectTheme, LocalizedTexts, SearchLocalizedTexts |
| Component Props | SeoSelectProps, SeoSelectSearchProps |
| Events | ResetEventData, SeoSelectEventType, SeoSelectEvents |
Event Constants
import { SeoSelectEvents } from 'seo-select/types';
// Use event constants for consistency
select.addEventListener(SeoSelectEvents.SELECT, (event) => {
console.log('Selected:', event.label);
});
select.addEventListener(SeoSelectEvents.SEARCH_CHANGE, (event) => {
console.log('Search text:', event.detail);
});Styling and Customization
Quick Styling Example
seo-select {
--select-border-color: #ccc;
--select-focus-color: #007bff;
--select-background: white;
--select-text-color: #333;
}
/* Dark mode */
seo-select[dark] {
--select-background: #374151;
--select-text-color: #f3f4f6;
--select-border-color: #6b7280;
}Complete CSS Variables Reference
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --select-padding | 0.5rem 0.8rem | Internal padding of select box |
| --select-min-height | 35px | Minimum height of select component |
| --select-min-width | 150px | Minimum width of select component |
| --select-border-width | 1px | Border thickness |
| --select-transition-duration | 0.3s | Animation transition duration |
| --select-transition-easing | ease | Animation easing function |
| --select-font-size | 12px | Font size of select text |
| --select-font-color | #1f1b25 | Font color of select text |
Basic Theme:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --select-basic-border-radius | 0 | Border radius for basic theme |
| --select-basic-box-shadow | none | Box shadow for basic theme |
| --select-basic-margin-bottom | 0 | Bottom margin for basic theme |
Float Theme:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --select-float-border-radius | 5px | Border radius for float theme |
| --select-float-box-shadow | 0 2px 4px rgba(0, 0, 0, 0.1) | Box shadow for float theme |
| --select-float-margin-bottom | 0 | Bottom margin for float theme |
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --select-multi-padding-right | 3rem | Right padding for multiple selection |
| --select-tags-gap | 0.25rem | Gap between tags in multiple mode |
| --select-tags-padding | 0.25rem 0 | Padding around tags container |
| --select-tags-min-height | 1.5rem | Minimum height of tags area |
| --tag-padding | 0.2rem 0.3rem | Internal padding of tags |
| --tag-gap | 0.5rem | Gap between individual tags |
| --tag-border-radius | 25rem | Border radius of tags (pill shape) |
| --tag-border-width | 1px | Border thickness of tags |
| --tag-remove-size | 1rem | Size of tag remove button |
| --tag-remove-border-radius | 50% | Border radius of remove button |
| --tag-remove-transition | all 0.2s ease | Transition for remove button |
Basic Dropdown:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dropdown-box-shadow | 0 5px 10px rgba(0, 0, 0, 0.1) | Box shadow of dropdown |
| --dropdown-border-width | 1px | Border thickness of dropdown |
| --dropdown-z-index | 1000 | Z-index stacking order |
| --dropdown-basic-border-radius | 0 | Border radius for basic theme dropdown |
Float Theme Dropdown:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dropdown-float-border-radius | 5px | Border radius for float theme dropdown |
| --dropdown-float-box-shadow | 0 8px 16px rgba(0, 0, 0, 0.15) | Enhanced shadow for float theme |
| --dropdown-float-top | 130% | Dropdown position from select box |
| --dropdown-float-animation-duration | 0.2s | Animation duration for float theme |
| --dropdown-float-animation-easing | ease-out | Animation easing for float theme |
| --dropdown-float-slide-distance | -20px | Slide distance for animation |
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --search-input-padding | 0.3rem | Internal padding of search input |
| --search-input-text-indent | 1.5rem | Text indentation for search icon space |
| --search-icon-left | 0.7rem | Left position of search icon |
| --search-icon-size | 1rem | Size of search icon |
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --loading-container-padding | 1rem 2rem | Padding around loading container |
| --loading-dots-gap | 0.5rem | Gap between loading dots |
| --loading-dots-margin-bottom | 1rem | Bottom margin of dots container |
| --loading-dot-size | 0.5rem | Size of individual loading dots |
| --loading-animation-duration | 1.4s | Duration of loading animation |
| --loading-text-font-size | 0.9rem | Font size of loading text |
| --loading-dot-delay-1 | -0.32s | Animation delay for first dot |
| --loading-dot-delay-2 | -0.16s | Animation delay for second dot |
| --loading-dot-delay-3 | 0s | Animation delay for third dot |
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --no-data-container-padding | 1rem 2rem | Padding of "no data" container |
| --no-data-text-font-size | 0.9rem | Font size of "no data" text |
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --option-padding | 0 0.8rem | Internal padding of option items |
| --option-line-height | 300% | Line height of option items |
| --option-check-mark-margin | 0.5rem | Margin of checkmark in options |
Single Select Reset:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --reset-button-right | 3rem | Right position of reset button |
| --reset-button-padding | 0 0.5rem | Internal padding of reset button |
| --reset-button-height | 80% | Height of reset button |
| --reset-button-font-size | 0.9rem | Font size of reset button |
| --reset-button-transition | all 0.2s ease | Transition for reset button |
Multiple Select Reset:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --multi-reset-button-size | 1.5rem | Size of multi-select reset button |
| --multi-reset-button-position | -0.6rem | Position adjustment for multi reset |
| --multi-reset-button-border-radius | 50% | Border radius of multi reset button |
| --multi-reset-button-font-size | 0.9rem | Font size of multi reset button |
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --arrow-right | 0.8rem | Right position of dropdown arrow |
| --arrow-font-size | 0.9rem | Font size of dropdown arrow |
| --arrow-margin-top | -0.1rem | Top margin adjustment for arrow |
| --arrow-transition | transform 0.2s ease | Transition for arrow rotation |
Primary Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --primary-color | #3253de | Main brand color |
| --primary-hover | #003766 | Primary color on hover state |
| --primary-bg-color | #e5f1fbf2 | Primary background color |
| --secondary-color | #5f77ca | Secondary brand color |
| --secondary-hover | #303c65f2 | Secondary color on hover state |
| --secondary-bg-color | #eff1faf2 | Secondary background color |
Semantic State Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --success-color | pick(green, 5) | Success state color |
| --success-hover | pick(green, 6) | Success color on hover |
| --success-bg-color | pick(green, 0) | Success background color |
| --error-color | pick(red, 5) | Error state color |
| --error-hover | pick(red, 6) | Error color on hover |
| --error-bg-color | color.mix(#fff, pick(red, 1), 25%) | Error background color |
| --warning-color | pick(orange, 4) | Warning state color |
| --warning-hover | pick(orange, 5) | Warning color on hover |
| --warning-bg-color | color.mix(#fff, pick(orange, 1), 25%) | Warning background color |
| --disabled-color | color.adjust(pick(gray, 3), $lightness: 5%) | Disabled element color |
Typography Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --font-color | color.mix(#000, pick(indigo, 10), 70%) | Primary text color |
| --font-secondary-color | pick(gray, 5) | Secondary text color |
UI Element Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --border-color | pick(gray, 3) | Default border color |
| --box-head-border-color | color.mix(#fff, pick(gray, 2), 35%) | Box header border color |
Extended Color Palette (Open Color System): The component uses a sophisticated color system based on Open Color with primary color mixing:
| Color Name | Usage | Available Shades |
|------------|-------|------------------|
| gray | Neutral elements, borders, backgrounds | 0-10 (lightest to darkest) |
| red | Error states, destructive actions | 0-10 |
| pink | Accent colors, highlights | 0-10 |
| grape | Decorative elements | 0-10 |
| violet | Special highlights | 0-10 |
| indigo | Primary variants | 0-10 |
| blue | Information states, links | 0-10 |
| cyan | Cool accents | 0-10 |
| teal | Fresh accents | 0-10 |
| green | Success states, positive actions | 0-10 |
| lime | Fresh highlights | 0-10 |
| yellow | Warning states, attention | 0-10 |
| orange | Warning states, alerts | 0-10 |
Using the Color System:
// Access colors using the pick() function
.my-element {
background-color: pick(blue, 2); // Light blue
border-color: pick(blue, 5); // Medium blue
color: pick(blue, 8); // Dark blue
}Background Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-select-bg | #374151 | Background color in dark mode |
| --dark-dropdown-bg | #374151 | Dropdown background in dark mode |
| --dark-tag-bg | #4b5563 | Tag background in dark mode |
| --dark-search-input-bg | #374151 | Search input background in dark mode |
| --dark-accent-bg | #1f2937 | Darker background for special elements |
| --dark-card-bg | #374151 | Card/container background |
| --dark-surface-bg | #4b5563 | Surface element background |
Border Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-border-color | #6b7280 | Border color in dark mode |
| --dark-border-hover-color | #60a5fa | Border color on hover in dark mode |
| --dark-border-focus-color | #60a5fa | Border color on focus in dark mode |
Text Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-text-color | #f3f4f6 | Primary text color in dark mode |
| --dark-text-secondary-color | #d1d5db | Secondary text color in dark mode |
| --dark-placeholder-color | #9ca3af | Placeholder color in dark mode |
| --dark-highlight-color | #fbbf24 | Highlight/accent color in dark mode |
Dark Mode State Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-success-color | #10b981 | Success state color in dark mode |
| --dark-warning-color | #f59e0b | Warning state color in dark mode |
| --dark-error-color | #ef4444 | Error state color in dark mode |
| --dark-info-color | #3b82f6 | Information state color in dark mode |
Option Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-option-hover-bg | #4b5563 | Option background on hover |
| --dark-option-selected-bg | #3b82f6 | Selected option background |
| --dark-option-focused-bg | #4b5563 | Focused option background |
| --dark-option-disabled-color | #9ca3af | Disabled option text color |
Tag Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-tag-text-color | #f3f4f6 | Tag text color in dark mode |
| --dark-tag-border-color | #60a5fa | Tag border color in dark mode |
| --dark-tag-remove-hover-bg | #ef4444 | Tag remove button hover background |
Button Colors:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-reset-button-color | #d1d5db | Reset button color in dark mode |
| --dark-reset-button-hover-color | #ef4444 | Reset button hover color |
| --dark-multi-reset-button-bg | #6b7280 | Multi reset button background |
Shadow Effects:
| Variable | Default Value | Description |
|----------|---------------|-------------|
| --dark-float-box-shadow | 0 4px 6px rgba(0, 0, 0, 0.4), 0 2px 4px rgba(0, 0, 0, 0.2) | Float theme shadow in dark mode |
| --dark-dropdown-box-shadow | 0 10px 20px rgba(0, 0, 0, 0.5), 0 4px 8px rgba(0, 0, 0, 0.3) | Dropdown shadow in dark mode |
| --dark-search-input-focus-shadow | 0 0 0 2px rgba(96, 165, 250, 0.3), 0 4px 12px rgba(0, 0, 0, 0.3) | Search input focus shadow |
License
MIT License - see LICENSE file for details.
