Vue Lightbox

Galeria de imagens e vídeos em tela cheia para Vue 3, construída sobre @reelkit/vue-lightbox.

Ver demonstração ao vivo →

Recursos

Imagens e vídeo
Slides de vídeo já incluídos
Gestos de toque
Deslize para navegar
Deslizar para fechar
Deslize para cima e dispense
Navegação por teclado
Setas e Escape
Tela cheia
API entre navegadores
Transições
Deslizar, esmaecer, virar, aproximar
Pré-carregamento
±2 vizinhos buscados antes
Botão de som
Mudo por slide
Estados de carregamento
Girador e slot próprio
Tratamento de erros
Ícone de erro e slot próprio
Slots com escopo
6 zonas personalizáveis
v-model
Ligação de mão dupla com v-model:is-open
Estado na URL
Links para compartilhar e favoritar

Instalação

bash

Não esqueça de importar os estilos:

typescript
Ícones

Os controles padrão usam lucide-vue-next para os ícones. Se você prefere outra biblioteca de ícones, use os slots com escopo #controls e #navigation para fornecer os seus.

Uso básico

Importe a folha de estilo e o componente LightboxOverlay, e comande a abertura e o fechamento com v-model:is-open.

App.vue

Slots com escopo

Seis slots nomeados com escopo permitem personalizar por completo as superfícies do overlay. Omita o slot para manter o padrão embutido; não coloque nada dentro do slot (com v-if="false", por exemplo) para esconder aquela seção inteira.

SlotEscopoDescrição
#slideSlideSlotScopeSubstitui o conteúdo de cada slide (necessário para slides de vídeo)
#controlsControlsSlotScopeSubstitui a barra de controles do topo (fechar, contador, tela cheia)
#navigationNavigationSlotScopeSubstitui as setas de avançar e voltar
#infoInfoSlotScopeSubstitui o gradiente de título e descrição na base
#loadingLoadingSlotScopeIndicador de carregamento próprio
#errorErrorSlotScopeIndicador de erro próprio
vue

Suporte a vídeo

Os slides de vídeo são opcionais, para que o bundle padrão fique livre de toda a fiação de áudio e vídeo. Chame useVideoSlideRenderer(items) e repasse o VideoSlideRenderer / VideoControlsRenderer devolvidos aos slots #slide e #controls do overlay. Envolva o overlay no SoundProvider devolvido, para que o botão de som embutido tenha contexto.

vue

O elemento <video> compartilhado que move os slides de vídeo segue o mesmo padrão do reel player do Vue — no iOS, a reprodução continua ao trocar de slide sem exigir um novo gesto do leitor a cada um.

Tela cheia

Use useFullscreen, de @reelkit/vue, para observar ou alternar o estado de tela cheia de um elemento referenciado. O botão de tela cheia embutido da galeria usa esse mesmo composable.

vue

Estado na URL

Ver demonstração ao vivo →

Monte um controlador com useOverlayUrlState, de @reelkit/vue, e entregue-o ao LightboxUrlOverlay como controller: a partir daí, quem manda na galeria é a barra de endereços. Ela se abre quando o parâmetro nomeia um slide e se fecha quando o parâmetro some. Os links dão para compartilhar, e o botão voltar fecha a galeria. É um componente separado do LightboxOverlay, então cada um carrega exatamente um comando do estado aberto — o modelo is-open ou o controller da URL, nunca os dois.

Chaves prontas

Você pode endereçar os slides com uma chave pronta — espalhe urlIndexKey (por posição) ou urlStableIdKey (por um id estável) no controlador — as duas reexportadas por @reelkit/vue. Veja o guia de estado na URL e a API do core.

Voltar só fecha quando você abriu de dentro do app — o link empilhou uma entrada, então voltar desempilha até a galeria. Um link compartilhado aberto direto em uma aba nova não tem histórico atrás de si, então o voltar do navegador sai do site; o botão de fechar ou o Escape removem o parâmetro ali mesmo e mantêm você na galeria.

vue

O composable recebe um objeto de opções e devolve um UrlStateController (com set, index, value). Guarde-o para o controle programático: set é a escrita de baixo nível que o overlay usa internamente (troca de slide, e set(null) para fechar). Ele também conduz o overlay por código — set(index) o abre, exatamente como navegar até o parâmetro. Ainda assim, prefira um link para abrir: o href dá para compartilhar, abre em nova aba e o botão voltar o fecha — tudo de graça, sem nenhum handler.

As opções completas de useOverlayUrlState (param, adapter, codec, locator) estão na referência da API para Vue.

O próprio LightboxUrlOverlay recebe apenas :controller (obrigatório), um emit @close e todas as props visuais e de comportamento que o LightboxOverlay repassa (items, transition-fn, os slots com escopo e assim por diante) — mas nenhum is-open.

  • Abrir custa uma entrada no histórico; percorrer os slides a substitui, então cem deslizes não acrescentam nenhuma — um único passo para trás sempre sai da galeria.
  • Um link compartilhado como ?photo=3 abre a galeria naquele slide. Um parâmetro que não nomeia slide nenhum é retirado da URL, em vez de afirmar um slide que não abre.

Em um app com rotas, passe um adaptador. Escrever direto no histórico deixa a localização do roteador desatualizada, e a navegação seguinte derruba o parâmetro.

vue

Links estáveis. O índice é posicional, então um favorito abre outra imagem assim que a lista muda de ordem. urlStableIdKey usa o id estável de cada item, varrendo a lista atual — uma chamada resolve o caso comum.

vue

Passe hashCodec: base64UrlCodec para escrever o id em base64url na URL — é um disfarce reversível, não um hash criptográfico.

Quer endereçar por outro campo (um slug), ou paginar um feed infinito com locateAsync? Monte o codec e o locator você mesmo: o codec escreve a identidade na URL, o locator descobre onde ela está agora.

vue

Galerias infinitas ou paginadas. locate é síncrono, então só responde pelos itens já carregados — um link compartilhado para a imagem 400 de um feed que carregou 20 volta vazio. locateAsync é o plano B, chamado somente quando ele falha: carregue as páginas necessárias e devolva o índice que a identidade acabou tendo.

Atalho

Vai endereçar pelo id do item? Dispense o codec e o locator escritos à mão — passe locateAsync direto para urlStableIdKey({ items, locateAsync }) (ele busca quando falha e então devolve o índice). A versão mais completa abaixo serve para endereçar por outro campo, ou para ter controle total.

vue

Enquanto a busca corre, a galeria fica fechada e o parâmetro é deixado em paz, então o link direto sobrevive. Um null ou uma rejeição derrubam o parâmetro. Uma resposta que chega depois de a URL ter mudado, depois de um fechamento ou depois da desmontagem é descartada, então uma busca lenta não pode abrir um slide que ninguém pediu. O que ela devolver é palavra final — informa o índice dos dados que acabou de buscar, e a galeria o aceita como está, sem reler items, que o Vue ainda não renderizou de novo.

Referência da API

Props do LightboxOverlay

LightboxOverlayProps

PropTipoPadrãoDescrição
isOpenbooleanobrigatórioControla a visibilidade; com false, o overlay sai do DOM. Dá para ligar com v-model:is-open.
itemsLightboxItem[]obrigatórioArray de itens (imagens ou vídeos)
initialIndexnumber0Índice, começando em zero, do item visível no início
transitionFnTransitionTransformFnslideTransitionFunção da transição entre slides. Importe uma das prontas (slideTransition, flipTransition, lightboxFadeTransition, lightboxZoomTransition) ou passe a sua. Sem esta prop, vale slideTransition.
showInfobooleantrueSe a camada de título e descrição aparece
showControlsbooleantrueSe a barra de controles do topo aparece (fechar, contador, tela cheia)
showNavigationbooleantrueSe as setas de avançar e voltar aparecem (somente no desktop)
transitionDurationnumber300Duração da animação do slide em ms
swipeDistanceFactornumber0.12Fração mínima da distância de deslize (0–1) para trocar de slide
swipeToCloseDirection'up' | 'down''up'Direção do gesto de deslizar para fechar no celular
loopbooleanfalseSe o slider passa do último slide de volta ao primeiro
enableNavKeysbooleantrueLiga a navegação pelas setas do teclado
enableWheelbooleantrueLiga a navegação pela roda do mouse
wheelDebounceMsnumber200Duração do debounce dos eventos de roda em ms
ariaLabelstring'Image gallery'Rótulo acessível da região do diálogo

Props do LightboxUrlOverlay

LightboxUrlOverlayProps

Aceita todas as props visuais e de comportamento acima, menos is-open, substituída por controller. Emite close, slide-change e api-ready, mas nenhum update:is-open. initial-index é ignorada aqui — quem escolhe o slide é a posição do controlador, então um valor passado ao lado dela seria sobrescrito a cada abertura.

PropTipoPadrãoDescrição
controllerUrlStateControllerobrigatórioControlador vindo de useOverlayUrlState. A posição dele decide se o overlay está aberto e qual slide aparece; o overlay escreve de volta por ele na troca de slide e no fechamento.

Eventos do LightboxOverlay

EventoCargaDescrição
closevoidEmitido quando o leitor fecha a galeria
slide-changenumberEmitido com o novo índice do slide ativo depois de uma troca
api-readyLightboxApiEmitido assim que o slider fica pronto, expondo a API imperativa
update:is-openbooleanEmitido no fechamento; é o que viabiliza o v-model:is-open

Interface LightboxItem

CampoTipoObrigatórioDescrição
srcstringsimURL da imagem ou do vídeo
type'image' | 'video'nãoTipo do item. O padrão é 'image'
posterstringnãoImagem de miniatura dos itens de vídeo
titlestringnãoTítulo mostrado na camada de informações
descriptionstringnãoDescrição mostrada abaixo do título
widthnumbernãoLargura original da imagem em pixels
heightnumbernãoAltura original da imagem em pixels

Tipos de escopo dos slots

TipoCampos
SlideSlotScope{ item, index, size: [number, number], isActive, onReady, onWaiting, onError }
ControlsSlotScope{ item, activeIndex, count, isFullscreen, onClose, onToggleFullscreen }
NavigationSlotScope{ item, activeIndex, count, onPrev, onNext }
InfoSlotScope{ item, index }
LoadingSlotScope{ item, activeIndex }
ErrorSlotScope{ item, activeIndex }

Transições

Passe qualquer TransitionTransformFn pela prop transition-fn. Importar apenas a transição que você usa deixa o bundler descartar as outras. Sem esta prop, vale slideTransition.

FunçãoDescrição
slideTransitionO padrão. Deslocamento horizontal entre os slides; reexportada de @reelkit/vue.
lightboxFadeTransitionEsmaecimento cruzado com um empurrãozinho horizontal. Vive em @reelkit/vue-lightbox.
flipTransitionVirada 3D em torno do eixo Y; reexportada de @reelkit/vue.
lightboxZoomTransitionO slide que entra vai de 70% a 100% de escala, com esmaecimento. Vive em @reelkit/vue-lightbox.
vue

Carregamento de conteúdo e tratamento de erros

Quando você assume a renderização pelo slot #slide, três callbacks de ciclo de vida ficam disponíveis no escopo do slot para informar o estado de carregamento. A galeria acompanha o estado de cada slide e mostra o girador ou o ícone de erro conforme o caso. Um pré-carregador guarda em cache as URLs quebradas, então voltar a um slide que falhou pula a nova tentativa.

Callbacks de ciclo de vida

CallbackTipoDescrição
onReady() => voidAvisa que o conteúdo do slide carregou (a imagem foi decodificada, por exemplo)
onWaiting() => voidAvisa que o conteúdo do slide está carregando (mostra o girador)
onError() => voidAvisa que o conteúdo do slide não carregou (mostra o ícone de erro)

Ligando os callbacks no #slide

vue

Slot de carregamento próprio

Use o slot #loading para substituir o girador padrão.

vue

Slot de erro próprio

Use o slot #error para substituir o ícone padrão de imagem quebrada.

vue

Classes CSS

Todas as classes CSS são simples (sem escopo), então dá para alcançá-las com seletores de especificidade maior em uma folha de estilo carregada depois de @reelkit/vue-lightbox/styles.css. Para mudar cor, tamanho e z-index, prefira as propriedades CSS documentadas na seção Temas, abaixo.

ClasseComponenteDescrição
.rk-lightbox-overlayOverlayContêiner raiz (fundo em tela cheia)
.rk-lightbox-top-shadeOverlayGradiente do topo, atrás dos controles
.rk-lightbox-spinnerOverlayGirador de carregamento padrão
.rk-lightbox-errorOverlayContêiner do estado de erro (imagem quebrada)
.rk-lightbox-error-textOverlayTexto do estado de erro
.rk-lightbox-controls-leftControlsContêiner dos controles no canto superior esquerdo
.rk-lightbox-btnControlsBotão de controle (tela cheia, som e afins)
.rk-lightbox-closeControlsBotão de fechar
.rk-lightbox-counterControlsEtiqueta contadora de imagens
.rk-lightbox-navNavigationSeta de navegação (avançar e voltar)
.rk-lightbox-nav-prevNavigationSeta de voltar
.rk-lightbox-nav-nextNavigationSeta de avançar
.rk-lightbox-infoInfoContêiner de título e descrição
.rk-lightbox-info-titleInfoTítulo da imagem
.rk-lightbox-info-descriptionInfoDescrição da imagem
.rk-lightbox-slideSlideContêiner do slide
.rk-lightbox-imgSlideElemento de imagem
.rk-lightbox-video-containerVideoSlideContêiner do slide de vídeo (opcional)
.rk-lightbox-video-elementVideoSlideElemento de vídeo (opcional)
.rk-lightbox-video-posterVideoSlideImagem de pôster do vídeo (opcional)

Temas

Sobrescreva qualquer propriedade CSS --rk-lightbox-* em :root (ou em qualquer ancestral de .rk-lightbox-overlay) para trocar o tema. Declarações direto em .rk-lightbox-overlay sombreariam os valores herdados, então mantenha as sobrescritas em um seletor ancestral.

TokenPadrãoO que controla
--rk-lightbox-overlay-bg#000Cor do fundo
--rk-lightbox-overlay-z9999z-index do overlay
--rk-lightbox-top-shade-height80pxAltura do gradiente do topo
--rk-lightbox-top-shade-bglinear-gradient(rgba(0,0,0,0.6), transparent)Gradiente do topo
--rk-lightbox-edge-padding16pxRecuo da borda para fechar, navegação e controles
--rk-lightbox-btn-bgrgba(0, 0, 0, 0.5)Fundo padrão dos botões de fechar, navegação e dos pequenos
--rk-lightbox-btn-bg-hoverrgba(255, 255, 255, 0.2)Fundo desses botões ao passar o mouse
--rk-lightbox-btn-fg#fffCor do ícone desses botões
--rk-lightbox-btn-size36pxTamanho dos botões pequenos (tela cheia e afins)
--rk-lightbox-close-size40pxTamanho do botão de fechar
--rk-lightbox-nav-size48pxTamanho das setas de avançar e voltar
--rk-lightbox-nav-opacity0.7Opacidade das setas em repouso
--rk-lightbox-counter-bgrgba(0, 0, 0, 0.5)Fundo da etiqueta do contador
--rk-lightbox-counter-fg#fffCor do texto do contador
--rk-lightbox-info-bglinear-gradient(transparent, rgba(0,0,0,0.8))Gradiente que escurece o fundo da legenda
--rk-lightbox-title-size18pxTamanho da fonte do título
--rk-lightbox-description-size14pxTamanho da fonte da descrição
--rk-lightbox-video-bg#000Cor das faixas em volta do <video>
css

Acessibilidade

A raiz do overlay é um diálogo modal (role="dialog", aria-modal="true"). Defina a prop aria-label para mudar o que o leitor de tela anuncia; o padrão é "Image gallery". Cada slide carrega role="group", aria-roledescription="slide" e um aria-label derivado da posição (por exemplo, "Image 2 of 5").

A galeria captura o foco ao abrir e o devolve ao gatilho ao fechar. Tab e Shift+Tab percorrem os elementos focáveis lá dentro; um foco que escapa (clique fora, foco por código) é trazido de volta. Implementado com captureFocusForReturn e createFocusTrap, de @reelkit/vue.

Atalhos de teclado

TeclaAção
ArrowLeftImagem anterior
ArrowRightPróxima imagem
EscapeFecha a galeria (ou sai da tela cheia, se estiver nela)