WMN DevKit — biblioteca WmnUI, o design system PHP do WMN. Ir para o site
Framework WMN · Interface

WmnUI

Biblioteca PHP para geração de HTML com o design system WMN. O CSS já está embutido no servidor — nenhuma tag <link> é necessária nas páginas dos seus módulos.

Início

O que é WmnUI?

Biblioteca PHP para geração de HTML com o design system WMN. O CSS já está embutido no servidor — nenhuma tag <link> é necessária.

Requisitos: PHP 8.0+  |  Arquivo: pacote/wmnui.php

Como incluir

<?php
require_once __DIR__ . '/pacote/wmnui.php';

Estrutura mínima de uma página

<?php
require_once __DIR__ . '/pacote/wmnui.php';

WmnUI::pagina('Título da Página', 'Nome do Usuário', function() {

    WmnUI::cabecalho('Título', 'Subtítulo opcional', function() {
        WmnUI::botao('Ação principal', '#', 'primary');
    });

    WmnUI::conteudo(function() {
        WmnUI::card('Seção', function() {
            echo 'Conteúdo da página aqui.';
        });
    });

});

Referência rápida de métodos

MétodoDescrição
pagina($titulo, $usuario, fn)Página completa (DOCTYPE + shellbar + body)
shellbar($titulo, $usuario, fn?)Barra superior com logo e avatar
cabecalho($titulo, $sub?, fn?)Cabeçalho com título, subtítulo e ações
conteudo(fn)Área de conteúdo principal
card($titulo, fn)Card com cabeçalho e corpo
secao($titulo)Título de seção com linha separadora
divisor()Linha horizontal divisória
botao($rotulo, $href?, $tipo?, $extra?)Botão ou link
botaoEnviar($rotulo, $tipo?, $extra?)Submit button para formulários
grupoBotoes(fn)Botões agrupados lado a lado
form($action, $method, fn)Tag <form>
formGrid(fn)Grid de 4 colunas responsivo
campo($label, $html, $obrig?, $ajuda?, $erro?)Campo com label e mensagens
input($nome, $tipo?, $valor?, $extra?, $comErro?)Retorna <input>
select($nome, $opcoes, $sel?, $extra?, $comErro?)Retorna <select>
textarea($nome, $valor?, $linhas?, $extra?, $comErro?)Retorna <textarea>
checkbox($nome, $label, $marcado?)Checkbox com label
radio($nome, $label, $valor, $marcado?)Radio button com label
formAcoes(fn)Botões alinhados à direita
abas(['Aba' => fn, ...], $abaAtiva?)Abas com painéis
tabela($cols, $linhas, $titulo?, fn?)Tabela com toolbar opcional
tileGrid($tiles)Grade de tiles para home/menu
badge($texto, $tipo?)Badge: '' | 'success' | 'error' | 'warning'
erro($mensagem)Bloco de erro visível
muted($texto)Texto com cor reduzida
Página e layout

Página e layout

pagina()

Gera o DOCTYPE, head com CSS, shellbar e fecha o body automaticamente. O avatar exibe as iniciais do usuário (ex.: MS para Maria Silva).

WmnUI::pagina('Meu App', 'Maria Silva', function() {
    // todo o conteúdo aqui dentro
});

cabecalho() — com botões de ação

WmnUI::cabecalho('Ordens de Serviço', 'Lista de OS abertas', function() {
    WmnUI::botao('Nova OS', '#', 'primary');
    WmnUI::botao('Exportar', '#', 'ghost');
});

card(), secao() e divisor()

WmnUI::card('Título do Card', function() {
    echo '<p>Conteúdo do card.</p>';
});

WmnUI::card('', function() {            // string vazia = card sem cabeçalho
    echo '<p>Conteúdo.</p>';
});

WmnUI::secao('Título de Seção');        // título + linha separadora
WmnUI::divisor();                       // apenas a linha
Botões

Botões

botao() — tipos e tamanhos

Pré-visualização
WmnUI::botao('Padrão');
WmnUI::botao('Primary', '#', 'primary');
WmnUI::botao('Accept',  '#', 'accept');
WmnUI::botao('Reject',  '#', 'reject');
WmnUI::botao('Warning', '#', 'warning');
WmnUI::botao('Ghost',   '#', 'ghost');

// Tamanhos
WmnUI::botao('Small', '#', 'small');
WmnUI::botao('Large', '#', 'large');

// href preenchido → gera <a href> em vez de <button>
WmnUI::botao('Abrir documentação', '/wmnui-docs.php', 'primary');

botaoEnviar() — submit de formulário

Diferença: botao() gera type="button"; botaoEnviar() gera type="submit" e envia o formulário.

WmnUI::botaoEnviar('Salvar');             // primary por padrão
WmnUI::botaoEnviar('Confirmar', 'accept');
WmnUI::botaoEnviar('Excluir', 'reject');

grupoBotoes(), speedbar() e onclick JS

WmnUI::grupoBotoes(function() {
    WmnUI::botao('Editar',   '#', 'primary');
    WmnUI::botao('Excluir',  '#', 'reject');
});

// Botões de ícone compactos
WmnUI::speedbar(function() {
    WmnUI::speedButton('💾', 'Salvar');
    WmnUI::speedButton('🗑️', 'Excluir');
});

// O 4º parâmetro é injetado literalmente na tag (onclick, id, data-*, disabled...)
WmnUI::botao('Dizer Olá', '', 'primary', 'onclick="dizOla()"');
Formulários

Formulários

input(), select(), textarea(), checkbox(), radio()

WmnUI::formGrid(function() {
    WmnUI::campo('Texto',  WmnUI::input('nome',  'text', '', 'placeholder="Digite..."'));
    WmnUI::campo('Número', WmnUI::input('qtd',   'number', '0'));
    WmnUI::campo('Data',   WmnUI::input('dt',    'date'));
    WmnUI::campo('Senha',  WmnUI::input('senha', 'password'));
});

// Chave => Rótulo (a chave é o valor enviado no POST)
WmnUI::select('status', ['' => 'Selecione...', 'ativo' => 'Ativo', 'inativo' => 'Inativo']);

WmnUI::textarea('obs', '', 3, 'placeholder="..."');
WmnUI::checkbox('aceito', 'Aceito os termos', true);
WmnUI::radio('sexo', 'Masculino', 'M', true);

campo() — label, obrigatório, ajuda e erro

// Normal
WmnUI::campo('Nome', WmnUI::input('nome', 'text'));

// Obrigatório (asterisco vermelho no label)
WmnUI::campo('E-mail', WmnUI::input('email', 'email'), true);

// Com texto de ajuda
WmnUI::campo('CPF', WmnUI::input('cpf'), false, 'Somente números.');

// Com erro (borda vermelha + mensagem)
WmnUI::campo('Campo',
    WmnUI::input('campo', 'text', $valor, '', isset($erros['campo'])),
    true, '', $erros['campo'] ?? '');

Formulário completo com validação

<?php
require_once __DIR__ . '/pacote/wmnui.php';

$erros = [];
$dados = [];
$salvo = null;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $dados = ['nome' => trim($_POST['nome'] ?? ''), 'email' => trim($_POST['email'] ?? '')];
    if ($dados['nome']  === '') $erros['nome']  = 'Informe o nome.';
    if ($dados['email'] === '') $erros['email'] = 'Informe o e-mail.';
    if (empty($erros)) { $salvo = $dados; $dados = []; }
}

WmnUI::pagina('Cadastro', 'Usuário', function() use ($erros, $dados, $salvo) {
    WmnUI::cabecalho('Novo Cadastro');
    WmnUI::conteudo(function() use ($erros, $dados, $salvo) {
        if ($salvo !== null) { WmnUI::badge('Cadastro realizado!', 'success'); return; }
        if (!empty($erros))  { WmnUI::erro(count($erros) . ' campo(s) com erro.'); }

        WmnUI::card('Dados', function() use ($erros, $dados) {
            WmnUI::form($_SERVER['PHP_SELF'], 'post', function() use ($erros, $dados) {
                WmnUI::formGrid(function() use ($erros, $dados) {
                    WmnUI::campo('Nome',
                        WmnUI::input('nome', 'text', $dados['nome'] ?? '', '', isset($erros['nome'])),
                        true, '', $erros['nome'] ?? '');
                    WmnUI::campo('E-mail',
                        WmnUI::input('email', 'email', $dados['email'] ?? '', '', isset($erros['email'])),
                        true, '', $erros['email'] ?? '');
                });
                WmnUI::formAcoes(function() {
                    WmnUI::botaoEnviar('Salvar');
                    WmnUI::botao('Cancelar', '#', 'ghost');
                });
            });
        });
    });
});
Abas

Abas

abas() — painéis e aba ativa

O segundo parâmetro define o rótulo da aba que deve abrir (útil para manter a aba ativa após um POST).

WmnUI::abas([
    'Dados'     => function() { echo '<p>Conteúdo da aba Dados.</p>'; },
    'Histórico' => function() { echo '<p>Conteúdo do Histórico.</p>'; },
    'Anexos'    => function() { echo '<p>Nenhum anexo.</p>'; },
]);

// Abrir numa aba específica
WmnUI::abas([ /* ... */ ], 'Histórico');
Tabelas

Tabelas

Assinatura

ParâmetroTipoObrigatórioDescrição
$colunasstring[]SimRótulos do cabeçalho
$linhasarray[]SimCada célula pode ser string ou callable
$titulostringNãoTexto exibido na toolbar acima da tabela
$toolbarcallable|nullNãoBotões/ações à direita do título
Regra da célula: se o valor é uma string, é exibido com escape HTML automático. Se é um callable (fn()), é executado e seu output vai direto para a célula — assim você insere badges, botões ou qualquer HTML.

Tabela simples + coluna com badge (fn)

WmnUI::tabela(
    ['ID', 'Nome', 'Status'],
    [
        ['1', 'João Silva',  fn() => WmnUI::badge('Ativo',   'success')],
        ['2', 'Maria Souza', fn() => WmnUI::badge('Inativo', 'error')],
        ['3', 'Pedro Costa', fn() => WmnUI::badge('Pendente','warning')],
    ]
);

Coluna de ações por linha

Use fn() use ($r) para capturar o ID/dados da linha e gerar botões com onclick dinâmico.

$linhas = array_map(function($r) {
    return [
        $r['ID'],
        $r['NOME'],
        fn() => WmnUI::badge($r['STATUS'] === 'A' ? 'Ativo' : 'Inativo',
                            $r['STATUS'] === 'A' ? 'success' : 'error'),
        fn() => WmnUI::grupoBotoes(function() use ($r) {
            WmnUI::botao('Editar',  '', 'small',        'onclick="abrirForm(' . $r['ID'] . ')"');
            WmnUI::botao('Excluir', '', 'small reject', 'onclick="excluir(' . $r['ID'] . ')"');
        }),
    ];
}, $registros);

WmnUI::tabela(['ID', 'Nome', 'Status', 'Ações'], $linhas);

Toolbar com título e botões + exemplo com banco

<?php
require_once __DIR__ . '/pacote/wmn.php';
require_once __DIR__ . '/pacote/wmnui.php';

$db     = Wmn::instancia();
$linhas = $db->buscar("SELECT ID, DESCRICAO, ATIVO FROM OS_TIPO ORDER BY DESCRICAO");

WmnUI::tabela(
    ['ID', 'Descrição', 'Ativo', 'Ações'],
    array_map(fn($r) => [
        $r['ID'],
        $r['DESCRICAO'],
        fn() => WmnUI::badge($r['ATIVO'] === 'S' ? 'Sim' : 'Não',
                            $r['ATIVO'] === 'S' ? 'success' : 'error'),
        fn() => WmnUI::grupoBotoes(function() use ($r) {
            WmnUI::botao('Editar',  '', 'small',        'onclick="abrirForm(' . $r['ID'] . ')"');
            WmnUI::botao('Excluir', '', 'small reject', 'onclick="excluir(' . $r['ID'] . ')"');
        }),
    ], $linhas),
    'Tipos (' . count($linhas) . ')',                              // título da toolbar
    fn() => WmnUI::botao('+ Novo', '', 'primary', 'onclick="abrirForm(0)"') // botões
);
Tiles

Tiles

tileGrid() — menu/home com tiles

WmnUI::tileGrid([
    [
        'titulo'    => 'Ordens de Serviço',
        'url'       => '/os',
        'numero'    => '24',      // número grande (opcional)
        'subtitulo' => 'abertas'  // texto abaixo do número (opcional)
    ],
    [
        'titulo' => 'Relatórios',
        'url'    => '/relatorios',
        'icone'  => '📊',         // emoji ou SVG (opcional)
    ],
]);
Utilitários

Badges e utilitários

badge(), erro(), muted()

Pré-visualização
PadrãoSucessoErroAtenção
WmnUI::badge('Padrão');
WmnUI::badge('Sucesso', 'success');
WmnUI::badge('Erro',    'error');
WmnUI::badge('Atenção', 'warning');

WmnUI::erro('Não foi possível salvar o registro.');

echo 'Texto normal — ';
WmnUI::muted('texto secundário com cor reduzida.');

Variáveis CSS (design tokens)

Definidas no CSS embutido do servidor — não devem ser sobrescritas, para manter a consistência visual.

Variável CSSUso
--wmn-blueCor primária (botões, links, foco)
--wmn-greenCor de sucesso / aceitar
--wmn-redCor de erro / rejeitar
--wmn-orangeCor de aviso
--wmn-textCor do texto principal
--wmn-subtextCor de texto secundário
--wmn-borderBorda padrão de campos
--wmn-bgFundo da página
--wmn-content-bgFundo de cards e tabelas
--wmn-radiusBorder-radius padrão (2px)
--wmn-shadowSombra padrão de cards
Exemplos práticos

Campo de texto → variável PHP → tela

O fluxo mais básico do PHP com formulário: o usuário envia, o PHP lê $_POST e a página é gerada com o valor.

Código completo (arquivo único)

<?php
require_once __DIR__ . '/pacote/wmnui.php';

// 1. Ler e sanitizar o valor enviado
$nome     = trim($_POST['nome'] ?? '');
$enviado  = isset($_POST['enviar']);
$erroNome = '';

// 2. Validar (só quando submetido)
if ($enviado && $nome === '') {
    $erroNome = 'Digite seu nome.';
}

// 3. Gerar a página — repasse as variáveis via use()
WmnUI::pagina('Olá!', '', function() use ($nome, $enviado, $erroNome) {
    WmnUI::cabecalho('Exemplo de formulário');
    WmnUI::conteudo(function() use ($nome, $enviado, $erroNome) {

        if ($enviado && $erroNome === '') {
            echo '<p style="font-size:20px">👋 Olá, <strong>'
               . htmlspecialchars($nome) . '</strong>!</p>';
        }

        WmnUI::card('Informe seu nome', function() use ($nome, $erroNome) {
            WmnUI::form($_SERVER['PHP_SELF'], 'post', function() use ($nome, $erroNome) {
                WmnUI::formGrid(function() use ($nome, $erroNome) {
                    WmnUI::campo('Seu nome',
                        WmnUI::input('nome', 'text', $nome, 'placeholder="Ex: João"', $erroNome !== ''),
                        true, '', $erroNome);
                });
                WmnUI::formAcoes(function() {
                    WmnUI::botaoEnviar('Enviar', 'primary', 'name="enviar"');
                });
            });
        });
    });
});

Conceitos-chave

ConceitoExplicação
$_POST['campo']Lê o valor enviado pelo formulário (string ou null)
trim()Remove espaços em branco extras
?? ''Null-coalescing: retorna '' se a chave não existe (GET inicial)
isset($_POST['enviar'])Detecta se o botão foi clicado (o botão precisa ter name=)
htmlspecialchars()Converte caracteres especiais para HTML seguro (evita XSS)
use($var)Injeta variáveis PHP dentro de closures (callbacks)
Regra de ouro: nunca imprima $_POST['x'] diretamente — sempre passe por htmlspecialchars() ou pelo WmnUI::input(..., $valor), que já faz o escape.