Skip to content

FilterSelect

One filter of a list: a button that says what it filters and what is applied, in the brand tint once it narrows the list, over a list of values with “All” first, counts and icons. Single or multiple selection; a search from eight options.

Language
Appearance

One value

import { useState } from 'react';
import { FilterSelect } from '@arbol-ai/ui';

const SingleExample = () => {
  const [status, setStatus] = useState<readonly string[]>([]);
  return (
    <FilterSelect
      allLabel="All statuses"
      label="Status"
      onChange={setStatus}
      options={[
        { value: 'scheduled', label: 'Scheduled' },
        { value: 'sent', label: 'Sent' },
        { value: 'paused', label: 'Paused' },
      ]}
      value={status}
    />
  );
};

<SingleExample />

Several values with counts

import { useState } from 'react';
import { FilterSelect } from '@arbol-ai/ui';
import type { FilterSelectOption } from '@arbol-ai/ui';

const RESULTS: FilterSelectOption[] = [
  {
    value: 'resolved',
    label: 'Resolved',
    count: 812,
    icon: <span aria-hidden className="bg-green-9 size-2 rounded-full" />,
  },
  {
    value: 'handoff',
    label: 'Handed off',
    count: 126,
    icon: <span aria-hidden className="bg-amber-9 size-2 rounded-full" />,
  },
  {
    value: 'missed',
    label: 'Missed',
    count: 64,
    icon: <span aria-hidden className="bg-red-9 size-2 rounded-full" />,
  },
];

const MultipleExample = () => {
  const [results, setResults] = useState<readonly string[]>(['missed']);
  return (
    <FilterSelect
      label="Result"
      onChange={setResults}
      options={RESULTS}
      selectionMode="multiple"
      value={results}
    />
  );
};

<MultipleExample />

Records

Agents, sites or services: each with a face and a second line that tells two apart, which the search reads too.

import { useState } from 'react';
import { Avatar, FilterSelect } from '@arbol-ai/ui';
import type { FilterSelectOption } from '@arbol-ai/ui';

const AGENTS: FilterSelectOption[] = [
  ['Front desk', 'Answers every call'],
  ['Reminders', 'Confirms appointments'],
  ['Collections', 'Calls about payments'],
  ['Front desk', 'North clinic, WhatsApp'],
  ['Surveys', 'Asks how the visit went'],
  ['Waiting list', 'Offers freed slots'],
  ['Results', 'Sends lab results'],
  ['After hours', 'Answers at night'],
].map(([label = '', description = ''], index) => ({
  value: `agt_${index}`,
  label,
  description,
  icon: <Avatar name={label} size="xs" />,
}));

const RecordsExample = () => {
  const [agents, setAgents] = useState<readonly string[]>([]);
  return (
    <FilterSelect allLabel="All agents" label="Agent" onChange={setAgents} options={AGENTS} value={agents} />
  );
};

<RecordsExample />

Records still loading

The list says so, and the button never shows the id of a value it has not read yet.

import { FilterSelect } from '@arbol-ai/ui';

<FilterSelect isLoading label="Site" onChange={() => undefined} options={[]} value={['site_01']} />

Source

The examples above are src/components/filter-select/filter-select.examples.tsx, which the library’s tests render too.

Type to search…

↑↓ navigate↵ selectEsc close