Como criar tours persistentes no app

Os tours de integração exigem sobreposições que permanecem enquanto os usuários interagem com os recursos destacados. Ao contrário dos popovers automáticos, os manuais não fecham quando o usuário clica em outro lugar da página. Combinar popover="manual" com o posicionamento de âncora CSS permite criar etapas de tour não modais e vinculadas.

HTML

<div id="feature-target">Highlight this feature</div>

<!-- MANDATORY: Enforce overlay dialog semantics and accessible name bindings -->
<div id="tour-step" popover="manual" role="dialog" aria-labelledby="tour-title">
  <!-- Assume an <h1> precedes this element in the full document outline -->
  <h2 id="tour-title">Step 1</h2>
  <p>Learn how to use this feature.</p>
  <button popovertarget="tour-step" popovertargetaction="hide">Got it</button>
</div>

CSS

#feature-target {
  anchor-name: --feature-target;
}

#tour-step {
  popover: manual;
  position-anchor: --feature-target;
  position-area: right center;
  inset: auto;
  margin: 1rem;
  padding: 1rem;
  border: 1px solid blue;
  border-radius: 0.5rem;
  background: aliceblue;
}

JavaScript

const tourStep = document.getElementById('tour-step');
tourStep.showPopover();
// MANDATORY: Programmatically route focus into the non-modal popover so keyboard/assistive technology users immediately perceive the new context
tourStep.querySelector('button').focus();

Diretrizes de implementação

  • OBRIGATÓRIO: use popover="manual" para evitar que a etapa do tour seja fechada acidentalmente durante a interação do usuário.
  • OBRIGATÓRIO: marque o contêiner com role="dialog" e vincule o título dele usando aria-labelledby.
  • OBRIGATÓRIO: mude o foco programático para dentro do popover imediatamente após a abertura para evitar o abandono do foco.
  • USE o posicionamento de âncora do CSS para vincular a etapa do tour ao recurso específico que está sendo explicado.
  • É RECOMENDÁVEL fornecer um botão "Fechar" ou "Próxima" explícito no popover que usa popovertargetaction="hide".

Estratégias de fallback

Alternativas e suporte do navegador para Popover

A API Popover é, em grande parte, um aprimoramento progressivo, mas os comportamentos que a definem (promoção de camada superior, fechamento leve e invocação de popovertarget) não têm equivalente somente em CSS. Os navegadores mais antigos precisam de um polyfill ou de um substituto manual, se você preferir não enviar um.

Polyfill: para oferecer suporte ao atributo popover em navegadores mais antigos, carregue condicionalmente @oddbird/popover-polyfill. OBRIGATÓRIO: detecte o recurso verificando a propriedade popover em HTMLElement.prototype e carregue o polyfill somente quando não houver suporte nativo. NÃO o carregue incondicionalmente.

Com um bundler ou mapa de importação:

// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
  import("@oddbird/popover-polyfill");
}

Sem um bundler, importe de uma CDN dentro de um <script type="module">:

<script type="module">
  if (!("popover" in HTMLElement.prototype)) {
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  }
</script>

Observação sobre o estilo: o polyfill não pode definir a pseudoclasse :popover-open real. Por isso, ele aplica uma classe .\:popover-open. OBRIGATÓRIO: combine os dois com :is() ou :where(). Caso contrário, os navegadores que não têm :popover-open vão descartar toda a regra:

[popover]:is(:popover-open, .\:popover-open) {
  display: block;
}

Como alternativa, para um substituto legado sem um polyfill, use position: fixed e calcule manualmente as coordenadas usando getBoundingClientRect() ou use o posicionamento padrão com inset: auto, se isso for aceitável para o caso de uso.

anchor-positioning

Para oferecer suporte a navegadores sem posicionamento de âncora, use um polyfill ou um substituto de CSS puro.

Opção 1: fallback de polyfill

O polyfill @oddbird/css-anchor-positioning pode ser usado para emular o posicionamento de âncoras. Ele não é compatível com âncoras implícitas. Portanto, é OBRIGATÓRIO adicionar nomes de âncoras explícitos ao gatilho. Além disso, o polyfill não oferece suporte a position-area em popovers. Portanto, use anchor() nos encartes desejados em vez de position-area.

<script type="module">
  if (!CSS.supports('anchor-name: --foo')) {
    await import("https://unpkg.com/@oddbird/css-anchor-positioning");
  }
</script>
#tour-step {
  /* If using the anchor positioning polyfill with a popover, DO use `anchor()` functions instead of `position-area`. */
  left: anchor(right);
  top: anchor(top);
}
Opção 2: substituto de CSS sem polyfill

Se você preferir não usar um polyfill, defina a dica como uma posição fixa na parte de baixo da janela de visualização usando @supports not.

@supports not (anchor-name: --foo) {
  #tour-step {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    margin: 0;
    border-radius: 0;
  }
}