Angular Lightbox

Galeria de imagens e vídeos em tela cheia para Angular, construída sobre @reelkit/angular-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
Imagens vizinhas buscadas 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 de template
6 zonas personalizáveis
OnPush
Sinais do Angular com OnPush
Estado na URL
Links para compartilhar e favoritar
Apresentação
Avanço automático opcional, com play/pause
Download
Botão opcional que salva o item ativo

Instalação

bash
npm install @reelkit/angular-lightbox @reelkit/angular lucide-angular

Registre a folha de estilos uma única vez:

typescript
// Anywhere that runs at startup — main.ts, app.config.ts, a component file.
import '@reelkit/angular-lightbox/styles.css';

// Or, if you keep CSS out of TypeScript, from your global stylesheet:
//   @import '@reelkit/angular-lightbox/styles.css';
// Or register it in angular.json:
//   "styles": ["node_modules/@reelkit/angular-lightbox/styles.css"]
Ícones

Os controles padrão usam lucide-angular para os ícones. Se você prefere outra biblioteca de ícones, use os slots de template rkLightboxControls e rkLightboxNavigation para fornecer os seus.

Início rápido

Importe os estilos e o componente standalone RkLightboxOverlayComponent no array imports do seu componente.

gallery.component.ts
import { Component } from '@angular/core';
import {
  RkLightboxOverlayComponent,
  type LightboxItem,
} from '@reelkit/angular-lightbox';
import '@reelkit/angular-lightbox/styles.css';

const images: LightboxItem[] = [
  {
    src: '/cdn/samples/images/image-01.jpg',
    title: 'Mountain River',
    description: 'A beautiful mountain river',
  },
  {
    src: '/cdn/samples/images/image-02.jpg',
    title: 'Snowy Peaks',
  },
  {
    src: '/cdn/samples/images/image-03.jpg',
    title: 'Misty Forest',
    description: 'Morning fog over the forest canopy',
  },
  {
    src: '/cdn/samples/images/image-04.jpg',
    title: 'Autumn Trail',
  },
  {
    src: '/cdn/samples/images/image-05.jpg',
    title: 'Ocean Cliff',
    description: 'Dramatic cliffs above the Pacific',
  },
  {
    src: '/cdn/samples/images/image-06.jpg',
    title: 'Desert Dunes',
  },
];

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RkLightboxOverlayComponent],
  template: `
    <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px">
      @for (img of images; track img.src; let i = $index) {
        <button (click)="openIndex = i" style="aspect-ratio:4/3;cursor:pointer">
          <img [src]="img.src" style="width:100%;height:100%;object-fit:cover" />
        </button>
      }
    </div>

    <rk-lightbox-overlay
      [isOpen]="openIndex !== null"
      [items]="images"
      [initialIndex]="openIndex ?? 0"
      (closed)="openIndex = null"
    />
  `,
})
export class AppComponent {
  images = images;
  openIndex: number | null = null;
}
Onde o overlay é renderizado

Ao contrário dos lightboxes de React e Vue, que movem o overlay para o fim de document.body, o rk-lightbox-overlay é renderizado onde você o coloca e cobre a tela com position: fixed. Mantenha-o fora de qualquer ancestral com transform, perspective, filter ou will-change: transform: esse ancestral vira o bloco de contenção do overlay, então o lightbox assume o tamanho dele em vez da viewport e é cortado pelo seu overflow. Um ancestral que cria o próprio contexto de empilhamento também limita o quanto --rk-lightbox-overlay-z consegue elevar o lightbox. Em troca, os tokens --rk-lightbox-* definidos em qualquer ancestral chegam ao lightbox.

Slots de template

Quatro diretivas de slot de template permitem personalizar por completo a interface do overlay, sem precisar copiar o componente. Cada slot recebe um objeto de contexto fortemente tipado.

DiretivaTipo do contextoDescrição
[rkLightboxControls]LightboxControlsContextSubstitui a barra de controles do topo (botão de fechar, contador, botão de tela cheia)
[rkLightboxNavigation]LightboxNavContextSubstitui as setas de avançar e voltar
[rkLightboxInfo]LightboxInfoContextSubstitui o gradiente de título e descrição na base
[rkLightboxSlide]LightboxSlideContextSubstitui o conteúdo de cada slide (necessário para slides de vídeo)
[rkLightboxLoading]LightboxLoadingContextIndicador de carregamento próprio; a classe da diretiva é RkLightboxLoadingDirective
[rkLightboxError]LightboxErrorContextIndicador de erro próprio; a classe da diretiva é RkLightboxErrorDirective
typescript
import {
  RkLightboxOverlayComponent,
  RkLightboxControlsDirective,
  RkLightboxNavigationDirective,
  RkLightboxInfoDirective,
  RkCloseButtonComponent,
  RkCounterComponent,
  RkFullscreenButtonComponent,
  type LightboxItem,
  type LightboxControlsContext,
  type LightboxNavContext,
} from '@reelkit/angular-lightbox';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RkLightboxOverlayComponent,
    RkLightboxControlsDirective,
    RkLightboxNavigationDirective,
    RkLightboxInfoDirective,
    RkCloseButtonComponent,
    RkCounterComponent,
    RkFullscreenButtonComponent,
  ],
  template: `
    <rk-lightbox-overlay [isOpen]="isOpen" [items]="images" (closed)="isOpen = false">

      <!-- Custom controls bar -->
      <ng-template rkLightboxControls
                   let-onClose="onClose"
                   let-activeIndex="activeIndex"
                   let-count="count"
                   let-isFullscreen="isFullscreen"
                   let-onToggleFullscreen="onToggleFullscreen">
        <div style="position:absolute;top:0;left:0;right:0;padding:12px;
                    display:flex;align-items:center;justify-content:space-between">
          <rk-close-button (clicked)="onClose()" />
          <rk-counter [currentIndex]="activeIndex + 1" [count]="count" />
          <rk-fullscreen-button
            [isFullscreen]="isFullscreen"
            (toggled)="onToggleFullscreen()" />
        </div>
      </ng-template>

      <!-- Custom navigation -->
      <ng-template rkLightboxNavigation
                   let-onPrev="onPrev"
                   let-onNext="onNext"
                   let-activeIndex="activeIndex"
                   let-count="count">
        <button (click)="onPrev()" [disabled]="activeIndex === 0">&#8592;</button>
        <button (click)="onNext()" [disabled]="activeIndex === count - 1">&#8594;</button>
      </ng-template>

      <!-- Custom info overlay -->
      <ng-template rkLightboxInfo let-item let-index="index">
        <div style="position:absolute;bottom:0;left:0;right:0;padding:16px;
                    background:linear-gradient(transparent,rgba(0,0,0,0.6))">
          <h3 style="color:#fff">{{ item.title }}</h3>
          <p style="color:rgba(255,255,255,0.7)">{{ item.description }}</p>
        </div>
      </ng-template>

    </rk-lightbox-overlay>
  `,
})
export class AppComponent {
  images: LightboxItem[] = [];
  isOpen = false;
}

Suporte a vídeo

Para ter slides de vídeo é preciso optar por eles, pelo slot de template rkLightboxSlide e pelo RkLightboxVideoSlideComponent. Esse desenho evita embutir o player de vídeo em galerias que só precisam de imagens.

O botão de som embutido só aparece quando um SoundStateService é fornecido acima de <rk-lightbox-overlay>: é essa instância compartilhada que faz o toque chegar ao vídeo, já que o slide vem do seu template. Sem ela, controle o elemento direto com setLightboxVideoMuted.

typescript
import {
  RkLightboxOverlayComponent,
  RkLightboxSlideDirective,
  RkLightboxVideoSlideComponent,
  type LightboxItem,
  type LightboxSlideContext,
} from '@reelkit/angular-lightbox';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RkLightboxOverlayComponent,
    RkLightboxSlideDirective,
    RkLightboxVideoSlideComponent,
  ],
  template: `
    <rk-lightbox-overlay [isOpen]="isOpen" [items]="items" (closed)="isOpen = false">
      <ng-template rkLightboxSlide
                   let-item
                   let-index="index"
                   let-size="size"
                   let-isActive="isActive"
                   let-autoAdvance="autoAdvance"
                   let-onReady="onReady"
                   let-onEnded="onEnded">
        @if (item.type === 'video') {
          <!-- With autoAdvance the video plays once and reports its end -->
          <rk-lightbox-video-slide
            [src]="item.src"
            [poster]="item.poster"
            [slideKey]="'lightbox-' + index"
            [size]="size"
            [isActive]="isActive"
            [loop]="!autoAdvance"
            [onReady]="onReady"
            [onEnded]="onEnded"
          />
        } @else {
          <img [src]="item.src"
               [style.width.px]="size[0]"
               [style.height.px]="size[1]"
               style="object-fit:contain" />
        }
      </ng-template>
    </rk-lightbox-overlay>
  `,
})
export class AppComponent {
  isOpen = false;
  items: LightboxItem[] = [
    { src: '/photo.jpg', title: 'Photo' },
    { src: '/clip.mp4', type: 'video', poster: '/clip-thumb.jpg', title: 'Video' },
  ];
}

Tela cheia

Use fullscreenSignal, requestFullscreen e exitFullscreen, de @reelkit/angular, para observar ou alternar o estado de tela cheia.

typescript
import { fullscreenSignal, requestFullscreen, exitFullscreen } from '@reelkit/angular';

@Component({ ... })
export class AppComponent {
  readonly isFullscreen = fullscreenSignal();

  toggle(container: HTMLElement): void {
    if (this.isFullscreen()) {
      exitFullscreen();
    } else {
      requestFullscreen(container);
    }
  }
}

Estado na URL

Ver demonstração ao vivo →

RkLightboxUrlOverlayComponent é um componente à parte cujo estado aberto vive na barra de endereços. Monte um controlador com createOverlayUrlState e entregue-o como [controller]: a galeria se abre quando o parâmetro nomeia um slide e se fecha quando ele some. Os links dão para compartilhar, e o botão voltar fecha a galeria em vez de sair da página.

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/angular. Veja o guia de estado na URL e a API do core.

typescript
import { RkLightboxUrlOverlayComponent } from '@reelkit/angular-lightbox';
import { createOverlayUrlState, urlIndexKey, urlStableIdKey } from '@reelkit/angular';

@Component({
  imports: [RkLightboxUrlOverlayComponent, RouterLink],
  template: `
    @for (image of images(); track image.src; let i = $index) {
      <a [routerLink]="[]" [queryParams]="{ photo: i }">
        <img [src]="image.src" alt="" />
      </a>
    }

    <rk-lightbox-url-overlay [controller]="photo" [items]="images()" />
  `,
})
export class GalleryComponent {
  protected readonly images = signal(photos);

  protected readonly photo = createOverlayUrlState({
    param: 'photo',
    ...urlIndexKey(() => this.images().length),
  });
}

Chame-o em um contexto de injeção — na inicialização de um campo ou no construtor. Ele se liga na hora e se solta pelo DestroyRef, então um componente destruído com a galeria aberta não deixa nenhuma escuta para trás. As opções completas estão na referência da API para Angular.

  • Abrir empilha uma entrada no histórico. Percorrer os slides substitui essa entrada, então N passos não acrescentam nenhuma e um único passo para trás sempre sai da galeria.
  • Voltar só fecha quando a galeria foi aberta de dentro do app — foi o link que empilhou a entrada. 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 ✕ ou o Escape removem o parâmetro ali mesmo e você continua na página.
  • Um parâmetro que não nomeia slide nenhum — um favorito velho, um valor editado à mão — é retirado da URL, em vez de ficar afirmando um slide que não abre.
  • Os slots de template funcionam sem mudança: o componente de URL faz ele mesmo as seis consultas de slot e repassa cada template à galeria, então rkLightboxControls e seus irmãos ficam dentro dele exatamente como ficariam dentro de rk-lightbox-overlay.
  • Em uma aplicação com rotas, passe um adaptador construído sobre o Router. Escrever no histórico por trás do Router deixa a localização dele desatualizada, e a navegação seguinte derruba o parâmetro.

Em um app com rotas, passe um adaptador. Escrever no histórico por trás do Router deixa a localização dele desatualizada, e a navegação seguinte derruba o parâmetro; então construa um adaptador sobre o Router e passe-o como adapter:

typescript
import { createRouterUrlAdapter } from '@reelkit/angular/ng-router-url-adapter';

const adapter = createRouterUrlAdapter();

const photo = createOverlayUrlState({
  param: 'photo',
  adapter,
  ...urlIndexKey(() => this.images().length),
});

Links estáveis. O índice é posicional — um ?photo=3 favoritado 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.

typescript
const photo = createOverlayUrlState({
  param: 'photo',
  ...urlStableIdKey({ items: () => this.images() }),
});

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 (o fio) e o locator (a busca) você mesmo:

typescript
const photo = createOverlayUrlState({
  param: 'photo',
  codec: { decode: (raw) => raw, encode: (id) => id },
  locator: {
    locate: (id) => this.images().findIndex((x) => x.id === id),
    identify: (index) => this.images()[index].id,
  },
});

Galerias infinitas ou paginadas. locate é síncrono, então só responde pelas imagens já carregadas — um link compartilhado para a imagem 400 de um feed que carregou 20 volta vazio. locateAsync é o plano B, chamado somente quando locate falha: carregue as páginas necessárias e devolva o índice que a identidade acabou tendo. 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.

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.

typescript
const photo = createOverlayUrlState({
  param: 'photo',
  codec: { decode: (raw) => raw, encode: (id) => id },
  locator: {
    locate: (id) => this.images().findIndex((x) => x.id === id),
    identify: (index) => this.images()[index].id,
    locateAsync: async (id) => {
      const loaded = await loadById(id); // or loadUntil(id) — fetch just that one, or page up to it
      if (!loaded) return null; // exhausted — link names no item
      this.images.set(loaded); // commit; the overlay renders from this
      return loaded.findIndex((x) => x.id === id); // wherever it landed
    },
  },
});

Avanço automático

Defina [autoAdvance]="true" para tocar a galeria como uma apresentação assim que ela abre. Vem desligado, então uma galeria que já existe renderiza e se comporta como antes.

  • Imagens ficam por autoAdvanceInterval (5000 ms por padrão), contados a partir do momento em que a imagem carregou, então uma imagem lenta nunca é pulada antes de alguém vê-la. Uma imagem que falha ao carregar conta a partir do erro.
  • Vídeos tocam uma vez em vez de repetir e passam adiante quando terminam. Num template rkLightboxSlide, ligue [loop]="!autoAdvance" e [onEnded]="onEnded" em rk-lightbox-video-slide, como em Suporte a vídeo.
  • Ela espera enquanto o mouse repousa sobre um controle (um botão, um link ou a legenda), durante um deslize e enquanto a página está oculta, e depois continua de onde parou.
  • Navegar à mão (setas, teclas, roda do mouse, deslize) começa o intervalo do novo slide do zero; a apresentação continua ligada.
  • No último slide ela para, a menos que loop esteja definido. O botão de play/pause nos controles mostra o estado e deixa quem assiste alterná-lo.

A apresentação roda fora da zone do Angular, então seus frames de animação não disparam detecção de mudanças. Um template rkLightboxControls próprio recebe isAutoAdvancing e, só quando autoAdvance está ligado, onToggleAutoAdvance — renderize rk-play-pause-button quando ele estiver lá. A temporização em si é o createSlideshowController de @reelkit/core; veja o guia de reprodução automática e a API do core.

typescript
import { Component } from '@angular/core';
import {
  RkCloseButtonComponent,
  RkLightboxControlsDirective,
  RkLightboxOverlayComponent,
  RkPlayPauseButtonComponent,
  type LightboxItem,
} from '@reelkit/angular-lightbox';

@Component({
  selector: 'app-gallery',
  imports: [
    RkLightboxOverlayComponent,
    RkLightboxControlsDirective,
    RkPlayPauseButtonComponent,
    RkCloseButtonComponent,
  ],
  template: `
    <rk-lightbox-overlay
      [isOpen]="isOpen"
      [items]="items"
      [autoAdvance]="true"
      [autoAdvanceInterval]="4000"
      (closed)="isOpen = false"
    >
      <!-- Optional: a custom bar shows the toggle only when its handler is there -->
      <ng-template rkLightboxControls let-ctx>
        @if (ctx.onToggleAutoAdvance) {
          <rk-play-pause-button
            [playing]="ctx.isAutoAdvancing"
            (toggled)="ctx.onToggleAutoAdvance()"
          />
        }
        <rk-close-button (clicked)="ctx.onClose()" />
      </ng-template>
    </rk-lightbox-overlay>
  `,
})
export class GalleryComponent {
  isOpen = false;
  items: LightboxItem[] = [{ src: '/beach.jpg' }, { src: '/forest.jpg' }];
}

Download

Defina [showDownload]="true" para acrescentar um botão de download aos controles. Ele salva o item ativo a partir do seu downloadUrl, ou de src na falta dele, com o nome downloadName, ou com o último segmento da URL na falta dele.

O arquivo é buscado e salvo, porque o navegador ignora o atributo download num link de outra origem e abriria o arquivo em vez de salvá-lo. Quando a busca falha — em geral um servidor de outra origem que não envia cabeçalhos CORS — o arquivo abre numa nova aba, onde quem assiste ainda pode salvá-lo. Sirva os arquivos com Access-Control-Allow-Origin para salvar com um clique. O botão fica desativado enquanto um download está em andamento.

Um template rkLightboxControls próprio recebe isDownloading e, só quando showDownload está ligado, onDownload — renderize rk-download-button quando ele estiver lá. O helper é o downloadFile de @reelkit/core; veja o guia de download.

typescript
import { Component } from '@angular/core';
import {
  RkCloseButtonComponent,
  RkDownloadButtonComponent,
  RkLightboxControlsDirective,
  RkLightboxOverlayComponent,
  type LightboxItem,
} from '@reelkit/angular-lightbox';

@Component({
  selector: 'app-gallery',
  imports: [
    RkLightboxOverlayComponent,
    RkLightboxControlsDirective,
    RkDownloadButtonComponent,
    RkCloseButtonComponent,
  ],
  template: `
    <rk-lightbox-overlay
      [isOpen]="isOpen"
      [items]="items"
      [showDownload]="true"
      (closed)="isOpen = false"
    >
      <!-- Optional: a custom bar shows the button only when its handler is there -->
      <ng-template rkLightboxControls let-ctx>
        @if (ctx.onDownload) {
          <rk-download-button
            [downloading]="ctx.isDownloading"
            (pressed)="ctx.onDownload()"
          />
        }
        <rk-close-button (clicked)="ctx.onClose()" />
      </ng-template>
    </rk-lightbox-overlay>
  `,
})
export class GalleryComponent {
  isOpen = false;
  items: LightboxItem[] = [
    {
      src: '/beach-1600.jpg',
      // Save the original rather than the resized preview
      downloadUrl: '/beach-original.jpg',
      downloadName: 'beach.jpg',
    },
  ];
}

Botões de controle

ComponenteSeletorInputs / outputsDescrição
RkPlayPauseButtonComponentrk-play-pause-button[playing], (toggled)Alternador da apresentação (ícone Play/Pause, aria-pressed enquanto toca). Mostrado pelos controles padrão com autoAdvance.
RkDownloadButtonComponentrk-download-button[downloading], (pressed)Botão de download, desativado enquanto downloading. Mostrado pelos controles padrão com showDownload.
RkSoundButtonComponentrk-sound-button[muted], (toggled)Botão de mudo para itens de vídeo. Mostrado pelos controles padrão num slide de vídeo; coloque-o no seu próprio template rkLightboxControls para mantê-lo.

Inputs do RkLightboxUrlOverlayComponent

Aceita todos os inputs de rk-lightbox-overlay, menos isOpen, substituído por um controlador. Os outputs são os mesmos, closed e slideChange; quem fecha é a URL, então closed é um aviso, não o mecanismo.

InputTipoPadrãoDescrição
controllerUrlStateControllerobrigatórioControlador vindo de createOverlayUrlState. A posição dele decide se a galeria está aberta e qual slide aparece; o componente escreve de volta por ele na troca de slide e no fechamento.

Inputs do RkLightboxOverlayComponent

InputTipoPadrãoDescrição
isOpenbooleanobrigatórioControla a visibilidade; com false, o overlay sai do DOM
itemsLightboxItem[]obrigatórioArray de itens da galeria (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 este input, 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
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
autoAdvancebooleanfalseToca a galeria como uma apresentação. Veja Avanço automático.
autoAdvanceIntervalnumber5000Quanto tempo cada imagem fica durante a apresentação, em ms, contado a partir do momento em que carregou
showDownloadbooleanfalseAcrescenta um botão de download para o item ativo. Veja Download.
ariaLabelstring'Image gallery'Rótulo acessível da região do diálogo

Os inputs do slider acima (transitionDuration, swipeDistanceFactor, loop, enableNavKeys, enableWheel, wheelDebounceMs) são tipados por ReelProxyProps. Use-o para tipar um componente wrapper que os repassa ao lightbox.

Outputs do RkLightboxOverlayComponent

OutputTipoDescrição
closedEventEmitter<void>Emitido quando o leitor fecha a galeria
slideChangeEventEmitter<number>Emitido quando o índice do slide ativo muda

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
downloadUrlstringnãoO que o botão de download salva. O padrão é src
downloadNamestringnãoNome do arquivo salvo. O padrão é o último segmento do caminho da URL

Tipos de contexto dos slots de template

TipoCampos
LightboxControlsContext{ item, activeIndex, count, isFullscreen, isAutoAdvancing, isDownloading, onClose, onToggleFullscreen, onToggleAutoAdvance?, onDownload? }
LightboxNavContext{ item, onPrev, onNext, activeIndex, count }
LightboxInfoContext{ $implicit: LightboxItem, index }
LightboxSlideContext{ $implicit: LightboxItem, index, size: [number, number], isActive, autoAdvance, onReady, onWaiting, onError, onEnded }
LightboxLoadingContext{ $implicit: activeIndex, item } — o que o template rkLightboxLoading recebe
LightboxErrorContext{ $implicit: activeIndex, item } — o que o template rkLightboxError recebe

Transições

Passe qualquer TransitionTransformFn pelo input transitionFn. Importar apenas a transição que você usa deixa o bundler descartar as outras. Sem este input, vale slideTransition.

FunçãoDe onde vemDescrição
slideTransition@reelkit/angular-lightboxDeslizamento horizontal comum (padrão)
lightboxFadeTransition@reelkit/angular-lightboxEsmaecimento cruzado entre as imagens
flipTransition@reelkit/angular-lightboxEfeito de virada de carta em 3D
lightboxZoomTransition@reelkit/angular-lightboxAproximação, do menor até o tamanho normal
typescript
import {
  RkLightboxOverlayComponent,
  lightboxFadeTransition,
} from '@reelkit/angular-lightbox';

@Component({
  imports: [RkLightboxOverlayComponent],
  template: `
    <rk-lightbox-overlay
      [isOpen]="isOpen"
      [items]="images"
      [transitionFn]="lightboxFadeTransition"
      (closed)="isOpen = false"
    />
  `,
})
export class GalleryComponent {
  protected readonly lightboxFadeTransition = lightboxFadeTransition;
}

Carregamento de conteúdo e tratamento de erros

Ao usar o slot de template rkLightboxSlide, três callbacks de ciclo de vida ficam disponíveis no contexto 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 rkLightboxSlide

html
<rk-lightbox-overlay [isOpen]="isOpen" [items]="items" (closed)="isOpen = false">
  <ng-template rkLightboxSlide
               let-item
               let-size="size"
               let-isActive="isActive"
               let-onReady="onReady"
               let-onWaiting="onWaiting"
               let-onError="onError">
    @if (item.type === 'video') {
      <rk-lightbox-video-slide
        [item]="item"
        [size]="size"
        [isActive]="isActive"
      />
    } @else {
      <img [src]="item.src"
           [style.width.px]="size[0]"
           [style.height.px]="size[1]"
           style="object-fit:contain"
           (load)="onReady()"
           (error)="onError()" />
    }
  </ng-template>
</rk-lightbox-overlay>

Template de carregamento próprio

Use a diretiva rkLightboxLoading para substituir o girador padrão.

html
<rk-lightbox-overlay [isOpen]="isOpen" [items]="items" (closed)="isOpen = false">
  <ng-template rkLightboxLoading let-index let-item="item">
    <div style="display:flex;flex-direction:column;align-items:center;color:#fff">
      <span>Loading image {{ index + 1 }}...</span>
      <span style="opacity:0.6">{{ item.title }}</span>
    </div>
  </ng-template>
</rk-lightbox-overlay>

Template de erro próprio

Use a diretiva rkLightboxError para substituir o ícone de erro padrão.

html
<rk-lightbox-overlay [isOpen]="isOpen" [items]="items" (closed)="isOpen = false">
  <ng-template rkLightboxError let-index let-item="item">
    <div style="display:flex;flex-direction:column;align-items:center;color:#ef4444">
      <span>Failed to load</span>
      <span style="opacity:0.6">{{ item.title ?? item.src }}</span>
    </div>
  </ng-template>
</rk-lightbox-overlay>

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/angular-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-img-errorOverlayContêiner do estado de erro (imagem quebrada)
.rk-lightbox-img-error-textOverlayTexto do estado de erro
.rk-lightbox-swipe-hintOverlayDica de deslize no celular
.rk-lightbox-emptyOverlayTexto do estado vazio
.rk-lightbox-controls-leftControlsContêiner dos controles no canto superior esquerdo
.rk-lightbox-btnControlsBotão de controle (tela cheia e afins)
.rk-lightbox-play-pauseControlsBotão de play/pause da apresentação (com .rk-lightbox-btn)
.rk-lightbox-downloadControlsBotão de download (com .rk-lightbox-btn)
.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-titleInfoTítulo da imagem
.rk-lightbox-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)
.rk-lightbox-video-errorVideoSlideContêiner do estado de erro do vídeo

Temas

Cada cor, tamanho, z-index e transição vive em uma propriedade CSS. Sobrescreva uma ou várias em :root (ou em qualquer ancestral da galeria) para trocar o tema sem mexer no código dos componentes. Os tokens são os mesmos do lightbox do React, então as sobrescritas valem para os dois bindings.

TokenPadrãoO que controla
--rk-lightbox-overlay-bg#000Cor do fundo em tela cheia
--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)Cor do gradiente do topo
--rk-lightbox-edge-padding16pxRecuo da borda para fechar, navegação e controles do canto superior esquerdo
--rk-lightbox-controls-gap12pxEspaço entre os controles do canto superior esquerdo
--rk-lightbox-transition0.2sDuração da transição dos botões ao passar o mouse
--rk-lightbox-blur8pxRaio do desfoque atrás de botões e etiquetas
--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-btn-disabled-opacity0.5Opacidade de um botão pequeno desativado (download em andamento)
--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-fg#fffCor do texto do contador
--rk-lightbox-counter-bgrgba(0, 0, 0, 0.5)Fundo da etiqueta do contador
--rk-lightbox-counter-size14pxTamanho da fonte do contador
--rk-lightbox-counter-padding6px 12pxRespiro interno da etiqueta do contador
--rk-lightbox-counter-radius20pxArredondamento da etiqueta do contador
--rk-lightbox-spinner-size28pxLargura e altura do girador padrão
--rk-lightbox-spinner-duration0.8sDuração de uma volta do girador
--rk-lightbox-error-fgrgba(255, 255, 255, 0.4)Cor do ícone e do texto de erro
--rk-lightbox-info-bglinear-gradient(transparent, rgba(0,0,0,0.8))Gradiente que escurece o fundo da legenda
--rk-lightbox-info-padding24pxRespiro interno da legenda
--rk-lightbox-title-size18pxTamanho da fonte do título
--rk-lightbox-description-size14pxTamanho da fonte da descrição
--rk-lightbox-hint-fgrgba(255, 255, 255, 0.5)Cor do texto da dica de deslize
--rk-lightbox-hint-bgrgba(0, 0, 0, 0.3)Fundo da etiqueta da dica de deslize
--rk-lightbox-video-bg#000Cor das faixas em volta do <video>

Cole o trecho abaixo em uma folha de estilo carregada depois de @reelkit/angular-lightbox/styles.css.

css
/* Brand the lightbox */
:root {
  --rk-lightbox-overlay-bg: #0f172a;
  --rk-lightbox-btn-bg: rgba(99, 102, 241, 0.65);
  --rk-lightbox-btn-bg-hover: rgba(168, 85, 247, 0.85);
  --rk-lightbox-nav-size: 56px;
  --rk-lightbox-counter-bg: rgba(99, 102, 241, 0.65);
  --rk-lightbox-info-bg: linear-gradient(
    transparent,
    rgba(99, 102, 241, 0.55) 60%,
    rgba(168, 85, 247, 0.85)
  );
}

Acessibilidade

A raiz do overlay é um diálogo modal (role="dialog", aria-modal="true"). Defina o input ariaLabel 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 do título da imagem e da posição.

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/core.

Atalhos de teclado

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