Upgrade to Pro — share decks privately, control downloads, hide ads and more …

新登場!PopoverAPIでSide Modal(anai)を作ろう!

新登場!PopoverAPIでSide Modal(anai)を作ろう!

Saitama.js Vol.6の登壇資料です!

ikuma-t

June 24, 2023
Tweet

More Decks by ikuma-t

Other Decks in Programming

Transcript

  1. Side Modal 著名なデザインシステムでそれっぽ いコンポーネントを持っているのは、 Twillio のPaste とshadcn/ui だけだっ た。 なおshadcn/ui

    のSheet は背面が動か せないので、単純にダイアログが横か ら出るだけ。 Components Side Modal A Side Modal is a page overlay that displays information that does not block the user from interacting with the rest of the page. Version 3.0.1 Github Storybook Peer review pending Open dialog Default Dark Twilio Dark Evergreen Twilio Paste
  2. Side Modal…anai? The Side Modal component is a non-modal dialog

    that sits on top of the right side of the page. It is meant for situations like a preview of a record while looking at a table.
  3. 1. リストを表示する とりあえずリストとして表示します。 1 <ul class="todo-list"> 2 <li class="todo-item"> 3

    <p class="todo-name"> サンプル1</p> 4 <p class="todo-date">2023-06-24 13:00:00</p> 5 </li> 6 <li class="todo-item"> 7 <p class="todo-name"> サンプル2</p> 8 <p class="todo-date">2023-06-24 13:00:00</p> 9 </li> 10 </ul> 1 /* 文字部分のスタイルは省略 */ 2 .todo-item { 3 margin: 0.5rem 0; 4 list-style: none; 5 height: 4rem; 6 border-bottom: 1px solid #d1d5db; 7 padding: 0.5rem; 8 }
  4. 2. ポップオーバーが表示されるようにする 今回はPopover API を使用します。Popover API を使うことで、JavaScript なしでポップオーバーを作成できます。 3 <button

    4 class="todo-content" 5 popovertarget="popover" 6 > 7 <!-- ... --> 8 </button> 1 <ul class="todo-list"> 2 <li class="todo-item"> 9 </li> 10 <!-- ... --> 11 </ul> 12 <div id="popover" popover> 13 <button 14 id="close-button" 15 popovertarget="popover" 16 popovertargetaction="hide"> 17 ✖ 18 ️ </button> 19 <p id="popover-content"> サンプル1</p> 20 </div>
  5. 3. スタイルを SideModal(anai) 風に調整する :popover-open - CSS: カスケーディングスタイルシート | MDN

    擬似クラス :popover-open を使用することで、ポップオーバーの表示中のスタイルを変更できます。 ` ` 1 :popover-open { 2 border: 1px solid #d1d5db; 3 padding-inline: 1rem; 4 width: 40%; 5 height: 100%; 6 /* デフォルトではinset: 0 になっているので、上書き */ 7 inset: unset; 8 top: 0; 9 right: 0; 10 box-shadow: -10px 0px 15px -5px rgba(0, 0, 0, 0.2 11 animation: slideIn 200ms ease-in-out; 12 } 13 14 /* ポップオーバー出現時のアニメーション */ 15 @keyframes slideIn { 16 0% {  translate: 100% 0 0;  } 17 100% {  translate: 0 0 0;  } 18 }
  6. 4. ポップオーバーの幅を変更できるようにする 2 <div class="resizer"></div> 1 <div id="popover" popover> 3

    <button id="close-button" class="close-button" po 4 <p id="popover-content"> サンプル1</p> 5 </div> 10 cursor: col-resize; 1 .resizer { 2 position: absolute; 3 left: 0px; 4 width: 0px; 5 flex-grow: 0; 6 z-index: 109; 7 top: -1px; 8 bottom: -1px; 9 pointer-events: auto; 11 height: 100%; 12 width: 12px; 13 margin-left: -6px; 14 } 1 const resizer = document.querySelector(".resizer"); 2 const popover = document.querySelector("#popover"); 3 let mouseDown = false; 4 let startX, startWidth; 5 6 resizer.addEventListener("mousedown", (e) => { 7 mouseDown = true; 8 startX = e.clientX; 9 startWidth = parseInt(document.defaultView.getCom 10 }); 11 document.addEventListener("mousemove", (e) => { 12 if (!mouseDown) return; 13 const minWidth = 200; 14 const dx = e.clientX - startX; 15 const newWidth = startWidth - dx; 16 const maxWidth = document.documentElement.clientW 17 if (newWidth > minWidth && newWidth < maxWidth) { 18 popover.style.width = startWidth - dx + "px"; 19 popover.style.left = e.clientX + "px"; 20 } 21 }); 22 document.addEventListener("mouseup", () => { mouseD