Ir para o conteúdo
Secções
Idioma, atualmente Português
Sistema de design Rastrillo

Opções e ações

Os controlos com que se escolhe entre opções, e as linhas que terminam um formulário. Cada um fica dentro de um rst-box com espaçamento, porque é essa a regra que estes parciais assumem.

Cada exemplo funciona de verdade, mas as suas ligações não levam a lado nenhum. HTML mostra a marcação para copiar.

field-select

O invólucro do field à volta de um select nativo. A partir de dez opções, o select ativa a caixa com filtro do select.js; o que o formulário envia continua a ser o select nativo.

Três opções: um select nativo

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-field>
  <label rst-field-label for="sel_few">Função</label>
  <select rst-input id="sel_few" name="sel_few">
    <option value="admin" selected>Administrador</option>
    <option value="editor">Editor</option>
    <option value="member">Membro</option>
  </select>
</div>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "field-select" dict
    "ID" "sel_few"
    "Name" "sel_few"
    "Label" "Função"
    "Options" (list
        (dict "Label" "Administrador" "Selected" true "Value" "admin")
        (dict "Label" "Editor" "Value" "editor")
        (dict "Label" "Membro" "Value" "member"))}}

Doze opções: a caixa combinada com filtro

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-field>
  <label rst-field-label for="sel_many">Cidade</label>
  <select rst-input id="sel_many" name="sel_many" data-rst-select data-rst-select-filter="Escreva para filtrar" data-rst-select-results="{n} resultados" data-rst-select-result-one="1 resultado" data-rst-select-no-matches="Sem correspondências" aria-describedby="sel_many-help">
    <option value="dublin" selected>Dublin</option>
    <option value="lisbon">Lisboa</option>
    <option value="madrid">Madrid</option>
    <option value="berlin">Berlim</option>
    <option value="rome">Roma</option>
    <option value="athens">Atenas</option>
    <option value="helsinki">Helsínquia</option>
    <option value="reykjavík">Reiquiavique</option>
    <option value="warsaw">Varsóvia</option>
    <option value="zagreb">Zagreb</option>
    <option value="tallinn">Tallinn</option>
    <option value="valletta">Valeta</option>
  </select>
  <p rst-field-help id="sel_many-help">Comece a escrever para filtrar.</p>
</div>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "field-select" dict
    "ID" "sel_many"
    "Name" "sel_many"
    "Label" "Cidade"
    "Options" (list
        (dict "Label" "Dublin" "Selected" true "Value" "dublin")
        (dict "Label" "Lisboa" "Value" "lisbon")
        (dict "Label" "Madrid" "Value" "madrid")
        (dict "Label" "Berlim" "Value" "berlin")
        (dict "Label" "Roma" "Value" "rome")
        (dict "Label" "Atenas" "Value" "athens")
        (dict "Label" "Helsínquia" "Value" "helsinki")
        (dict "Label" "Reiquiavique" "Value" "reykjavík")
        (dict "Label" "Varsóvia" "Value" "warsaw")
        (dict "Label" "Zagreb" "Value" "zagreb")
        (dict "Label" "Tallinn" "Value" "tallinn")
        (dict "Label" "Valeta" "Value" "valletta"))
    "Help" "Comece a escrever para filtrar."}}

A partir de dez opções, o parcial ativa o select.js. Abaixo de dez, não: procurar entre um punhado de itens é mobília, não ajuda.

Doze opções, Plain: a melhoria recusada

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-field>
  <label rst-field-label for="sel_plain">Cidade</label>
  <select rst-input id="sel_plain" name="sel_plain">
    <option value="dublin" selected>Dublin</option>
    <option value="lisbon">Lisboa</option>
    <option value="madrid">Madrid</option>
    <option value="berlin">Berlim</option>
    <option value="rome">Roma</option>
    <option value="athens">Atenas</option>
    <option value="helsinki">Helsínquia</option>
    <option value="reykjavík">Reiquiavique</option>
    <option value="warsaw">Varsóvia</option>
    <option value="zagreb">Zagreb</option>
    <option value="tallinn">Tallinn</option>
    <option value="valletta">Valeta</option>
  </select>
</div>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "field-select" dict
    "ID" "sel_plain"
    "Name" "sel_plain"
    "Label" "Cidade"
    "Options" (list
        (dict "Label" "Dublin" "Selected" true "Value" "dublin")
        (dict "Label" "Lisboa" "Value" "lisbon")
        (dict "Label" "Madrid" "Value" "madrid")
        (dict "Label" "Berlim" "Value" "berlin")
        (dict "Label" "Roma" "Value" "rome")
        (dict "Label" "Atenas" "Value" "athens")
        (dict "Label" "Helsínquia" "Value" "helsinki")
        (dict "Label" "Reiquiavique" "Value" "reykjavík")
        (dict "Label" "Varsóvia" "Value" "warsaw")
        (dict "Label" "Zagreb" "Value" "zagreb")
        (dict "Label" "Tallinn" "Value" "tallinn")
        (dict "Label" "Valeta" "Value" "valletta"))
    "Plain" true}}

Obrigatório, com um erro

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-field>
  <label rst-field-label for="sel_error">Função</label>
  <select rst-input id="sel_error" name="sel_error" required aria-invalid="true" aria-describedby="sel_error-error">
    <option value="admin" selected>Administrador</option>
    <option value="editor">Editor</option>
    <option value="member">Membro</option>
  </select>
  <p rst-field-error id="sel_error-error" role="alert">Escolha uma função para esta pessoa.</p>
</div>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "field-select" dict
    "ID" "sel_error"
    "Name" "sel_error"
    "Label" "Função"
    "Options" (list
        (dict "Label" "Administrador" "Selected" true "Value" "admin")
        (dict "Label" "Editor" "Value" "editor")
        (dict "Label" "Membro" "Value" "member"))
    "Required" true
    "Error" "Escolha uma função para esta pessoa."}}

Escrito à mão, com optgroups

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-field>
  <label rst-field-label for="sel_grouped">Região</label>
  <select rst-input id="sel_grouped" name="sel_grouped" data-rst-select data-rst-select-filter="Escreva para filtrar" data-rst-select-results="{n} resultados" data-rst-select-result-one="1 resultado" data-rst-select-no-matches="Sem correspondências">
    <optgroup label="Europa">
      <option value="dublin" selected>Dublin</option>
      <option value="lisbon">Lisboa</option>
      <option value="warsaw">Varsóvia</option>
    </optgroup>
    <optgroup label="Américas">
      <option value="montreal">Montreal</option>
      <option value="lima">Lima</option>
      <option value="austin">Austin</option>
    </optgroup>
    <optgroup label="Ásia">
      <option value="osaka">Osaka</option>
      <option value="hanoi">Hanói</option>
      <option value="dhaka">Daca</option>
    </optgroup>
    <optgroup label="África">
      <option value="accra">Acra</option>
      <option value="nairobi">Nairóbi</option>
      <option value="tunis">Tunes</option>
    </optgroup>
  </select>
</div>

Aqui o Options é uma lista plana, por isso as opções agrupadas são marcação que a aplicação escreve. O select.js desenha os grupos em vez de os deitar fora; um select escrito à mão também pode recusar a melhoria por completo com data-rst-select="false".

field-check

O único mecanismo de comutação: uma caixa de verificação a sério com aspeto de interruptor, sem perder teclado nem leitor de ecrã.

Ligado

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<label rst-switch>
  <input type="checkbox" name="notify_on" checked>
  <span rst-switch-track aria-hidden="true"></span>
  Enviar-me um e-mail sobre respostas
</label>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "field-check" dict
    "Name" "notify_on"
    "Label" "Enviar-me um e-mail sobre respostas"
    "Checked" true}}

Desligado

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<label rst-switch>
  <input type="checkbox" name="notify_off">
  <span rst-switch-track aria-hidden="true"></span>
  Enviar-me um e-mail sobre menções
</label>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "field-check" dict
    "Name" "notify_off"
    "Label" "Enviar-me um e-mail sobre menções"}}

Desativado

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<label rst-switch>
  <input type="checkbox" name="notify_disabled" disabled>
  <span rst-switch-track aria-hidden="true"></span>
  Enviar-me um resumo semanal por e-mail
</label>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "field-check" dict
    "Name" "notify_disabled"
    "Label" "Enviar-me um resumo semanal por e-mail"
    "Disabled" true}}

choice-field

Cartões de opção: o grupo de rádios ou caixas que preferimos. O Title fica curto; o Desc explica.

Escolha uma

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<fieldset rst-choice>
  <legend>Plano</legend>
  <div rst-choice-cards>
    <label>
      <input type="radio" name="plan" value="free">
      <span>
        <span rst-choice-title>Gratuito</span>
        <span rst-choice-desc>Um projeto, apoio da comunidade.</span>
      </span>
    </label>
    <label>
      <input type="radio" name="plan" value="pro" checked>
      <span>
        <span rst-choice-title>Pro</span>
        <span rst-choice-desc>Projetos ilimitados e uma caixa de apoio.</span>
      </span>
    </label>
  </div>
</fieldset>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "choice-field" dict
    "Legend" "Plano"
    "Name" "plan"
    "Options" (list
        (dict "Desc" "Um projeto, apoio da comunidade." "Title" "Gratuito" "Value" "free")
        (dict "Checked" true "Desc" "Projetos ilimitados e uma caixa de apoio." "Title" "Pro" "Value" "pro"))}}

Escolha as que quiser

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<fieldset rst-choice>
  <legend>Enviar-me</legend>
  <div rst-choice-cards>
    <label>
      <input type="checkbox" name="digest" value="replies" checked>
      <span>
        <span rst-choice-title>Respostas</span>
        <span rst-choice-desc>No momento.</span>
      </span>
    </label>
    <label>
      <input type="checkbox" name="digest" value="weekly">
      <span>
        <span rst-choice-title>Resumo semanal</span>
        <span rst-choice-desc>Às segundas de manhã.</span>
      </span>
    </label>
  </div>
</fieldset>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "choice-field" dict
    "Legend" "Enviar-me"
    "Name" "digest"
    "Type" "checkbox"
    "Options" (list
        (dict "Checked" true "Desc" "No momento." "Title" "Respostas" "Value" "replies")
        (dict "Desc" "Às segundas de manhã." "Title" "Resumo semanal" "Value" "weekly"))}}

form-foot

A linha final de um formulário: um botão de envio principal e uma ligação opcional para cancelar. Cancelar é uma ligação, porque sair de um formulário é navegar.

Guardar e cancelar

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-form-foot>
  <button rst-btn="primary lg" type="submit">Guardar publicação</button>
  <a rst-btn="lg" href="/posts">Voltar às publicações</a>
</div>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "form-foot" dict
    "Submit" "Guardar publicação"
    "CancelHref" "/posts"
    "CancelLabel" "Voltar às publicações"}}

Só enviar

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-form-foot>
  <button rst-btn="primary lg" type="submit">Enviar convite</button>
</div>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "form-foot" dict "Submit" "Enviar convite"}}

Em repouso: o botão antes de acontecer alguma coisa

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-form-foot>
  <button rst-btn="primary lg" type="submit">Publicar</button>
  <a rst-btn="lg" href="/posts">Voltar às publicações</a>
</div>

Coloque isto dentro de <section rst-box><form rst-form>.

{{template "form-foot" dict
    "Submit" "Publicar"
    "CancelHref" "/posts"
    "CancelLabel" "Voltar às publicações"}}

Um botão que MUDA alguma coisa recebe um estado de carregamento; um botão que apenas revela alguma coisa — uma divulgação, um menu pendente, um separador — não. O rastrillo.js aplica essa regra a todos os botões de envio de todos os formulários, sem nada para ativar.

A trabalhar: o que o rastrillo.js escreve quando o formulário sai

Pré-visualização

Coloque isto dentro de <section rst-box><form rst-form>.

<div rst-form-foot>
  <button rst-btn="primary lg" type="submit" aria-busy="true" disabled>
    <span rst-spin aria-hidden="true"></span>
    Publicar
  </button>
  <a rst-btn="lg" href="/posts">Voltar às publicações</a>
</div>

Apenas o botão em que se clicou: todos os outros botões de envio do formulário mantêm o seu nome e o seu valor, e o próprio formulário fica protegido contra um segundo envio. data-busy="false" desativa a regra, no formulário ou num botão; data-busy-label substitui o texto. Sem scripts nada disto acontece e o formulário é enviado exatamente como sempre foi, por isso a idempotência continua a ser tarefa do servidor.

confirm-form

A linha de ações da página de confirmação. As ações destrutivas têm rota própria em vez de um diálogo, por isso não há nada para programar.

Destrutivo

Pré-visualização

Coloque isto dentro de <section rst-box>.

<form rst-form-actions method="post" action="/posts/1/delete">
  <input type="hidden" name="csrf" value="tok-123">
  <input type="hidden" name="id" value="1">
  <a rst-btn="ghost lg" href="/posts/1">Cancelar</a>
  <button type="submit" rst-btn="danger lg">Eliminar esta publicação</button>
</form>

Coloque isto dentro de <section rst-box>.

{{template "confirm-form" dict
    "Action" "/posts/1/delete"
    "Label" "Eliminar esta publicação"
    "Danger" true
    "Hidden" (list (list "csrf" "tok-123") (list "id" "1"))
    "CancelHref" "/posts/1"}}

Caso normal, com a redação de cancelar por omissão

Pré-visualização

Coloque isto dentro de <section rst-box>.

<form rst-form-actions method="post" action="/posts/1/publish">
  <a rst-btn="ghost lg" href="/posts/1">Cancelar</a>
  <button type="submit" rst-btn="primary lg">Publicar</button>
</form>

Coloque isto dentro de <section rst-box>.

{{template "confirm-form" dict
    "Action" "/posts/1/publish"
    "Label" "Publicar"
    "CancelHref" "/posts/1"}}

Sem CancelLabel, por isso a ligação de cancelar é redigida a partir do catálogo.