Skip to content

ComboBox Component Demo

This page demonstrates the ComboBox component with various configurations and examples.

Basic ComboBox

A simple combobox where users can select from options or type their own value.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedValue"
    :items="items"
    placeholder="Select or type your own..."
  />
</template>

<script setup>
import { ref } from 'vue';

const selectedValue = ref(null);
const items = ref([
  { text: 'Apple', value: 'apple' },
  { text: 'Banana', value: 'banana' },
  { text: 'Cherry', value: 'cherry' },
  { text: 'Date', value: 'date' },
  { text: 'Elderberry', value: 'elderberry' },
]);
</script>

Demo

Selected: None

💡 Tip: Type anything and press Enter or click outside to create a custom value

Tag Input (Multiple Selection)

Create custom tags or select from suggestions.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedTags"
    :items="suggestions"
    :multiple="true"
    placeholder="Type tags and press Enter..."
  />
</template>

<script setup>
import { ref } from 'vue';

const selectedTags = ref([]);
const suggestions = ref([
  { text: 'JavaScript', value: 'js' },
  { text: 'TypeScript', value: 'ts' },
  { text: 'Python', value: 'py' },
  { text: 'Java', value: 'java' },
  { text: 'C++', value: 'cpp' },
]);
</script>

Demo

Selected: None

💡 Tip: Type any text and press Enter to create custom tags

Email Address Input

Perfect for email input with suggestions and custom entries.

Code Example

vue
<template>
  <OComboBox
    v-model="emails"
    :items="suggestions"
    :multiple="true"
    placeholder="Type email addresses..."
  />
</template>

<script setup>
import { ref } from 'vue';

const emails = ref([]);
const suggestions = ref([
  { text: 'john@example.com', value: 'john@example.com' },
  { text: 'jane@example.com', value: 'jane@example.com' },
  { text: 'bob@example.com', value: 'bob@example.com' },
]);
</script>

Demo

Emails: None

Create Event Handling

Track when custom items are created.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedValues"
    :items="items"
    :multiple="true"
    placeholder="Add colors..."
    @create="handleCreate"
  />
  
  <div v-if="createdItems.length > 0">
    <h4>Recently Created:</h4>
    <ul>
      <li v-for="(created, index) in createdItems" :key="index">
        {{ created.value }} at {{ created.timestamp }}
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const selectedValues = ref([]);
const items = ref([
  { text: 'Red', value: 'red' },
  { text: 'Blue', value: 'blue' },
  { text: 'Green', value: 'green' },
]);
const createdItems = ref([]);

const handleCreate = (item, value) => {
  createdItems.value.push({ 
    item, 
    value, 
    timestamp: new Date().toLocaleTimeString() 
  });
};
</script>

Demo

Selected: None

Clearable Input

ComboBox with a clear button.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedValue"
    :items="items"
    :clearable="true"
    placeholder="Select or type..."
  />
</template>

<script setup>
import { ref } from 'vue';

const selectedValue = ref('custom-value');
const items = ref([
  { text: 'Option 1', value: 'opt1' },
  { text: 'Option 2', value: 'opt2' },
  { text: 'Option 3', value: 'opt3' },
]);
</script>

Demo

Selected: custom-value

Selected Items on Top

Keep chosen options at the top of the list.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedFrameworks"
    :items="frameworks"
    :multiple="true"
    :selected-on-top="true"
    placeholder="Select frameworks..."
  />
</template>

<script setup>
import { ref } from 'vue';

const selectedFrameworks = ref(['vue', 'react']);
const frameworks = ref([
  { text: 'React', value: 'react' },
  { text: 'Vue', value: 'vue' },
  { text: 'Angular', value: 'angular' },
  { text: 'Svelte', value: 'svelte' },
  { text: 'Ember', value: 'ember' },
  { text: 'Solid', value: 'solid' },
]);
</script>

Demo

Selected: vue, react

Custom Filter Function

Search across multiple properties.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedProducts"
    :items="products"
    :multiple="true"
    :filter-function="customFilter"
    placeholder="Search by name, category, or brand..."
  />
</template>

<script setup>
import { ref } from 'vue';

const selectedProducts = ref([]);
const products = ref([
  { text: 'Apple MacBook Pro', value: 'mbp', category: 'laptop', brand: 'Apple' },
  { text: 'Apple iPhone 15', value: 'iphone15', category: 'phone', brand: 'Apple' },
  { text: 'Samsung Galaxy S24', value: 's24', category: 'phone', brand: 'Samsung' },
  { text: 'Dell XPS 13', value: 'xps', category: 'laptop', brand: 'Dell' },
  { text: 'Microsoft Surface Pro', value: 'surface', category: 'tablet', brand: 'Microsoft' },
]);

const customFilter = (item, searchText) => {
  const text = item.text.toLowerCase();
  const category = item.category.toLowerCase();
  const brand = item.brand.toLowerCase();
  const search = searchText.toLowerCase();
  
  return text.includes(search) || category.includes(search) || brand.includes(search);
};
</script>

Demo

Selected: None

💡 Try searching "laptop", "Apple", or "phone"

Disabled State

ComboBox in disabled state.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedValue"
    :items="items"
    :disabled="true"
    placeholder="This field is disabled"
  />
</template>

<script setup>
import { ref } from 'vue';

const selectedValue = ref('custom-disabled-value');
const items = ref([
  { text: 'Option 1', value: 'opt1' },
  { text: 'Option 2', value: 'opt2' },
]);
</script>

Demo

Selected: custom-disabled-value

Readonly State

ComboBox in readonly state.

Code Example

vue
<template>
  <OComboBox
    v-model="selectedValue"
    :items="items"
    :readonly="true"
    placeholder="This field is readonly"
  />
</template>

<script setup>
import { ref } from 'vue';

const selectedValue = ref('readonly-custom');
const items = ref([
  { text: 'Value 1', value: 'val1' },
  { text: 'Value 2', value: 'val2' },
]);
</script>

Demo

Selected: readonly-custom

Different Placements

ComboBox with various placement options.

Code Example

vue
<template>
  <div class="placement-examples">
    <OComboBox
      v-model="selectedValue"
      :items="items"
      placement="bottom"
      placeholder="Bottom (default)"
    />
    
    <OComboBox
      v-model="selectedValue"
      :items="items"
      placement="top"
      placeholder="Top"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';

const selectedValue = ref(null);
const items = ref([
  { text: 'Option 1', value: 'opt1' },
  { text: 'Option 2', value: 'opt2' },
  { text: 'Option 3', value: 'opt3' },
]);
</script>

<style scoped>
.placement-examples {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  padding: 4rem 2rem;
}
</style>

Demo

Form Integration

ComboBox integrated into a form with validation.

Code Example

vue
<template>
  <form @submit.prevent="submitForm" class="form-example">
    <div class="form-group">
      <label>Username</label>
      <OComboBox
        v-model="formData.username"
        :items="usernameSuggestions"
        placeholder="Select or type username..."
      />
      <span v-if="formErrors.username" class="error">{{ formErrors.username }}</span>
    </div>
    
    <div class="form-group">
      <label>Skills</label>
      <OComboBox
        v-model="formData.skills"
        :items="skillsSuggestions"
        :multiple="true"
        placeholder="Add your skills..."
      />
      <span v-if="formErrors.skills" class="error">{{ formErrors.skills }}</span>
    </div>
    
    <div class="form-group">
      <label>Notes/Tags</label>
      <OComboBox
        v-model="formData.notes"
        :items="[]"
        :multiple="true"
        placeholder="Type notes or tags..."
      />
      <span v-if="formErrors.notes" class="error">{{ formErrors.notes }}</span>
    </div>
    
    <div class="form-actions">
      <button type="submit" class="submit-btn">Submit Form</button>
      <button type="button" @click="validateForm" class="validate-btn">Validate Only</button>
    </div>
  </form>
</template>

<script setup>
import { reactive, ref } from 'vue';

const formData = reactive({
  username: null,
  skills: [],
  notes: [],
});

const formErrors = reactive({
  username: '',
  skills: '',
  notes: '',
});

const usernameSuggestions = ref([
  { text: 'john_doe', value: 'john_doe' },
  { text: 'jane_smith', value: 'jane_smith' },
  { text: 'bob_wilson', value: 'bob_wilson' },
]);

const skillsSuggestions = ref([
  { text: 'JavaScript', value: 'js' },
  { text: 'TypeScript', value: 'ts' },
  { text: 'Vue.js', value: 'vue' },
  { text: 'React', value: 'react' },
  { text: 'Node.js', value: 'node' },
]);

const validateForm = () => {
  formErrors.username = !formData.username ? 'Username is required' : '';
  formErrors.skills = formData.skills.length === 0 ? 'At least one skill is required' : '';
  formErrors.notes = formData.notes.length === 0 ? 'At least one note is required' : '';
};

const submitForm = () => {
  validateForm();
  if (!formErrors.username && !formErrors.skills && !formErrors.notes) {
    console.log('Form submitted:', formData);
    alert('Form submitted successfully!');
  }
};
</script>

<style scoped>
.form-example {
  max-width: 500px;
  padding: 1.5rem;
  border: 1px solid #e5e7eb;
  border-radius: 0.5rem;
  background: #fafafa;
}

.form-group {
  margin-bottom: 1.5rem;
}

.form-group label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 600;
  color: #374151;
}

.error {
  color: #ef4444;
  font-size: 0.875rem;
  margin-top: 0.25rem;
  display: block;
}

.form-actions {
  display: flex;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.submit-btn, .validate-btn {
  padding: 0.625rem 1.25rem;
  border: none;
  border-radius: 0.375rem;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.2s;
}

.submit-btn {
  background: #3b82f6;
  color: white;
}

.submit-btn:hover {
  background: #2563eb;
}

.validate-btn {
  background: #6b7280;
  color: white;
}

.validate-btn:hover {
  background: #4b5563;
}
</style>

Demo