Блогът на Гонзо

Достъпен превключвател за нощен режим в сайта

Преди няколко дни Атанас Йонков сподели своя статия за добавяне на превключвател за нощен режим към сайт на WordPress. Решението е елегантно и би вършило чудесна работа, ако не беше проблемът с достъпността на самия превключвател. И тъй като в неговия блог няма коментари, реших, че ще е най-добре да опиша нужните промени в публикация в моя.

В какво се състои проблемът в решението на Атанас? За превключване към нощен режим той използва div със закачена JavaScript функция, която да обслужва събитието click, т.е. единствено интеракция с мишка или натискане с пръст. Но тъй като div не е интерактивен елемент в HTML той не може да приема фокус от клавиатурата и няма да реагира на никакви взаимодействия с нея. Това го прави неизползваем за онези потребители, които поради някаква причина не могат да използват мишка.

Проблемът може лесно да се реши ако използваме елемента button. Той по подразбиране приема фокус, реагира както ва взаимодействия с мишката, така и на клавишите за нов ред и интервал. Може да бъде стилизиран със CSS по същия начин както всеки друг елемент. Да видим как ще изглежда кодът тогава (ще подчертая промените с получер шрифт):

<button type="button" class="wpnm-button">
    <div class="wpnm-button-inner-left"></div>
    <div class="wpnm-button-inner"></div>
</button>
.wpnm-button {
    padding: 0;
    border: none;
    background: none;
    font-size: 1rem;
}

След като променихме елемента, се налага да направим и някои промени в стиловете – тъй като бутоните има подразбиращи се стилове, които да ги накарат да изглеждат като бутони, ние ще трябва да ги пренапишем.

Тъй като вече използваме интерактивен елемент, можем да добавим стилове, които да го отличават когато фокусът е върху него, когато е посочен с мишката или натиснат. Но това ще го оставим за домашно…

Вече имаме хубав бутон, достъпен за потребителите, използващи клавиатура, но на бутонът му липсва текстов етикет. Той е важен за потребителите, използващи екранен четец – когато курсорът на четеца или фокуса попадне на този бутон, той няма да може да даде подходящо описание на потребителя и потребителя няма да може да разбере какво прави този бутон. Най-добре би било текстовия етикет да е видим непосредствено до заобления превключвател, но за да не разваляме изчистения дизайн ще добавим скрит етикет чрез атрибута aria-label. Освен това ще е добре потребителя да може да разбере дали в момента нощния режим е включен или изключен. Състоянието на бутона можем да укажем с атрибута aria-pressed. Този атрибут служи за указване на състоянието на бутони с две състояние (включено – изключено, натиснат – ненатиснат), точно като нашия превключвател към нощен режим.

<button type="button" class="wpnm-button" aria-label="<?php esc_attr_e( 'Dark mode switch', 'textdomain' ); ?>" aria-pressed="false">
    <div class="wpnm-button-inner-left"></div>
    <div class="wpnm-button-inner"></div>
</button>
jQuery(function($) {
    /*Click on dark mode icon. Add dark mode classes and wrappers. 
    Store user preference through sessions*/
    var $button = $('.wpnm-button'),
        $body = $('body');
    $button.click(function() {
        // Show either moon or sun.
        $button.toggleClass('active');
        // If dark mode is selected.
        if ($button.hasClass('active')) {
            //Add dark mode class to the body
            $body.addClass('dark-mode');
            //Save user preference to Storage
            localStorage.setItem('darkMode', true);
            // Reflect the state on the button itself.
            $button.attr('aria-pressed', true);
        } else {
            $body.removeClass('dark-mode');
            localStorage.removeItem('darkMode');
            // Reflect the state on the button itself.
            $button.attr('aria-pressed', false);
        }
    })
    //Check Storage. Display user preference 
    if (localStorage.getItem("darkMode")) {
        $body.addClass('dark-mode');
        $button.addClass('active');
        // Reflect the state on the button itself.
        $button.attr('aria-pressed', true);
    }
})

Както виждате, за етикета на бутона използвах PHP код, който да позволи етикетът да бъде част от преводите на темата или разширението. По този начин с малко помощ от общността на WordPress темата или разширението ни може да достигне до повече потребители.

Освен, че добавих промяна на атрибута aria-pressed, в JavaScript добавих и една оптимизация – можем да запазим в променливи jQuery референциите към бутона и елемента body, за да си спестим търсенето в DOM при всяко изпълняване на части от кода. Макар в случая да не е чак толкова критично, ако страницата има твърде много елементи или имаме много скриптове, подобен подход може да има съществен ефект върху производителността.

Това е минимума от промени, с които да направим превключвателя достъпен. Можем да подобрим още нещата, като например направим етикета видим когато фокуса е върху бутона. Това може да стане с техниката, описана от Adrian Rosseli за добавяне на достъпен етикет на емотикони, и която използвам за бутоните за споделяне в разширението ми Minimal Share Buttons (има ги и под тази статия). Можем да използваме чист JavaScript вместо jQuery, с което да намалим обема на изтегляните скриптове (освен ако така или иначе не използваме и други скриптове, зависещи от jQuery). И можем вместо допълнителен клас active върху бутона да използваме атрибута aria-pressed и в CSS за промяна на изгледа когато е включен нощния режим. За целта ще ни помогне CSS селектор по атрибут: .wpnm-button[aria-pressed="true"].

Споделяне

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *