AiFieldRequest

AiFieldRequest — обезличенная панель вместо AI-поля ввода, когда системе нужен ответ человека: заголовок, слот контента, раскрытие длинного текста и две кнопки действий.

Компонент не решает, когда появиться, не хранит ответ и не отправляет его — только показывает содержимое и сообщает о нажатии. Анимация замены поля ввода и Escape остаются на стороне чата.

Когда использовать

  • Нужна панель подтверждения / опросника на месте AI-поля ввода.
  • Контент приходит снаружи (текст сейчас, форма или шаги опросника позже).

Когда не нужен

  • Инлайн-баннер подсказки у поля — @cloud-ru/ds-ai-field-banner / @cloud-ru/ds-ai-field-notice.
  • Модалка или drawer с произвольным футером — @cloud-ru/ds-modal / @cloud-ru/ds-drawer.

Анатомия

Title

title — вопрос к человеку. Заголовок строится по формуле «действие + тип объекта» и заканчивается знаком вопроса: «Удалить виртуальную машину?», «Добавить правило в группу безопасности?», «Остановить кластер?». Так человек с первой строки понимает, что именно подтверждает; подробности живут в content. Максимум две строки, дальше обрезка по последнему целому слову.

Actions

primaryAction и secondaryAction — объекты кнопок: label (подпись) и onClick (клик). У primaryAction есть ещё loading — состояние отправки. Оба пропса обязательны, подписи задаёт потребитель.

Appearance (default primary)

Цвет основной кнопки:

  • primary — зелёная filled-кнопка.
  • destructive — красная filled-кнопка (для удаления).

Вторичная кнопка всегда outline neutral. Подписи обеих кнопок задаёт потребитель.

Content slot

content — тело панели, любой ReactNode: сейчас текст, позже форма или шаги опросника. Поэтому предел свёрнутого состояния задаётся высотой maxHeight (по умолчанию 88 px), а не числом строк. Строка обрезается через TruncateString: число строк вычисляется из maxHeight с округлением вниз до целых строк, чтобы не резать глифы. Любое другое содержимое ограничивается по maxHeight как есть. Кнопка «Показать» появляется автоматически, если контент не влезает; «Скрыть» в раскрытом виде видна всегда. Подписи кнопки раскрытия — «Показать» / «Скрыть».

Hint

hint — подпись под карточкой. Не рендерится, если не задана.

Loading

primaryAction.loading — индикатор на основной кнопке, вторичная кнопка недоступна, повторный клик по основной отсекается; раскрытие описания остаётся доступным.

Height

Корень не выше родителя (max-height: 100%). Заголовок и футер с кнопками остаются на месте; в раскрытом виде скроллится только слот контента.

Установка

pnpm add @cloud-ru/ds-ai-field-request
import { AiFieldRequest } from '@cloud-ru/ds-ai-field-request';

Примеры использования

Default

DefaultСвёрнутое состояние: длинный текст обрезан по `maxHeight`, кнопка «Показать» появилась сама
Удалить виртуальную машину?
Виртуальная машина будет остановлена и удалена вместе с дисками. Снимки и резервные копии останутся доступны в хранилище, восстановить машину из них можно в любой момент.
Подсказка под панелью
tsx
import { AiFieldRequest, APPEARANCE } from '@cloud-ru/ds-ai-field-request';

const CONTENT =
  'Виртуальная машина будет остановлена и удалена вместе с дисками. Снимки и резервные копии останутся доступны в хранилище, восстановить машину из них можно в любой момент.';

export function Default() {
  return (
    <AiFieldRequest
      title='Удалить виртуальную машину?'
      content={CONTENT}
      hint='Подсказка под панелью'
      appearance={APPEARANCE.Primary}
      primaryAction={{ label: 'Подтвердить' }}
      secondaryAction={{ label: 'Отмена' }}
    />
  );
}

Destructive

Destructive`appearance="destructive"` — красная основная кнопка
Удалить виртуальную машину?
Диски будут удалены вместе с машиной. Операция необратима.
Подсказка под панелью
tsx
import { AiFieldRequest, APPEARANCE } from '@cloud-ru/ds-ai-field-request';

export function Destructive() {
  return (
    <AiFieldRequest
      title='Удалить виртуальную машину?'
      content='Диски будут удалены вместе с машиной. Операция необратима.'
      hint='Подсказка под панелью'
      appearance={APPEARANCE.Destructive}
      primaryAction={{ label: 'Удалить' }}
      secondaryAction={{ label: 'Отмена' }}
    />
  );
}

Expanded

ExpandedРаскрытое состояние: содержимое целиком, кнопка «Скрыть»
Удалить виртуальную машину?
Виртуальная машина будет остановлена и удалена вместе с дисками. Снимки и резервные копии останутся доступны в хранилище, восстановить машину из них можно в любой момент. Сетевые интерфейсы и публичные адреса освободятся сразу после удаления.
Подсказка под панелью
tsx
import { AiFieldRequest, APPEARANCE } from '@cloud-ru/ds-ai-field-request';
import { useState } from 'react';

const CONTENT =
  'Виртуальная машина будет остановлена и удалена вместе с дисками. Снимки и резервные копии останутся доступны в хранилище, восстановить машину из них можно в любой момент. Сетевые интерфейсы и публичные адреса освободятся сразу после удаления.';

export function Expanded() {
  const [open, setOpen] = useState(true);

  return (
    <AiFieldRequest
      title='Удалить виртуальную машину?'
      content={CONTENT}
      hint='Подсказка под панелью'
      appearance={APPEARANCE.Primary}
      open={open}
      onOpenChange={setOpen}
      primaryAction={{ label: 'Подтвердить' }}
      secondaryAction={{ label: 'Отмена' }}
    />
  );
}

Loading

Loading`primaryAction.loading` — индикатор на основной кнопке, вторичная кнопка недоступна
Удалить виртуальную машину?
Диски будут удалены вместе с машиной.
Подсказка под панелью
tsx
import { AiFieldRequest, APPEARANCE } from '@cloud-ru/ds-ai-field-request';

export function Loading() {
  return (
    <AiFieldRequest
      title='Удалить виртуальную машину?'
      content='Диски будут удалены вместе с машиной.'
      hint='Подсказка под панелью'
      appearance={APPEARANCE.Primary}
      primaryAction={{ label: 'Подтвердить', loading: true }}
      secondaryAction={{ label: 'Отмена' }}
    />
  );
}

Props

Types

PropsAiFieldRequestProps
PropTypeDefaultRequiredDescription
appearance"destructive" | "primary"primarynoЦвет основной кнопки: `primary` или `destructive`. По умолчанию `primary`.
classNamestring—noДоп. класс корня.
contentReactNode—noСлот тела панели (текст, форма, опросник).
data-test-idstringai-field-requestno
hintReactNode—noПодпись под карточкой. Не рендерится, если не задана.
maxHeightnumber88noМаксимальная высота свёрнутого содержимого в px. По умолчанию `88`. Слот принимает любой ReactNode, поэтому предел задаётся высотой, а не числом строк. Для строкового `content` высота округляется вниз до целого числа строк, чтобы не резать глифы; для любого другого содержимого это обычный предел по высоте.
onOpenChange((open: boolean) => void)—noКолбэк смены раскрытия.
openboolean—noControlled — раскрыто содержимое. Без `open` компонент uncontrolled, стартует свёрнутым.
primaryActionAiFieldRequestPrimaryAction—yesОсновная кнопка действий: подпись, клик и состояние отправки. Обязательный пропс.
secondaryActionAiFieldRequestAction—yesВторичная кнопка действий: подпись и клик. Обязательный пропс.
titleReactNode—yesЗаголовок панели. Максимум две строки с обрезкой. Обязательный пропс.

Unions

Types

AiFieldRequestProps

Unions

Storybook

Figma