GrPromptDialog
Берут, когда нужно одно значение.
Обзор
Когда брать
- нужно одно значение — имя папки, причина отказа, комментарий к возврату: заводить экран ради одного поля дорого;
- значение проверяется —
rulesиrequiredработают до подтверждения,fieldErrorпоказывает отказ сервера; - текст длинный —
multilineсautosizeпревращает поле в область ввода; - вызов из кода —
useDialogService().prompt()возвращает Promise со значением.
Когда взять другое
| Нужно | Берите |
|---|---|
| Спросить согласие, а не значение | GrConfirmDialog |
| Полей несколько | GrDialog + GrForm |
| Поле живёт на самом экране | GrFormField + GrInput |
| Выбрать из готовых вариантов | GrDialog + GrSelect |
Playground контролы выводятся из API, а не пишутся руками
Окно откроется поверх страницы с пропами, заданными справа.
0 изменено· состояние — в адресе
<GrPromptDialog
title="Rename the report"
label="Report name"
v-model="value"
/>Примеры 3 у каждого — живое демо и его код
Переименование отчёта из его строки
v-model:valueкладёт текущее имя в поле до открытия окна — переименование почти всегда начинается с него, — аv-modelдержит окно.confirmприносит новое значение, а не только факт согласия.Revenue by planUpdated TodayChurned accounts Q3Updated YesterdayOverdue invoicesUpdated 2 days agoПричина возврата
Причина не помещается в строку:
multilineпревращает поле в многострочное,autosizeрастит его вместе с ответом, аmaxlengthсshow-countназывает предел раньше, чем в него упрутся, — полоса прокрутки в трёх строках спрятала бы написанное.Order #4820 · Wool cardigan, navy, LDelivered on 2 October · returnable until 30 OctoberDeliveredИмя проекта, которое должен принять сервер
rulesпроверяют вид имени в окне, аfield-errorставит отказ сервера под поле. Сclose-on-confirm="false"окно закрывается, только когда проект создан;confirm-loadingиpersistentдержат его на месте, пока отвечает сервер. Попробуйте «q4-campaign».Projects · 2website-relaunchbilling-migration
API порождается из пакета · разойтись не может
Props
| Prop | Type | по умолчанию | Описание |
|---|---|---|---|
title | string | undefined | undefined | Заголовок окна, он же его доступное имя. Не задан — берётся из локали. |
required | boolean | undefined | true | Пустое значение не подтверждается; ошибка видна после первого ухода из поля или попытки подтвердить. По умолчанию `true`. |
size | "sm" | "md" | "lg" | "xl" | "full" | undefined | undefined | Ширина окна по шкале `GrDialog`: от `sm` до `xl`, `full` — во весь экран. По умолчанию `md`. |
placeholder | string | undefined | undefined | Подсказка в пустом поле. |
name | string | undefined | undefined | Имя поля. В наборе не за компанию: менеджеры паролей опираются и на него, а сохранение значения без имени у части из них просто не срабатывает. |
description | string | undefined | undefined | Пояснение над полем. Слот `default` его заменяет. |
label | string | undefined | undefined | Подпись поля, она же его доступное имя. Не задана — берётся из локали. |
closeOnBackdrop | boolean | undefined | true | Закрывать по клику на подложку. По умолчанию `true`; при `persistent` на время подтверждения или проверки `rules` выключается. |
closeOnEsc | boolean | undefined | true | Закрывать по Esc. По умолчанию `true`; при `persistent` на время подтверждения или проверки `rules` выключается. |
showHeader | boolean | undefined | true | Показывать шапку с заголовком и кнопкой закрытия. По умолчанию `true`. |
showCloseButton | boolean | undefined | true | Кнопка закрытия в шапке. По умолчанию `true`; при `persistent` тоже остаётся. |
headerConfig | GrDialogSectionConfig | undefined | undefined | Поля и линия шапки: `paddingX`, `paddingY`, `bordered`. |
footerConfig | GrDialogSectionConfig | undefined | undefined | Поля и линия подвала с кнопками. |
bodyConfig | GrDialogSectionConfig | undefined | undefined | Поля тела окна. `bordered` у тела не применяется. |
closeLabel | string | undefined | undefined | A11y-лейбл кнопки закрытия (i18n). |
buttonSize | "xs" | "sm" | "md" | "lg" | undefined | undefined | Размер обеих кнопок подвала. Не задан — кнопки берут размер из `GrConfigProvider`. |
confirmText | string | undefined | undefined | Подпись кнопки подтверждения. Не задана — берётся из локали. |
cancelText | string | undefined | undefined | Подпись кнопки отмены. Не задана — берётся из локали. |
confirmVariant | GrButtonVariant | undefined | "primary" | Вес кнопки подтверждения. По умолчанию `primary`. |
confirmTone |
| "primary" | Тон кнопки подтверждения: `danger` — для необратимого действия. По умолчанию `primary`. |
error | ResponseErrorInfo | null | undefined | null | Структура ошибки ответа сервера для показа общим блоком в теле диалога (через `GrResponseErrorBanner`). `null` — блок скрыт. |
confirmLoading | boolean | undefined | false | Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). |
confirmDisabled | boolean | undefined | false | Принудительно дизейблит кнопку Confirm. |
closeOnConfirm | boolean | undefined | true | Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`. `false` — отдаёт управление закрытием наружу (нужно `useDialogService`). |
persistent | boolean | undefined | false | Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт подтверждение или проверка `rules`. Кнопка закрытия и «Отмена» остаются: окно без единого выхода — ловушка. |
rows | number | undefined | undefined | Высота многострочного поля в строках. |
rules | GrFormRule | GrFormRule[] | undefined | undefined | Правила проверки значения — те же, что у `GrForm` (`required`, `type`, `min`/`max`/`len`, `pattern`, свой в т.ч. асинхронный `validator`). Прогоняются на blur (после первого касания) и на подтверждении. |
autocomplete | string | undefined | undefined | Что у человека спрашивают — для браузера и менеджера паролей (`current-password`, `new-password`, `one-time-code`, `off`). Из `inputType` не выводится: у одного и того же `password` три разных правильных значения, и окно не знает, спрашивают у него старый пароль, новый или одноразовый код. Значение выбирает потребитель. |
inputmode |
| undefined | Программная клавиатура на мобильных. |
maxlength | number | undefined | undefined | Ограничение длины; со `showCount` рисуется счётчик. |
showCount | boolean | undefined | false | Счётчик символов под полем; с `maxlength` — в виде `len/maxlength`. |
requiredErrorText | string | undefined | undefined | Текст ошибки для пустого значения при `required=true` (i18n). |
inputType | GrInputType | undefined | "text" | Тип однострочного поля. В многострочном режиме не применяется. |
autocapitalize | "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | undefined | Автозаглавная у программной клавиатуры. Пара к `autocomplete="off"` для секретов, которые вводят руками: резервный код 2FA сверяется байт в байт, а клавиатура поднимает первую букву. |
spellcheck | boolean | undefined | undefined | Проверка орфографии. Вторая половина той же пары. |
multiline | boolean | undefined | false | Многострочный ввод: вместо `GrInput` рисуется `GrTextarea`. |
autosize | boolean | undefined | false | Автоподбор высоты многострочного поля под содержимое. |
fieldError | string | null | undefined | null | Внешняя ошибка поля ввода (например, серверная валидация). Имеет приоритет над встроенной проверкой. `null`/`undefined` — нет внешней ошибки. |
modelValueобязательныйv-model | boolean | — | Открыто ли окно (`v-model`). Отмена закрывает его всегда, подтверждение — при `closeOnConfirm`. |
valueобязательныйv-model | string | — | Значение поля (`v-model:value`). Между открытиями окно его не сбрасывает. |
Слоты
| Slot | Type | Описание |
|---|---|---|
default | any | Содержимое диалога вместо текста из пропа `description`. |
error | { error: ResponseErrorInfo | null; } | Разбор ошибки вместо встроенного баннера. |
footer | any | Кнопки диалога вместо пары «отмена и подтверждение». |
События
| Event | Сигнатура | Описание |
|---|---|---|
update:modelValue | (event: "update:modelValue", value: boolean): void | — |
confirm | (event: "confirm", value: string): void | — |
cancel | (event: "cancel"): void | — |
update:value | (event: "update:value", value: string): void | — |
Типы
Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.
import type { GrPromptDialogProps, GrPromptDialogEmits } from '@feugene/granularity/components/GrPromptDialog'Файлdist/types/components/GrPromptDialog/GrPromptDialog.vue.d.ts
interface GrPromptDialogProps {
/** Открыто ли окно (`v-model`). Отмена закрывает его всегда, подтверждение — при `closeOnConfirm`. */
modelValue: boolean;
/** Значение поля (`v-model:value`). Между открытиями окно его не сбрасывает. */
value: string;
/** Заголовок окна, он же его доступное имя. Не задан — берётся из локали. */
title?: string;
/** Пояснение над полем. Слот `default` его заменяет. */
description?: string;
/** Подпись поля, она же его доступное имя. Не задана — берётся из локали. */
label?: string;
/** Подсказка в пустом поле. */
placeholder?: string;
/**
* Закрывать по клику на подложку. По умолчанию `true`; при `persistent` на время подтверждения
* или проверки `rules` выключается.
*/
closeOnBackdrop?: boolean;
/**
* Закрывать по Esc. По умолчанию `true`; при `persistent` на время подтверждения или проверки
* `rules` выключается.
*/
closeOnEsc?: boolean;
/** Показывать шапку с заголовком и кнопкой закрытия. По умолчанию `true`. */
showHeader?: boolean;
/** Кнопка закрытия в шапке. По умолчанию `true`; при `persistent` тоже остаётся. */
showCloseButton?: boolean;
/** Ширина окна по шкале `GrDialog`: от `sm` до `xl`, `full` — во весь экран. По умолчанию `md`. */
size?: GrDialogSize;
/** Поля и линия шапки: `paddingX`, `paddingY`, `bordered`. */
headerConfig?: GrDialogSectionConfig;
/** Поля и линия подвала с кнопками. */
footerConfig?: GrDialogSectionConfig;
/** Поля тела окна. `bordered` у тела не применяется. */
bodyConfig?: GrDialogSectionConfig;
/** A11y-лейбл кнопки закрытия (i18n). */
closeLabel?: string;
/** Размер обеих кнопок подвала. Не задан — кнопки берут размер из `GrConfigProvider`. */
buttonSize?: GrButtonSize;
/** Подпись кнопки подтверждения. Не задана — берётся из локали. */
confirmText?: string;
/** Подпись кнопки отмены. Не задана — берётся из локали. */
cancelText?: string;
/** Текст ошибки для пустого значения при `required=true` (i18n). */
requiredErrorText?: string;
/** Вес кнопки подтверждения. По умолчанию `primary`. */
confirmVariant?: GrButtonVariant;
/** Тон кнопки подтверждения: `danger` — для необратимого действия. По умолчанию `primary`. */
confirmTone?: GrButtonTone;
/**
* Пустое значение не подтверждается; ошибка видна после первого ухода из поля или попытки
* подтвердить. По умолчанию `true`.
*/
required?: boolean;
/** Тип однострочного поля. В многострочном режиме не применяется. */
inputType?: GrInputType;
/** Программная клавиатура на мобильных. */
inputmode?: InputHTMLAttributes['inputmode'];
/** Ограничение длины; со `showCount` рисуется счётчик. */
maxlength?: number;
/** Счётчик символов под полем; с `maxlength` — в виде `len/maxlength`. */
showCount?: boolean;
/**
* Что у человека спрашивают — для браузера и менеджера паролей
* (`current-password`, `new-password`, `one-time-code`, `off`).
*
* Из `inputType` не выводится: у одного и того же `password` три разных
* правильных значения, и окно не знает, спрашивают у него старый пароль,
* новый или одноразовый код. Значение выбирает потребитель.
*/
autocomplete?: string;
/**
* Имя поля. В наборе не за компанию: менеджеры паролей опираются и на него, а
* сохранение значения без имени у части из них просто не срабатывает.
*/
name?: string;
/**
* Автозаглавная у программной клавиатуры. Пара к `autocomplete="off"` для
* секретов, которые вводят руками: резервный код 2FA сверяется байт в байт, а
* клавиатура поднимает первую букву.
*/
autocapitalize?: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';
/** Проверка орфографии. Вторая половина той же пары. */
spellcheck?: boolean;
/** Многострочный ввод: вместо `GrInput` рисуется `GrTextarea`. */
multiline?: boolean;
/** Высота многострочного поля в строках. */
rows?: number;
/** Автоподбор высоты многострочного поля под содержимое. */
autosize?: boolean;
/**
* Правила проверки значения — те же, что у `GrForm` (`required`, `type`,
* `min`/`max`/`len`, `pattern`, свой в т.ч. асинхронный `validator`).
* Прогоняются на blur (после первого касания) и на подтверждении.
*/
rules?: GrFormRule | GrFormRule[];
/**
* Структура ошибки ответа сервера для показа общим блоком в теле диалога
* (через `GrResponseErrorBanner`). `null` — блок скрыт.
*/
error?: ResponseErrorInfo | null;
/**
* Внешняя ошибка поля ввода (например, серверная валидация). Имеет приоритет
* над встроенной проверкой. `null`/`undefined` — нет внешней ошибки.
*/
fieldError?: string | null;
/** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */
confirmLoading?: boolean;
/** Принудительно дизейблит кнопку Confirm. */
confirmDisabled?: boolean;
/**
* Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`.
* `false` — отдаёт управление закрытием наружу (нужно `useDialogService`).
*/
closeOnConfirm?: boolean;
/**
* Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт
* подтверждение или проверка `rules`. Кнопка закрытия и «Отмена» остаются:
* окно без единого выхода — ловушка.
*/
persistent?: boolean;
}interface GrPromptDialogEmits {
/** Окно закрыто (`v-model`): кнопкой, крестиком, Esc или кликом по подложке. */
(e: 'update:modelValue', value: boolean): void;
/** Значение поля изменилось при вводе (`v-model:value`). */
(e: 'update:value', value: string): void;
/**
* Значение подтверждено — кнопкой или `Enter` в однострочном поле — и прошло `required` и
* `rules`. Окно закрывается следом, если не выключен `closeOnConfirm`.
*/
(e: 'confirm', value: string): void;
/** Нажата кнопка отмены. Крестик, Esc и подложка закрывают окно без этого события. */
(e: 'cancel'): void;
}Файлdist/types/components/GrPromptDialog/config.d.ts
const grPromptDialogConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrPromptDialog">;Доступность
Клавиши
EscTab / Shift+Tab
| Клавиша | Действие |
|---|---|
| Esc | закрыть верхнее окно (если closeOnEsc) |
| Tab / Shift+Tab | цикл внутри фокус-ловушки |
Полный контракт пакета: docs/keyboard.md ↗
Использование из прозы библиотеки
Поле
multiline переключает GrInput на GrTextarea (rows, autosize) —
причина отказа или комментарий не должны собираться через слот. Для
однострочного поля есть inputType (email, password, number, …) и
inputmode. maxlength со showCount рисует счётчик; он уже связан с полем
через aria-describedby.
Поле обязано представиться браузеру
autocomplete, name, autocapitalize и spellcheck доезжают до поля в обеих
ветвях — и однострочной, и многострочной. Умолчание у всех — отсутствие
атрибута: окно ничего не додумывает.
dialog.prompt('Подтвердите пароль', {
inputType: 'password',
autocomplete: 'current-password',
name: 'password',
})Без них менеджер паролей поле не опознаёт: 1Password, Safari и Chrome смотрят на
autocomplete и на имя поля, и подтверждение пароля приходится набирать руками
на каждом действии.
autocomplete из inputType не выводится. У одного и того же password три
разных правильных значения — current-password, new-password,
one-time-code, — и окно не знает, которое из них верно: им спрашивают и старый
пароль, и новый, и одноразовый код. Догадка здесь была бы враньём.
autocapitalize и spellcheck — пара к autocomplete="off" для секретов,
которые вводят руками. Резервный код 2FA сверяется байт в байт, а генерируется в
смешанном регистре: без autocapitalize="off" мобильная клавиатура поднимает
первую букву.
Те же четыре поля есть у dialog.prompt — расхождение между декларативным и
императивным путями сторожит гейт GrDialogService/__tests__/promptSurface.test.ts.
id полю не задаётся: его генерирует GrFormField, а поле читает из контекста.
Литеральный id ломал ровно то, ради чего он был написан — два открытых
диалога (обычный и через сервис) давали дубликат DOM-id, и <label for> уводил
на чужой инпут.
Проверка значения
required (по умолчанию true) — быстрая синхронная проверка «непусто». Она
блокирует кнопку и не ходит в асинхронный движок.
Всё остальное — проп rules с теми же правилами, что у GrForm: type,
min/max/len, pattern, свой в том числе асинхронный validator.
Третьего частного случая валидации в пакете нет — это тот же
runFieldRules, и сообщения резолвит тот же
createGrFormMessageResolver (оба публичны).
<GrPromptDialog
v-model="open"
v-model:value="email"
:rules="{ type: 'email', message: 'Нужен рабочий адрес' }"
/>Правила прогоняются на blur (после первого касания) и на подтверждении. Пока проверка идёт, кнопка показывает загрузку; ответ устаревшего прогона отбрасывается — асинхронное правило может вернуться уже после того, как значение сменилось.
Ошибка приходит и снаружи: fieldError (серверная валидация поля) сильнее
встроенных проверок, error рисует общий баннер в теле окна.
Фокус и клавиатура
При открытии фокус уходит в поле, а не на панель окна: диалог существует
ровно ради ввода. Сделано на стороне содержимого, а не пропом initialFocus
у GrModal, — элемент рождается внутри поддерева диалога, и возврат его же
пропом наверх замыкает рендер в цикл.
Enter в однострочном поле подтверждает. В многострочном режиме Enter
остаётся переводом строки, и подтверждают кнопкой.
Пропы этого примера