প্রকাশ করার জন্য সোয়াইপ করুন

সোয়াইপ-টু-রিভিল প্যাটার্ন ব্যবহারকারীদের একটি ফোরগ্রাউন্ড সারি বা কন্টেন্ট প্যান অনুভূমিকভাবে স্লাইড করতে দেয় যাতে লুকানো UI প্রকাশ করা যায়—যেমন প্রাসঙ্গিক অ্যাকশন বোতাম (পিন করুন, মিউট করুন, আর্কাইভ করুন, মুছুন) বা একটি সেকেন্ডারি সাইড মেনু—অটোমেটিক কোনও অ্যাকশন অ্যাক্টিভেট না করেই। সোয়াইপ করার সময় কোনও অ্যাকশন করার পরিবর্তে, কন্টেনারটি স্ন্যাপ করে খুলে যায় এবং ইন্টার‍্যাক্টিভ কন্ট্রোল দেখায় যা ব্যবহারকারী পরীক্ষা করে দেখতে এবং চালু করতে পারেন অথবা বন্ধ করার জন্য আবার সোয়াইপ করতে পারেন।

সম্পূর্ণ-প্রস্থ সোয়াইপ জেসচারের জন্য যা অবিলম্বে থ্রেশহোল্ডের পরে কোনও আইটেমকে কমিট এবং খারিজ করে, সরানোর জন্য সোয়াইপ করুন দেখুন। উল্লম্ব স্ক্রল কন্টেনারের উপরে লুকানো হেডার দেখানোর জন্য, দেখানোর জন্য টানুন দেখুন।

কীভাবে প্রয়োগ করতে হয়

আপনি কোনও তালিকা আইটেমে অ্যাকশন বোতাম বা স্ক্রল করা যায় এমন পেনের পাশে সাইড মেনু দেখাচ্ছেন কিনা, মেকানিক্স একই: CSS স্ক্রল স্ন্যাপ (scroll-snap-type: x mandatory) এবং overscroll-behavior: chain-এর মাধ্যমে কনফিগার করা বাইরের অনুভূমিক স্ক্রল কন্টেনারের মধ্যে ফোরগ্রাউন্ড কন্টেন্ট এবং লুকানো প্যানেল র‍্যাপ করুন। ব্রাউজারের নেটিভ স্ক্রলিং ইঞ্জিন জাভাস্ক্রিপ্ট জেসচার লিসেনার ছাড়াই মোমেন্টাম, স্ন্যাপিং, কীবোর্ড ফোকাস স্ক্রলিং এবং স্ক্রল চেইনিং ম্যানেজ করে।

ধাপ ১: সোয়াইপ র‍্যাপার, কন্টেন্ট ও প্রকাশিত প্যানেল মার্ক-আপ করুন

.SwipeReveal স্ক্রল কন্টেনারের মধ্যে প্রথমে ফোরগ্রাউন্ড কন্টেন্ট এবং তারপরে প্রকাশ করা কন্ট্রোল (অ্যাকশন বোতাম বা সাইড মেনু) রাখুন। কন্টেন্টটি DOM অর্ডারে প্রথমে থাকার কারণে, স্ক্রল কন্টেনার স্বাভাবিকভাবেই স্ক্রল অফসেট 0-এ শুরু হয় এবং প্যানেলটি স্ক্রিনের ডানদিকে লুকানো থাকে।

<!-- Example A: List item with revealable action buttons -->
<div class="SwipeReveal">
  <div class="SwipeReveal-content">
    <strong>Design review notes</strong>
    <p>Updated component specs for the Q3 release.</p>
  </div>
  <div class="SwipeReveal-panel" role="group" aria-label="Item actions">
    <button type="button">Pin</button>
    <button type="button">Archive</button>
    <button type="button">Delete</button>
  </div>
</div>

<!-- Example B: Scrollable content pane with a revealable side menu -->
<div class="SwipeReveal" role="region" aria-label="Document preview with swipeable side menu">
  <div class="SwipeReveal-content is-scrollable" tabindex="0">
    <h2>Article Preview</h2>
    <p>Scroll vertically through this pane, or swipe left to reveal the side menu...</p>
  </div>
  <nav class="SwipeReveal-panel" aria-label="Contextual menu">
    <a href="#share">Share</a>
    <a href="#bookmark">Bookmark</a>
    <a href="#export">Export PDF</a>
  </nav>
</div>

ধাপ ২: অনুভূমিক স্ন্যাপ কন্টেনার ও overscroll-behavior: chain কনফিগার করুন

আপনি যখন কোনও এলিমেন্টকে শুধুমাত্র সোয়াইপ-টু-রিভিল এফেক্ট তৈরি করার জন্য একটি বাইরের স্ক্রল কন্টেনারে র‍্যাপ করেন, তখন সেই বাইরের র‍্যাপারটি ডকুমেন্টের (বা অন্য প্যারেন্ট স্ক্রল কন্টেনারের) ভিতরে একটি ইন্টারমিডিয়েট স্ক্রলার হয়ে যায়।

overscroll-behavior-এর চারটি কীওয়ার্ড স্বাধীনভাবে নিয়ন্ত্রণ করে যে অতিরিক্ত স্ক্রল পূর্বপুরুষ স্ক্রল কন্টেনারে (স্ক্রল চেইনিং) প্রচার করে কিনা এবং কন্টেনারটি স্থানীয় ওভারস্ক্রল অ্যাফর্ডেন্স যেমন ইলাস্টিক রাবার-ব্যান্ড স্ট্রেচিং বা এজ গ্লো (স্থানীয় বাউন্ডারি এফেক্ট) দেখায় কিনা:

মান স্ক্রল চেইনিং (অ্যানসেস্টরে প্রোপাগেট করে) লোকাল বাউন্ডারি এফেক্ট (রাবার-ব্যান্ড / গ্লো) 'সোয়াইপ-টু-রিভিল' ফিচারে ভূমিকা
auto হ্যাঁ হ্যাঁ ডিফল্ট অ্যাকশন; ইনার কন্টেন্ট স্ক্রলারে এটি চালু রাখুন যেখানে স্বাভাবিক বাউন্স ফিডব্যাক প্রয়োজন, তবে আউটার সোয়াইপ র‍্যাপারে এটি এড়িয়ে চলুন যেখানে এটি মেনুকে বাউন্স করায়
chain হ্যাঁ না বাইরের .SwipeReveal স্ক্রলারে ব্যবহার করুন যাতে অতিরিক্ত স্ক্রল চেইন প্যারেন্ট স্ক্রলারে (যেমন ডকুমেন্ট) মেনু বা অ্যাকশন স্ট্রিপ বাউন্স না করেই চলে যায়
contain না হ্যাঁ কন্টেনারের মধ্যে স্ক্রল ট্র্যাপ করে, তবে লোকালি বাউন্স করে
none না না লোকাল বাউন্স এবং স্ক্রল চেইনিং টু অ্যানসেস্টর, দুটিই ব্লক করে

.SwipeReveal-কে দুটি কলামের গ্রিড (grid-template-columns: 100% max-content) হিসেবে তৈরি করুন যেখানে .SwipeReveal-content, start-এ স্ন্যাপ করে এবং .SwipeReveal-panel, end-এ স্ন্যাপ করে:

.SwipeReveal {
  /* Column 1: full-width content. Column 2: auto-sized actions or side menu. */
  display: grid;
  grid-template-columns: 100% max-content;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;

  /* Prevent the swipe wrapper and revealed panel from bouncing locally while
     still chaining excess scroll into the parent scroller (the document). */
  overscroll-behavior: chain;
}

@media (prefers-reduced-motion: no-preference) {
  .SwipeReveal {
    scroll-behavior: smooth;
  }
}

.SwipeReveal-content {
  scroll-snap-align: start;
  scroll-initial-target: nearest;
  background: Canvas;
}

.SwipeReveal-content:focus-visible {
  outline: auto;
  outline-offset: -2px;
}

.SwipeReveal-content.is-scrollable {
  block-size: 20rem;
  overflow: auto;
  /* Keeps default `overscroll-behavior: auto` so the content pane retains
     its normal bounce effect while chaining horizontal swipes to `.SwipeReveal`. */
}

.SwipeReveal-panel {
  /* Snapping a trailing panel to `end` (or a leading panel to `start`) brings
     all controls fully into view while keeping the adjacent edge of the content visible. */
  scroll-snap-align: end;
  display: flex;

  &:first-child {
    scroll-snap-align: start;
  }
}

আপনি যদি তিনটি কলাম (grid-template-columns: max-content 100% max-content) বা দুটি কলাম (max-content 100%) ব্যবহার করে বাঁদিকে (inline-start) কন্ট্রোল দেখাতে চান, তাহলে .SwipeReveal-content-এর আগে লিডিং .SwipeReveal-panel রাখুন। .SwipeReveal-content-এ scroll-initial-target: nearest থাকার কারণে, স্ক্রল কন্টেনার প্রথমে লিডিং প্যানেলের পরিবর্তে কন্টেন্ট কলামে থাকে।

ধাপ ৩: কীবোর্ড ফোকাসে ফোকাস করা যায় এমন কন্টেন্ট প্যানে আবার স্ন্যাপ করা

.SwipeReveal-panel-এর মধ্যে থাকা বোতাম বা লিঙ্কগুলি স্ক্রিনে দেখা যায় না, তাই কীবোর্ড ব্যবহার করে সেগুলিতে ট্যাব করলে, ফোকাস করা কন্ট্রোল দেখানোর জন্য .SwipeReveal অটোমেটিক স্ক্রল করে। তবে, .SwipeReveal-content যেহেতু বাইরের কন্টেনারের প্রস্থের 100% জুড়ে থাকে, তাই সাইড প্যানেল খোলা থাকলেও এর বেশিরভাগ অংশ স্ক্রলপোর্টের ভিতরেই থাকে—তাই Shift+Tab প্রেস করে ফোকাস আবার .SwipeReveal-content-এ (বা এর ভিতরে ফোকাস করা যায় এমন কোনও এলিমেন্টে) ফিরিয়ে আনলে, ট্র্যাকটি অটোমেটিক 0-এ স্ক্রল করবে না।

.SwipeReveal-content-এ focusin-এর জন্য শুনুন এবং event.target.matches(':focus-visible') চেক করুন যাতে প্যানে কীবোর্ড ফোকাস বা যেকোনও ডিসেন্ডেন্ট স্ন্যাপ .SwipeReveal-content পয়েন্টার ক্লিক বা টাচ ড্র্যাগকে বাধা না দিয়ে শুরুতে ফিরে যায়:

for (const content of document.querySelectorAll('.SwipeReveal-content')) {
  content.addEventListener('focusin', (event) => {
    if (event.target.matches(':focus-visible')) {
      content.scrollIntoView({
        block: 'nearest',
        inline: 'start',
      });
    }
  });
}

পেশাদার পদ্ধতি ও সমস্যা

  • proximity-এর পরিবর্তে scroll-snap-type: x mandatory ব্যবহার করুন। proximity-এর মাধ্যমে, হালকা সোয়াইপ করলে অ্যাকশন বোতাম বা সাইড মেনু আংশিকভাবে দেখা যেতে পারে।
  • অবশ্যই বাইরের অনুভূমিক সোয়াইপ-টু-রিভিল স্ক্রলারে (.SwipeReveal) overscroll-behavior: chain সেট করুন যাতে স্ক্রলটি প্যারেন্ট স্ক্রলারে চেইন করা যায় এবং রিভিল করা মেনু বা অ্যাকশন স্ট্রিপ বাউন্স না করে।
  • ইনার স্ক্রলযোগ্য কন্টেন্ট প্যানে (.SwipeReveal-content.is-scrollable) overscroll-behavior: auto (ডিফল্ট) ছেড়ে দিন যেখানে আপনি চান যে স্বাভাবিক বাউন্স ফিডব্যাক হোক এবং একই সাথে বাইরের সোয়াইপ স্ক্রলারে অনুভূমিক সোয়াইপ চেইন করা হোক।
  • আসল ফোকাস করা যায় এমন DOM কন্ট্রোল (<button>, <a>) হিসেবে প্রকাশ করা অ্যাকশন ও সাইড-মেনু আইটেম প্রয়োগ করুন। .SwipeReveal-content ফোকাস করা যায় এমন হলে বা এতে ফোকাস করা যায় এমন কন্ট্রোল থাকলে, event.target.matches(':focus-visible')-এর সাথে focusin লিসনার পেয়ার করুন যাতে scrollIntoView({ block: 'nearest', inline: 'start' }) কল করা যায়, যাতে কন্টেন্ট প্যানে আবার ট্যাব করলে পয়েন্টার ইন্টার‍্যাকশন প্রভাবিত না করেই সাইড প্যানেল বন্ধ হয়ে যায়।
  • কখনও wheel, touchmove বা pointermove ইভেন্ট জাভাস্ক্রিপ্টে ইন্টারসেপ্ট করবেন না যাতে কন্টেন্ট ম্যানুয়ালি অনুবাদ করা যায় বা স্ক্রল চেইনিং এমুলেট করা যায়। মূল থ্রেড জেসচার ইন্টারসেপশন কম্পোজিটর-চালিত স্ক্রলিং ব্লক করে, নেটিভ স্ক্রল মোমেন্টাম ভেঙে দেয় এবং প্রতিক্রিয়াশীলতা হ্রাস করে।

ফলব্যাক

.SwipeReveal কন্টেনার .SwipeReveal-content-এর আগে বাঁদিকে (inline-start) .SwipeReveal-panel রাখলে, যেসব ব্রাউজারে scroll-initial-target: nearest কাজ করে না, সেগুলি প্রথমে লিডিং প্যানেল সহ স্ক্রল অফসেট 0-এ রেন্ডার করবে।

আপনার বেসলাইন টার্গেট scroll-initial-target সাপোর্ট না করলে, CSS.supports('scroll-initial-target', 'nearest')-এর মাধ্যমে সাপোর্ট শনাক্ত করুন এবং load-এ behavior: 'instant'-এর সাথে scrollTo() কল করুন যাতে লিডিং প্যানেল সহ কন্টেনার পৃষ্ঠা স্ক্রল না করেই সরাসরি .SwipeReveal-content-এ চলে যায়:

প্রোগ্রেসিভ এনহ্যান্সমেন্ট

জাভাস্ক্রিপ্ট ফলব্যাক ছাড়াই overscroll-behavior: chain এবং scrollbar-width: none-কে প্রোগ্রেসিভ এনহ্যান্সমেন্ট হিসেবে বিবেচনা করুন:

  • অটোমেটিক CSS ক্যাসকেড ফলব্যাক: overscroll-behavior-এর প্রাথমিক ভ্যালু হল auto। যেসব ব্রাউজার এখনও chain কীওয়ার্ড শনাক্ত করতে পারে না, সেগুলি পার্স করার সময় overscroll-behavior: chain উপেক্ষা করে এবং auto রেখে দেয়। যেহেতু auto আগে থেকেই পূর্বপুরুষ স্ক্রল কন্টেনারে স্ক্রল চেইনিংয়ের অনুমতি দেয়, তাই সোয়াইপ-টু-রিভিল জেসচার এবং পেরেন্ট ওয়ার্কের স্ক্রল চেইনিং, সব ব্রাউজারেই কাজ করে; যেসব ব্রাউজার এটি সাপোর্ট করে সেগুলি শুধু বাইরের সোয়াইপ র‍্যাপারে অবাঞ্ছিত রাবার-ব্যান্ড বাউন্সকে দমন করে।
  • contain বা none ওভাররাইড করা: কোনও বেস স্টাইলশিট বা ইউটিলিটি ক্লাস overscroll-behavior: contain বা none সেট করলে, overscroll-behavior: chain-এর ঠিক আগে overscroll-behavior: auto ঘোষণা করুন যাতে যেসব ব্রাউজার এখনও chain সাপোর্ট করে না সেগুলি ট্র্যাপ করার পরিবর্তে পেরেন্ট এলিমেন্টে চেইন স্ক্রল করতে পারে।
  • স্ক্রলবার লুকানো (scrollbar-width: none): অনুভূমিক স্ক্রলবার ট্র্যাক লুকানো শুধুমাত্র বাহ্যিক সৌন্দর্য বাড়ানোর জন্য; কোনও পুরনো ইঞ্জিন scrollbar-width: none উপেক্ষা করলে, সোয়াইপ-টু-রিভিল কন্টেনার স্ট্যান্ডার্ড স্ক্রলবারের সাথে সম্পূর্ণ কার্যকরী থাকে।