Select
Select component is used to select one or more options from a list of items. We have two different types of select:
- EnumSelect (used to select one or more options from a list of items)
- RemoteSelect (used to select one or more options from a list of items fetched from a remote source)
EnumSelect
import { useState } from "react";
import { EnumSelect, useEnumSelectState } from "swash/v2/EnumSelect";
const fruits: Fruit[] = [
{
name: "Apple",
id: 1,
icon: (
<div>π</div>
),
},
...
];
const [value, setValue] = useState<Fruit | null>(null);
const enumSelect = useEnumSelectState({
value: value,
onChange: setValue,
items: fruits,
title: "Favorite fruit",
required: false,
disabledSelector: () => false,
labelElementSelector: (fruit) => <h3>{fruit.name}</h3>,
labelSelector: (fruit) => fruit.name,
valueSelector: (fruit) => fruit.id.toString(),
appearance: "default",
emptyMessage: "No fruits",
footer: <div>
Ceci est un footer
</div>
});
() => (
<div className="not-prose">
<EnumSelect
state={enumSelect}
placeholder="Select a fruit..."
placeholderIcon={
<div className="flex h-[1em] w-[1em] items-center justify-center">
π
</div>
}
aria-label="Fruits"
scale="lg"
/>
</div>
)
EnumSelectState
To use EnumSelect
you have to pass an EnumSelectState
object to the component. This object is created using useEnumSelectState
hook.
In the next part you will learn how to use this hook.
items
items
is an array of objects. Each object represents an option in the select.
The items should have the following shape:
const items = [
{
value: 1,
label: "Apple",
},
];
value
and label
can be replaced by the keywords of your choice, but you will need to adjust valueSelector
and labelSelector
accordingly.
onChange
onChange
is a function that takes an item. This function will be called when the selected values change.
valueSelector
valueSelector
is a function that takes an item and returns the value of the item (it needs to be a string). This value will be used to compare the item with the selected value.
labelSelector
labelSelector
is a function that takes an item and returns the label of the item (it can be a string or a ReactElement). This label will be used to display options and the selected value.
labelElementSelector (optional)
labelElementSelector
is a function that takes an item and returns the label of the item (it can be a string or a ReactElement). This label will be used to display options only.
iconSelector (optional)
iconSelector
is a function that takes an item and returns a ReactElement. This icon will be displayed next to the label of the item.
disabledSelector (optional)
disabledSelector
is a function that takes an item and returns a boolean. This boolean will be used to disable the item.
required (optional)
required
is a boolean that indicates if the select is required or not.
If the select is required, the user will not be able to clear the select value.
title (optional)
title
is a string that will be used as the label of the select.
In some case it will be used as the placeholder of the select.
emptyMessage (optional)
emptyMessage
is a string or a ReactElement that will be displayed in the select popover when there are no options is empty.
footer (optional)
footer
is a ReactElement that will be displayed in the select popover footer.
appearance (optional)
appearance
is a string that indicates the appearance of the select value.
It could be default
or chip
.
chip
is used to display the selected value as a chip.
EnumSelectState with multiple values
It works the same way as EnumSelectState, but you have to pass an array of values to the value
prop.
import { useState } from "react";
import { EnumSelect, useEnumSelectState } from "swash/v2/EnumSelect";
const [value, setValue] = useState<Fruit[]>([]);
const enumSelect = useEnumSelectState({
value: value,
onChange: setValue,
items: fruits,
title: "Favorite fruit",
required: false,
disabledSelector: () => false,
labelElementSelector: (fruit) => <h3>{fruit.name}</h3>,
iconSelector: (fruit) => fruit.icon,
labelSelector: (fruit) => fruit.name,
valueSelector: (fruit) => fruit.id.toString(),
appearance: "default",
emptyMessage: "No fruits"
});
() => (
<div className="not-prose">
<EnumSelect state={enumSelect} />
</div>
)
EnumSelect props
placeholder (optional)
placeholder
is a string that will be used as the placeholder of the select.
placeholderIcon (optional)
placeholderIcon
is a ReactElement that will be displayed next to the placeholder.
scale (optional)
scale
is a string that indicates the scale of the select.
It could be sm
, md
or lg
.
Default value is md
.
Select remote
import { useEffect, useMemo, useState } from "react";
import { RemoteSelect, useRemoteSelectState } from "swash/v2/RemoteSelect";
import { useStoreState } from "swash/utils/useStoreState";
const fruits: Fruit[] = [
{ id: 1, name: "Apple" },
{ id: 2, name: "Apricot" },
...
];
const LIMIT = 10;
const combobox = useComboboxStore();
const search = useStoreState(combobox, "value");
const [value, setValue] = useState<Fruit[]>([]);
const [offset, setOffset] = useState<number>(0);
useEffect(() => {
setOffset(0);
}, [search]);
const data = useMemo(() => {
const matches = fruits.filter((fruit) =>
fruit.name.includes(search)
);
return {
items: matches.slice(0, Math.min(offset + LIMIT, matches.length)),
hasMore: matches.length > offset + LIMIT,
totalCount: matches.length,
};
}, [search, offset]);
const enumSelect = useRemoteSelectState({
value: value,
onChange: setValue,
data,
combobox,
loading: false,
fetchMore: (previousData) => {
setOffset(previousData.items.length);
},
getItem: (id) => {
const fruit = fruits.find((f) => f.id === Number(id));
if (!fruit) {
throw new Error(`Fruit not found`);
}
return fruit;
},
title: "Favorite fruit",
appearance: "chip",
labelSelector: (fruit) => fruit.name,
valueSelector: (fruit) => fruit.id.toString(),
searchable: true
});
() => (
<div className="not-prose">
<RemoteSelect state={enumSelect} />
</div>
)
RemoteSelectState
To use RemoteSelect
you have to pass an RemoteSelectState
object to the component. This object is created using useRemoteSelectState
hook.
This following props are the same as EnumSelectState
props:
onChange
valueSelector
labelSelector
labelElementSelector
iconSelector
disabledSelector
required
title
emptyMessage
appearance
value
combobox
combobox
is a ComboboxStore object. This object is created using useComboboxStore
hook.
data
data
is an object that should have the following shape:
const data = {
items: [
{
value: 1,
label: "Apple",
},
],
totalCount: 1,
hasMore: 1,
};
items works the same way as EnumSelectState
items.
fetchMore
fetchMore
is a function that is called when the user scrolls to the bottom of the list. This function should fetch more items and update the data
object.
getItem
getItem
is a function that takes an id and returns an item. This function is used to get the item from the id when the user selects an item.
searchable (optional)
searchable
is a boolean that indicates if the select is searchable or not.
Default value is true
.
RemoteSelect props
The props are the same as EnumSelect
props.