Skip to content
animorio
IT
All components

The drafted share dialog

Dialogs, Transitions, SVG, PhysicsGSAP, CSS onlyAdvancedCompressed weight: Demo 16 KBGSAP 28 KBFreeDownload the zip

The share dialog for an architecture studio’s drawings, drawn the way a sheet is drawn: four blue construction lines come in from the edges of the screen like the rules of a drafting machine, swing on springs and stop where the sides will be, the pen inks the outline and the paper fills in with a hatch that thickens until its lines meet. Inviting someone runs the bottom rule out again and down to the new size while the person is drafted into the list, in a square with their own hatched material; copying the link draws its dimension line underneath, marked Copied.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The drafted share dialog</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/jost@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the drafted share dialog: Share draws the dialog the way an architect draws a sheet. Blue construction lines
         slide in like the rules of a drafting machine and spring into place, the outline is inked along them, the
         paper fills in with a hatch, and the words come last. A new collaborator is drafted into the list the same
         way, and a copied link gets its dimension line. -->
    <span class="slot" data-slot data-autoclic>
      <button class="opener" type="button" aria-haspopup="dialog" data-open>
        <svg class="opener__icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="9.5" cy="8" r="3.6"/><path d="M3.2 19.5c.7-3.4 3.2-5.4 6.3-5.4 1.7 0 3.2.6 4.3 1.6M18.2 13.2v6.6M14.9 16.5h6.6"/></svg>
        <span>Share</span>
      </button>
      <span class="slot__ticks" aria-hidden="true"></span>
    </span>
  </main>

  <dialog class="share" aria-modal="true" aria-labelledby="share-title" aria-describedby="share-sub" data-dialog>
    <div class="share__veil" data-veil></div>
    <div class="frame" data-frame>
      <div class="frame__shade" data-shade></div>
      <div class="frame__paper" data-paper></div>
      <div class="frame__body" tabindex="-1" data-body>
        <header class="head" data-part>
          <div class="head__text">
            <h2 class="head__title" id="share-title">Share “Casa Albera”</h2>
            <p class="head__sub" id="share-sub">Schematic design, 14 drawings</p>
          </div>
          <button class="close" type="button" aria-label="Close" data-close>
            <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6.5 6.5l11 11M17.5 6.5l-11 11"/></svg>
          </button>
        </header>

        <form class="invite" novalidate data-invite data-part>
          <label class="label" for="invite-email">Invite people</label>
          <div class="invite__row">
            <input class="field invite__email" id="invite-email" type="email" inputmode="email" autocomplete="off" spellcheck="false" placeholder="Email address" aria-describedby="invite-note" data-email>
            <span class="select invite__role">
              <label class="sr" for="invite-role">Permission</label>
              <select class="field" id="invite-role" data-role>
                <option value="view">Can view</option>
                <option value="edit">Can edit</option>
              </select>
              <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 10l5 5 5-5"/></svg>
            </span>
            <button class="btn btn--ink invite__send" type="submit" disabled data-send>Invite</button>
          </div>
          <p class="note" id="invite-note" data-note>They get an email with a link to the drawings.</p>
        </form>

        <section class="people" aria-labelledby="people-title">
          <h3 class="label" id="people-title" data-part>People with access</h3>
          <ul class="people__list" data-list>
            <li class="person" data-part data-email="marta@orsa.studio">
              <span class="avatar mat-brick" aria-hidden="true"><span class="avatar__fill"></span><span class="avatar__ini">MF</span></span>
              <span class="person__text"><span class="person__name">Marta Ferrante (you)</span><span class="person__mail">marta@orsa.studio</span></span>
              <span class="person__owner">Owner</span>
            </li>
            <li class="person" data-part data-email="jonas@orsa.studio">
              <span class="avatar mat-steel" aria-hidden="true"><span class="avatar__fill"></span><span class="avatar__ini">JL</span></span>
              <span class="person__text"><span class="person__name">Jonas Lindqvist</span><span class="person__mail">jonas@orsa.studio</span></span>
              <span class="select select--quiet">
                <label class="sr" for="role-jonas">Permission for Jonas Lindqvist</label>
                <select class="field" id="role-jonas" data-person-role>
                  <option value="view">Can view</option>
                  <option value="edit" selected>Can edit</option>
                  <option value="remove">Remove access</option>
                </select>
                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 10l5 5 5-5"/></svg>
              </span>
            </li>
            <li class="person" data-part data-email="priya@greywater.eng">
              <span class="avatar mat-timber" aria-hidden="true"><span class="avatar__fill"></span><span class="avatar__ini">PR</span></span>
              <span class="person__text"><span class="person__name">Priya Raman</span><span class="person__mail">priya@greywater.eng</span></span>
              <span class="select select--quiet">
                <label class="sr" for="role-priya">Permission for Priya Raman</label>
                <select class="field" id="role-priya" data-person-role>
                  <option value="view" selected>Can view</option>
                  <option value="edit">Can edit</option>
                  <option value="remove">Remove access</option>
                </select>
                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 10l5 5 5-5"/></svg>
              </span>
            </li>
          </ul>
        </section>

        <section class="link" data-part data-link-part>
          <label class="label" for="share-link">Link to the drawings</label>
          <div class="link__row">
            <input class="field link__url" id="share-link" type="text" readonly value="orsa.studio/p/casa-albera" data-link>
            <button class="btn btn--line link__copy" type="button" data-copy>
              <span class="link__icons" aria-hidden="true">
                <svg class="link__chain" viewBox="0 0 24 24" data-chain><path d="M10 14a4.2 4.2 0 0 0 6 0l3-3a4.2 4.2 0 0 0-6-6l-1.1 1.1M14 10a4.2 4.2 0 0 0-6 0l-3 3a4.2 4.2 0 0 0 6 6l1.1-1.1"/></svg>
                <svg class="link__tick" viewBox="0 0 24 24" data-tick><path d="M5 12.6l4.4 4.4L19 7.4"/></svg>
              </span>
              <span data-copy-label>Copy link</span>
            </button>
          </div>
          <div class="link__foot">
            <p class="note" data-hint>Anyone with this link can view.</p>
            <svg class="dim" aria-hidden="true" data-dim></svg>
          </div>
        </section>

        <p class="sr" aria-live="polite" data-live></p>
      </div>
    </div>
    <svg class="draft" aria-hidden="true" data-draft></svg>
  </dialog>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

57 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The drafted share dialog” from Animorio and fit it into my site

What it does

On a white background a graphite button 56 pixels tall with the icon of a person and a plus and the word Share; with the mouse over it, two blue lines come out of each of its four corners, like the crop marks of a sheet: the same lines the dialog will have. Pressed, the page is veiled in grey and four blue lines as long as the screen come in from its four edges, two horizontal and two vertical, like the rules of a drafting machine: they run towards the middle, go a little past where the sides will be, come back and stop, the vertical ones a moment after the others. Along them the pen inks the outline in graphite, each side from its corner like a pinwheel, while the lines draw back until only the crossings at the corners are left; the paper fills in with a white hatch at 45 degrees whose lines thicken until they touch, and only then do the words come in. The Share button under the dialog goes before the paper arrives. In the dialog: Share “Casa Albera”, the schematic design with 14 drawings; the field to invite a person by email with the choice of Can view or Can edit and the Invite button, off while the field is empty; the three people who already have access, each in a square of paper with their own hatched material (masonry, steel, timber) and the initials on a white tag, the owner with Owner and the others with their permission; the link to the drawings with the Copy link button. Inviting a correct address runs the dialog’s bottom rule out across the screen again and brings it down to the new size with a small bounce, the link slides down with it and in the empty place the new person is drafted: their rules come in, the square is inked, the material (glass) is hatched in diagonally and the initials appear, then the address and Invite sent. A wrong address turns the field red, it shakes, and the note underneath says how to write it; one already there lights up that person’s row. Copy link copies the link, the button says Copied with a tick that draws itself, and under the link its technical-drawing dimension appears: first the word Copied, then the line running from it to both ends of the link, the extension lines dropping and the 45-degree ticks closing it; after 2.4 seconds it goes and the note comes back. Every permission can be changed, and Remove access rubs the person out: the initials and the material draw back, the square comes apart and the dialog gets shorter. Close, Escape or a tap outside rub it out in reverse: the words go, the hatch opens up, the outline draws back to the corners and the rules leave the screen, while the Share button comes back with a small bounce.

How it works

Rules on springs

The four construction lines are lines in an SVG as big as the dialog element, and each has its own distance from the side it belongs to: a damped spring, x'' = −ω²x − 2ζω·x', in steps of 1/240 of a second on GSAP’s ticker, with the step limited to 1/30. They start just off the screen on their own side, with ω = 12/DRAFT and ζ = 1 − 0.7·BOUNCE, so they go past and come back; the vertical ones leave 0.06 seconds later. While they run they are as long as the screen; then a second value, from 0 to 1, shortens them to OVERSHOOT pixels past the corners.

The pinwheel outline

The four graphite sides are four more lines, each growing from its own corner, clockwise, all together with the same progress: top from the left, right from the top, bottom from the right, left from the bottom. Each side is half its width longer at both ends, so the corners close without dots. Everything is redrawn at every frame from the dialog’s real measures, and when nothing moves nothing is redrawn.

The hatched paper

The paper is a repeating-linear-gradient at 135 degrees with a 10 pixel period, white from 0 to calc(var(--fill) · 10px) and transparent after: GSAP takes --fill from 0 to 1, the white lines thicken until they touch and the paper is solid. Once done, a class swaps it for plain white, because a repeating gradient can leave a hairline seam. The words come in afterwards, one after the other, once the paper is closed.

The bottom rule and the new person

The dialog’s top is fixed when it opens, so an extra row makes it grow downwards only. Inviting, the height goes from the old one to the new with back.out(1.7) and the link section slides from the same distance with the same curve, so it stays with the bottom edge; the bottom rule runs out as long as the screen for a little over half a second. Meanwhile the new person’s square is drafted in its own SVG with the same function as the dialog, small: rules coming in from 12 pixels, sides inked, the material uncovered by a triangle clip-path widening diagonally, the initials last.

The link’s dimension

Copying, the link’s width is measured on a canvas with the field’s font, from the first letter to the last, in whole pixels. Underneath, an SVG draws the dimension: the word Copied in the middle, the two strokes of the line running from it to the ends by animating x2, the extension lines dropping by animating y2 and the 45-degree ticks growing from their middle with back.out. The link is copied with navigator.clipboard and, where it is missing, by selecting the field and with execCommand.

A real dialog

It is a native dialog opened with showModal (the page behind is out of reach) with aria-modal, aria-labelledby and aria-describedby; the focus goes to the email field for who uses the keys and to the sheet for a finger or the mouse, Tab goes round the dialog’s controls without leaving, Escape stops the cancel event and closes it with its drawing, and at the end the focus goes back to Share. Every field has its label, the confirmations go through an aria-live region, the error through aria-invalid and aria-describedby too. A click from a script on the button’s frame (the library’s preview) makes a plain round, open and close, and a full one, open, type an address and invite it, copy and close; closing puts everything back as it was, and it goes by the state, not by a fixed list.

Values to change

NameFileDefaultWhat it changes
DRAFTscript.js0.8The seconds the dialog takes to be drafted: rules, outline, paper and words.
BOUNCEscript.js0.6How far the rules swing past their place before they settle, from 0 to 1.
OVERSHOOTscript.js28How far the blue construction lines run past the corners, in pixels.
PUT_AWAYscript.js0.42The seconds the dialog takes to be rubbed out.
DIMscript.js0.24How dark the page goes behind the dialog, from 0 to 1.
HOLDscript.js2.4The seconds Copied stays under the link.

Try them in the Playground

When to use it

For sharing a project, a folder, a sheet or a document with other people in a work tool: an architecture or design studio, a drawing program, a file archive. The drafting suits products that talk about measures and plans; without the gesture, what is left is a complete, accessible share dialog.

On phones

At 390 pixels the dialog is 358 wide, 16 pixels from the sides, and the crossings shorten so they do not touch the edge of the screen. The address has a line of its own, the permission and Invite go under it; the permission column narrows to leave room for the names, and Copy link keeps only its icon (the words stay for screen readers) so the whole link can be read. The fields are 16 pixels, so Safari does not zoom the page, and the close button is 44 tall. With many people the dialog reaches the height of the screen and scrolls inside.

With reduced motion

No running rules, no outline being drawn, no hatch: the Share button fades and the dialog appears already drawn with a fade, and leaves the same way. The invited person appears with a fade and the dialog takes its new size at once; the link’s dimension appears already drawn; a wrong field turns red without shaking and the buttons do not squash.

Pitfalls

  • The Share button sits right under the dialog: while the paper filled in with its hatch it showed through the white lines, a striped black rectangle under the words. If the dialog covers it, the button fades before the paper comes and returns only once the paper has gone.
  • The new person’s square was drawn at once, while the link section was still sliding over it: for a frame its rules cut across the words Link to the drawings. Now its lines stay transparent until their turn, and the row stays empty until the link has gone past.
  • Closing, the hatch opened while the words were still fading, and the letters showed over the stripes. Now the words have all gone before the paper starts to open.
  • Fading with opacity the SVG as big as the screen, or the whole dialog with its blurred shadow, showed the layer’s box in Chromium as a darker rectangle round the dialog. Now the single lines and the single layers (shadow, paper, content) fade, never the group.
  • The dialog’s close event comes a moment after the closing: if the dialog had been opened again meanwhile (the preview can click quickly), the script put it back to rest while it was open and the preview lost its step. Now the event is ignored if the dialog is open again.
  • On a phone the link and the owner’s name were cut off with an ellipsis. The permission column narrows to 108 pixels and Copy link keeps only its icon, with the words hidden for screen readers.
  • Inviting someone while the dialog was still being drawn, the script stopped every animation of the rows to slide them, their entrance fades included: the people already there and the link stayed invisible. Now only the height and the slide stop, and the fades finish.
  • The scheda’s video lasts 6.4 seconds from the poster, with the dialog open: with one round only (open, invite, copy, close) it showed the invite and the copy but never the dialog being drawn. The preview’s rounds now alternate, a plain one (open and close) and a full one, so in the video the dialog is rubbed out and drawn again.
  • The bottom of the dialog has to move together with what is under the new row: the height and the link’s slide use the same duration and the same back.out curve, and the bottom is read again at every frame while it grows, so the blue rules and the outline follow it without coming apart.

Libraries

GSAP 3.15.0, Jost (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 16 KB; the libraries: GSAP 28 KB.

Testing

Tested on 7 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All components