CityCombobox
Combobox de busca assíncrona de cidades com debounce e indicador de carregamento.
Carregando...
Instalação
npx @kobana/ui add city-comboboxDependências instaladas automaticamente: button, command, popover (shadcn/ui), lucide-react
Importação
import { CityCombobox } from "@/components/kobana/city-combobox"
import type { CityOption } from "@/components/kobana/city-combobox"Props
| Prop | Tipo | Default | Descrição |
|---|---|---|---|
value | string | — | Valor selecionado (corresponde a CityOption.value) |
onValueChange | (value: string) => void | — | Disparado quando o usuário seleciona uma cidade |
onSearch | (query: string) => Promise<CityOption[]> | — | Callback assíncrono que busca cidades pelo termo digitado |
placeholder | string | "Selecione uma cidade" | Texto exibido quando nada está selecionado |
disabled | boolean | false | Desabilita o controle |
emptyText | string | "Nenhuma cidade encontrada." | Texto exibido quando a busca não retorna resultados |
className | string | — | Classes adicionais aplicadas ao botão de disparo |
CityOption
interface CityOption {
value: string
label: string
}Uso
async function searchCities(query: string): Promise<CityOption[]> {
const res = await fetch(`/api/cities?search=${encodeURIComponent(query)}`)
const data = await res.json()
return data.cities.map((c) => ({ value: c.ibgeCode, label: `${c.name} - ${c.state}` }))
}
function Example() {
const [city, setCity] = React.useState("")
return (
<CityCombobox
value={city}
onValueChange={setCity}
onSearch={searchCities}
/>
)
}O componente faz debounce de 300ms no termo digitado antes de chamar onSearch, exibe um spinner enquanto a busca está em andamento e não conhece nenhuma URL de API — a fonte de dados é totalmente injetada via onSearch.