Documentação/Componentes
COMPONENTES / PAGINAÇÃO

Paginação

Crie paginação estática, dinâmica ou híbrida e personalize completamente os botões de navegação.

StaticDynamicHybridCustom controls

Escolha o tipo certo#

TipoFonteMelhor uso
EstáticaLista pronta de templatesTutoriais, painéis e páginas com layout diferente
DinâmicaArray dividido por pageSizeUsuários, logs, ranking e resultados de banco
HíbridaIntrodução fixa + array dinâmicoCatálogo com capa ou instruções antes dos itens

Paginação estática#

Registre uma lista quando cada página já é conhecida durante o carregamento.

TSDiscord/Interactions/GuidePages.ts
const page = (title: string, content: string) =>  new MessageBuilder()    .addComponents(      new ContainerBuilder()        .setAccentColor(0xa571f4)        .addTextDisplayComponents(          new TextDisplayBuilder().setContent(            '## ' + title + '' + content + 'Página ${pages.current}/${pages.total}'          )        )    )    .template()Client.registerPaginator('guide-pages', [  { id: 'intro', name: 'Introdução', template: page('Introdução', 'Como usar o painel.') },  { id: 'config', name: 'Configuração', template: page('Configuração', 'Escolha seus canais.') },  { id: 'finish', name: 'Finalização', template: page('Tudo pronto', 'Revise e confirme.') }])
TSDiscord/Commands/Guide.ts
Client.slash({  data: new SlashCommandBuilder()    .setName('guide')    .setDescription('Abre o guia paginado.'),  execute: async interaction => {    await interaction.paginatorRequest('guide-pages', {      ephemeral: true,      pageIndex: 0    })  }})

Paginação dinâmica#

O paginator divide data, chama render para a fatia atual e injeta o contexto da página.

TSDiscord/Interactions/UserPages.ts
type UserRecord = {  id: string  name: string  level: number}const users: UserRecord[] = await userRepository.list()const paginator = Paginator.dynamic({  id: 'users-pages',  data: users,  pageSize: 5,  render: async (items, context) => {    const rows = items.map((user, index) =>      (context.pageIndex * 5 + index + 1) +      '. **' + user.name + '** — nível ' + user.level    )    return new MessageBuilder()      .addComponents(        new ContainerBuilder().addTextDisplayComponents(          new TextDisplayBuilder().setContent(            '## Usuários' + rows.join('') +            'Página ' + context.page + '/' + context.pageCount          )        )      )      .template()  }})Client.registerPaginator('users-pages', paginator)
ContextoValor
itemsItens da página atual
pageNúmero amigável, começando em 1
pageIndexÍndice interno, começando em 0
pageCountQuantidade total de páginas
totalItemsQuantidade total de registros

Dados novos a cada solicitação#

Use uma definição factory para consultar banco ou API quando o usuário abre a paginação, não durante o boot.

TSpaginator factory
Client.registerPaginator('audit-pages', async context => {  const guildId = context.guildId  const records = guildId ? await auditRepository.list(guildId) : []  return Paginator.dynamic({    id: 'audit-pages',    data: records,    pageSize: 10,    ownerId: context.ownerId,    guildId,    render: (items, page) => new MessageBuilder()      .addComponents(        new ContainerBuilder().addTextDisplayComponents(          new TextDisplayBuilder().setContent(            '## Auditoria' +            items.map(item => '- ' + item.summary).join('') +            '' + page.page + '/' + page.pageCount          )        )      )      .template()  })})

Paginação híbrida#

A primeira página é fixa; as seguintes vêm de uma coleção dinâmica.

TScatalog-paginator.ts
const intro = new MessageBuilder()  .addComponents(    new ContainerBuilder()      .setAccentColor(0x6485ff)      .addTextDisplayComponents(        new TextDisplayBuilder().setContent(          '## Catálogo NinenityUse **Próxima** para explorar os projetos.'        )      )  )  .template()const paginator = Paginator.hybrid({  id: 'catalog-pages',  intro,  data: projects,  pageSize: 3,  render: (items, context) => new MessageBuilder()    .addComponents(      new ContainerBuilder().addTextDisplayComponents(        new TextDisplayBuilder().setContent(          items.map(project => '### ' + project.name + '' + project.summary).join('') +          'Página ' + context.page + '/' + context.pageCount        )      )    )    .template()})Client.registerPaginator('catalog-pages', paginator)

Botões de paginação personalizados#

Inclua uma action row no próprio template e marque a ação de cada botão. O runtime detecta os controles e não adiciona uma segunda linha.

TScustom-controls.ts
const controls = new ActionRowBuilder<MessageActionRowComponentBuilder>()  .addComponents(    new ButtonBuilder()      .setCustomId('guide-pages:first')      .setLabel('Primeira')      .setEmoji('⏮')      .setStyle(ButtonStyle.Secondary)      .setPaginationAction('first'),    new ButtonBuilder()      .setCustomId('guide-pages:back')      .setLabel('Voltar')      .setEmoji('◀')      .setStyle(ButtonStyle.Secondary)      .setPaginationAction('back'),    new ButtonBuilder()      .setCustomId('guide-pages:next')      .setLabel('Próxima')      .setEmoji('▶')      .setStyle(ButtonStyle.Primary)      .setPaginationAction('next'),    new ButtonBuilder()      .setCustomId('guide-pages:last')      .setLabel('Última')      .setEmoji('⏭')      .setStyle(ButtonStyle.Secondary)      .setPaginationAction('last')  )const page = new MessageBuilder()  .addComponents(    new ContainerBuilder()      .addTextDisplayComponents(        new TextDisplayBuilder().setContent(          'Página ${pages.current} de ${pages.total}'        )      )      .addActionRowComponents(controls)  )  .template()
  • O prefixo do customId deve ser exatamente o ID registrado no paginator.
  • back e previous são entendidos como a página anterior; no builder use setPaginationAction('back').
  • Use first e last apenas quando a quantidade de páginas justifica esses atalhos.
  • O runtime hidrata os tokens pages.current e pages.total antes de enviar.

Personalizar rótulos automáticos#

Se as páginas não incluem controles, Paginator cria a linha e você pode trocar os rótulos.

TSautomatic-controls.ts
const paginator = Paginator.static({  id: 'help-pages',  pages: [introPage, commandsPage, settingsPage],  controls: {    first: 'Início',    previous: 'Voltar',    next: 'Avançar',    last: 'Fim'  }})Client.registerPaginator('help-pages', paginator)