Hold Button <mv-hold-button>

Botão “Segure para confirmar” para ações destrutivas: enquanto ele é pressionado, um líquido sobe por dentro (ou entra pela lateral) e inverte o rótulo onde o cobre, soltar antes da hora o esvazia, e segurar até o fim termina com uma marca de seleção, um rótulo de concluído e mv-confirm.

CategoriaMicrointerações
TipoWeb Component (<mv-hold-button>)
Statusestável
Keywordshold, long-press, confirm, destructive, delete, progress, safety, liquid

When to use

  • A destructive action such as deleting an account or project should require a deliberate press and hold
  • An important but non-destructive action should be protected from accidental clicks with an accent hold gauge

Avoid when

  • The user must read consequences or type a confirmation before proceeding → use Dialog instead
  • The action stops a long-running process and users should see what they keep before stopping → use Salvage Stop instead
  • The action is frequent and harmless; forcing a hold slows users down for no benefit → use Button instead

Instalação

node scripts/add.mjs hold-button --out ./src/marvelous

Agente de IA com o servidor MCP do Marvelous UI: install_components({ slugs: ["hold-button"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Arquivos copiados (dependências incluídas): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, components/hold-button/hold-button.js, components/hold-button/hold-button.css.

Uso

Início rápido, a menor marcação que funciona:

<mv-hold-button done-label="Project deleted">Hold to delete</mv-hold-button>

Marcação de referência, para usar como ponto de partida e personalizar com atributos, data-* e variáveis CSS:

<div style="display:grid;gap:1.25rem;width:100%;max-width:440px">
  <div style="display:grid;gap:.9rem;padding:1.1rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
    <div style="display:grid;gap:.25rem">
      <strong style="font-size:.95rem">Delete “Lumen website redesign”</strong>
      <span style="font-size:.82rem;color:var(--mv-fg-muted)">All 48 files and their history will be permanently deleted.</span>
    </div>
    <div style="display:flex;gap:.6rem;align-items:center;flex-wrap:wrap">
      <mv-hold-button duration="1600" done-label="Project deleted" id="hb-demo-delete">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M10 11v6M14 11v6M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2l1-12M9 7V4h6v3"/></svg>
        Hold to delete
      </mv-hold-button>
      <span id="hb-demo-log" style="font-size:.8rem;color:var(--mv-fg-subtle)">Let go early to cancel.</span>
    </div>
  </div>
  <div style="display:flex;gap:.75rem;align-items:center;justify-content:center;flex-wrap:wrap">
    <mv-hold-button data-variant="accent" data-fill="sweep" duration="1000" done-label="Published" style="--mv-hold-button-radius:var(--mv-radius-full)">Hold to publish</mv-hold-button>
  </div>
</div>
<script type="module">
  const el = document.getElementById("hb-demo-delete");
  el?.addEventListener("mv-confirm", () => {
    const log = document.getElementById("hb-demo-log");
    if (log) log.textContent = "mv-confirm received at " + new Date().toLocaleTimeString("en-US");
  });
</script>

API

Attributes

NameTipoDefaultDescription
durationnumber1500Required hold time (ms).
done-labelstringConfirmedLabel (and announcement) once confirmed.
hintstringPress and hold to confirmInstruction: accessible description, and the bubble shown after a tap that did not hold.
resetnumber2400Return to the initial state after confirmation (ms, 0 = stays confirmed).
disabledbooleanDisables the button.
data-variantaccent(danger)Accent color instead of danger (non-destructive actions).
data-fillsweep(rise)The liquid fills from the start edge instead of rising from the bottom.
data-stateidle | holding | rewinding | armed | doneSet by the component.

Properties

NameTipoDescription
progressnumberProgress 0..1 (read-only).
strings{ hint?, done?, again? }Overrides for the default texts (translation). The hint and done-label attributes win; again = "Press again to confirm".

Methods

NameDescription
resetState({ instant })Returns to the initial state (rewinds, or instantly).

Events

NameDescription
mv-confirmThe hold went all the way.

Content structure

NameDescription
(content)Label, SVG icon included.

CSS variables

NameDefaultDescription
--mv-hold-button-colorvar(--mv-danger)Fill and text color.
--mv-hold-button-fgwhiteText on the fill.
--mv-hold-button-radiusvar(--mv-radius-md)Radius.

Accessibility

A real <button> described by the instruction (aria-describedby). Keyboard: hold Space or Enter (key repeat is ignored, releasing drains the liquid, Escape or losing focus cancels). A tap never confirms: it shows the instruction and nudges the button. A click with no press behind it (screen readers, switch access) arms the button (“Press again to confirm”, announced, 5 s) and a second one confirms, so the action never depends on a timed gesture alone. Confirmation is announced by a role=status region and the button becomes aria-disabled while confirmed. Touch: no context menu during the press, scrolling cancels, a short vibration on completion where supported. Reduced motion: the level stays (it carries information), the rolling surface, the nudge and the slides go away. Forced colors: the liquid is drawn in Highlight with HighlightText on it.

Esta página foi traduzida com IA. Informar um problema de tradução