Vitral 0.2
Sobreposição

Popover

Um diálogo não modal ancorado ao que o abriu, que fecha com Escape, um clique fora ou saindo com Tab.

Importação

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

Compartilhar

Um flyout com um campo e um botão dentro.

<script setup lang="ts">import { Button, InputText, Popover } from '@vitral/vue';import { ref } from 'vue'; const share = ref<InstanceType<typeof Popover> | null>(null);const copied = ref(false);const link = 'https://vitral.dev/s/7f3a9c'; function copy() {    navigator.clipboard?.writeText(link).catch(() => {});    copied.value = true;    setTimeout(() => (copied.value = false), 1500);}</script> <template>    <Button        label="Share"        icon="externalLink"        aria-haspopup="dialog"        :aria-expanded="share?.visible ? 'true' : 'false'"        :aria-controls="share?.visible ? share?.id : undefined"        @click="share?.toggle($event)"    />    <Popover ref="share" aria-labelledby="share-title">        <div style="display: flex; flex-direction: column; gap: 0.75rem; width: 20rem">            <strong id="share-title">Share this document</strong>            <div style="display: flex; gap: 0.5rem">                <InputText :model-value="link" readonly aria-label="Link" fluid />                <Button :label="copied ? 'Copied' : 'Copy'" :icon="copied ? 'check' : 'copy'" severity="secondary" @click="copy" />            </div>            <small style="color: var(--vt-text-muted-color)">Anyone with the link can view.</small>        </div>    </Popover></template>

Posicionamento

`placement` escolhe o lado; ele inverte quando não há espaço.

<script setup lang="ts">import { Button, Popover } from '@vitral/vue';import { ref } from 'vue'; const members = ref<InstanceType<typeof Popover> | null>(null);const people = [    { name: 'Ana Souza', role: 'Owner' },    { name: 'Bruno Lima', role: 'Editor' },    { name: 'Carla Dias', role: 'Viewer' }];</script> <template>    <Button        label="Team members"        icon="user"        severity="secondary"        aria-haspopup="dialog"        :aria-expanded="members?.visible ? 'true' : 'false'"        @click="members?.toggle($event)"    />    <Popover ref="members" placement="right-start" aria-label="Team members">        <ul style="list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; min-width: 14rem">            <li v-for="p in people" :key="p.name" style="display: flex; justify-content: space-between; gap: 1rem">                <span>{{ p.name }}</span>                <small style="color: var(--vt-text-muted-color)">{{ p.role }}</small>            </li>        </ul>        <Button label="Manage" variant="link" size="small" style="margin-top: 0.5rem" @click="members?.hide()" />    </Popover></template>

API

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

Props

NomeTipoDescrição
placementOverlayPlacementOnde abre em relação ao alvo; inverte quando não há espaço. O padrão é `'bottom-start'`.
dismissablebooleanFecha com um clique fora. O padrão é true.
closeOnEscapebooleanO padrão é true.
offsetnumberDistância até o alvo, em pixels. O padrão é 8.
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——

Slots

NomeProps do slotDescrição
default(props: { closeCallback: () => void })—