প্রগ্রেস রিং

প্রোগ্রেস রিং (বা বৃত্তাকার প্রোগ্রেস বার) কোনও টাস্কের স্ট্যাটাস সম্পর্কে ভিজ্যুয়াল ফিডব্যাক প্রদান করে। লিনিয়ার প্রগ্রেস বারের মতো নয়, এর বৃত্তাকার আকৃতি ড্যাশবোর্ড, কার্ড কম্পোনেন্ট বা যেকোনও সীমিত জায়গার জন্য আদর্শ।

এই নির্দেশিকা নিম্নলিখিত উপায়ে প্রগ্রেস রিং প্রয়োগ করে:

  • নেটিভ <progress> এলিমেন্টকে সিম্যান্টিক ফাউন্ডেশন হিসেবে ব্যবহার করা যাতে স্ক্রিন রিডার ও কীবোর্ড ব্যবহারকারীরা কম্পোনেন্টটি সহজেই অ্যাক্সেস করতে পারেন।
  • conic-gradient() এবং mask-image-এর সাহায্যে কম্পোনেন্ট স্টাইল করা, SVG পাথ ম্যানিপুলেশনের জটিলতা ছাড়াই সম্পূর্ণ রেসপন্সিভ এবং থিমেবল রিংয়ের অনুমতি দেয়।
  • প্রোগ্রেস ফিলের মসৃণ, GPU-অ্যাক্সিলারেটেড ট্রানজিশন চালু করতে CSS কাস্টম প্রপার্টি ও @property ব্যবহার করা।

এই পদ্ধতিটি শুধুমাত্র SVG-ভিত্তিক সমাধানের চেয়ে বেশি পছন্দ করা হয় কারণ এটি ARIA-এর পরিবর্তে সিম্যান্টিক <progress> এলিমেন্ট ব্যবহার করে এবং বিদ্যমান লেআউট, ডিজাইন সিস্টেম এবং টাইপোগ্রাফির সাথে আরও সহজে ইন্টিগ্রেট করে।

অনির্দিষ্ট লোডিং স্টেট ম্যানেজ করার জন্য লোডিং স্পিনার দেখুন।

প্রয়োগ

১. Markup

ভিজ্যুয়াল রিং এবং ঐচ্ছিক সেন্টার কন্টেন্ট, দুটিই ধরে রাখতে র‍্যাপার ব্যবহার করুন। <progress> এলিমেন্টটি সিম্যান্টিক সোর্স অফ ট্রুথ হিসেবে থেকে যায়। নেটিভ প্রোগ্রেস বার অ্যাক্সেসযোগ্য রেখেও সেটি ভিজ্যুয়ালি লুকানোর জন্য ইউটিলিটি ক্লাস ব্যবহার করুন।

<div class="ring-wrapper">
  <progress value="75" max="100" aria-label="Task progress" class="progress-ring"></progress>
  <!-- Optional: Content to display in the center -->
  <div class="ring-content">
    75%
  </div>
</div>

২. স্টাইল

নেটিভ UI লুকানো হচ্ছে

<progress> এলিমেন্টকে প্রোগ্রেস রিং হিসেবে স্টাইল করতে, প্রথমে প্রোগ্রেস বারের জন্য ডিফল্ট ব্রাউজার স্টাইলিং লুকান।

/* Hide native bars */
progress.loading-spinner:indeterminate::-webkit-progress-bar {
  display: none;
  background: none;
}
progress.loading-spinner:indeterminate::-webkit-progress-value {
  display: none;
  background: none;
}
progress.loading-spinner:indeterminate::-moz-progress-bar {
  display: none;
  background: none;
}
progress.loading-spinner:indeterminate::slider-fill {
  display: none;
  background: none;
}

কন্টেনার ও রিং

র‍্যাপার পজিশনিং কনটেক্সট প্রদান করে। <progress> এলিমেন্ট ভিজ্যুয়াল গ্রেডিয়েন্ট ম্যানেজ করে।

.progress-ring-wrapper {
  position: relative;
  display: grid;
  place-items: center;
}

progress.progress-ring {
  --size: 150px;
  --thickness: 16px;
  --track-color: #f1f5f9;
  --fill-color: #3b82f6;
  --value: attr(value type(<number>));
  width: var(--size);
  height: var(--size);

  transition: --value 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 50%;

  background: conic-gradient(
    var(--fill-color) calc(var(--value) * 1%),
    var(--track-color) 0
  );

  /* MANDATORY: Clip the background to the border-area. */
  background-clip: border-area;
  border: var(--thickness) solid transparent;
  background-origin: border-box;
}

.progress-ring-content {
  /* Positioned in the center of the wrapper */
  position: absolute;
}

এছাড়াও, আপনি radial-gradient ব্যবহার করে গোলাকার এন্ড ক্যাপ তৈরি করতে পারবেন।

@property-এর মাধ্যমে মসৃণ ট্রানজিশন চালু করুন

ভ্যালু পরিবর্তন হলে প্রগ্রেস রিং মসৃণভাবে অ্যানিমেট করতে, --value-কে একটি সংখ্যাসূচক কাস্টম প্রপার্টি হিসেবে রেজিস্টার করুন।

মোশন সেনসিটিভিটি আছে এমন ব্যবহারকারীরা ভ্যালুর মধ্যে ট্রানজিশন বিভ্রান্তিকর বলে মনে করতে পারেন। ডিফল্ট হিসেবে ০ সেকেন্ড (অবিলম্বে) সময়সীমা সেট করে prefers-reduced-motion মিডিয়া কোয়েরি মেনে চলুন এবং কোনও পছন্দ না থাকা ব্যবহারকারীদের জন্য আরও বেশি সময় সেট করুন।

@property --value {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

progress.progress-ring {
  transition: --value 0s ease-in-out;
  @media (prefers-reduced-motion: no-preference) {
    transition-duration: 0.4s;
  }
}

৩. প্রোগ্রেস আপডেট

ভ্যালু পরিবর্তন হলে, <progress> এলিমেন্টে value অ্যাট্রিবিউট এবং .progress-ring-content-এর টেক্সট কন্টেন্ট (যদি শতাংশ দেখানো হয়) আপডেট করুন।

৪. ঐচ্ছিক সাফল্যের স্ট্যাটাস

টাস্ক সম্পূর্ণ হলে রিংয়ের চেহারা অটোমেটিক আপডেট করতে (যেমন, রঙ পরিবর্তন করে সবুজ করা) আপনি CSS অ্যাট্রিবিউট সিলেক্টর ব্যবহার করতে পারেন।

/* Change the fill color to green when the progress reaches 100% */
progress.progress-ring[value="100"] {
  --fill-color: #10b981;
}

ফলব্যাক স্ট্র্যাটেজি

<progress> এলিমেন্টের মধ্যে কোনও ফলব্যাক ভ্যালু যোগ করবেন না। এটি সহায়ক প্রযুক্তি দ্বারা ব্যবহৃত হয় না এবং সমস্ত আধুনিক ব্রাউজার দ্বারা উপেক্ষা করা হয়।

অ্যানিমেশন ফলব্যাক

@property কাজ না করলে, রিংটি মসৃণভাবে ট্রানজিশন করার পরিবর্তে সাথে সাথে নতুন ভ্যালুতে জাম্প করবে। বেশিরভাগ ক্ষেত্রে এটি ঠিক আছে এবং কোনও কার্যকারিতা নষ্ট করে না।

ট্রানজিশন যদি একেবারেই প্রয়োজনীয় হয়, তাহলে আপনি @property-এর জন্য চেক করতে পারেন এবং পুরনো ব্রাউজারে --value ইন্টারপোলেট করতে requestAnimationFrame() লুপ ব্যবহার করতে পারেন।

যেসব ব্রাউজারে এখনও background-clip: border-area কাজ করে না, সেগুলিতে <progress> এলিমেন্টের কেন্দ্র ফাঁকা করতে mask-image ব্যবহার করুন।

@supports not (background-clip: border-area) {
  mask-image: radial-gradient(
    transparent calc(50% - var(--thickness)),
    black calc(50% - var(--thickness) + 0.5px)
  );
  border: 0;
}

যেসব ব্রাউজার কোনও প্রপার্টির জন্য attr() CSS ফাংশন সাপোর্ট করে না, সেগুলির ক্ষেত্রে --value কাস্টম প্রপার্টিতে value অ্যাট্রিবিউট অটোমেটিক সিঙ্ক করতে MutationObserver ব্যবহার করুন।

if (!CSS.supports("width: attr(value type(<number>))")) {
  const observer = new MutationObserver(() => {
    progress.style.setProperty("--value", progress.getAttribute("value"));
  });
  observer.observe(progress, {
    attributes: true,
    attributeFilter: ["value"],
  });
}