API Reference frappe_ui_phx v#0.3.1

Copy Markdown View Source

Modules

Componentes Phoenix LiveView com a identidade visual do Frappe UI.

Aritmética de calendário pura usada pelo DatePicker (semana começando no domingo).

Grade horizontal, rótulos do eixo Y e rótulos de categorias (SVG).

Gráfico de barras agrupadas (SVG no servidor, cores do tema, estados loading/empty/error).

Geometria compartilhada pelos gráficos de eixos (barras, linhas, áreas): área de plotagem, escala Y, posições X por categoria e grade. Funções puras.

Cartão que enquadra um gráfico: título, subtítulo, ações e o gráfico no corpo.

Gráfico de rosca (SVG no servidor). data é [%{label, value}]; valores ≤ 0 são ignorados.

Moldura comum dos gráficos com os estados :loading, :empty e :error (visualmente distintos); no estado :ready mostra o gráfico.

Legenda: marcador colorido + nome. items é [%{label, color}] ou vem das séries.

Gráficos de linha e de área (SVG no servidor), com pontos, dicas e estados.

Mapas de calor: matriz linhas × colunas e calendário (estilo contribuições).

Cartão de indicador: rótulo, valor grande e variação percentual opcional (verde sobe, vermelho cai).

Gráficos de proporção: barra percentual empilhada e funil.

Diagrama de Sankey: links é [%{source, target, value}]; os nós e as colunas (profundidade) são derivados dos links. Ciclos não são suportados e falham alto.

Matemática pura dos gráficos: escalas lineares, "números bonitos" para eixos, paleta de cores do tema e formatação numérica estável para SVG.

Gráfico de dispersão: séries de pontos {x, y} em eixos numéricos.

Dica de um ponto de dado, desenhada em SVG: aparece quando o pai tem a classe group e está em hover/foco (CSS puro). Complementa o <title> nativo.

Catálogo de componentes: módulo, função, categoria e título. Fonte única usada por use FrappeUIPhx (imports), pelo mostruário (navegação e especificação) e pelo teste que garante que nenhum componente público fica sem catálogo.

Seções recolhíveis sobre <details> nativo (teclado e leitores de tela de graça). Por padrão só uma seção fica aberta por vez (atributo name do HTML, agrupado pelo id); com multiple, qualquer combinação. open no item abre desde o servidor.

Único lugar onde se decide "link ou botão" para um item de ação (navegação, abas, menus). NavItem, MenuItem e Tabs renderizam por aqui.

Alerta com título, descrição e ação opcional. Temas gray | blue | green | amber | red.

Posicionamento de flutuantes por CSS Anchor Positioning (sem JS).

Avatar com imagem ou iniciais do label. Formas circle | square.

Selo de status: temas gray | blue | green | amber | red | violet, variantes solid | subtle | outline | ghost.

Folha inferior (mobile): um Dialog com placement: :bottom; abre/fecha com show_dialog/1 e hide_dialog/1.

Trilha de navegação; o último item é a página atual (aria-current="page").

Botão do Frappe UI: variantes solid | subtle | outline | ghost, temas gray | blue | green | red, tamanhos xs | sm | md | lg.

Calendário mensal com eventos (visão de agenda). O mês exibido e o dia selecionado são assigns do servidor; navegar e escolher são eventos (on_prev, on_next, on_today, on_select com %{"date" => "2026-03-09"}).

Caixa de seleção com rótulo opcional. Emite o hidden com "false" como o core_components do Phoenix, para que o desmarcado chegue ao servidor.

Editor de código: <textarea> monoespaçado com numeração de linhas, tecla Tab que indenta e rótulo da linguagem. É um campo de formulário comum (name, phx-change, field).

Seleção única com busca. Aceita field (Phoenix/Ecto); a escolha é um radio nativo do formulário.

Paleta de comandos (Ctrl/⌘ + K): busca, grupos e navegação por teclado. Abre como o Dialog (mesmo hook nativo: foco preso, Esc, backdrop) e o hook próprio só filtra a lista, move a seleção com ↑/↓ e aciona o item com Enter. O que cada item faz é decidido pelo servidor (click) ou por navegação.

Menu de contexto (botão direito) sobre uma região. O hook colocated só posiciona e abre o popover no cursor; o que cada item faz é decidido pelo servidor (click) ou por navegação.

Seletor de data com calendário (LiveComponent: o mês exibido é estado próprio).

Casca de página para desktop: :sidebar à esquerda e o conteúdo rolável à direita.

Diálogo modal sobre <dialog> nativo (foco preso, Esc e backdrop pelo navegador).

Avatar gerado pelo DiceBear a partir de uma seed: a mesma style + seed + options dá sempre o mesmo desenho. Mesmos tamanhos e formas do FrappeUIPhx.Components.Avatar, de quem herda o visual (composição).

Linha divisória horizontal ou vertical.

Menu suspenso sem JavaScript: Popover API (light-dismiss e Esc nativos) + CSS Anchor Positioning (inverte para cima quando falta espaço).

Campo de duração: mostra 1h 30m quando o valor são segundos e aceita o que FrappeUIPhx.Duration entende. Combine com FrappeUIPhx.Ecto.Duration no schema.

Editor de texto rico (negrito, itálico, título, listas, código, link) que guarda Markdown num <input type=hidden>, então participa do formulário e do phx-change como qualquer campo.

Mensagem(ns) de erro. Aceita uma string, uma lista de strings ou nil (não renderiza nada).

Área de envio sobre allow_upload/3 do LiveView: arrastar-e-soltar, lista de arquivos com progresso, cancelamento e erros em português. Quem decide o que fazer com o arquivo (consume_uploaded_entries/3) é o servidor.

Rótulo + controle + descrição + erros, escolhendo o controle por type.

Rótulo de campo; required acrescenta o asterisco e deve espelhar o required do controle.

Cartão que aparece em hover ou foco do gatilho, com pequeno atraso (CSS puro).

Ícone Lucide por nome, renderizado como <svg> inline (veja FrappeUIPhx.Icons).

Classes compartilhadas por TextInput, Textarea e Select (função pura).

Linha de lista com ícone, título, subtítulo e ações; navegável por navigate/patch/href.

Atalho de teclado: uma <kbd> por tecla (keys={["Ctrl", "K"]}).

Diálogo com a lista de atalhos: shortcuts={[%{label: "Buscar", keys: ["Ctrl", "K"]}]}.

Tabela de objetos: colunas por slot (:col), ações por linha (:action), seleção por checkbox e reordenação por arrastar-e-soltar. O estado (selected, ordem de rows) vive no servidor; cada interação é um evento.

Lista agrupada e recolhível: group_by (função linha → rótulo) forma os grupos; os recolhidos (collapsed) são um assign do servidor e o cabeçalho de cada grupo dispara on_toggle com %{"group" => rótulo}. Colunas por slot, como em list. Experimental.

Texto de carregamento com spinner.

Item de menu (Dropdown, ContextMenu): navega (navigate/patch/href) ou dispara evento (click) e fecha o popover pai. Tema :gray ou :red.

Casca para telas estreitas: cabeçalho, conteúdo rolável e navegação inferior (:nav).

Seleção múltipla com busca e selos. Envia name[] (mais um "" para permitir esvaziar); combine com FrappeUIPhx.Ecto.StringList, que descarta o vazio.

Item de navegação com ícone e rótulo (Tabs, TabButtons, Sidebar, SidebarRail, SettingsDialog, MobileShell). Navega por patch/navigate/href ou dispara click (evento ou %JS{}) — a decisão "link ou botão" é de FrappeUIPhx.Components.Action. O estado ativo é decidido por quem chama (assign do servidor).

Base de Combobox e MultiSelect: gatilho + painel (Popover API) com busca e opções que são <input type=radio|checkbox> nativos — então a seleção já é valor de formulário e dispara o phx-change sem nenhum JS de negócio.

Cabeçalho de página: breadcrumbs opcionais, título e ações.

Campo de senha com botão de mostrar/ocultar. A alternância é só visual (JS.toggle_attribute no type); o valor nunca é reenviado ao HTML.

Código de verificação / PIN: uma caixa por caractere, com avanço automático, Backspace que volta, setas, colar o código inteiro e preenchimento por SMS (autocomplete="one-time-code").

Painel flutuante com conteúdo livre: Popover API + CSS Anchor Positioning (sem JS).

Barra de progresso (value de 0 a 100) com rótulo e valor opcionais.

Grupo de opções exclusivas (<input type=radio> nativos); options como em Select.

Avaliação em estrelas (1..max). Cada estrela é um <input type=radio>, então funciona em formulários e phx-change; o preenchimento vem do valor no servidor. Combine com FrappeUIPhx.Ecto.Rating no schema.

Confirmação visual transitória ("Salvo") sem useEffect/timer: o servidor devolve um valor que muda a cada sucesso (at, ex. um timestamp) e o :key remonta o elemento, reiniciando a animação CSS que termina em opacidade 0.

Região rolável com barras finas e discretas (CSS nativo); focável para rolagem por teclado.

Seleção nativa. options aceita lista de strings, {rótulo, valor} ou keyword; prompt adiciona uma primeira opção vazia.

Diálogo de configurações: navegação lateral por seções (:tab) e o conteúdo da seção ativa. A seção ativa (active) é um assign do servidor.

Barra lateral de navegação. O item ativo (active) e o recolhimento (collapsed) são assigns do servidor; recolhida, só os ícones aparecem.

Trilho estreito só com ícones (rótulo acessível e title); ativo por assign.

Bloco animado para estados de carregamento; dimensione por class (ex.: h-4 w-32).

Controle deslizante (<input type=range>); min <= value <= max é pré-condição.

Lista reordenável por arrastar-e-soltar (HTML5 nativo).

Indicador de carregamento; herda a cor do texto.

Indicador de etapas. A etapa atual (current, índice a partir de 0; igual ao número de etapas = tudo concluído) é um assign do servidor, e o estado de cada etapa (:done | :current | :upcoming) é derivado dele. Com on_go, as etapas concluídas viram botões que voltam para elas (%{"step" => índice}). Experimental.

Interruptor. É um checkbox nativo (peer), então funciona em formulários sem JS.

Abas em formato de botões segmentados; a ativa é um assign do servidor (active).

Abas cujo item ativo é decidido por um assign (active), nunca por estado do cliente. Cada :tab navega (patch/navigate) ou dispara evento (click). O conteúdo do painel ativo vai no inner_block.

Campo de uma linha. Aceita field={@form[:campo]} (Phoenix/Ecto) ou name/value avulsos. Restrições (required, maxlength, min, pattern, placeholder...) vão direto ao <input>; o servidor continua sendo a barreira real (o required aqui espelha a regra do changeset).

Campo de várias linhas; mesmo contrato de FrappeUIPhx.Components.TextInput.

Alternador claro/escuro. Cada opção é um link ?theme=… tratado por FrappeUIPhx.Plug.Theme, que persiste a escolha em sessão e cookie; o tema atual (current) vem do servidor (@frappe_ui_theme). Experimental.

Seletor de horário (<input type=time> nativo, com o teclado/relógio do dispositivo); step em segundos.

Container de toasts: mostra mensagens de flash (renderizadas no servidor) e as enviadas por FrappeUIPhx.Toast.put_toast/4 (via hook colocated).

Dica visual sem JavaScript: aparece em hover e em foco do conteúdo envolvido.

Árvore de nós %{id, label, icon, children}. Expansão (expanded) e seleção (selected) são assigns do servidor; cada clique é um evento (on_toggle/on_select com %{"id" => id}). Com on_drop, os nós de um mesmo nível podem ser reordenados por arrastar-e-soltar.

Resolve e valida o módulo configurado para um ponto de extensão (IconResolver, ToastSink, ErrorTranslator, Translator). Um módulo inexistente ou sem o callback falha na primeira chamada com mensagem clara, em vez de um UndefinedFunctionError no meio da renderização.

Design by Contract para os componentes.

URL da API HTTP do DiceBear (avatares gerados a partir de uma seed).

Duração em segundos ⇄ texto digitado (1h 30m, 90m, 45s, 1:30, 1:30:15, 5400).

Ecto.Type para o campo Duration do Frappe UI: guarda segundos (inteiro não negativo) e aceita no cast o que um usuário digita

Opções de Select/Combobox a partir de um campo Ecto.Enum, para que a lista da tela e o domínio nunca divirjam

Ecto.ParameterizedType para avaliação em estrelas: inteiro de 0 a max (padrão 5). Aceita string vindo do formulário.

Ecto.Type para listas de textos (tags, MultiSelect): persiste como {:array, :string} e aceita no cast uma lista ou uma string separada por vírgula. Descarta vazios e repetidos, preservando a ordem.

Contrato de tradução de erros de changeset {mensagem, opções}.

Tradutor padrão de erros de changeset: interpola %{chave} da mensagem com as opções do erro, sem depender de Gettext nem do próprio Ecto.

Costura entre Phoenix.HTML.FormField (changeset/Ecto) e os controles.

Fundamentos visuais do Frappe UI (cores, tipografia, raios, sombras, anel de foco e cores de gráficos) como dados, lidos de priv/foundations.json, que mix tokens.sync gera da mesma fonte dos tokens do CSS. Alimenta as páginas de Fundamentos do mostruário e serve de referência em código (ex.: listar tokens).

Contrato de como o nome de ícone usado no projeto vira um nome do catálogo Lucide (FrappeUIPhx.Icons). Serve para apelidos do projeto ("salvar" -> "save")

Resolvedor padrão: o nome já é do catálogo Lucide e passa direto.

Catálogo de ícones Lucide: nomes, tags, aliases (nomes antigos) e busca.

Um componente LiveView por ícone Lucide (atalhos de FrappeUIPhx.Icons.Svg).

Renderiza um ícone do catálogo como <svg> inline, com as propriedades do Lucide.

Edições idempotentes nos arquivos do app host (CSS, JS, mix.exs), em funções puras conteúdo -> {:ok, novo, mudou?} | {:error, motivo}. A task mix frappe_ui_phx.install só lê/escreve arquivos em volta delas.

on_mount que copia o tema resolvido por FrappeUIPhx.Plug.Theme (guardado na sessão) para socket.assigns.frappe_ui_theme, mantendo o estado autoritativo no servidor também dentro do LiveView.

Subconjunto seguro de Markdown usado pelo Editor: ## título, listas (- e 1.), parágrafos, **negrito**, _itálico_, `código` e [texto](https://url).

Serve frappe_ui.css (tokens) e frappe_ui_icons.css da própria dependência em /frappe_ui/, para quem prefere <link> a @import no app.css.

Resolve o tema ("light" ou "dark") e o expõe em conn.assigns.frappe_ui_theme para o layout raiz: <html data-theme={@frappe_ui_theme}>.

Textos fixos da biblioteca (rótulos de acessibilidade, mensagens auxiliares), em português por padrão, sobrescrevíveis sem copiar componentes.

API de servidor para toasts (substitui toast() do Frappe UI).

Contrato de como um toast chega ao cliente. A implementação padrão (FrappeUIPhx.ToastSink.PushEvent) usa push_event/3; troque via config

Entrega o toast ao hook .Toast pelo evento frappe-ui:toast.

Contrato para traduzir os textos fixos da biblioteca.

Mix Tasks

Configura o app Phoenix atual para usar a biblioteca. Idempotente: pode rodar quantas vezes quiser.