Skip to content
Devix Open Source

Guide

React, Vue, Svelte and the rest

React

import { Combobox } from '@devix-labs/combobox/react';
import '@devix-labs/combobox/styles.css';

<Combobox
  name="labels"
  value={labels}
  onChange={setLabels}
  maxTags={5}
  options={suggestions}
  placeholder="Add a label"
/>

Controlled (value + onChange) or uncontrolled (defaultValue). The component renders a plain <input> and enhances it after mount, so server rendering produces working markup and hydration matches — and because values are written through the native setter, React's change tracking never goes stale, which is tagify's open React issue.

Vue

<script setup>
import { Combobox } from '@devix-labs/combobox/vue';
const labels = ref(['design']);
</script>

<template>
  <Combobox v-model="labels" name="labels" :options="{ maxTags: 5 }" />
</template>

Svelte

<script>
  import { combobox } from '@devix-labs/combobox/svelte';
</script>

<input use:combobox={{ name: 'labels', maxTags: 5 }} />

Web component

<script type="module" src="https://www.devix.pk/cdn/oss/combobox@1.0.0/element.js"></script>

<form>
  <dx-combobox name="topics" max-tags="5" placeholder="Add a topic"></dx-combobox>
</form>

Form-associated: the tags post as topics repeated, exactly like a multi-select, with no hidden input of your own.

Laravel

<input id="labels" name="labels" value="{{ old('labels', $post->labels->implode(',')) }}">
$request->validate(['labels' => ['nullable', 'string']]);
$labels = collect(explode(',', $request->string('labels')))->filter()->unique();

The hidden input holds a comma-separated list, so a plain controller needs no JSON parsing. With the web component you get labels[] as an array instead.

Updated 15 Sep 2026