<HelpWidget /> do @userkit/react é o mesmo painel
como código — com controle de estilo (unstyled), o arranjo inline e os
componentes no meio do seu. Para os outros componentes por script — login, conta,
planos —, veja Componentes por script.
O que a página paga
Uma requisição, e as outras só quando alguém precisa:
O primeiro traz o cliente, o botão e a decisão de desenhá-lo. O segundo é o React
e o painel. Quem nunca pede ajuda nunca o baixa; quem tem uma resposta não lida
recebe o painel sozinho, porque a prévia da mensagem é justamente o que não pode
esperar por um clique — e quem leva o ponteiro até o botão recebe o painel um
instante antes do clique, que é o que faz ele abrir na hora.
O último são os componentes, e é pequeno porque tudo o que ele divide com o
painel — React, o cliente, a folha de estilo — é o arquivo de cima. Uma página
sem nenhum
[data-userkit] e sem chamada a UserKit.mount() não o baixa, e
uma página que usa o widget e um componente baixa o React uma vez.
Instalado por npm, o painel está no seu bundle e é carregado com a página. Por
script, ele é buscado quando é preciso — o que torna esta forma mais leve na
maioria das páginas, e não uma versão pior.
Onde ele desenha
Numshadow root no fim do <body>. O elemento hospedeiro e as tags <script>
que acrescentamos ao <head> são os únicos nós nossos na sua árvore; tudo o que
é desenhado fica dentro da fronteira, e o seu CSS não entra nela — nem um
* { }, nem um !important em button. É a diferença central em relação ao
pacote npm, onde o seu CSS alcança os componentes de propósito.
O botão só aparece se houver algo atrás dele: artigos publicados (público, não
precisa de sessão) ou o chat ligado com uma sessão de contato. Nenhum dos dois, e a
página fica exatamente como estava — um botão na frente do nada abre um pedido de
desculpas.
Os componentes, na mesma tag
Owidget.js não é só o botão do canto: ele monta os mesmos drop-ins do
Componentes por script, na página que já o
carrega.
<script> para pôr um aviso no topo de uma página que já tinha suporte. Os nomes,
os data-* e os eventos são os de lá, e data-auto="false" desliga a montagem
automática aqui também.
O
userkit.js continua existindo, e a diferença é uma só: ele não tem o botão
flutuante. Uma tela de login ou uma página de preços quer os componentes e nada no
canto; um produto que já tem o widget instalado não precisa dele. Carregar os dois
na mesma página não faz mal, em qualquer ordem: um cliente só, uma sessão só,
uma contagem de páginas só, e o widget acrescenta o botão em cima do que o outro
arquivo já iniciou. Uma segunda tag de widget.js é ignorada do mesmo jeito.A única regra é que as duas tags levem a mesma data-publishable-key. Uma
página é um ambiente: a sessão, os eventos na fila e as chaves guardadas são
dele, então uma segunda chave não tem como conviver com a primeira. A tag que
nomear outra avisa no console e não faz nada.Configuração
Tudo por atributo:data-whats-new é o único que vem desligado, e a razão é uma troca real: a aba
alcança quem abre o painel, e o diálogo alcança todo mundo — ao custo de aparecer
por cima da página de alguém que entrou para fazer outra coisa. Ligue quando o que
você publica precisa ser lido, não só ficar disponível. Os dois não se duplicam:
ser exibido é o que marca uma nota como lida, então o que aparecer primeiro esvazia
o outro.
Claro, escuro, ou o que a pessoa escolheu
Semdata-theme, o botão e o painel seguem o prefers-color-scheme de quem está
lendo — que é o certo na maioria das páginas, e é o que somos há bastante tempo.
Não serve para uma aplicação que decide sozinha: se o tema dela é uma classe no
<html>, o sistema operacional pode dizer escuro enquanto o interruptor no
cabeçalho diz claro, e aí o widget é a única caixa da tela na paleta errada. Não
dá para corrigir isso com CSS: o painel vive dentro de um shadow root que a folha
de estilo da página não alcança. Por isso é um atributo.
@userkit/react põe <ChangelogBadge /> e <NotificationBell /> no cabeçalho
dela, ao lado do avatar. Esta forma tem um botão e um painel, e nenhum cabeçalho
onde pendurar um sino.
Uma página que prefere decidir em código omite os atributos e chama init:
window.UserKit
show() funciona antes de o painel existir: ele é buscado e abre em seguida, o que
faz um botão “Ajuda” no seu próprio menu funcionar sem que você espere nada.
Esperar o script
A tag édefer, então a sua página não tem como saber quando ela rodou. ready()
é a resposta: uma promessa que resolve com o cliente assim que a sessão deste
domínio foi restaurada — ou com null se não havia chave publicável nenhuma.
Um botão só
Se o seu produto já tem um “Suporte” no cabeçalho,data-launcher="false" tira o
nosso do canto. O painel continua intacto — UserKit.show() abre ele do seu botão,
que é justamente o motivo de esconder o launcher em vez de não instalar o widget.
Para uma decisão que acontece em código — “esconde enquanto este modal está
aberto” — use hideLauncher(). Um comando vale mais que o atributo a partir
daí, e resetLauncher() é a única volta: um override que expirasse sozinho seria o
nosso botão reaparecendo por cima de um checkout por razões que ninguém consegue
reconstruir.
Com o painel aberto o botão é desenhado de qualquer forma, porque ali ele não é um
launcher — é o X do painel.
Desenhar o seu próprio botão
subscribe publica o que o widget sabe sobre si mesmo, que é exatamente o que um
botão seu precisa para se desenhar:
available é a mesma resposta que decide se o nosso botão aparece — um botão na
frente de nada é um botão que abre um pedido de desculpas. E unread é o mesmo
número do nosso badge, contado uma vez só: uma linha que a própria pessoa escreveu
nunca conta como não lida, e duas contagens independentes acabariam discordando
sobre isso na frente dela.
Identificar quem está na página
O script nunca cria um contato sozinho. Uma tag que começasse a criar linhas para tráfego de landing page seria o pior padrão possível — a decisão é sua, aqui como no pacote npm:hash é o que o seu
servidor assinou; nunca gere esse HMAC no navegador.
CSP
Se o seu site temContent-Security-Policy, o loader e os arquivos que ele busca
precisam de script-src, a API de connect-src, e o logo e os avatares que o
seu ambiente serve, de img-src:
style-src próprio: dentro do shadow root ela é uma
folha construída (adoptedStyleSheets), que essa diretiva não governa. Duas
coisas ainda dependem de style-src 'unsafe-inline' — um navegador sem folhas
construídas, e a paleta escura definida no painel, que os componentes desenham
como um <style> dentro da própria árvore. Sem isso o widget desenha em claro,
e nada mais se perde.
O crossorigin="anonymous" na tag é o que faz um erro nosso chegar ao seu
window.onerror com stack em vez de como "Script error.", e o que deixa o
script carregar numa página que envia Cross-Origin-Embedder-Policy.
Não publicamos hash de SRI para widget.js de propósito: ele é o arquivo que muda
para que uma correção chegue à sua página sem você publicar nada, e um hash fixo é
exatamente o contrário disso. O painel, esse sim, é imutável — o nome dele carrega
o hash do conteúdo.
O que só existe no npm
appearance.unstylede o seu próprio CSS por cima- o arranjo
inline, dentro do fluxo da página useHelpWidget()e o resto dos hooks- passar funções e objetos como props direto no JSX — aqui isso é
UserKit.mount()ou umaddEventListenerno elemento