@nexdom/uimed-vue 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/dialogs/dialog/dialog.vue.d.ts +10 -0
- package/dist/components/dialogs/dialog/dialog.vue_vue_type_script_setup_true_lang.js +41 -5
- package/dist/components/dialogs/dialog/types.d.ts +5 -3
- package/dist/composables/dialogs/use-dialog-focus.js +16 -2
- package/dist/composables/dialogs/use-dialog.d.ts +2 -1
- package/dist/composables/dialogs/use-dialog.js +2 -1
- package/dist/styles/settings.scss +0 -1
- package/package.json +1 -1
- package/skills/uimed-vue/references/api/components/dialog.md +11 -11
- package/skills/uimed-vue/references/api/composables/use-confirm.md +1 -1
- package/skills/uimed-vue/references/api/composables/use-dialog.md +3 -2
- package/skills/uimed-vue/references/api/composables/use-unsaved-changes.md +1 -1
- package/skills/uimed-vue/references/guide/components/dialog.md +7 -7
- package/skills/uimed-vue/references/guide/composables/use-confirm.md +2 -2
- package/skills/uimed-vue/references/guide/composables/use-dialog.md +2 -2
- package/skills/uimed-vue/references/guide/composables/use-unsaved-changes.md +1 -1
|
@@ -17,10 +17,20 @@ import { DialogProps } from "./types.js";
|
|
|
17
17
|
*/
|
|
18
18
|
declare const _default: typeof __VLS_export;
|
|
19
19
|
declare const __VLS_export: __VLS_WithSlots<import("vue", { with: { "resolution-mode": "import" } }).DefineComponent<DialogProps & {
|
|
20
|
+
/**
|
|
21
|
+
* Whether the dialog is open. Updated to `false` when the user closes it with the "Fechar" button
|
|
22
|
+
* at its top right, `Esc`, a click outside or the browser's back button, once its leave transition
|
|
23
|
+
* ends.
|
|
24
|
+
*/
|
|
20
25
|
modelValue?: boolean;
|
|
21
26
|
}, {}, {}, {}, {}, import("vue", { with: { "resolution-mode": "import" } }).ComponentOptionsMixin, import("vue", { with: { "resolution-mode": "import" } }).ComponentOptionsMixin, {
|
|
22
27
|
"update:modelValue": (value: boolean) => any;
|
|
23
28
|
}, string, import("vue", { with: { "resolution-mode": "import" } }).PublicProps, Readonly<DialogProps & {
|
|
29
|
+
/**
|
|
30
|
+
* Whether the dialog is open. Updated to `false` when the user closes it with the "Fechar" button
|
|
31
|
+
* at its top right, `Esc`, a click outside or the browser's back button, once its leave transition
|
|
32
|
+
* ends.
|
|
33
|
+
*/
|
|
24
34
|
modelValue?: boolean;
|
|
25
35
|
}> & Readonly<{
|
|
26
36
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { icons } from "../../../consts/icons.js";
|
|
1
2
|
import button_default from "../../button/button.js";
|
|
2
3
|
import { dialogHostKey } from "./dialog-host-key.js";
|
|
3
4
|
import { useDialogFocus } from "../../../composables/dialogs/use-dialog-focus.js";
|
|
4
5
|
import { useDialogLoading } from "../../../composables/dialogs/use-dialog-loading.js";
|
|
5
6
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, mergeModels, mergeProps, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, useModel, useTemplateRef, watch, withCtx } from "vue";
|
|
6
|
-
import { VCard, VDialog } from "vuetify/components";
|
|
7
|
+
import { VCard, VCardItem, VCardText, VCardTitle, VDialog, VIconBtn } from "vuetify/components";
|
|
7
8
|
//#region src/components/dialogs/dialog/dialog.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
-
const _hoisted_1 =
|
|
9
|
+
const _hoisted_1 = { class: "text-truncate" };
|
|
10
|
+
const _hoisted_2 = ["id"];
|
|
9
11
|
var dialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
10
12
|
inheritAttrs: false,
|
|
11
13
|
__name: "dialog",
|
|
@@ -36,6 +38,11 @@ var dialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCom
|
|
|
36
38
|
emits: ["update:modelValue"],
|
|
37
39
|
setup(__props) {
|
|
38
40
|
const props = __props;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the dialog is open. Updated to `false` when the user closes it with the "Fechar" button
|
|
43
|
+
* at its top right, `Esc`, a click outside or the browser's back button, once its leave transition
|
|
44
|
+
* ends.
|
|
45
|
+
*/
|
|
39
46
|
const model = useModel(__props, "modelValue");
|
|
40
47
|
const maxWidths = {
|
|
41
48
|
small: 400,
|
|
@@ -56,6 +63,14 @@ var dialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCom
|
|
|
56
63
|
watch(model, (value) => isActive.value = value);
|
|
57
64
|
const { isLoading } = useDialogLoading(() => props.actions);
|
|
58
65
|
const { focusFirstElement } = useDialogFocus(() => isActive.value, () => card.value?.$el);
|
|
66
|
+
/**
|
|
67
|
+
* Closes the dialog from its close button, unless an action loads. The icon button's `disabled`
|
|
68
|
+
* only blocks pointer clicks and leaves the native `disabled` attribute out, hence its
|
|
69
|
+
* `aria-disabled`.
|
|
70
|
+
*/
|
|
71
|
+
function close() {
|
|
72
|
+
if (!isLoading.value) isActive.value = false;
|
|
73
|
+
}
|
|
59
74
|
function onAfterLeave() {
|
|
60
75
|
model.value = false;
|
|
61
76
|
host?.afterLeave();
|
|
@@ -78,10 +93,31 @@ var dialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCom
|
|
|
78
93
|
default: withCtx(() => [createCommentVNode(" `data-u-dialog` identifies the card to the dialogs opened from this one "), createVNode(unref(VCard), {
|
|
79
94
|
ref_key: "card",
|
|
80
95
|
ref: card,
|
|
81
|
-
title: title.value,
|
|
82
96
|
"data-u-dialog": ""
|
|
83
97
|
}, createSlots({
|
|
84
|
-
|
|
98
|
+
default: withCtx(() => [createVNode(unref(VCardItem), null, {
|
|
99
|
+
default: withCtx(() => [createCommentVNode(" The card's title prop has no room for the close button, so the title is built by hand.\n The flex classes place the button at the end, and the truncation brings back the ellipsis\n that the flex layout turns off "), createVNode(unref(VCardTitle), { class: "d-flex justify-space-between align-center" }, {
|
|
100
|
+
default: withCtx(() => [createElementVNode("span", _hoisted_1, toDisplayString(title.value), 1), createVNode(unref(VIconBtn), {
|
|
101
|
+
icon: unref(icons).close,
|
|
102
|
+
"aria-label": "Fechar",
|
|
103
|
+
"aria-disabled": unref(isLoading),
|
|
104
|
+
variant: "text",
|
|
105
|
+
size: "small",
|
|
106
|
+
"data-u-dialog-close": "",
|
|
107
|
+
disabled: unref(isLoading),
|
|
108
|
+
onClick: close
|
|
109
|
+
}, null, 8, [
|
|
110
|
+
"icon",
|
|
111
|
+
"aria-disabled",
|
|
112
|
+
"disabled"
|
|
113
|
+
])]),
|
|
114
|
+
_: 1
|
|
115
|
+
})]),
|
|
116
|
+
_: 1
|
|
117
|
+
}), createVNode(unref(VCardText), null, {
|
|
118
|
+
default: withCtx(() => [createElementVNode("div", { id: unref(contentId) }, [renderSlot(_ctx.$slots, "default")], 8, _hoisted_2)]),
|
|
119
|
+
_: 3
|
|
120
|
+
})]),
|
|
85
121
|
_: 2
|
|
86
122
|
}, [props.actions?.length ? {
|
|
87
123
|
name: "actions",
|
|
@@ -92,7 +128,7 @@ var dialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCom
|
|
|
92
128
|
}, 1040, ["onClick"]);
|
|
93
129
|
}), 128))]),
|
|
94
130
|
key: "0"
|
|
95
|
-
} : void 0]),
|
|
131
|
+
} : void 0]), 1536)]),
|
|
96
132
|
_: 3
|
|
97
133
|
}, 8, [
|
|
98
134
|
"modelValue",
|
|
@@ -2,7 +2,8 @@ import { ButtonProps } from "../../button/types.js";
|
|
|
2
2
|
//#region src/components/dialogs/dialog/types.d.ts
|
|
3
3
|
export type DialogSize = "small" | "medium" | "large";
|
|
4
4
|
/**
|
|
5
|
-
* Props exposed by the {@link Dialog} component.
|
|
5
|
+
* Props exposed by the {@link Dialog} component. Every dialog displays a "Fechar" button at the top
|
|
6
|
+
* right of its title, which closes it as `Esc` and a click outside do.
|
|
6
7
|
*/
|
|
7
8
|
export type DialogProps = {
|
|
8
9
|
/**
|
|
@@ -14,8 +15,9 @@ export type DialogProps = {
|
|
|
14
15
|
* Buttons displayed at the bottom of the dialog, right-aligned, in the given order.
|
|
15
16
|
* Place the main action last. When undefined or empty, no actions area is rendered.
|
|
16
17
|
* Clicking an action doesn't close the dialog: set `v-model` to `false` in `onClick`.
|
|
17
|
-
* While any action is `loading`, the user can't close the dialog with
|
|
18
|
-
* the browser's back button, but setting `v-model` to
|
|
18
|
+
* While any action is `loading`, the user can't close the dialog with the "Fechar" button at its
|
|
19
|
+
* top right, `Esc`, a click outside or the browser's back button, but setting `v-model` to
|
|
20
|
+
* `false` still closes it.
|
|
19
21
|
*/
|
|
20
22
|
actions?: DialogButtonAction[];
|
|
21
23
|
/**
|
|
@@ -2,7 +2,10 @@ import { onMounted, toValue, watch } from "vue";
|
|
|
2
2
|
//#region src/composables/dialogs/use-dialog-focus.ts
|
|
3
3
|
/** Focus state of the closed dialogs, by their card, for the dialogs opened from them. */
|
|
4
4
|
const closedDialogs = /* @__PURE__ */ new WeakMap();
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Elements that can get the focus when the dialog opens. The first one in the dialog gets it, unless
|
|
7
|
+
* it's the close button.
|
|
8
|
+
*/
|
|
6
9
|
const focusable = [
|
|
7
10
|
"button:not([disabled])",
|
|
8
11
|
"[href]",
|
|
@@ -12,6 +15,16 @@ const focusable = [
|
|
|
12
15
|
"[tabindex]:not([tabindex=\"-1\"])"
|
|
13
16
|
].join(", ");
|
|
14
17
|
/**
|
|
18
|
+
* Focusable elements other than the dialog's close button, marked with `data-u-dialog-close`,
|
|
19
|
+
* which only gets the focus when it's the only one.
|
|
20
|
+
*/
|
|
21
|
+
const focusableExceptClose = `:is(${focusable}):not([data-u-dialog-close])`;
|
|
22
|
+
/**
|
|
23
|
+
* Focusable elements that aren't disabled through `aria-disabled`, such as the close button while an
|
|
24
|
+
* action loads, which keyboard navigation skips. Without one, the focus stays on the dialog itself.
|
|
25
|
+
*/
|
|
26
|
+
const focusableEnabled = `:is(${focusable}):not([aria-disabled="true"])`;
|
|
27
|
+
/**
|
|
15
28
|
* Moves the focus into a dialog once it opens and back to where it was when it closes, including
|
|
16
29
|
* when dialogs are opened from others. Internal to the dialog components.
|
|
17
30
|
* @param isActive - Whether the dialog is displayed. It turns `false` as soon as the dialog starts
|
|
@@ -38,7 +51,8 @@ function useDialogFocus(isActive, card) {
|
|
|
38
51
|
if (hasFocus(element) && (target instanceof HTMLElement || target instanceof SVGElement)) target.focus();
|
|
39
52
|
}
|
|
40
53
|
function focusFirstElement() {
|
|
41
|
-
toValue(card)
|
|
54
|
+
const element = toValue(card);
|
|
55
|
+
(element?.querySelector(focusableExceptClose) ?? element?.querySelector(focusableEnabled))?.focus();
|
|
42
56
|
}
|
|
43
57
|
return { focusFirstElement };
|
|
44
58
|
}
|
|
@@ -25,7 +25,8 @@ export default function useDialog(): {
|
|
|
25
25
|
* Displays a dialog. Dialogs are displayed one at a time, in the order they were requested.
|
|
26
26
|
* @param {DialogOptions} options - Options for the dialog.
|
|
27
27
|
* @returns the `value` of the clicked action, or `undefined` when the dialog is closed by the
|
|
28
|
-
* default action, the `Esc` key, a click outside it or the
|
|
28
|
+
* default action, the "Fechar" button at its top right, the `Esc` key, a click outside it or the
|
|
29
|
+
* browser's back button.
|
|
29
30
|
*
|
|
30
31
|
* @example
|
|
31
32
|
* ```ts
|
|
@@ -54,7 +54,8 @@ function useDialog() {
|
|
|
54
54
|
* Displays a dialog. Dialogs are displayed one at a time, in the order they were requested.
|
|
55
55
|
* @param {DialogOptions} options - Options for the dialog.
|
|
56
56
|
* @returns the `value` of the clicked action, or `undefined` when the dialog is closed by the
|
|
57
|
-
* default action, the `Esc` key, a click outside it or the
|
|
57
|
+
* default action, the "Fechar" button at its top right, the `Esc` key, a click outside it or the
|
|
58
|
+
* browser's back button.
|
|
58
59
|
*
|
|
59
60
|
* @example
|
|
60
61
|
* ```ts
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# UDialog
|
|
2
2
|
|
|
3
3
|
Componente para exibir conteúdo em uma janela modal, sobre a página, até que ela seja fechada.
|
|
4
|
-
O título e as ações ficam fixos enquanto o conteúdo rola.
|
|
4
|
+
O título e as ações ficam fixos enquanto o conteúdo rola. Toda janela apresenta um botão "Fechar" no canto superior direito.
|
|
5
5
|
|
|
6
6
|
## Props
|
|
7
7
|
|
|
8
|
-
| Prop | Tipo | Padrão | Descrição
|
|
9
|
-
| ------------ | --------------------------------- | ---------- |
|
|
10
|
-
| `modelValue` | `boolean` | `false` | Indica se a janela está aberta. Use com `v-model`. Quando o usuário fecha a janela, passa a ser `false` somente ao fim da animação de fechamento.
|
|
11
|
-
| `title` | `string` | | Título da janela, em texto simples (HTML não é interpretado), em uma única linha: títulos longos são cortados com reticências. Também é o nome acessível da janela; sem título, o nome acessível é o conteúdo.
|
|
12
|
-
| `actions` | [`DialogButtonAction[]`](#action) | | Botões exibidos no rodapé da janela, alinhados à direita, nesta ordem. Sem ações, o rodapé não é exibido. Enquanto alguma ação está `loading`, o usuário não consegue fechar a janela; o `v-model` ainda pode fechá-la. |
|
|
13
|
-
| `size` | `"small" \| "medium" \| "large"` | `"medium"` | Largura máxima da janela: `small` (400px), `medium` (560px) ou `large` (800px).
|
|
14
|
-
| `dataTestid` | `string` | | Id do componente para uso em testes automatizados.
|
|
8
|
+
| Prop | Tipo | Padrão | Descrição |
|
|
9
|
+
| ------------ | --------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
10
|
+
| `modelValue` | `boolean` | `false` | Indica se a janela está aberta. Use com `v-model`. Quando o usuário fecha a janela, passa a ser `false` somente ao fim da animação de fechamento. |
|
|
11
|
+
| `title` | `string` | | Título da janela, em texto simples (HTML não é interpretado), em uma única linha: títulos longos são cortados com reticências. Também é o nome acessível da janela; sem título, o nome acessível é o conteúdo. |
|
|
12
|
+
| `actions` | [`DialogButtonAction[]`](#action) | | Botões exibidos no rodapé da janela, alinhados à direita, nesta ordem. Sem ações, o rodapé não é exibido. Enquanto alguma ação está `loading`, o usuário não consegue fechar a janela e o botão "Fechar" fica desabilitado; o `v-model` ainda pode fechá-la. |
|
|
13
|
+
| `size` | `"small" \| "medium" \| "large"` | `"medium"` | Largura máxima da janela: `small` (400px), `medium` (560px) ou `large` (800px). |
|
|
14
|
+
| `dataTestid` | `string` | | Id do componente para uso em testes automatizados. |
|
|
15
15
|
|
|
16
16
|
### `Action`
|
|
17
17
|
|
|
@@ -24,9 +24,9 @@ Estende [`UButtonProps`](./button.md#props) com as seguintes propriedades adicio
|
|
|
24
24
|
|
|
25
25
|
## Eventos
|
|
26
26
|
|
|
27
|
-
| Evento | Retorno | Descrição
|
|
28
|
-
| ------------------- | --------- |
|
|
29
|
-
| `update:modelValue` | `boolean` | Retorna `false` quando o usuário fecha a janela pela tecla `Esc`, por um clique fora dela ou pelo botão "voltar", somente ao fim da animação de fechamento. `Esc`, um clique fora ou o "voltar"
|
|
27
|
+
| Evento | Retorno | Descrição |
|
|
28
|
+
| ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
29
|
+
| `update:modelValue` | `boolean` | Retorna `false` quando o usuário fecha a janela pelo botão "Fechar", pela tecla `Esc`, por um clique fora dela ou pelo botão "voltar", somente ao fim da animação de fechamento. Enquanto alguma ação está `loading`, o botão "Fechar" fica desabilitado, e `Esc`, um clique fora ou o "voltar" não fecham a janela nem emitem o evento. |
|
|
30
30
|
|
|
31
31
|
## Slots
|
|
32
32
|
|
|
@@ -56,7 +56,7 @@ Os diálogos de `confirm` compartilham a fila de diálogos do [`useDialog`](./us
|
|
|
56
56
|
|
|
57
57
|
- a ação falha;
|
|
58
58
|
- o usuário clica no botão de cancelamento;
|
|
59
|
-
- o usuário pressiona a tecla `Esc` ou clica fora do diálogo;
|
|
59
|
+
- o usuário clica no botão "Fechar" no canto superior direito, pressiona a tecla `Esc` ou clica fora do diálogo;
|
|
60
60
|
- o usuário usa o botão "voltar" do navegador, em aplicações que usam o [Vue Router](https://router.vuejs.org/), exceto quando ele leva a uma página aberta com `router.replace` (como a página pela qual o usuário entrou na aplicação).
|
|
61
61
|
|
|
62
62
|
### Acessibilidade
|
|
@@ -56,14 +56,15 @@ Os diálogos são apresentados um de cada vez, na ordem em que foram solicitados
|
|
|
56
56
|
|
|
57
57
|
`dialog` resolve o `value` da ação clicada, ou `undefined` quando o diálogo é fechado:
|
|
58
58
|
|
|
59
|
-
-
|
|
59
|
+
- pela ação padrão "Fechar";
|
|
60
|
+
- pelo botão "Fechar" no canto superior direito;
|
|
60
61
|
- pela tecla `Esc`;
|
|
61
62
|
- por um clique fora do diálogo;
|
|
62
63
|
- pelo botão "voltar" do navegador, em aplicações que usam o [Vue Router](https://router.vuejs.org/), exceto quando ele leva a uma página aberta com `router.replace` (como a página pela qual o usuário entrou na aplicação).
|
|
63
64
|
|
|
64
65
|
### Acessibilidade
|
|
65
66
|
|
|
66
|
-
O foco inicia na primeira ação, fica restrito ao diálogo enquanto ele estiver aberto e volta ao elemento de origem quando ele fecha. O diálogo é identificado pelo título (ou pela mensagem, quando não houver título) e descrito pela mensagem.
|
|
67
|
+
O foco inicia na primeira ação (nunca no botão "Fechar" do canto superior direito), fica restrito ao diálogo enquanto ele estiver aberto e volta ao elemento de origem quando ele fecha. O diálogo é identificado pelo título (ou pela mensagem, quando não houver título) e descrito pela mensagem.
|
|
67
68
|
|
|
68
69
|
## Exemplo
|
|
69
70
|
|
|
@@ -50,7 +50,7 @@ Para marcar o formulário como salvo, atribua a `previous` uma cópia do valor a
|
|
|
50
50
|
Quando o componente é renderizado por um `<RouterView>` do [Vue Router](https://router.vuejs.org/) (diretamente ou dentro de uma página), sair da página com alterações apresenta um diálogo de [confirmação](./use-confirm.md):
|
|
51
51
|
|
|
52
52
|
- "Sair sem salvar" continua a navegação;
|
|
53
|
-
- "Continuar editando", a tecla `Esc` ou um clique fora do diálogo cancelam a navegação.
|
|
53
|
+
- "Continuar editando", o botão "Fechar" no canto superior direito, a tecla `Esc` ou um clique fora do diálogo cancelam a navegação.
|
|
54
54
|
|
|
55
55
|
`hasChanges` é lido no momento da navegação, então uma navegação feita logo depois de atualizar `previous` acontece sem diálogo. Enquanto o diálogo estiver aberto, novas navegações reaproveitam a mesma resposta, que vale para a navegação mais recente. Em aplicações com Vue Router e histórico do navegador (`createWebHistory` ou `createWebHashHistory`), o botão "voltar" do navegador passa pela mesma verificação e, com o diálogo aberto, não o fecha (ao contrário do [`useConfirm`](./use-confirm.md)): a resposta passa a valer para o "voltar". Cada chamada de `useUnsavedChanges` com alterações apresenta o seu diálogo.
|
|
56
56
|
|
|
@@ -9,7 +9,7 @@ A janela abre e fecha pelo `v-model`. Para apresentar apenas uma mensagem ou ped
|
|
|
9
9
|
|
|
10
10
|
## Uso
|
|
11
11
|
|
|
12
|
-
A prop `title` define o título da janela, em texto simples e em uma única linha (títulos longos são cortados com reticências), e o conteúdo vai no slot padrão. A prop `actions` define os botões exibidos no rodapé, alinhados à direita, nesta ordem. Coloque a ação principal por último.
|
|
12
|
+
A prop `title` define o título da janela, em texto simples e em uma única linha (títulos longos são cortados com reticências), e o conteúdo vai no slot padrão. Toda janela apresenta, no canto superior direito, um botão "Fechar" com o ícone "x", inclusive as janelas sem título. A prop `actions` define os botões exibidos no rodapé, alinhados à direita, nesta ordem. Coloque a ação principal por último.
|
|
13
13
|
|
|
14
14
|
Clicar em uma ação **não fecha** a janela: feche-a no `onClick`, alterando o `v-model` para `false`.
|
|
15
15
|
|
|
@@ -36,7 +36,7 @@ const actions: DialogAction[] = [{ label: "Fechar", onClick: () => (open.value =
|
|
|
36
36
|
|
|
37
37
|
### Fechando a janela
|
|
38
38
|
|
|
39
|
-
Além das ações, o usuário pode fechar a janela pela tecla `Esc` ou clicando fora dela.
|
|
39
|
+
Além das ações, o usuário pode fechar a janela pelo botão "Fechar" no canto superior direito, pela tecla `Esc` ou clicando fora dela.
|
|
40
40
|
|
|
41
41
|
O botão "voltar" do navegador também fecha a janela, sem sair da página, em aplicações que usam o [Vue Router](https://router.vuejs.org/). A exceção é quando o "voltar" leva a uma página aberta com `router.replace`, como a página pela qual o usuário entrou na aplicação: nesse caso, a navegação acontece e a janela continua aberta.
|
|
42
42
|
|
|
@@ -46,7 +46,7 @@ Quando o usuário fecha a janela por um desses meios, ela começa a sumir na hor
|
|
|
46
46
|
- se o `@update:model-value` recusar a atualização, mantendo o valor `true`, a janela continua fechada com o `v-model` em `true`;
|
|
47
47
|
- se a janela for removida da página antes do fim da animação (por um `v-if`, por exemplo), o `v-model` continua `true`.
|
|
48
48
|
|
|
49
|
-
Enquanto alguma ação apresenta um indicador de carregamento (`loading`), o usuário não consegue fechar a janela por nenhum desses meios:
|
|
49
|
+
Enquanto alguma ação apresenta um indicador de carregamento (`loading`), o usuário não consegue fechar a janela por nenhum desses meios: o botão "Fechar" fica desabilitado e, pela tecla `Esc` ou por um clique fora, a janela faz uma breve animação, continua aberta e o `v-model` não muda. Exceto no caso do `router.replace` acima, o "voltar" também não sai da página nesse meio tempo. Ações apenas desabilitadas (`disabled`) não impedem o fechamento nem desabilitam o botão "Fechar". A aplicação ainda pode fechar a janela a qualquer momento, atribuindo `false` ao `v-model`.
|
|
50
50
|
|
|
51
51
|
Em uma página que usa [useUnsavedChanges](../composables/use-unsaved-changes.md) e tem alterações não salvas, o "voltar" é verificado pela página antes da janela, inclusive durante o carregamento: o diálogo "Alterações não salvas" aparece sobre a janela. "Continuar editando" mantém o usuário na página, com a janela aberta, e "Sair sem salvar" sai da página, mesmo que a ação ainda esteja em carregamento.
|
|
52
52
|
|
|
@@ -55,7 +55,7 @@ Em uma página que usa [useUnsavedChanges](../composables/use-unsaved-changes.md
|
|
|
55
55
|
<u-button @click="open = true">Abrir janela</u-button>
|
|
56
56
|
<p>v-model: {{ open }}</p>
|
|
57
57
|
<u-dialog v-model="open" title="Fechando a janela">
|
|
58
|
-
Feche esta janela pela tecla <code>Esc</code> ou clicando fora dela.
|
|
58
|
+
Feche esta janela pelo botão "Fechar", pela tecla <code>Esc</code> ou clicando fora dela.
|
|
59
59
|
</u-dialog>
|
|
60
60
|
</template>
|
|
61
61
|
|
|
@@ -69,7 +69,7 @@ const open = ref(false);
|
|
|
69
69
|
|
|
70
70
|
### Foco
|
|
71
71
|
|
|
72
|
-
Ao abrir, a janela coloca o foco no primeiro elemento focável do conteúdo, como um campo de formulário, ou, se não houver, na primeira ação. Enquanto a janela está aberta, a tecla `Tab` circula apenas entre os elementos dela. Ao fechar, o foco volta ao elemento que estava focado antes de a janela abrir, como o botão que a abriu.
|
|
72
|
+
Ao abrir, a janela coloca o foco no primeiro elemento focável do conteúdo, como um campo de formulário, ou, se não houver, na primeira ação. O botão "Fechar" só recebe o foco inicial quando é o único elemento focável da janela. Enquanto a janela está aberta, a tecla `Tab` circula apenas entre os elementos dela. Ao fechar, o foco volta ao elemento que estava focado antes de a janela abrir, como o botão que a abriu.
|
|
73
73
|
|
|
74
74
|
O título é o nome acessível da janela, anunciado por leitores de tela ao abri-la. Sem título, o conteúdo é anunciado no lugar.
|
|
75
75
|
|
|
@@ -79,7 +79,7 @@ O título é o nome acessível da janela, anunciado por leitores de tela ao abri
|
|
|
79
79
|
|
|
80
80
|
Para enviar um formulário pelas ações, use uma ação do tipo `submit` com a prop `form` apontando para o `id` do [formulário](./form.md). O evento `submit` do formulário só é disparado quando não há pendências de validação.
|
|
81
81
|
|
|
82
|
-
Enquanto os dados são salvos, a ação principal pode apresentar um indicador de carregamento (`loading`) e as demais podem ficar desabilitadas (`disabled`). Nesse meio tempo, a janela não fecha pela tecla `Esc`, por um clique fora dela nem pelo botão "voltar": o usuário acompanha o salvamento até o fim, e o exemplo fecha a janela depois de salvar.
|
|
82
|
+
Enquanto os dados são salvos, a ação principal pode apresentar um indicador de carregamento (`loading`) e as demais podem ficar desabilitadas (`disabled`). Nesse meio tempo, a janela não fecha pelo botão "Fechar", que fica desabilitado, pela tecla `Esc`, por um clique fora dela nem pelo botão "voltar": o usuário acompanha o salvamento até o fim, e o exemplo fecha a janela depois de salvar.
|
|
83
83
|
|
|
84
84
|
O exemplo copia o nome para o rascunho ao abrir a janela, e não ao fechá-la: ao cancelar, a ação passa o `v-model` para `false` enquanto a janela ainda está sumindo, e trocar o texto nesse momento seria visível.
|
|
85
85
|
|
|
@@ -174,7 +174,7 @@ function openSize(value: DialogSize) {
|
|
|
174
174
|
|
|
175
175
|
### Conteúdo longo
|
|
176
176
|
|
|
177
|
-
Quando o conteúdo não cabe na tela, apenas ele rola: o título e as ações continuam visíveis.
|
|
177
|
+
Quando o conteúdo não cabe na tela, apenas ele rola: o título, o botão "Fechar" e as ações continuam visíveis.
|
|
178
178
|
|
|
179
179
|
```vue
|
|
180
180
|
<template>
|
|
@@ -110,11 +110,11 @@ async function fail() {
|
|
|
110
110
|
|
|
111
111
|
### Fechando o diálogo
|
|
112
112
|
|
|
113
|
-
Além do botão de cancelamento, o usuário pode fechar o diálogo pela tecla `Esc` ou clicando fora dele. Nesses casos, `confirm` devolve `false` ao fim da animação de fechamento.
|
|
113
|
+
Além do botão de cancelamento, o usuário pode fechar o diálogo pelo botão "Fechar" no canto superior direito, pela tecla `Esc` ou clicando fora dele. Nesses casos, `confirm` devolve `false` ao fim da animação de fechamento.
|
|
114
114
|
|
|
115
115
|
O botão "voltar" do navegador também fecha o diálogo, sem sair da página, em aplicações que usam o [Vue Router](https://router.vuejs.org/). A exceção é quando o "voltar" leva a uma página aberta com `router.replace`, como a página pela qual o usuário entrou na aplicação: nesse caso, a navegação acontece e o diálogo continua aberto.
|
|
116
116
|
|
|
117
|
-
Enquanto a ação estiver em execução, o diálogo não fecha por nenhum desses meios e, exceto no caso do `router.replace` acima, o "voltar" também não sai da página.
|
|
117
|
+
Enquanto a ação estiver em execução, o diálogo não fecha por nenhum desses meios (o botão "Fechar" fica desabilitado) e, exceto no caso do `router.replace` acima, o "voltar" também não sai da página.
|
|
118
118
|
|
|
119
119
|
## Ver também
|
|
120
120
|
|
|
@@ -8,7 +8,7 @@ Os diálogos são apresentados um de cada vez, na ordem em que foram solicitados
|
|
|
8
8
|
|
|
9
9
|
### Diálogo simples
|
|
10
10
|
|
|
11
|
-
Sem a opção `actions`, o diálogo apresenta apenas
|
|
11
|
+
Sem a opção `actions`, o diálogo apresenta apenas a ação "Fechar", no rodapé, e resolve `undefined`.
|
|
12
12
|
|
|
13
13
|
```vue
|
|
14
14
|
<template>
|
|
@@ -69,7 +69,7 @@ async function openWithActions() {
|
|
|
69
69
|
|
|
70
70
|
### Fechando o diálogo
|
|
71
71
|
|
|
72
|
-
Além
|
|
72
|
+
Além das ações, o usuário pode fechar o diálogo pelo botão "Fechar" no canto superior direito, pela tecla `Esc` ou clicando fora dele. Nesses casos, o diálogo resolve `undefined` ao fim da animação de fechamento.
|
|
73
73
|
|
|
74
74
|
O botão "voltar" do navegador também fecha o diálogo, sem sair da página, em aplicações que usam o [Vue Router](https://router.vuejs.org/). A exceção é quando o "voltar" leva a uma página aberta com `router.replace`, como a página pela qual o usuário entrou na aplicação: nesse caso, a navegação acontece e o diálogo continua aberto.
|
|
75
75
|
|
|
@@ -72,7 +72,7 @@ const actions = computed<ComponentProps<typeof USection>["actions"]>(() => [
|
|
|
72
72
|
Com alterações, sair da página pelo Vue Router apresenta o diálogo "Alterações não salvas", com o foco inicial em "Continuar editando":
|
|
73
73
|
|
|
74
74
|
- "Sair sem salvar" continua a navegação;
|
|
75
|
-
- "Continuar editando", a tecla `Esc` ou um clique fora do diálogo cancelam a navegação, e o usuário continua na página com as suas alterações.
|
|
75
|
+
- "Continuar editando", o botão "Fechar" no canto superior direito, a tecla `Esc` ou um clique fora do diálogo cancelam a navegação, e o usuário continua na página com as suas alterações.
|
|
76
76
|
|
|
77
77
|
Sem alterações, a navegação acontece sem diálogo. Em aplicações com Vue Router e histórico do navegador (`createWebHistory` ou `createWebHashHistory`), o botão "voltar" do navegador também passa pela mesma verificação: ao cancelar, o endereço volta a ser o da página atual.
|
|
78
78
|
|