پرتوپرتو

اتوکامپلیت

کامپوننت Autocomplete برای جستجو و پیشنهاد نتایج

معرفی

کامپوننت Autocomplete یک input هوشمند با قابلیت نمایش پیشنهادهای لحظه‌ای است که شامل:

  • جستجوی Debounced (تاخیر هوشمند)
  • نمایش لیست پیشنهادها با scroll
  • Keyboard Navigation (پیمایش با کیبورد)
  • Click Outside (بسته شدن با کلیک خارج)
  • Loading State (نمایش وضعیت بارگذاری)
  • RTL Support (پشتیبانی کامل از راست به چپ)
  • Custom Render (سفارشی‌سازی نمایش هر مورد)

استفاده پایه

مثال ساده

با آیکون

Async (غیرهمزمان)

برای جستجوی سرور و API calls:

نسخه LTR (چپ به راست)

Props

Autocomplete

Prop

Type

AutocompleteItem

interface AutocompleteItem {
  value: string;    // مقدار یکتا
  label: string;    // برچسب نمایشی
  [key: string]: any; // فیلدهای اضافی دلخواه
}

موارد استفاده

جستجوی کاربران با API

import { Autocomplete } from "@parto-system-design/ui";
import { useState } from "react";

export function UserSearch() {
  const [value, setValue] = useState("");
  const [suggestions, setSuggestions] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  const handleSearch = async (query: string) => {
    setIsLoading(true);
    try {
      const response = await fetch(`/api/users/search?q=${query}`);
      const data = await response.json();
      setSuggestions(data.users);
    } catch (error) {
      console.error(error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <Autocomplete
      value={value}
      onValueChange={setValue}
      suggestions={suggestions}
      isLoading={isLoading}
      onSearch={handleSearch}
      placeholder="جستجوی کاربر..."
      minChars={2}
      dir="rtl"
      renderItem={(item) => (
        <div className="flex items-center gap-3">
          <img src={item.avatar} className="w-10 h-10 rounded-full" />
          <div>
            <div className="font-medium">{item.name}</div>
            <div className="text-sm text-muted-foreground">@{item.username}</div>
          </div>
        </div>
      )}
      onSelect={(user) => {
        console.log("Selected user:", user);
      }}
    />
  );
}

انتخاب کشور با آیکون

import { Autocomplete } from "@parto-system-design/ui";

const countries = [
  { value: "ir", label: "ایران", icon: "🇮🇷" },
  { value: "us", label: "آمریکا", icon: "🇺🇸" },
  { value: "uk", label: "انگلستان", icon: "🇬🇧" },
];

export function CountrySelect() {
  const [value, setValue] = useState("");
  const [suggestions, setSuggestions] = useState(countries);

  return (
    <Autocomplete
      value={value}
      onValueChange={setValue}
      suggestions={suggestions}
      onSearch={(query) => {
        setSuggestions(
          countries.filter((c) => c.label.includes(query))
        );
      }}
      placeholder="انتخاب کشور..."
      renderItem={(item) => (
        <div className="flex items-center gap-2">
          <span className="text-2xl">{item.icon}</span>
          <span>{item.label}</span>
        </div>
      )}
    />
  );
}

فرم با Autocomplete

import { Autocomplete, Button, Label } from "@parto-system-design/ui";
import { useState } from "react";

export function UserForm() {
  const [selectedUser, setSelectedUser] = useState("");

  return (
    <form className="space-y-4" dir="rtl">
      <div className="space-y-2">
        <Label>انتخاب کاربر</Label>
        <Autocomplete
          value={selectedUser}
          onValueChange={setSelectedUser}
          // ... props
        />
      </div>
      <Button type="submit">ارسال</Button>
    </form>
  );
}

Clear On Select

برای موارد استفاده مثل ارسال ایمیل که بعد از هر انتخاب input پاک شود:

<Autocomplete
  clearOnSelect={true}
  onSelect={(item) => {
    // Add to recipients list
    addRecipient(item);
  }}
/>

Keyboard Shortcuts

کلیدعملکرد
↓ Arrow Downحرکت به پیشنهاد بعدی
↑ Arrow Upحرکت به پیشنهاد قبلی
Enterانتخاب پیشنهاد فعال
Escapeبستن منوی پیشنهادها

ویژگی‌های کلیدی

  • Debounced Search: جلوگیری از درخواست‌های زیاد به سرور
  • Keyboard Navigation: پیمایش راحت با کیبورد
  • Click Outside: بسته شدن خودکار
  • Loading State: نمایش Spinner هنگام بارگذاری
  • Custom Render: سفارشی‌سازی کامل نمایش
  • RTL Support: پشتیبانی کامل از راست به چپ
  • Accessible: استاندارد accessibility
  • Type Safe: TypeScript با تعریف دقیق Types

نکات مهم

  • برای جستجوی API، حتماً از onSearch استفاده کنید
  • مقدار debounceDelay را بر اساس نیاز تنظیم کنید (300ms پیش‌فرض)
  • برای بهینه‌سازی، از minChars استفاده کنید تا جستجو با کاراکترهای کم شروع نشود
  • renderItem را برای سفارشی‌سازی کامل نمایش استفاده کنید
  • برای Controlled component از value و برای Uncontrolled از defaultValue استفاده کنید