Pular para o conteúdo principal

UI

A UI do Nexo facilita a criação do Display Components V2 do Discord com tipagem, validação e renderização pronta para envio.


🚀 Como funciona

  • 🧱 Você monta componentes com ui.*.
  • 🎨 Converte tudo para Components V2 com ui.render(...).
  • ✉️ Envia com ui.send(...).
  • 📎 Arquivos de ui.file(...) são anexados automaticamente.
  • ✅ Regras de tamanho/limites são validadas antes do envio.
Fluxo recomendado

ui.*ui.render(...)ui.send(...)


🧪 Exemplo curto

const { createCommand, CommandType, ui } = require('nexocord');

module.exports = createCommand({
name: 'componente',
description: 'Envia um componente simples',
type: CommandType.ChatInput,
async run(interaction) {
// Todo envio segue dois passos:

// 1. Montar os componentes com ui.render(...)
const components = ui.render(ui.text('## Título'), ui.divider());

// 2. Enviar com ui.send
await ui.send(interaction, { components, ephemeral: true });
},
});

🧰 Componentes

📝 Texto e separador

ui.text('Olá mundo');
ui.divider();

🔘 Botão / Row

ui.row(
ui.button({ label: 'Confirmar', customId: 'confirm:id' }),
ui.button({ label: 'Cancelar', customId: 'cancel:id', style: ButtonStyle.Danger }),
);
Dica

emoji também é aceito em ui.button({ ..., emoji: '✅' }).

📚 Select Menus

Os builders aceitam dois estilos de chamada:

  • ui.select.user('select:user', { placeholder: 'Selecione usuário' })
  • ui.select.user({ customId: 'select:user', placeholder: 'Selecione usuário' })
ui.row(
ui.select.string(
'select:id',
[
{ label: 'Opção A', value: 'a' },
{ label: 'Opção B', value: 'b' },
],
{ placeholder: 'Escolha...' },
),
);

ui.row(ui.select.user('select:user', { placeholder: 'Selecione usuário' }));
ui.row(ui.select.user({ customId: 'select:user', placeholder: 'Selecione usuário' }));

ui.row(ui.select.role('select:role', { placeholder: 'Selecione cargo' }));
ui.row(ui.select.role({ customId: 'select:role', placeholder: 'Selecione cargo' }));

ui.row(ui.select.channel('select:channel', [ChannelType.GuildText]));
ui.row(
ui.select.channel({
customId: 'select:channel',
channelTypes: [ChannelType.GuildText],
placeholder: 'Selecione canal',
}),
);

ui.row(ui.select.mentionable('select:mentionable'));
ui.row(ui.select.mentionable({ customId: 'select:mentionable' }));

ui.row(
ui.select.string({
customId: 'select:string',
options: [
{ label: 'Opção A', value: 'a' },
{ label: 'Opção B', value: 'b' },
],
placeholder: 'Escolha...',
}),
);

🧱 Section e thumbnail

ui.section(['Linha 1', 'Linha 2'], {
button: ui.button({ label: 'Abrir', customId: 'open:id' }),
});

ui.section(['Linha 1'], {
thumbnail: ui.thumbnail({
url: 'https://picsum.photos/id/1003/300/300',
description: 'Miniatura',
}),
});
Importante

Agrupa 1 a 3 textos com um botão ou miniatura acessória (não os dois).

ui.gallery(
{ url: 'https://cdn.example.com/a.png' },
{ url: 'https://cdn.example.com/b.png', description: 'Imagem B' },
);

ui.image({
url: 'https://cdn.example.com/banner.png',
description: 'Banner principal',
});

📎 Arquivos

const file = new AttachmentBuilder(Buffer.from('conteudo'), { name: 'exemplo.txt' });
ui.file.fromAttachment(file); // gera attachment://exemplo.txt automaticamente

📦 Container

ui.container(
{ color: '#0099ff' }, // opcional
ui.text('## Título'),
ui.divider(),
ui.row(ui.button({ label: 'OK', customId: 'ok' })),
);
Dica

Aceita color opcional nos formatos: '#0099ff', '0x0099ff' ou 0x0099ff.

📋 Limites e validações

Limites de tamanho:

  • 📏 Máximo 40 componentes por mensagem
  • 🔤 Texto: até 4.000 caracteres por bloco
  • 🔘 Rótulo de botão: 1-80 caracteres
  • 📚 Placeholder de select: até 150 caracteres

Estrutura de componentes:

  • 🔘 customId de botão/select: 1-100 caracteres
  • 📐 ui.row(...): 1-5 componentes por linha
  • 🚫 Select não pode ficar junto de outros componentes na mesma row
  • 📚 String select: 1-25 opções no máximo

URLs e arquivos:

  • 🖼️ Gallery: 1-10 itens
  • 🌐 URLs de mídia: devem começar com http:// ou https://