स्प्लिट बटन वाला कॉम्पोनेंट बनाना

स्प्लिट-बटन कॉम्पोनेंट को ऐक्सेस करने में आसान बनाने के तरीके के बारे में बुनियादी जानकारी.

इस पोस्ट में, मुझे स्प्लिट बटन बनाने के तरीके के बारे में अपनी राय शेयर करनी है . डेमो आज़माएं.

डेमो

अगर आपको वीडियो देखना ज़्यादा पसंद है, तो इस पोस्ट का YouTube वर्शन यहां दिया गया है:

खास जानकारी

स्प्लिट बटन ऐसे बटन होते हैं जिनमें एक मुख्य बटन और अतिरिक्त बटनों की सूची छिपी होती है. ये बटन, सामान्य कार्रवाई को दिखाने के लिए काम के होते हैं. साथ ही, ज़रूरत पड़ने पर ही दूसरी और कम इस्तेमाल की जाने वाली कार्रवाइयों को नेस्ट किया जाता है. स्प्लिट बटन, व्यस्त डिज़ाइन को कम से कम दिखाने में अहम भूमिका निभा सकता है. ऐडवांस स्प्लिट बटन, उपयोगकर्ता की पिछली कार्रवाई को भी याद रख सकता है और उसे मुख्य बटन के तौर पर दिखा सकता है.

स्प्लिट बटन, ईमेल ऐप्लिकेशन में मौजूद होता है. मुख्य कार्रवाई, ईमेल भेजना है. हालांकि, हो सकता है कि आपको ईमेल बाद में भेजना हो या ड्राफ़्ट के तौर पर सेव करना हो:

ईमेल ऐप्लिकेशन में दिखने वाले स्प्लिट बटन का उदाहरण.

शेयर की गई कार्रवाई की जगह अच्छी है, क्योंकि उपयोगकर्ता को इधर-उधर देखने की ज़रूरत नहीं है. उन्हें पता है कि ईमेल से जुड़े ज़रूरी काम, स्प्लिट बटन में मौजूद होते हैं.

पुर्ज़े

स्प्लिट बटन के ज़रूरी हिस्सों के बारे में जानने से पहले, आइए हम इनके पूरे ऑर्केस्ट्रेशन और उपयोगकर्ता अनुभव के बारे में बात करते हैं. यहां VisBug के ऐक्सेसिबिलिटी इंस्पेक्टर टूल का इस्तेमाल किया गया है. इससे कॉम्पोनेंट का मैक्रो व्यू दिखाने में मदद मिलती है. साथ ही, हर मुख्य हिस्से के लिए एचटीएमएल, स्टाइल, और ऐक्सेसिबिलिटी के पहलुओं को दिखाया जाता है.

स्प्लिट बटन बनाने वाले एचटीएमएल एलिमेंट.

सबसे ऊपर मौजूद स्प्लिट बटन कंटेनर

सबसे ऊपर मौजूद कॉम्पोनेंट एक इनलाइन फ़्लेक्सबॉक्स है. इसकी क्लास gui-split-button है. इसमें मुख्य कार्रवाई और .gui-popup-button शामिल हैं.

gui-split-button क्लास की जांच की गई है. इसमें इस क्लास में इस्तेमाल की गई सीएसएस प्रॉपर्टी दिखाई गई हैं.

मुख्य ऐक्शन बटन

शुरुआत में दिखने वाला और फ़ोकस किया जा सकने वाला <button>, कंटेनर में फ़िट होता है. साथ ही, फ़ोकस, होवर, और ऐक्टिव इंटरैक्शन के लिए, इसके दो कोनों के आकार मिलते-जुलते हैं, ताकि यह .gui-split-button में शामिल दिखे.

बटन एलिमेंट के लिए सीएसएस नियम दिखाने वाला इंस्पेक्टर.

पॉप-अप टॉगल बटन

"पॉप-अप बटन" सहायता एलिमेंट का इस्तेमाल, सेकंडरी बटन की सूची को चालू करने और उसे दिखाने के लिए किया जाता है. ध्यान दें कि यह <button> नहीं है और इस पर फ़ोकस नहीं किया जा सकता. हालांकि, यह .gui-popup के लिए पोज़िशनिंग ऐंकर है और पॉप-अप दिखाने के लिए इस्तेमाल किए गए :focus-within के लिए होस्ट है.

gui-popup-button क्लास के लिए सीएसएस के नियमों को दिखाने वाला इंस्पेक्टर.

पॉपअप कार्ड

यह फ़्लोटिंग कार्ड, अपने ऐंकर .gui-popup-button का चाइल्ड है. इसे ऐब्सलूट पोज़िशन पर रखा गया है और यह बटन की सूची को सिमैंटिक तौर पर रैप करता है.

gui-popup क्लास के लिए सीएसएस के नियम दिखाने वाला इंस्पेक्टर

सेकंडरी ऐक्शन

फ़ोकस किए जा सकने वाले <button> में, मुख्य ऐक्शन बटन के मुकाबले फ़ॉन्ट का साइज़ थोड़ा छोटा होता है. इसमें एक आइकॉन और मुख्य बटन के साथ काम करने वाली स्टाइल होती है.

बटन एलिमेंट के लिए सीएसएस नियम दिखाने वाला इंस्पेक्टर.

कस्टम प्रॉपर्टी

यहां दिए गए वैरिएबल, कलर हार्मनी बनाने और कॉम्पोनेंट में इस्तेमाल की गई वैल्यू में बदलाव करने में मदद करते हैं.

@custom-media --motionOK (prefers-reduced-motion: no-preference);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --light (prefers-color-scheme: light);

.gui-split-button {
  --theme:             hsl(220 75% 50%);
  --theme-hover:  hsl(220 75% 45%);
  --theme-active:  hsl(220 75% 40%);
  --theme-text:      hsl(220 75% 25%);
  --theme-border: hsl(220 50% 75%);
  --ontheme:         hsl(220 90% 98%);
  --popupbg:         hsl(220 0% 100%);

  --border: 1px solid var(--theme-border);
  --radius: 6px;
  --in-speed: 50ms;
  --out-speed: 300ms;

  @media (--dark) {
    --theme:             hsl(220 50% 60%);
    --theme-hover:  hsl(220 50% 65%);
    --theme-active:  hsl(220 75% 70%);
    --theme-text:      hsl(220 10% 85%);
    --theme-border: hsl(220 20% 70%);
    --ontheme:         hsl(220 90% 5%);
    --popupbg:         hsl(220 10% 30%);
  }
}

लेआउट और रंग

मार्कअप

यह एलिमेंट, कस्टम क्लास के नाम वाले <div> के तौर पर शुरू होता है.

<div class="gui-split-button"></div>

प्राइमरी बटन और .gui-popup-button एलिमेंट जोड़ें.

<div class="gui-split-button">
  <button>Send</button>
  <span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions"></span>
</div>

aria एट्रिब्यूट aria-haspopup और aria-expanded पर ध्यान दें. स्क्रीन रीडर के लिए, इन संकेतों के बारे में जानना ज़रूरी है, ताकि उसे स्प्लिट बटन की सुविधा और उसकी स्थिति के बारे में पता चल सके. title एट्रिब्यूट सभी के लिए मददगार होता है.

<svg> आइकॉन और .gui-popup कंटेनर एलिमेंट जोड़ें.

<div class="gui-split-button">
  <button>Send</button>
  <span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions">
    <svg aria-hidden="true" viewBox="0 0 20 20">
      <path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
    </svg>
    <ul class="gui-popup"></ul>
  </span>
</div>

पॉप-अप को सीधे तौर पर दिखाने के लिए, .gui-popup उस बटन का चाइल्ड होता है जो उसे बड़ा करता है. इस रणनीति में सिर्फ़ एक समस्या है. .gui-split-button कंटेनर में overflow: hidden का इस्तेमाल नहीं किया जा सकता, क्योंकि इससे पॉप-अप दिखने में समस्या आएगी.

<li><button> कॉन्टेंट से भरा हुआ <ul>, स्क्रीन रीडर को खुद को "बटन की सूची" के तौर पर दिखाएगा. यह वही इंटरफ़ेस है जो दिखाया जा रहा है.

<div class="gui-split-button">
  <button>Send</button>
  <span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions">
    <svg aria-hidden="true" viewBox="0 0 20 20">
      <path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
    </svg>
    <ul class="gui-popup">
      <li>
        <button>Schedule for later</button>
      </li>
      <li>
        <button>Delete</button>
      </li>
      <li>
        <button>Save draft</button>
      </li>
    </ul>
  </span>
</div>

मैंने https://heroicons.com से लिए गए आइकॉन, सेकेंडरी बटन में जोड़े हैं. इससे बटन ज़्यादा आकर्षक लगते हैं और रंग भी बेहतर दिखता है. प्राइमरी और सेकेंडरी, दोनों तरह के बटन के लिए आइकॉन जोड़ना ज़रूरी नहीं है.

<div class="gui-split-button">
  <button>Send</button>
  <span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions">
    <svg aria-hidden="true" viewBox="0 0 20 20">
      <path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
    </svg>
    <ul class="gui-popup">
      <li><button>
        <svg aria-hidden="true" viewBox="0 0 24 24">
          <path d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
        </svg>
        Schedule for later
      </button></li>
      <li><button>
        <svg aria-hidden="true" viewBox="0 0 24 24">
          <path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
        </svg>
        Delete
      </button></li>
      <li><button>
        <svg aria-hidden="true" viewBox="0 0 24 24">
          <path d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z" />
        </svg>
        Save draft
      </button></li>
    </ul>
  </span>
</div>

स्टाइल

एचटीएमएल और कॉन्टेंट के साथ, स्टाइल शीट में रंग और लेआउट की जानकारी दी जाती है.

स्प्लिट बटन कंटेनर को स्टाइल करना

इस रैपिंग कॉम्पोनेंट के लिए, inline-flex डिसप्ले टाइप सबसे सही है. ऐसा इसलिए, क्योंकि इसे स्प्लिट बटन, कार्रवाइयों या एलिमेंट के साथ इनलाइन फ़िट होना चाहिए.

.gui-split-button {
  display: inline-flex;
  border-radius: var(--radius);
  background: var(--theme);
  color: var(--ontheme);
  fill: var(--ontheme);

  touch-action: manipulation;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

स्प्लिट बटन.

<button> स्टाइलिंग

बटन, यह छिपाने में बहुत अच्छे होते हैं कि कितने कोड की ज़रूरत है. आपको ब्राउज़र की डिफ़ॉल्ट स्टाइल को पहले जैसा करना या बदलना पड़ सकता है. हालांकि, आपको कुछ इनहेरिटेंस लागू करने, इंटरैक्शन की स्थितियां जोड़ने, और उपयोगकर्ता की अलग-अलग प्राथमिकताओं और इनपुट टाइप के हिसाब से बदलाव करने की भी ज़रूरत होगी. बटन के स्टाइल तेज़ी से जुड़ जाते हैं.

ये बटन, सामान्य बटन से अलग होते हैं. ऐसा इसलिए, क्योंकि ये पैरंट एलिमेंट के साथ बैकग्राउंड शेयर करते हैं. आम तौर पर, बटन के बैकग्राउंड और टेक्स्ट का रंग बटन के हिसाब से तय होता है. हालांकि, ये इसे शेयर करते हैं और इंटरैक्शन के दौरान सिर्फ़ अपना बैकग्राउंड लागू करते हैं.

.gui-split-button button {
  cursor: pointer;
  appearance: none;
  background: none;
  border: none;

  display: inline-flex;
  align-items: center;
  gap: 1ch;
  white-space: nowrap;

  font-family: inherit;
  font-size: inherit;
  font-weight: 500;

  padding-block: 1.25ch;
  padding-inline: 2.5ch;

  color: var(--ontheme);
  outline-color: var(--theme);
  outline-offset: -5px;
}

कुछ सीएसएस स्यूडो-क्लास की मदद से इंटरैक्शन की स्थितियां जोड़ें. साथ ही, स्थिति के लिए मिलती-जुलती कस्टम प्रॉपर्टी का इस्तेमाल करें:

.gui-split-button button {
  

  &:is(:hover, :focus-visible) {
    background: var(--theme-hover);
    color: var(--ontheme);

    & > svg {
      stroke: currentColor;
      fill: none;
    }
  }

  &:active {
    background: var(--theme-active);
  }
}

डिजाइन इफ़ेक्ट को पूरा करने के लिए, मुख्य बटन में कुछ खास स्टाइल की ज़रूरत होती है:

.gui-split-button > button {
  border-end-start-radius: var(--radius);
  border-start-start-radius: var(--radius);

  & > svg {
    fill: none;
    stroke: var(--ontheme);
  }
}

आखिर में, हल्के रंग वाली थीम के बटन और आइकॉन में शैडो जोड़ी गई है, ताकि यह और भी बेहतर दिखे:

.gui-split-button {
  @media (--light) {
    & > button,
    & button:is(:focus-visible, :hover) {
      text-shadow: 0 1px 0 var(--theme-active);
    }
    & > .gui-popup-button > svg,
    & button:is(:focus-visible, :hover) > svg {
      filter: drop-shadow(0 1px 0 var(--theme-active));
    }
  }
}

एक बेहतरीन बटन में, माइक्रोइंटरैक्शन और छोटी-छोटी बारीकियों पर ध्यान दिया जाता है.

:focus-visible के बारे में नोट

ध्यान दें कि बटन स्टाइल में :focus के बजाय :focus-visible का इस्तेमाल किया गया है. :focus उपयोगकर्ता के लिए सुलभ यूज़र इंटरफ़ेस बनाने में अहम भूमिका निभाता है. हालांकि, इसमें एक कमी है: यह इस बारे में जानकारी नहीं देता कि उपयोगकर्ता को इसे देखना है या नहीं. यह किसी भी फ़ोकस के लिए लागू होगा.

नीचे दिए गए वीडियो में, इस माइक्रोइंटरैक्शन को आसान तरीके से समझाया गया है. इसमें बताया गया है कि :focus-visible एक बेहतर विकल्प कैसे है.

पॉप-अप बटन की स्टाइल बदलना

आइकॉन को बीच में रखने और पॉपअप बटन की सूची को ऐंकर करने के लिए, 4ch फ़्लेक्सबॉक्स. मुख्य बटन की तरह, यह भी तब तक पारदर्शी रहता है, जब तक इस पर कर्सर नहीं घुमाया जाता या इससे इंटरैक्ट नहीं किया जाता. साथ ही, इसे पूरा भरने के लिए स्ट्रेच किया जाता है.

स्प्लिट बटन का ऐरो वाला हिस्सा, जिसका इस्तेमाल पॉप-अप को ट्रिगर करने के लिए किया जाता है.

.gui-popup-button {
  inline-size: 4ch;
  cursor: pointer;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-inline-start: var(--border);
  border-start-end-radius: var(--radius);
  border-end-end-radius: var(--radius);
}

सीएसएस नेस्टिंग और :is() फ़ंक्शनल सिलेक्टर की मदद से, होवर, फ़ोकस, और ऐक्टिव स्टेट में लेयर करें:

.gui-popup-button {
  

  &:is(:hover,:focus-within) {
    background: var(--theme-hover);
  }

  /* fixes iOS trying to be helpful */
  &:focus {
    outline: none;
  }

  &:active {
    background: var(--theme-active);
  }
}

ये स्टाइल, पॉप-अप को दिखाने और छिपाने के लिए मुख्य हुक हैं. जब .gui-popup-button के किसी भी चाइल्ड पर focus हो, तो आइकॉन और पॉप-अप पर opacity, पोज़िशन, और pointer-events सेट करें.

.gui-popup-button {
  

  &:focus-within {
    & > svg {
      transition-duration: var(--in-speed);
      transform: rotateZ(.5turn);
    }
    & > .gui-popup {
      transition-duration: var(--in-speed);
      opacity: 1;
      transform: translateY(0);
      pointer-events: auto;
    }
  }
}

इन और आउट स्टाइल पूरी होने के बाद, आखिरी काम यह है कि उपयोगकर्ता की मोशन की प्राथमिकता के आधार पर, शर्त के हिसाब से ट्रांज़िशन ट्रांसफ़ॉर्म करें:

.gui-popup-button {
  

  @media (--motionOK) {
    & > svg {
      transition: transform var(--out-speed) ease;
    }
    & > .gui-popup {
      transform: translateY(5px);

      transition:
        opacity var(--out-speed) ease,
        transform var(--out-speed) ease;
    }
  }
}

कोड को ध्यान से देखने पर पता चलता है कि जिन लोगों को मोशन कम पसंद है उनके लिए, ओपैसिटी अब भी ट्रांज़िशन हो रही है.

पॉप-अप को स्टाइल करना

.gui-popup एलिमेंट, फ़्लोटिंग कार्ड बटन की सूची है. इसमें कस्टम प्रॉपर्टी और रिलेटिव यूनिट का इस्तेमाल किया जाता है, ताकि यह मुख्य बटन से थोड़ा छोटा दिखे. साथ ही, यह मुख्य बटन के साथ इंटरैक्टिव तरीके से मैच करे और ब्रैंड के रंग के हिसाब से हो. ध्यान दें कि आइकॉन में कंट्रास्ट कम है, वे पतले हैं, और शैडो में ब्रांड के नीले रंग का इस्तेमाल किया गया है. बटन की तरह ही, मज़बूत यूज़र इंटरफ़ेस (यूआई) और यूज़र एक्सपीरियंस (यूएक्स) इन छोटी-छोटी बातों का नतीजा होता है.

फ़्लोटिंग कार्ड एलिमेंट.

.gui-popup {
  --shadow: 220 70% 15%;
  --shadow-strength: 1%;

  opacity: 0;
  pointer-events: none;

  position: absolute;
  bottom: 80%;
  left: -1.5ch;

  list-style-type: none;
  background: var(--popupbg);
  color: var(--theme-text);
  padding-inline: 0;
  padding-block: .5ch;
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  font-size: .9em;
  transition: opacity var(--out-speed) ease;

  box-shadow:
    0 -2px 5px 0 hsl(var(--shadow) / calc(var(--shadow-strength) + 5%)),
    0 1px 1px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 10%)),
    0 2px 2px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 12%)),
    0 5px 5px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 13%)),
    0 9px 9px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 14%)),
    0 16px 16px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 20%))
  ;
}

आइकॉन और बटन को ब्रैंड के रंग दिए गए हैं, ताकि गहरे और हल्के रंग की थीम वाले हर कार्ड में उन्हें बेहतर तरीके से स्टाइल किया जा सके:

चेकआउट, तुरंत पेमेंट, और बाद के लिए सेव करने के लिंक और आइकॉन.

.gui-popup {
  

  & svg {
    fill: var(--popupbg);
    stroke: var(--theme);

    @media (prefers-color-scheme: dark) {
      stroke: var(--theme-border);
    }
  }

  & button {
    color: var(--theme-text);
    width: 100%;
  }
}

गहरे रंग वाली थीम के पॉप-अप में टेक्स्ट और आइकॉन की शैडो जोड़ी गई हैं. साथ ही, बॉक्स शैडो थोड़ी ज़्यादा गहरी है:

गहरे रंग वाली थीम में पॉप-अप.

.gui-popup {
  

  @media (--dark) {
    --shadow-strength: 5%;
    --shadow: 220 3% 2%;

    & button:not(:focus-visible, :hover) {
      text-shadow: 0 1px 0 var(--ontheme);
    }

    & button:not(:focus-visible, :hover) > svg {
      filter: drop-shadow(0 1px 0 var(--ontheme));
    }
  }
}

<svg> आइकॉन के सामान्य स्टाइल

सभी आइकॉन का साइज़, बटन font-size के हिसाब से तय किया जाता है. इसके लिए, ch यूनिट को inline-size के तौर पर इस्तेमाल किया जाता है. हर आइकॉन को कुछ स्टाइल भी दी गई हैं, ताकि आइकॉन को हल्का और स्मूद बनाया जा सके.

.gui-split-button svg {
  inline-size: 2ch;
  box-sizing: content-box;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2px;
}

दाएं से बाएं लेआउट

लॉजिकल प्रॉपर्टी, सभी मुश्किल काम करती हैं. यहां इस्तेमाल की गई लॉजिकल प्रॉपर्टी की सूची दी गई है: - display: inline-flex एक इनलाइन फ़्लेक्स एलिमेंट बनाता है. - padding शॉर्टहैंड के बजाय, padding-block और padding-inline को एक साथ इस्तेमाल करने पर, लॉजिकल साइड में पैडिंग के फ़ायदे मिलते हैं. - border-end-start-radius और friends, दस्तावेज़ की दिशा के हिसाब से कोनों को गोल करेंगे. - width के बजाय inline-size का इस्तेमाल करने से यह पक्का होता है कि साइज़, फ़िज़िकल डाइमेंशन से जुड़ा नहीं है. - border-inline-start से शुरुआत में बॉर्डर जुड़ जाता है. यह बॉर्डर, स्क्रिप्ट की दिशा के हिसाब से दाईं या बाईं ओर हो सकता है.

JavaScript

यहां दिए गए JavaScript का ज़्यादातर हिस्सा, ऐक्सेसिबिलिटी को बेहतर बनाने के लिए है. टास्क को थोड़ा आसान बनाने के लिए, मेरी दो हेल्पर लाइब्रेरी का इस्तेमाल किया जाता है. BlingBlingJS का इस्तेमाल, कम शब्दों में डीओएम क्वेरी और इवेंट लिसनर को आसानी से सेट अप करने के लिए किया जाता है. वहीं, roving-ux, पॉप-अप के लिए कीबोर्ड और गेमपैड के इंटरैक्शन को आसानी से ऐक्सेस करने में मदद करता है.

import $ from 'blingblingjs'
import {rovingIndex} from 'roving-ux'

const splitButtons = $('.gui-split-button')
const popupButtons = $('.gui-popup-button')

ऊपर दी गई लाइब्रेरी इंपोर्ट करने के बाद, एलिमेंट चुने जाते हैं और उन्हें वैरिएबल में सेव किया जाता है. इसके बाद, उपयोगकर्ता अनुभव को बेहतर बनाने के लिए कुछ फ़ंक्शन का इस्तेमाल किया जाता है.

रोविंग इंडेक्स

जब कीबोर्ड या स्क्रीन रीडर का फ़ोकस .gui-popup-button पर होता है, तो हम चाहते हैं कि फ़ोकस को .gui-popup-button में मौजूद पहले (या हाल ही में फ़ोकस किए गए) बटन पर भेज दिया जाए..gui-popup लाइब्रेरी, element और target पैरामीटर की मदद से ऐसा करने में हमारी मदद करती है.

popupButtons.forEach(element =>
  rovingIndex({
    element,
    target: 'button',
  }))

अब यह एलिमेंट, टारगेट <button> बच्चों पर फ़ोकस करता है. साथ ही, विकल्पों को ब्राउज़ करने के लिए, स्टैंडर्ड ऐरो की नेविगेशन की सुविधा चालू करता है.

aria-expanded को टॉगल करना

पॉप-अप के दिखने और छिपने की जानकारी, विज़ुअल तौर पर साफ़ तौर पर दिखती है. हालांकि, स्क्रीन रीडर को विज़ुअल क्यू से ज़्यादा जानकारी की ज़रूरत होती है. यहां JavaScript का इस्तेमाल, सीएसएस की मदद से :focus-within इंटरैक्शन को बेहतर बनाने के लिए किया जाता है. इसके लिए, स्क्रीन रीडर के लिए सही एट्रिब्यूट को टॉगल किया जाता है.

popupButtons.on('focusin', e => {
  e.currentTarget.setAttribute('aria-expanded', true)
})

popupButtons.on('focusout', e => {
  e.currentTarget.setAttribute('aria-expanded', false)
})

Escape बटन चालू करना

उपयोगकर्ता के फ़ोकस को जान-बूझकर किसी ट्रैप पर भेजा गया है. इसका मतलब है कि हमें उसे बाहर निकलने का तरीका बताना होगा. सबसे आम तरीका, Escape कुंजी का इस्तेमाल करने की अनुमति देना है. इसके लिए, पॉप-अप बटन पर कीप्रेस पर नज़र रखें. ऐसा इसलिए, क्योंकि बच्चों पर होने वाले कीबोर्ड इवेंट, इस पैरंट तक पहुंच जाएंगे.

popupButtons.on('keyup', e => {
  if (e.code === 'Escape')
    e.target.blur()
})

अगर पॉपअप बटन को कोई Escape कीस्ट्रोक दिखता है, तो वह blur() की मदद से, खुद से फ़ोकस हटा देता है.

स्प्लिट बटन पर हुए क्लिक

आखिर में, अगर उपयोगकर्ता बटन पर क्लिक करता है, टैप करता है या कीबोर्ड से इंटरैक्ट करता है, तो ऐप्लिकेशन को ज़रूरी कार्रवाई करनी होगी. यहां इवेंट बब्लिंग का इस्तेमाल फिर से किया गया है. हालांकि, इस बार इसका इस्तेमाल .gui-split-button कंटेनर पर किया गया है, ताकि चाइल्ड पॉप-अप या प्राइमरी ऐक्शन से बटन क्लिक को कैप्चर किया जा सके.

splitButtons.on('click', event => {
  if (event.target.nodeName !== 'BUTTON') return
  console.info(event.target.innerText)
})

नतीजा

अब आपको पता चल गया है कि मैंने यह कैसे किया. अब आप कैसे करेंगे‽ 🙂

आइए, हम अपने तरीकों में विविधता लाएं और वेब पर काॅन्टेंट पोस्ट करने के सभी तरीके जानें. डेमो बनाएं और मुझे ट्वीट करें. इसके बाद, मैं इसे यहां कम्यूनिटी रीमिक्स सेक्शन में जोड़ दूंगा!

कम्यूनिटी रीमिक्स