پرتوپرتو

دیالوگ ویرایش برچسب (LabelEditDialog)

دیالوگ کنترل‌شده برای ویرایش برچسب‌های خوشه‌بندی هوشمند — با فیلد متنی، تاگل «تولید‌شده توسط AI»، پیشنهادهای انتخاب سریع و اکشن حذف اختیاری.

معرفی

LabelEditDialog دیالوگ آماده‌ی ویرایش یک برچسب در جریان‌های خوشه‌بندی هوشمند است و مکمل LabelChip طراحی شده: وقتی کاربر روی آیکن مداد یک چیپ کلیک می‌کند، این دیالوگ با مقدار فعلی باز می‌شود و امکان تغییر متن برچسب، تغییر پرچم «تولید‌شده توسط AI» و انتخاب سریع از برچسب‌های موجود را فراهم می‌کند. کامپوننت نسبت به ذخیره‌سازی بی‌طرف است — نتیجه از طریق onSave به مصرف‌کننده تحویل داده می‌شود.

چه زمانی استفاده کنیم:

  • ویرایش سریع نام یک برچسب خوشه‌بندی (مثلاً برچسب‌های تولیدشده توسط AI در داشبورد تحلیل گفت‌وگوهای کمپین)
  • تأیید یا لغو وضعیت «تولید‌شده توسط AI» یک برچسب پس از بازبینی انسانی
  • یکدست‌سازی برچسب‌ها با انتخاب از پیشنهادهای موجود به‌جای تایپ آزاد

چه زمانی استفاده نکنیم:

  • ویرایش فرم‌های چندفیلدی یا رکوردهای کامل — از Dialog با فرم سفارشی استفاده کنید
  • گرفتن تأیید برای یک عمل مخرب به‌تنهایی — از ConfirmDialog یا AlertDialog استفاده کنید
  • افزودن یا انتخاب تگ به‌صورت inline داخل فرم‌ها — از فیلدهای انتخاب چندگزینه‌ای استفاده کنید
برچسب خوشه:بازخورد بسته‌بندی

استفاده

import { LabelEditDialog } from '@partodata/ui'
const [open, setOpen] = React.useState(false)
const [label, setLabel] = React.useState('بازخورد بسته‌بندی')
const [aiGenerated, setAiGenerated] = React.useState(true)

<LabelEditDialog
  open={open}
  onOpenChange={setOpen}
  initialValue={label}
  aiGenerated={aiGenerated}
  suggestions={['کمپین تخفیف فصلی', 'رونمایی محصول جدید']}
  onSave={(value, ai) => {
    setLabel(value)
    setAiGenerated(ai)
  }}
/>

دیالوگ کاملاً کنترل‌شده است: وضعیت باز/بسته را با open و onOpenChange از بیرون مدیریت می‌کنید. هر بار که دیالوگ باز می‌شود، فرم داخلی با initialValue و aiGenerated همگام می‌شود؛ بنابراین همیشه مقدار فعلی رکورد را پاس بدهید.

حالت‌ها و انواع

ترکیب با LabelChip

الگوی متداول: آیکن مداد چیپ (onEdit) دیالوگ را باز می‌کند و onSave نتیجه را به state یا backend می‌نویسد.

import { LabelChip, LabelEditDialog } from '@partodata/ui'

const [open, setOpen] = React.useState(false)
const [label, setLabel] = React.useState('گفتمان درباره برند')
const [ai, setAi] = React.useState(true)

<>
  <LabelChip aiGenerated={ai} onEdit={() => setOpen(true)}>
    {label}
  </LabelChip>
  <LabelEditDialog
    open={open}
    onOpenChange={setOpen}
    initialValue={label}
    aiGenerated={ai}
    onSave={(value, aiFlag) => {
      setLabel(value)
      setAi(aiFlag)
    }}
  />
</>

با اکشن حذف

اگر onDelete را پاس بدهید، یک دکمه destructive با متن «حذف» در فوتر ظاهر می‌شود (در سمت آغازین فوتر، جدا از انصراف/ذخیره). با کلیک روی آن، ابتدا onDelete فراخوانی و سپس دیالوگ بسته می‌شود. اگر این prop را ندهید، دکمه حذف اصلاً رندر نمی‌شود.

<LabelEditDialog
  open={open}
  onOpenChange={setOpen}
  initialValue="بازخورد بسته‌بندی"
  onSave={handleSave}
  onDelete={() => removeLabel(labelId)}
/>

پیشنهادهای انتخاب سریع

آرایه suggestions (معمولاً سایر برچسب‌های موجود در همان خوشه یا بورد) به‌صورت ردیفی از LabelChipهای قابل‌کلیک زیر فرم نمایش داده می‌شود. با انتخاب هر پیشنهاد، متن آن جایگزین مقدار فیلد می‌شود و تاگل «تولید‌شده توسط AI» خاموش می‌شود — چون انتخاب دستی به معنای بازبینی انسانی است.

<LabelEditDialog
  open={open}
  onOpenChange={setOpen}
  initialValue="نظر مثبت مشتری"
  suggestions={['کمپین تخفیف فصلی', 'رونمایی محصول جدید', 'همکاری برند با اینفلوئنسر']}
  onSave={handleSave}
/>

اعتبارسنجی داخلی دکمه ذخیره

دکمه «ذخیره» فقط زمانی فعال است که هر دو شرط برقرار باشد:

  • مقدار فیلد پس از trim خالی نباشد
  • مقدار یا پرچم AI نسبت به حالت اولیه تغییر کرده باشد (dirty)

مقدار ارسالی به onSave همیشه trim شده است. اعتبارسنجی‌های دیگر (یکتا بودن نام، محدودیت طول، قواعد سمت سرور) بر عهده مصرف‌کننده است.

زبان رشته‌های داخلی (locale)

عنوان، توضیح، برچسب فیلد، placeholder و متن دکمه‌ها برای سه زبان از پیش آماده است. پیش‌فرض fa است.

<LabelEditDialog open={open} onOpenChange={setOpen} initialValue="Seasonal campaign" locale="en" onSave={handleSave} />

راهنمای استفاده

بکنید

  • همیشه مقدار فعلی رکورد را در initialValue و aiGenerated پاس بدهید — فرم داخلی در هر بار باز شدن با همین مقادیر همگام می‌شود. - دیالوگ را با آیکن مداد LabelChip (prop onEdit) جفت کنید تا الگوی ویرایش برچسب در کل محصول یکدست بماند. - برچسب‌های موجود در همان خوشه یا بورد را به‌عنوان suggestions بدهید تا کاربر به‌جای ساخت برچسب تکراری، از موارد موجود انتخاب کند. - اگر حذف برچسب برگشت‌ناپذیر است، پیش از اجرای عملیات در onDelete یک مرحله تأیید (مثلاً ConfirmDialog) قرار دهید — خود دیالوگ بلافاصله بسته می‌شود.

نکنید

  • دیالوگ را بدون مدیریت open و onOpenChange رندر نکنید — این کامپوننت حالت غیرکنترل‌شده ندارد. - به اعتبارسنجی داخلی (غیرخالی بودن و dirty بودن) به‌عنوان تنها لایه اعتبارسنجی تکیه نکنید — یکتایی نام و قواعد کسب‌وکار را در onSave بررسی کنید. - کلیدهای داخلی نوع FlowKey یا شناسه‌های فنی را به‌عنوان متن برچسب نمایش ندهید — برچسب‌های خوانا و خنثی برای کاربر بنویسید. - از این دیالوگ برای ویرایش چند فیلد هم‌زمان استفاده نکنید — دامنه آن عمداً به یک برچسب محدود است.

Props

Prop

Type

دسترسی‌پذیری

  • روی Dialog دیزاین‌سیستم (مبتنی بر Radix Dialog) ساخته شده است: مودال با focus trap، بستن با Escape و کلیک روی overlay، و بازگشت فوکوس به عنصر آغازگر پس از بسته شدن.
  • عنوان و توضیح دیالوگ از طریق DialogTitle و DialogDescription به aria-labelledby و aria-describedby متصل می‌شوند.
  • فیلد متنی با Label استاندارد (اتصال htmlFor/id) برچسب‌گذاری شده و هنگام باز شدن دیالوگ به‌صورت هدفمند autoFocus می‌گیرد — الگوی پذیرفته‌شده برای دیالوگ‌هایی که در پاسخ به اقدام مستقیم کاربر باز می‌شوند.
  • تاگل «تولید‌شده توسط AI» یک Checkbox استاندارد داخل عنصر label است؛ کلیک روی متن هم آن را تغییر می‌دهد.
  • پیشنهادها چیپ‌های قابل‌کلیک با role="button" و tabIndex هستند و با کیبورد قابل انتخاب‌اند.
  • ذخیره از طریق submit فرم انجام می‌شود؛ دکمه بستن گوشه دیالوگ نیز متن صرفاً خوانا برای screen reader دارد.

تعامل با کیبورد

  • Escape: بستن دیالوگ بدون ذخیره - Tab / Shift+Tab: حرکت بین عناصر داخل دیالوگ (فوکوس داخل دیالوگ محبوس است) - Enter در فیلد متنی: ذخیره (اگر مقدار معتبر و تغییر کرده باشد) - Space: تغییر وضعیت تاگل «تولید‌شده توسط AI» - Enter یا Space روی یک پیشنهاد: انتخاب آن پیشنهاد

کامپوننت‌های مرتبط

  • LabelChip — نمایش خود برچسب (با نشانگر AI، درصد اطمینان و آیکن مداد)؛ این دیالوگ مکمل آن است و معمولاً از onEdit همان چیپ باز می‌شود.
  • Dialog — اگر فرم ویرایش سفارشی با چند فیلد یا چیدمان متفاوت نیاز دارید، به‌جای این کامپوننت از Dialog خام استفاده کنید.
  • ConfirmDialog — اگر حذف برچسب برگشت‌ناپذیر است، پیش از اجرای onDelete یک مرحله تأیید با آن اضافه کنید.
  • AlertDialog — برای هشدارهای بحرانی که کاربر حتماً باید پاسخ دهد و نباید با کلیک بیرون بسته شوند.