Vitral 0.2
Sobreposição

Dialog

Uma janela sobre a página, modal ou não, que leva o foco para dentro, o mantém ali e o devolve ao fechar.

Importação

main.ts
import { Dialog } from '@vitral/vue';

Básico

O cabeçalho dá nome ao diálogo; o rodapé é a faixa de botões.

<script setup lang="ts">import { Button, Dialog, InputText, Label, StackPanel } from '@vitral/vue';import { ref } from 'vue'; const visible = ref(false);const name = ref('Ana Souza');const email = ref('ana@example.com');</script> <template>    <Button label="Edit profile" icon="pencil" @click="visible = true" />    <Dialog v-model:visible="visible" header="Edit profile" style="width: 28rem">        <StackPanel spacing="0.875rem">            <span style="font-size: 0.875rem; color: var(--vt-text-muted-color)">Update how others see you.</span>            <StackPanel spacing="0.375rem">                <Label for="dlg-name">Name</Label>                <InputText id="dlg-name" v-model="name" fluid />            </StackPanel>            <StackPanel spacing="0.375rem">                <Label for="dlg-email">Email</Label>                <InputText id="dlg-email" v-model="email" type="email" fluid />            </StackPanel>        </StackPanel>        <template #footer>            <Button label="Cancel" severity="secondary" @click="visible = false" />            <Button label="Save" @click="visible = false" />        </template>    </Dialog></template>

Posição

O diálogo fica no centro, ao longo de uma borda ou num canto, e desliza a partir dali.

<script setup lang="ts">import { Button, Dialog } from '@vitral/vue';import { ref } from 'vue'; type Position = 'center' | 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; const positions: Position[] = ['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right'];const visible = ref(false);const position = ref<Position>('top'); function openAt(where: Position) {    position.value = where;    visible.value = true;}</script> <template>    <div style="display: grid; grid-template-columns: repeat(3, 8rem); gap: 0.5rem">        <Button v-for="p in positions" :key="p" :label="p" severity="secondary" size="small" @click="openAt(p)" />    </div>    <Dialog v-model:visible="visible" :header="`Position: ${position}`" :position="position" style="width: 22rem" dismissable-mask>        A press on the mask closes this one (<code>dismissable-mask</code>).    </Dialog></template>

Maximizável

Um botão faz o diálogo ocupar toda a viewport; o nome dele alterna entre Maximize e Restore.

<script setup lang="ts">import { Button, Dialog } from '@vitral/vue';import { ref } from 'vue'; const visible = ref(false);</script> <template>    <Button label="Terms of service" severity="secondary" @click="visible = true" />    <Dialog v-model:visible="visible" header="Terms of service" maximizable style="width: 36rem; height: 24rem">        <p v-for="n in 8" :key="n">            {{ n }}. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Donec ullamcorper nulla non metus            auctor fringilla, maecenas faucibus mollis interdum.        </p>        <template #footer>            <Button label="Decline" severity="secondary" @click="visible = false" />            <Button label="Accept" autofocus @click="visible = false" />        </template>    </Dialog></template>

Não modal

`modal: false` mantém a página utilizável: sem máscara, sem foco preso, sem bloqueio de rolagem. Escape continua fechando.

<script setup lang="ts">import { Button, Dialog, InputText } from '@vitral/vue';import { ref } from 'vue'; const visible = ref(false);</script> <template>    <Button label="Open a modeless dialog" severity="secondary" @click="visible = true" />    <Dialog v-model:visible="visible" header="Find" :modal="false" position="bottom-right" style="width: 20rem">        <InputText aria-label="Find text" placeholder="Search the page…" fluid />    </Dialog></template>

Overlays dentro

Abra o select e pressione Escape: o select fecha primeiro, e o diálogo fica.

<script setup lang="ts">import { Button, Dialog, Label, Select, StackPanel } from '@vitral/vue';import { ref } from 'vue'; const visible = ref(false);const role = ref<string | null>(null);const roles = [{ name: 'Viewer' }, { name: 'Editor' }, { name: 'Owner' }];</script> <template>    <Button label="Invite someone" severity="secondary" icon="user" @click="visible = true" />    <Dialog v-model:visible="visible" header="Invite" style="width: 24rem">        <StackPanel spacing="0.375rem">            <Label for="dlg-role">Role</Label>            <Select id="dlg-role" v-model="role" :options="roles" option-label="name" option-value="name" placeholder="Choose a role" fluid />        </StackPanel>        <template #footer>            <Button label="Send invite" :disabled="!role" @click="visible = false" />        </template>    </Dialog></template>

API

Lido de packages/vue/src/components/Dialog/types.ts, então diz o que o componente aceita de fato.

Props

NomeTipoDescrição
headerstringO título; ele dá nome ao diálogo. Sem ele, nomeie-o com `aria-label` ou `aria-labelledby`.
modalbooleanEscurece e bloqueia a página, prende o foco e trava a rolagem. O padrão é true.
closablebooleanMostra o botão de fechar. O padrão é true.
dismissableMaskbooleanFecha com um clique na máscara.
closeOnEscapebooleanO padrão é true.
positionDialogPosition—
maximizablebooleanAdiciona um botão que faz o diálogo ocupar a viewport.
blockScrollbooleanTrava a rolagem da página mesmo quando o diálogo não é modal.
showHeaderbooleanO padrão é true.
appendTostring`'body'` (o padrão), `'self'` para renderizar no lugar, ou um seletor.

Mais pt, dt e unstyled de BaseProps; veja pass-through e modo sem estilo.

Emits

EventoPayloadDescrição
show——
hide——
after-hide—Depois da animação de fechar, quando o diálogo já saiu da página.
maximize——
unmaximize——

Slots

NomeProps do slotDescrição
default——
header—Substitui o texto do título; ele continua dando nome ao diálogo.
footer——
closeicon——
maximizeicon(props: { maximized: boolean })—