প্রকাশিত: মার্চ 7, 2025
গতিশীল ওয়েব অ্যাপ্লিকেশন তৈরির জন্য বোতাম অপরিহার্য। বোতামগুলি মেনু খোলে, ক্রিয়াগুলি টগল করে এবং ফর্ম জমা দেয়। তারা ওয়েবে ইন্টারঅ্যাক্টিভিটির ভিত্তি প্রদান করে। বোতামগুলিকে সহজ এবং অ্যাক্সেসযোগ্য করা কিছু আশ্চর্যজনক চ্যালেঞ্জের দিকে নিয়ে যেতে পারে। মাইক্রো-ফ্রন্টেন্ড বা কম্পোনেন্ট সিস্টেম তৈরির ডেভেলপাররা এমন সমাধানের সম্মুখীন হতে পারে যা প্রয়োজনের চেয়ে জটিল হয়ে ওঠে। যদিও ফ্রেমওয়ার্ক সাহায্য করে, ওয়েব এখানে আরও কিছু করতে পারে।
Chrome 135 বৈশিষ্ট্যগুলির জন্য নতুন command
এবং commandfor
সাথে ঘোষণামূলক আচরণ প্রদানের জন্য, popovertargetaction
এবং popovertarget
বৈশিষ্ট্যগুলিকে উন্নত এবং প্রতিস্থাপন করার জন্য নতুন ক্ষমতা প্রবর্তন করে৷ এই নতুন বৈশিষ্ট্যগুলি বোতামগুলিতে যোগ করা যেতে পারে, ব্রাউজারটিকে সরলতা এবং অ্যাক্সেসযোগ্যতার বিষয়ে কিছু মূল সমস্যা সমাধান করতে দেয় এবং অন্তর্নির্মিত সাধারণ কার্যকারিতা প্রদান করে।
ঐতিহ্যগত নিদর্শন
ফ্রেমওয়ার্ক ছাড়া বোতামের আচরণ তৈরি করা প্রোডাকশন কোড বিকশিত হওয়ার সাথে সাথে কিছু আকর্ষণীয় চ্যালেঞ্জ তৈরি করতে পারে। যদিও HTML onclick
হ্যান্ডলারদের বোতামে অফার করে, কনটেন্ট সিকিউরিটি পলিসি (CSP) নিয়মের কারণে এগুলি প্রায়ই ডেমো বা টিউটোরিয়ালের বাইরে অননুমোদিত হয়। যদিও এই ইভেন্টগুলি বোতাম উপাদানগুলিতে প্রেরণ করা হয়, বোতামগুলি সাধারণত একটি পৃষ্ঠায় অন্যান্য উপাদানগুলিকে নিয়ন্ত্রণ করতে একটি পৃষ্ঠায় স্থাপন করা হয় যাতে একই সাথে দুটি উপাদান নিয়ন্ত্রণ করার জন্য কোডের প্রয়োজন হয়৷ আপনাকে নিশ্চিত করতে হবে যে এই মিথস্ক্রিয়াটি সহায়ক প্রযুক্তির ব্যবহারকারীদের কাছে অ্যাক্সেসযোগ্য। এটি প্রায়শই কোডটিকে কিছুটা এইরকম দেখায়:
<div class="menu-wrapper">
<button class="menu-opener" aria-expanded="false">
Open Menu
</button>
<div popover class="menu-content">
<!-- ... -->
</div>
</div>
<script type="module">
document.addEventListener('click', e => {
const button = e.target;
if (button.matches('.menu-opener')) {
const menu = button
.closest('.menu-wrapper')
.querySelector('.menu-content');
if (menu) {
button.setAttribute('aria-expanded', 'true');
menu.showPopover();
menu.addEventListener('toggle', e => {
// reset back to aria-expanded=false on close
if (e.newState == 'closed') {
button.setAttribute('aria-expanded', 'false');
}
}, {once: true})
}
}
});
</script>
এই পদ্ধতিটি একটু ভঙ্গুর হতে পারে, এবং কাঠামোর লক্ষ্য ergonomics উন্নত করা। প্রতিক্রিয়ার মতো ফ্রেমওয়ার্ক সহ একটি সাধারণ প্যাটার্ন একটি রাজ্য পরিবর্তনের জন্য ক্লিক ম্যাপিং জড়িত হতে পারে:
function MyMenu({ children }) {
const [isOpen, setIsOpen] = useState(false);
const open = useCallback(() => setIsOpen(true), []);
const handleToggle = useCallback((e) => {
// popovers have light dismiss which influences our state
setIsOpen(e.newState === 'open')
}, []);
const popoverRef = useRef(null);
useEffect(() => {
if (popoverRef.current) {
if (isOpen) {
popoverRef.current.showPopover();
} else {
popoverRef.current.hidePopover();
}
}
}, [popoverRef, isOpen]);
return (
<>
<button onClick={open} aria-expanded={isOpen}>
Open Menu
</button>
<div popover onToggle={handleToggle} ref={popoverRef}>
{children}
</div>
</>
);
}
অন্যান্য অনেক ফ্রেমওয়ার্কও একই রকম এরগনোমিক্স প্রদানের লক্ষ্য রাখে, উদাহরণস্বরূপ এটি AlpineJS এ লেখা হতে পারে:
<div x-data="{open: false}">
<button @click="open = !open; $refs.popover.showPopover()" :aria-expanded="open">
Open Menu
</button>
<div popover x-ref="popover" @toggle="open = $event.newState === 'open'">
<!-- ... -->
</div>
</div>
Svelte এ লেখার সময় এরকম কিছু দেখতে পারে:
<script>
let popover;
let open = false;
function togglePopover() {
open ? popover.hidePopover() : popover.showPopover();
open = !open;
}
</script>
<button on:click={togglePopover} aria-expanded={open}>
Open Menu
</button>
<div bind:this={popover} popover>
<!-- ... -->
</div>
কিছু ডিজাইন সিস্টেম বা লাইব্রেরি একটি ধাপ এগিয়ে যেতে পারে, বোতাম উপাদানগুলির চারপাশে মোড়ক প্রদান করে যা রাষ্ট্রের পরিবর্তনগুলিকে এনক্যাপসুলেট করে। এটি একটি ট্রিগার উপাদানের পিছনে রাজ্যের পরিবর্তনগুলিকে বিমূর্ত করে, উন্নত ergonomics এর জন্য সামান্য নমনীয়তা ট্রেড করে:
import {MenuTrigger, MenuContent} from 'my-design-system';
function MyMenu({children}) {
return (
<MenuTrigger>
<button>Open Menu</button>
</MenuTrigger>
<MenuContent>{children}</MenuContent>
);
}
প্যাটার্নের জন্য কমান্ড এবং কমান্ড
গুণাবলীর জন্য command
এবং commandfor
সাহায্যে, বোতামগুলি এখন নমনীয়তা বিসর্জন ছাড়াই একটি কাঠামোর ergonomics এনে ঘোষণামূলকভাবে অন্যান্য উপাদানের উপর কাজ করতে পারে। commandfor
বোতামটি একটি আইডি নেয়— for
অ্যাট্রিবিউটের অনুরূপ—যখন command
বিল্ট-ইন মান গ্রহণ করে, আরও পোর্টেবল এবং স্বজ্ঞাত পদ্ধতিকে সক্ষম করে।
উদাহরণ: কমান্ড এবং কমান্ডফর সহ একটি খোলা মেনু বোতাম
নিম্নলিখিত HTML বোতাম এবং মেনুর মধ্যে ঘোষণামূলক সম্পর্ক সেট আপ করে যা ব্রাউজারকে আপনার জন্য যুক্তি এবং অ্যাক্সেসযোগ্যতা পরিচালনা করতে দেয়। aria-expanded
পরিচালনা বা অতিরিক্ত জাভাস্ক্রিপ্ট যোগ করার কোন প্রয়োজন নেই।
<button commandfor="my-menu" command="show-popover">
Open Menu
</button>
<div popover id="my-menu">
<!-- ... -->
</div>
popovertargetaction
এবং popovertarget
সাথে command
এবং commandfor
তুলনা করা
আপনি যদি আগে popover
ব্যবহার করে থাকেন, তাহলে আপনি হয়তো popovertarget
এবং popovertargetaction
বৈশিষ্ট্যের সাথে পরিচিত হতে পারেন। এগুলি যথাক্রমে commandfor
এবং command
অনুরূপভাবে কাজ করে - ব্যতীত এগুলি পপোভারের জন্য নির্দিষ্ট। command
এবং commandfor
অ্যাট্রিবিউট এই পুরানো অ্যাট্রিবিউটগুলিকে সম্পূর্ণভাবে প্রতিস্থাপন করে। নতুন বৈশিষ্ট্যগুলি পুরোনো বৈশিষ্ট্যগুলিকে সমর্থন করে, সেইসাথে নতুন ক্ষমতা যোগ করে।
অন্তর্নির্মিত কমান্ড
command
অ্যাট্রিবিউটে অন্তর্নির্মিত আচরণের একটি সেট রয়েছে যা ইন্টারেক্টিভ উপাদানগুলির জন্য বিভিন্ন API তে ম্যাপ করে:
-
show-popover
:el.showPopover()
এর মানচিত্র। -
hide-popover
:el.hidePopover()
এর মানচিত্র। -
toggle-popover
:el.togglePopover()
এর মানচিত্র। -
show-modal
:dialogEl.showModal()
। -
close
:dialogEl.close()
এর মানচিত্র।
এই কমান্ডগুলি তাদের জাভাস্ক্রিপ্ট সমকক্ষের সাথে মানচিত্র তৈরি করে, পাশাপাশি অ্যাক্সেসযোগ্যতাকে স্ট্রীমলাইন করে (যেমন aria-details
এবং aria-expanded
সমতুল্য সম্পর্ক প্রদান), ফোকাস ব্যবস্থাপনা এবং আরও অনেক কিছু।
উদাহরণ: command
এবং commandfor
সহ একটি নিশ্চিতকরণ ডায়ালগ
<button commandfor="confirm-dialog" command="show-modal">
Delete Record
</button>
<dialog id="confirm-dialog">
<header>
<h1>Delete Record?</h1>
<button commandfor="confirm-dialog" command="close" aria-label="Close" value="close">
<img role="none" src="/close-icon.svg">
</button>
</header>
<p>Are you sure? This action cannot be undone</p>
<footer>
<button commandfor="confirm-dialog" command="close" value="cancel">
Cancel
</button>
<button commandfor="confirm-dialog" command="close" value="delete">
Delete
</button>
</footer>
</dialog>
মুছুন রেকর্ড বোতামে ক্লিক করলে ডায়ালগটি একটি মডেল হিসাবে খুলবে, যখন বন্ধ করুন , বাতিল করুন বা মুছুন বোতামে ক্লিক করলে ডায়ালগটি বন্ধ হয়ে যাবে এবং ডায়ালগে একটি "close"
ইভেন্ট পাঠানো হবে, যার একটি returnValue
বৈশিষ্ট্য রয়েছে যা বোতামের মানের সাথে মেলে। এটি পরবর্তী কি করতে হবে তা নির্ধারণ করতে ডায়ালগে একটি একক ইভেন্ট শ্রোতার বাইরে জাভাস্ক্রিপ্টের প্রয়োজনীয়তা হ্রাস করে:
dialog.addEventListener("close", (event) => {
if (event.target.returnValue == "cancel") {
console.log("cancel was clicked");
} else if (event.target.returnValue == "close") {
console.log("close was clicked");
} else if (event.target.returnValue == "delete") {
console.log("delete was clicked");
}
});
কাস্টম কমান্ড
অন্তর্নির্মিত কমান্ডগুলি ছাড়াও, আপনি --
উপসর্গ ব্যবহার করে কাস্টম কমান্ডগুলি সংজ্ঞায়িত করতে পারেন। কাস্টম কমান্ডগুলি টার্গেট এলিমেন্টে একটি "command"
ইভেন্ট প্রেরণ করবে (বিল্ট-ইন কমান্ডের মতো), কিন্তু অন্যথায় বিল্ট-ইন মানগুলির মতো কোনও অতিরিক্ত যুক্তি সম্পাদন করবে না। এটি এমন উপাদানগুলি তৈরি করার জন্য নমনীয়তা দেয় যা র্যাপার উপাদানগুলি প্রদান না করেই বিভিন্ন উপায়ে বোতামগুলিতে প্রতিক্রিয়া জানাতে পারে, লক্ষ্য উপাদানের জন্য DOM অতিক্রম করতে পারে, বা রাজ্যের পরিবর্তনগুলিতে ম্যাপিং বোতাম ক্লিকগুলি। এটি আপনাকে আপনার উপাদানগুলির জন্য HTML এর মধ্যে একটি API প্রদান করতে দেয়:
<button commandfor="the-image" command="--rotate-landscape">
Landscape
</button>
<button commandfor="the-image" command="--rotate-portrait">
Portrait
</button>
<img id="the-image" src="photo.jpg">
<script type="module">
const image = document.getElementById("the-image");
image.addEventListener("command", (event) => {
if ( event.command == "--rotate-landscape" ) {
image.style.rotate = "-90deg"
} else if ( event.command == "--rotate-portrait" ) {
image.style.rotate = "0deg"
}
});
</script>
ShadowDOM-এ কমান্ড
commandfor
বৈশিষ্ট্যটি একটি আইডি নেয়, ছায়া DOM অতিক্রম করার চারপাশে বিধিনিষেধ রয়েছে। এই ক্ষেত্রে আপনি .commandForElement
প্রপার্টি সেট করতে JavaScript API ব্যবহার করতে পারেন যা শ্যাডো রুট জুড়ে যেকোনো উপাদান সেট করতে পারে:
<my-element>
<template shadowrootmode=open>
<button command="show-popover">Show popover</button>
<slot></slot>
</template>
<div popover><!-- ... --></div>
</my-element>
<script>
customElements.define("my-element", class extends HTMLElement {
connectedCallback() {
const popover = this.querySelector('[popover]');
// The commandForElement can set cross-shadow root elements.
this.shadowRoot.querySelector('button').commandForElement = popover;
}
});
</script>
ভবিষ্যতের প্রস্তাবগুলি ছায়া সীমানা জুড়ে রেফারেন্স শেয়ার করার একটি ঘোষণামূলক উপায় প্রদান করতে পারে, যেমন রেফারেন্স টার্গেট প্রস্তাব ।
এরপর কি?
ওয়েবসাইটগুলি ব্যবহার করে এমন সাধারণ কার্যকারিতা কভার করার জন্য আমরা নতুন বিল্ট-ইন কমান্ডের সম্ভাবনাগুলি অন্বেষণ করতে থাকব। প্রস্তাবিত ধারণাগুলি ওপেন UI প্রস্তাবে কভার করা হয়েছে। কিছু ধারণা ইতিমধ্যেই অন্বেষণ করা হয়েছে:
-
<details>
উপাদান খোলা এবং বন্ধ করা। -
<input>
এবং<select>
উপাদানগুলির জন্য একটি"show-picker"
কমান্ড,showPicker()
এ ম্যাপিং। -
<video>
এবং<audio>
উপাদানগুলির জন্য প্লেব্যাক কমান্ড। - উপাদান থেকে পাঠ্য বিষয়বস্তু অনুলিপি.
আমরা কমিউনিটি ইনপুটকে স্বাগত জানাই—আপনার যদি পরামর্শ থাকে তাহলে ওপেন UI ইস্যু ট্র্যাকারে একটি সমস্যা ফাইল করতে দ্বিধা করবেন না।
আরও জানুন
স্পেসিফিকেশন এবং MDN- এ command
এবং commandfor
সম্পর্কে আরও তথ্য খুঁজুন।