Exclusifbêta

Origami <mv-origami>

Des panneaux qui se plient comme du papier. Variante Fold : un accordéon sur <details> natif dont le contenu est découpé en bandes qui se déplient en zigzag en 3D, avec lumière et ombre sur chaque pli, reflets sur les arêtes, grain du papier, rebond élastique et plis qui restent visibles une fois ouvert. Variante Letter : une enveloppe cachetée qui s’ouvre, sa lettre en glisse, passe au premier plan et se déplie en trois volets, en ligne ou dans une boîte de dialogue modale, pour une annonce ou une invitation.

CatégorieAffichage de données
TypeWeb Component (<mv-origami>)
Statutbêta
Keywordsexclusive, accordion, disclosure, details, faq, fold, paper, 3d, letter, envelope, announcement, modal, invitation

When to use

  • A showcase or brand page wants an accordion whose panels unfold like folded paper in 3D
  • An announcement or invitation should arrive as a sealed envelope that opens into a letter
  • A special message should open in a modal letter with focus trap and fold back on close

Avoid when

  • A plain, fast disclosure for everyday settings or help content is needed → use Accordion instead
  • Users open and close panels frequently, like in a dense app; the fold animation slows repeated use
  • A standard confirmation or form must appear in a modal → use Dialog instead

Installation

node scripts/add.mjs origami --out ./src/marvelous

Agent IA avec le serveur MCP de Marvelous UI : install_components({ slugs: ["origami"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Fichiers copiés (dépendances comprises) : tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/origami/origami.js, components/origami/origami.css.

Utilisation

Balisage de référence : partez de celui-ci et personnalisez-le avec les attributs, data-* et les variables CSS :

<div id="og-demo" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,22rem),1fr));gap:2rem 2.5rem;width:min(100%,62rem);margin-inline:auto;align-items:start">
  <style>
    #og-demo h3 { margin:0 0 .75rem; font-size:.75rem; font-weight:600; letter-spacing:.08em; text-transform:uppercase; color:var(--mv-fg-muted) }
    #og-demo .mv-origami-sheet p { margin:0 0 .6rem }
    #og-demo .mv-origami-sheet ul { margin:.25rem 0 .6rem; padding-left:1.1rem }
    #og-demo .og-letter h4 { margin:0 0 .15rem; font-size:1.375rem; letter-spacing:-.01em }
    #og-demo .og-letter .og-date { margin:0 0 1.1rem; color:var(--mv-fg-muted); font-size:.75rem; letter-spacing:.04em; text-transform:uppercase }
    #og-demo .og-letter p { margin:0 0 .75rem }
    #og-demo .og-letter .og-where { display:grid; grid-template-columns:auto 1fr; gap:.2rem .9rem; margin:1rem 0; padding:.75rem .9rem; border-radius:var(--mv-radius-md); background:color-mix(in oklab, var(--mv-accent) 7%, transparent); font-size:.8125rem }
    #og-demo .og-letter .og-where dt { color:var(--mv-fg-muted) }
    #og-demo .og-letter .og-where dd { margin:0; font-weight:500 }
    #og-demo .og-sign { margin:1rem 0 1.25rem; font:italic 500 1.125rem/1.2 "Segoe Script","Bradley Hand",cursive }
    #og-demo .og-actions { display:flex; gap:.5rem; flex-wrap:wrap }
    #og-demo .og-hint { margin:.9rem 0 0; text-align:center; color:var(--mv-fg-muted); font-size:.75rem }
  </style>

  <section aria-labelledby="og-faq-t">
    <h3 id="og-faq-t">Frequently asked questions</h3>
    <mv-origami id="og-faq" type="single">
      <details>
        <summary>How long does shipping take?</summary>
        <p>Orders placed before 2 p.m. ship the same day from our Brooklyn studio.</p>
        <ul>
          <li>Standard: 3-5 business days, free over $60</li>
          <li>Express: next-day delivery by 1 p.m.</li>
          <li>Pickup point: 48 hours, at 8,000+ locations nationwide</li>
        </ul>
        <p>You’ll get a tracking link by email as soon as your order ships.</p>
      </details>
      <details>
        <summary>Can I return an item?</summary>
        <p>Yes, you have 30 days after delivery to change your mind. Returns are free at any pickup point: print the label from your account, drop off the package, done.</p>
        <p>Refunds are issued to the original payment method within 5 business days of the package reaching the studio.</p>
      </details>
      <details>
        <summary>Where are your lamps made?</summary>
        <p>Every shade is shaped by hand in our Brooklyn studio. The ceramic bases come from a family-run pottery in Vermont, and the fabric cords are woven in North Carolina.</p>
      </details>
      <details>
        <summary>Do you offer a warranty?</summary>
        <p>Every lamp comes with a 5-year warranty on parts and labor. If something breaks, we repair it instead of replacing it. That’s craftsmanship too.</p>
      </details>
    </mv-origami>
  </section>

  <section aria-labelledby="og-letter-t">
    <h3 id="og-letter-t">Announcement</h3>
    <mv-origami variant="letter" id="og-letter" label="News from the studio">
      <div class="mv-origami-address"><small>Nomad Studio · Brooklyn</small>For you, Priya</div>
      <article class="mv-origami-letter og-letter">
        <h4>We’re moving!</h4>
        <p class="og-date">Brooklyn, Sep 23</p>
        <p>Dear Priya,</p>
        <p>After six wonderful years on Bergen Street, the studio is growing. We’ll finally have room to welcome you while we work, and to run lampshade-making classes on Saturdays.</p>
        <dl class="og-where">
          <dt>Address</dt><dd>14 Water Street, Brooklyn</dd>
          <dt>Grand opening</dt><dd>Saturday, Oct 18, from 11 a.m.</dd>
        </dl>
        <p>We’d love to raise a glass with you that day.</p>
        <p class="og-sign">Lena &amp; the whole team</p>
        <div class="og-actions">
          <button class="mv-button" type="button">I’ll be there</button>
          <button class="mv-button" data-variant="ghost" type="button" data-origami-close>Fold the letter</button>
        </div>
      </article>
    </mv-origami>
    <p class="og-hint">Click the envelope · <button class="mv-button" data-variant="link" data-size="sm" type="button" data-origami-open="og-modal">Open in a dialog</button></p>

    <mv-origami variant="letter" id="og-modal" modal label="Grand opening invitation">
      <div class="mv-origami-address"><small>Nomad Studio · Brooklyn</small>For you, Priya</div>
      <article class="mv-origami-letter og-letter">
        <h4>You’re invited</h4>
        <p class="og-date">Saturday, Oct 18 · 11 a.m.</p>
        <p>Come see the new studio at 14 Water Street: live shade-making demos, coffee from the roaster next door, and 15% off the whole collection for the occasion.</p>
        <p class="og-sign">See you soon, Lena</p>
        <div class="og-actions">
          <button class="mv-button" type="button" data-origami-close>Thanks, see you Saturday!</button>
        </div>
      </article>
    </mv-origami>
  </section>

  <script type="module">
    await customElements.whenDefined("mv-origami");
    const faq = document.getElementById("og-faq");
    // Show the fold once, a moment after the page appears.
    setTimeout(() => faq.toggle(0, true), 500);
  </script>
</div>

API

Attributes

NameTypeDefaultDescription
variantfold | letterfoldFolded accordion, or a letter in its envelope.
foldsnumberauto (≈ 1 fold / 52 px, 3 to 10)fold: number of paper strips.
typesingle | multiplemultiplefold: single folds the other panels when one opens (animated, unlike the native name attribute).
openbooleanletter: letter unfolded (on load: opened without animation).
modalbooleanletter: the envelope opens in a modal <dialog> (Escape or a backdrop click folds it back).
labelstringA letter for youletter: name of the envelope (button, back of the letter, dialog).
data-origami-closebooleanOn a button inside the letter: folds it back into the envelope.
data-origami-openidOn a button anywhere: opens the letter <mv-origami id="…">.

Methods

NameDescription
toggle(index | details, force?)fold: opens / folds a panel; letter: toggles the letter.
show() / hide()letter: unfolds / folds.

Events

NameDescription
mv-toggleStart of an opening or closing. detail: { open, item? }.

Content structure

NameDescription
details > summary + contentfold: everything after the <summary> becomes the sheet (.mv-origami-sheet, created if missing).
.mv-origami-letterletter: the letter content (real, accessible content).
.mv-origami-addressletter: handwritten text on the back of the envelope (<small> for the sender).

CSS classes

NameDescription
mv-origami-item / -panel / -sheetfold: <details> element, animated container and paper sheet.
mv-origami-stage / -strip / -face / -shadefold: cloned strips (aria-hidden) while folding.
mv-origami-desk / -envelope / -env-*letter: scene, open button and envelope parts (back, flap, pocket, seal).
mv-origami-folded / -leaf-*letter: letter folded in three during the animation.

CSS variables

NameDefaultDescription
--mv-origami-paperwarm off-white / deep grayPaper color.
--mv-origami-inkvar(--mv-fg)Text color on the paper.
--mv-origami-creaseStroke of the creases that stay visible.
--mv-origami-texturePaper grain (image, none to remove it).
--mv-origami-envelope / --mv-origami-sealEnvelope kraft paper, seal wax.
--mv-origami-letter-width34remLetter width.
--mv-origami-perspective1800px3D depth of the fold.
--mv-origami-scriptHandwriting font for the address.

Accessibility

fold: native <details>/<summary> semantics (Enter, Space, find-in-page opens the right panel); the animated strips are aria-hidden, inert clones with no duplicate ids, and the real content takes over as soon as the paper lies flat. letter: the envelope is a real button (aria-expanded, aria-controls); once unfolded, the letter (a region named by its heading) receives focus; “Fold” returns focus to the envelope; in modal mode, a native <dialog> with focus trap, Escape and focus return. Reduced motion: instant opening, the creases stay drawn on the paper as a static cue. Loops only run during an animation.

Cette page a été traduite par IA. Signaler un problème de traduction