Skip to content
Aggarly OS
  • Getting Started
    • Introduction
  • Foundations
    • Colors
    • Spacing
    • Radius
    • Typography
    • Shadows
    • Z-Index
    • Gradients
    • Tokens
    • RTL & Direction
    • Theming
  • Layout
    • Containers
    • Grid System
    • Layout Utilities
  • Components
    • Alerts
    • Avatars
    • Buttons
    • Button Group
    • Badges
    • Inputs
    • Select
    • Checkbox
    • Counters-timers
    • Radio
    • Switch
    • Stepper
    • Select-pro
    • Cards
    • Modals
    • Dropdown
    • Popover
    • Tooltip
    • Accordion
    • Breadcrumb
    • Tabs
    • Navbar
    • List Group
    • Toasts
    • Skeleton
    • Pagination
    • Progress
    • Table
    • Icons
    • Form
    • Ribbons
    • Spinner
    • Offcanvas
    • Feedback
    • Grid
    • Data UI
  • Data UI
    • Overview
  • Platform
    • Reference DataCore
  • Widgets
    • KPI
    • Analytics
    • Behavior
  • Brand
    • Logo
    • Brand Usage
Components/Select-pro

Select Pro

SelectPro is the premium combobox/multi-select for Aggarly Design System: search, chips, keyboard support, optional virtualization for large lists, and API-backed infinite scroll through ApiSelect.

Single Select with Search

Use for large enumerations where search is faster than scrolling.

Search + keyboard support.
Show code
Single search (JSX)
import { SelectPro } from "@/design-system/components/SelectPro";

export function Example() {
  return (
    <SelectPro
      label="Environment"
      placeholder="Select environment"
      options={[
        { value: "prod", label: "Production", keywords: ["live"] },
        { value: "staging", label: "Staging" },
        { value: "sandbox", label: "Sandbox" },
      ]}
      defaultValue="prod"
      helper="Search + keyboard support."
    />
  );
}

Multi Select with Search

Chips + listbox. Backspace removes last chip when the query is empty.

AdminViewer
Multi-select chips + search.
Show code
Multi select (JSX)
import { SelectPro } from "@/design-system/components/SelectPro";

export function Example() {
  return (
    <SelectPro
      multiple
      label="Roles"
      placeholder="Select roles"
      searchPlaceholder="Search roles…"
      options={[
        { value: "owner", label: "Owner" },
        { value: "admin", label: "Admin" },
        { value: "editor", label: "Editor" },
        { value: "viewer", label: "Viewer" },
        { value: "restricted", label: "Restricted" },
      ]}
      defaultValue={["admin", "viewer"]}
      helper="Multi-select chips + search."
    />
  );
}

Single Select with Avatars

Enterprise pattern: assignee/owner selects with avatar + name.

T1Workspace admin One
Premium pattern: avatar + name with searchable list.
Show code
Avatar single select (JSX)
import { SelectPro } from "@/design-system/components/SelectPro";
import { Avatar } from "@/design-system/components/Avatar";

const PEOPLE = [
  { id: "t1", name: "Workspace admin One", initials: "T1", tone: "primary" },
  { id: "su", name: "Supervisor", initials: "SU", tone: "success" },
];

export function Example() {
  return (
    <SelectPro
      label="Assignee"
      placeholder="Select a person"
      options={PEOPLE.map((p) => ({
        value: p.id,
        label: p.name,
        keywords: [p.initials],
        meta: p,
      }))}
      renderLeading={(opt) => {
        const p = opt.meta as any;
        return <Avatar size="xs" name={p.name} initials={p.initials} tone={p.tone} variant="soft" />;
      }}
      renderOption={(opt) => {
        const p = opt.meta as any;
        return (
          <>
            <Avatar size="xs" name={p.name} initials={p.initials} tone={p.tone} variant="soft" />
            <span className="selectpro__option-text">{p.name}</span>
          </>
        );
      }}
    />
  );
}

Multi Select with Avatars

Enterprise pattern: team selectors. Chips render avatar + name.

T1Workspace admin OneWorkspace admin OneSUSupervisorSupervisor
Chips render avatar + name (enterprise team selector).
Show code
Avatar multi select (JSX)
import { SelectPro } from "@/design-system/components/SelectPro";
import { Avatar } from "@/design-system/components/Avatar";

export function Example() {
  return (
    <SelectPro
      multiple
      label="Care team"
      placeholder="Select people"
      options={[
        { value: "t1", label: "Workspace admin One", meta: { name: "Workspace admin One", initials: "T1", tone: "primary" } },
        { value: "su", label: "Supervisor", meta: { name: "Supervisor", initials: "SU", tone: "success" } },
      ]}
      renderChipLabel={(opt) => {
        const p = opt.meta as any;
        return (
          <>
            <Avatar size="xs" name={p.name} initials={p.initials} tone={p.tone} variant="soft" />
            <span>{p.name}</span>
          </>
        );
      }}
      renderOption={(opt) => {
        const p = opt.meta as any;
        return (
          <>
            <Avatar size="xs" name={p.name} initials={p.initials} tone={p.tone} variant="soft" />
            <span className="selectpro__option-text">{p.name}</span>
          </>
        );
      }}
    />
  );
}

Virtualized Menu (5k+ options)

Recommended for performance. Only renders visible rows.

Virtualized menu for performance.
Show code
Virtualized SelectPro (JSX)
import { SelectPro } from "@/design-system/components/SelectPro";

export function Example() {
  const options = Array.from({ length: 5000 }, (_, i) => ({
    value: `opt-${i + 1}`,
    label: `Option ${i + 1}`,
    keywords: [`#${i + 1}`],
  }));

  return (
    <SelectPro
      label="Virtualized (5k+)"
      placeholder="Search 5,000 options"
      options={options}
      virtualization={{ threshold: 400 }}
    />
  );
}

API Select with Infinite Scroll

Cursor pagination + infinite scroll (recommended for massive datasets like users).

Scroll to load more results.
Show code
ApiSelect pagination (JSX)
import { ApiSelect } from "@/design-system/components/ApiSelect";

export function Example() {
  return (
    <ApiSelect
      label="Users (paged API)"
      placeholder="Search users"
      url="/api/demo/users-paged"
      queryParam="q"
      minQueryLength={1}
      preloadOnOpen={false}
      pagination={{ enabled: true, pageSize: 50 }}
    />
  );
}