TipTap no React Native: editor de rich text móvel
Um memorando não é apenas texto simples. É uma ideia estruturada: títulos, negrito, listas com marcadores, blocos de código... e, acima de tudo, listas de verificação interativas. Em um aplicativo colaborativo como o TAMSIV, uma lista de verificação se torna uma verdadeira ferramenta de coordenação de equipe. O problema? Integrar um editor de rich text completo em um aplicativo React Native é um desafio técnico que poucos desenvolvedores abordam de frente.
Passei três semanas construindo este editor. Três semanas de bugs de WebView, problemas de teclado móvel e sincronização em tempo real. Aqui está tudo o que aprendi.
Pontos-chave a serem lembrados:
- TipTap funciona no React Native via WebView com uma ponte bidirecional JSON
- Listas de verificação colaborativas exigem dois modos: validação "single" e "everyone"
- A sincronização ocorre no nível dos itens individuais, não do documento inteiro
- O teclado móvel é o maior desafio técnico da integração
- Supabase Realtime permite sincronização em tempo real sem CRDT complexo
Por que um editor de rich text em um aplicativo móvel?
A resposta curta: porque o texto simples não é suficiente. Quando você anota um memorando em uma reunião, você quer colocar um título, sublinhar uma ideia importante, criar uma lista de ações. Um campo TextInput básico não permite nada disso.
Avaliei várias opções antes de começar. A observação era simples: os aplicativos de produtividade que fazem sucesso em 2026 — Notion, Obsidian, Craft — todos oferecem um editor rico. Tornou-se um padrão. Um memorando de voz que se transforma em texto simples é coisa do passado.
No TAMSIV, o editor de rich text é usado principalmente em memorandos — aquelas notas longas que você dita por voz e depois quer enriquecer manualmente. O pipeline de voz gera texto estruturado, e o editor permite ajustá-lo.
Como o TipTap funciona no React Native?
TipTap é um editor fantástico na web. É baseado em ProseMirror, extensível, bem documentado e a comunidade é ativa. O problema: o React Native não tem DOM. O TipTap não pode funcionar nativamente.
A solução que adotei: uma WebView que incorpora o editor TipTap completo. A arquitetura se decompõe assim:
- Lado da WebView: O TipTap é executado em um ambiente web clássico, com toda a sua potência
- Ponte bidirecional: as mensagens passam entre o React Native e a WebView via
postMessage/onMessage - Serialização JSON: o conteúdo do editor é serializado em JSON TipTap, enviado para a ponte e depois armazenado em HTML no banco de dados
Este padrão não é ideal — ele adiciona uma camada de complexidade — mas é o único que permite ter um editor rico completo no celular sem reescrever o ProseMirror do zero.
Quais funcionalidades o editor suporta?
O editor TAMSIV suporta um conjunto completo de formatação:
- Títulos (H1, H2, H3) para estruturar memorandos longos
- Negrito e itálico para ênfase
- Listas com marcadores e numeradas
- Blocos de código para desenvolvedores (sim, mesmo em um aplicativo de produtividade)
- Listas de verificação interativas — o coração do sistema colaborativo
A escolha foi deliberada: sem tabelas, sem incorporações, sem fórmulas. Cada funcionalidade adicionada complexifica a ponte da WebView e aumenta o risco de bugs. Optei por um editor poderoso, mas focado.
O teclado móvel é o maior desafio técnico?
Sim, sem dúvida. E se você já desenvolveu com WebViews em dispositivos móveis, sabe do que estou falando.
O problema fundamental: quando o usuário digita na WebView, o teclado nativo do smartphone se abre. Mas a WebView não é um componente nativo — ela não se comunica naturalmente com o sistema de gerenciamento de teclado do Android ou iOS. Resultado:
- O cursor desaparece sob o teclado
- A rolagem automática não segue a digitação
- O redimensionamento da visualização está incorreto
- Em alguns dispositivos Android, o teclado fecha e reabre aleatoriamente
A solução exigiu código específico por plataforma. No Android, eu escuto os eventos resize na WebView e ajusto manualmente a altura. No iOS, é um pouco mais previsível graças ao KeyboardAvoidingView, mas ainda é preciso gerenciar a rolagem do cursor manualmente.
Passei quase uma semana inteira apenas nos problemas de teclado. É o tipo de assunto invisível para o usuário final — quando funciona, ninguém percebe — mas que pode arruinar a experiência se for mal gerenciado.
Como funcionam as listas de verificação colaborativas?
As listas de verificação são o cerne do valor colaborativo do TAMSIV. Uma lista de compras compartilhada, uma ata de reunião com ações, um protocolo de equipe — todos esses casos de uso dependem de listas de verificação. Mas uma lista de verificação colaborativa não funciona como uma lista de verificação pessoal.
Implementei dois modos de validação:
Modo "Single": um só é suficiente
Caso de uso: "Comprar o café". O primeiro membro da equipe que o faz marca o item. Está feito. Não é necessário que todos confirmem — uma única pessoa é suficiente.
No banco de dados, é simples: um booleano is_checked e um checked_by (UUID do usuário). O primeiro que marca "ganha".
Modo "Everyone": todos devem validar
Caso de uso: "Ler a ata da reunião". Queremos garantir que cada membro da equipe leu e confirmou. O item só é "feito" quando 100% dos membros o marcaram.
No banco de dados, é mais complexo: uma tabela de validação armazena o status por usuário e por item. Cada marcação é independente. A interface do usuário exibe uma barra de progresso ("3/5 validaram") e colore o item de forma diferente de acordo com o status.
Este sistema de dupla validação é inspirado no que ferramentas profissionais como Jira ou Monday.com fazem, mas adaptado para um uso mais leve — grupos familiares, pequenas equipes, associações.
Como é feita a sincronização em tempo real?
A sincronização é a última peça do quebra-cabeça. Quando duas pessoas editam o mesmo memorando ou marcam itens ao mesmo tempo, tudo precisa permanecer consistente.
Eu uso o Supabase Realtime para propagar as mudanças. A escolha técnica importante: a sincronização é feita no nível dos itens individuais, não do documento inteiro. Quando você marca um item, apenas esse item é atualizado e propagado — não todo o memorando.
Por que essa escolha? Porque sincronizar um documento inteiro cria conflitos de mesclagem impossíveis de resolver sem um sistema do tipo CRDT (Conflict-free Replicated Data Types). Os CRDTs são elegantes na teoria, mas adicionam uma complexidade enorme para um caso de uso que não o necessita.
O fluxo de sincronização:
- O usuário marca um item na WebView
- A ponte envia a mudança para o React Native
- O React Native escreve no Supabase via o serviço dedicado
- O Supabase Realtime propaga a mudança para todos os assinantes
- Os outros clientes recebem a atualização e atualizam sua WebView
Latência típica: 200 a 500ms. Não é o Google Docs, mas é mais do que suficiente para listas de verificação e memorandos colaborativos. O importante é que as mudanças nunca sejam perdidas.
Quais são as armadilhas a serem evitadas com o TipTap no celular?
Após três semanas de integração, aqui estão as armadilhas que eu gostaria de ter conhecido antes de começar:
1. O tamanho do bundle da WebView. O TipTap com todas as suas extensões é pesado. Tive que ser seletivo nas extensões importadas. Cada extensão não utilizada adicionava peso ao carregamento inicial da WebView.
2. O tempo de carregamento inicial. A primeira abertura do editor é lenta (~300ms) porque a WebView precisa carregar, analisar o HTML, inicializar o TipTap. Adicionei um skeleton loader para mascarar esse atraso.
3. O gerenciamento de memória. As WebViews consomem muita memória. Em dispositivos de baixo custo (Android Go, por exemplo), isso pode ser um problema. Implementei um sistema de lazy loading que só carrega a WebView quando o usuário realmente abre o editor.
4. Os atalhos de teclado. Em tablets com teclado externo, os usuários esperam Ctrl+B para negrito, Ctrl+I para itálico. Esses atalhos funcionam nativamente na WebView do TipTap, mas é preciso garantir que não sejam capturados pelo React Native antes de chegar à WebView.
5. O copiar-colar. O conteúdo copiado do editor deve ser formatado corretamente como rich text E texto simples. O TipTap gerencia isso nativamente, mas a ponte da WebView às vezes pode quebrar a formatação.
Como o pipeline de voz se integra com o editor?
É aqui que tudo se conecta. O pipeline de voz do TAMSIV permite ditar um memorando por voz. A IA transcreve, estrutura e gera texto formatado. Este texto chega ao editor TipTap já estruturado — com títulos, listas, às vezes até listas de verificação pré-preenchidas.
O usuário pode então modificar o conteúdo manualmente: adicionar uma lista de verificação, reformatar um parágrafo, inserir um bloco de código. É a combinação voz + editor rico que torna o TAMSIV único. A voz para a captura rápida, o editor para o refinamento.
Este padrão se alinha com o que explico no artigo sobre o gravador de voz: a voz é uma ferramenta de captura, não uma ferramenta de edição. O editor de rich text preenche exatamente essa lacuna.
Quais alternativas ao TipTap existem para o React Native?
Antes de escolher TipTap + WebView, avaliei outras abordagens:
- Markdown nativo: mais leve, mas a experiência de edição é medíocre no celular. O usuário precisa conhecer a sintaxe Markdown.
- React Native customizado com TextInput: possível para negrito/itálico básico, mas incontrolável para listas, blocos de código e listas de verificação.
- Quill.js em WebView: semelhante ao TipTap, mas menos extensível e a comunidade é menos ativa.
- Editor nativo (Swift/Kotlin): o melhor desempenho, mas dobra o trabalho de desenvolvimento, pois é preciso manter duas bases de código.
TipTap + WebView é o melhor compromisso: um único código para ambas as plataformas, máxima extensibilidade e uma comunidade ativa para bugs.
O que aprendi sobre a dívida técnica dos editores
Um editor de rich text é o tipo de recurso que parece simples na superfície, mas esconde uma complexidade imensa. Cada novo formato suportado (tabelas, imagens embutidas, menções @) adiciona interações imprevistas com o resto do sistema.
A lição principal: começar minimalista e adicionar progressivamente. Comecei com títulos + negrito + listas. As listas de verificação vieram depois. Os blocos de código ainda depois. A cada adição, eu validava a estabilidade em ambas as plataformas antes de passar para a próxima.
É exatamente a mesma filosofia que apliquei ao refatoramento da arquitetura: uma complexidade controlada em vez de uma dívida técnica que se acumula. Isso também se alinha com os princípios que detalho no artigo sobre a reestruturação do banco de dados.
Se você está desenvolvendo um aplicativo móvel e está considerando um editor de rich text, meu conselho: comece validando o teclado móvel. Se essa parte funcionar, o resto seguirá. Se não funcionar, nenhuma quantidade de recursos salvará a experiência do usuário.
O editor do TAMSIV não é o mais poderoso do mercado — Notion e Craft fazem melhor. Mas é suficiente para o caso de uso alvo, funciona em modo colaborativo e se integra nativamente com o pipeline de voz. Às vezes, "suficiente e confiável" vale mais do que "espetacular e instável".
FAQ
O TipTap é gratuito para uso comercial?
Sim. O TipTap é de código aberto sob licença MIT. O núcleo do editor e a maioria das extensões são gratuitos. Apenas algumas extensões "Pro" (colaboração avançada, gerenciamento de comentários) são pagas, mas não são necessárias para a maioria dos casos de uso.
O editor funciona offline?
O editor em si funciona perfeitamente offline, pois é executado em uma WebView local. Apenas a sincronização em tempo real requer uma conexão. As modificações são enfileiradas e sincronizadas quando a rede é restabelecida.
Qual é a diferença entre uma lista de verificação "single" e "everyone"?
No modo "single", apenas um membro precisa marcar para validar o item (ex: "comprar o café"). No modo "everyone", cada membro deve marcar individualmente (ex: "ler a ata"). O modo é configurável por item no editor.
O desempenho é adequado em dispositivos de baixo custo?
Sim, com precauções. O carregamento lento da WebView evita carregar o editor até que seja necessário. Nos dispositivos mais modestos, o tempo de abertura inicial pode chegar a 500ms, mas a edição permanece fluida uma vez carregada.
Por que não usar um CRDT para sincronização?
Os CRDTs (como Yjs ou Automerge) são poderosos, mas adicionam uma complexidade significativa. Para listas de verificação e memorandos colaborativos, a sincronização por item via Supabase Realtime é suficiente e muito mais simples de manter.