Common
useAttentionPulse
Composable interno per la pulsazione di attenzione di un overlay, quando un'interazione non ha effetto e serve un'azione esplicita.
Composable interno — utilizzato da
DialogeConfirmDialogsul click alla mask.
Introdotto nella 1.9.0 insieme ai dialoghi non dismissibili dal backdrop: il click sulla mask non chiude nulla, e senza riscontro visivo l'interfaccia sembra bloccata. Il composable gestisce la finestra temporale in cui applicare la classe dell'animazione.
Firma TypeScript
export function useAttentionPulse(durationMs?: number): UseAttentionPulseResult
export interface UseAttentionPulseResult {
isPulsing: Ref<boolean>;
pulse: () => void;
}
Parametri
| Parametro | Tipo | Descrizione |
|---|---|---|
durationMs | number | Durata della pulsazione, allineata ai keyframes CSS (default: 320) |
Valore di Ritorno
| Proprietà | Tipo | Descrizione |
|---|---|---|
isPulsing | Ref<boolean> | true mentre la pulsazione è in corso: applicare .hs-overlay-attention |
pulse | () => void | Avvia (o riavvia) la pulsazione |
Esempio
<script setup lang="ts">
import { useAttentionPulse } from '@/composables/common'
const { isPulsing, pulse } = useAttentionPulse()
const handleOverlayClick = (event: MouseEvent) => {
if (event.target !== event.currentTarget) return
emit('maskClick', event)
if (props.dismissableMask) {
requestClose('mask', event)
return
}
pulse()
}
</script>
<template>
<div class="hs-modal-container" :class="{ 'hs-overlay-attention': isPulsing }" />
</template>
Animazione CSS
L'animazione vera è in CSS, sulla classe .hs-overlay-attention:
@keyframes hs-overlay-attention {
0% { scale: 1; }
35% { scale: 1.015; }
70% { scale: 0.995; }
100% { scale: 1; }
}
Due scelte importanti:
- agisce sulla proprietà
scale, non sutransform: quest'ultimo è occupato dal riposizionamento del dialogo trascinabile, che durante la pulsazione non deve saltare; - è disattivata sotto
prefers-reduced-motion: reduce(WCAG 2.3.3).
Su click ripetuti la classe viene rimossa e riapplicata in due frame distinti, così i keyframes ripartono da capo: rimuoverla e riaggiungerla nello stesso tick non cambierebbe il DOM e l'animazione non si riavvierebbe.