Build faster with Premium Chakra UI Components 💎
Learn moreWe’ve just shipped Chakra UI v3.19! This release introduces two new components - the Combobox and the Download Trigger, along with quality improvements to make building with Chakra even smoother.
The Combobox is a versatile input component that combines a text input with a listbox, allowing users to filter a list of options and select single or multiple values.
Comboboxes are deceptively tricky, you want keyboard support, screen reader accessibility, filtering, controlled/uncontrolled behavior, and easy customization. We built this so you don't have to wire all that up yourself.
The basic combobox provides a searchable dropdown with single selection.
"use client"
import {
Combobox,
Portal,
useFilter,
useListCollection,
} from "@chakra-ui/react"
const Demo = () => {
const { contains } = useFilter({ sensitivity: "base" })
const { collection, filter } = useListCollection({
initialItems: frameworks,
filter: contains,
})
return (
<Combobox.Root
collection={collection}
onInputValueChange={(e) => filter(e.inputValue)}
width="320px"
>
<Combobox.Label>Select framework</Combobox.Label>
<Combobox.Control>
<Combobox.Input placeholder="Type to search" />
<Combobox.IndicatorGroup>
<Combobox.ClearTrigger />
<Combobox.Trigger />
</Combobox.IndicatorGroup>
</Combobox.Control>
<Portal>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.Empty>No items found</Combobox.Empty>
{collection.items.map((item) => (
<Combobox.Item item={item} key={item.value}>
{item.label}
<Combobox.ItemIndicator />
</Combobox.Item>
))}
</Combobox.Content>
</Combobox.Positioner>
</Portal>
</Combobox.Root>
)
}
const frameworks = [
{ label: "React", value: "react" },
{ label: "Solid", value: "solid" },
{ label: "Vue", value: "vue" },
{ label: "Angular", value: "angular" },
{ label: "Svelte", value: "svelte" },
{ label: "Preact", value: "preact" },
{ label: "Qwik", value: "qwik" },
{ label: "Lit", value: "lit" },
{ label: "Alpine.js", value: "alpinejs" },
{ label: "Ember", value: "ember" },
{ label: "Next.js", value: "nextjs" },
]
Pass the multiple
prop to the Combobox.Root
to enable multiple selection.
This allows users to select multiple items from the list.
"use client"
import {
Badge,
Combobox,
Portal,
Wrap,
createListCollection,
} from "@chakra-ui/react"
import { useMemo, useState } from "react"
const skills = [
"JavaScript",
"TypeScript",
"React",
"Node.js",
"GraphQL",
"PostgreSQL",
]
const Demo = () => {
const [searchValue, setSearchValue] = useState("")
const [selectedSkills, setSelectedSkills] = useState<string[]>([])
const filteredItems = useMemo(
() =>
skills.filter((item) =>
item.toLowerCase().includes(searchValue.toLowerCase()),
),
[searchValue],
)
const collection = useMemo(
() => createListCollection({ items: filteredItems }),
[filteredItems],
)
const handleValueChange = (details: Combobox.ValueChangeDetails) => {
setSelectedSkills(details.value)
}
return (
<Combobox.Root
multiple
closeOnSelect
width="320px"
value={selectedSkills}
collection={collection}
onValueChange={handleValueChange}
onInputValueChange={(details) => setSearchValue(details.inputValue)}
>
<Wrap gap="2">
{selectedSkills.map((skill) => (
<Badge key={skill}>{skill}</Badge>
))}
</Wrap>
<Combobox.Label>Select Skills</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.IndicatorGroup>
<Combobox.Trigger />
</Combobox.IndicatorGroup>
</Combobox.Control>
<Portal>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel>Skills</Combobox.ItemGroupLabel>
{filteredItems.map((item) => (
<Combobox.Item key={item} item={item}>
{item}
<Combobox.ItemIndicator />
</Combobox.Item>
))}
<Combobox.Empty>No skills found</Combobox.Empty>
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Portal>
</Combobox.Root>
)
}
The DownloadTrigger component makes it simple to trigger file downloads directly from your UI. It comes in handy when you're offering downloadable reports, exporting images, or triggering async-generated files.
Pass the data you want to download to the data
prop, and specify the
fileName
and mimeType
of the file.
import { Button, DownloadTrigger } from "@chakra-ui/react"
const data = "The quick brown fox jumps over the lazy dog"
const Demo = () => {
return (
<DownloadTrigger
data={data}
fileName="sample.txt"
mimeType="text/plain"
asChild
>
<Button variant="outline">Download txt</Button>
</DownloadTrigger>
)
}
You can trigger downloads from a promise that returns a Blob
, File
, or
string
.
"use client"
import { Button, DownloadTrigger } from "@chakra-ui/react"
import { LuImageDown } from "react-icons/lu"
const data = async () => {
const res = await fetch("https://picsum.photos/200/300")
return res.blob()
}
const Demo = () => {
return (
<DownloadTrigger
data={data}
fileName="sample.jpg"
mimeType="image/jpeg"
asChild
>
<Button variant="outline">
<LuImageDown /> Download
</Button>
</DownloadTrigger>
)
}
Fix issue where passing d
prop to chakra.path
adds it to styles not as a
direct attribute.
Fix issue where responsive semantic tokens did not get applied.
To upgrade to the latest version, run:
npm install @chakra-ui/react@latest