Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♿ [#2625] Add mobile design for keeping accessibility functions available on small screens #1470

Merged
merged 2 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions INSTALL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,6 @@ development machine.

git clone [email protected]:maykinmedia/open-inwoner.git
cd open-inwoner
# initialize submodules
git submodule update --init --recursive

This will include the `Open-Inwoner-Design-Tokens`_ subdirectory. When all is built and run this is where the OIP design tokens CSS will be generated. When this repository gets updated, it needs to be pulled again.

.. _Open-Inwoner-Design-Tokens: https://github.com/maykinmedia/open-inwoner-design-tokens
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might not be a bad idea to still include a reference to this repo? Not in these steps indeed, but just as a note (perhaps in step 5, "Note the project makes use of the open-inwoner-design-tokens package, which contains the project's design tokens for the NL Design System."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, I could, though programmatically it has the same importance as all other NPM packages needed for this project to work, so NLDS package is just another Node module now.
This Readme contained a remnant from when we were still using some subdirectory packages.


3. Install all required (backend) libraries.
**Tip:** You can use the ``bootstrap.py`` script to install the requirements
Expand Down Expand Up @@ -138,6 +132,9 @@ using ``npm run watch``.
.. _ECMA: https://ecma-international.org/
.. _Sass: https://sass-lang.com/

**Note:** The project makes use of the `open-inwoner-design-tokens package`_ , a node module which contains the values for the project's design tokens from the NL Design System.

.. _open-inwoner-design-tokens package: https://github.com/maykinmedia/open-inwoner-design-tokens

ElasticSearch
-------------
Expand Down
39 changes: 13 additions & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@emotion/styled": "^11.3.0",
"@fortawesome/fontawesome-free": "^6.4.2",
"@joeattardi/emoji-button": "^4.6.4",
"@open-inwoner/design-tokens": "^0.0.6-alpha.1",
"@open-inwoner/design-tokens": "^0.0.7-alpha.2",
"@tarekraafat/autocomplete.js": "^10.2.6",
"bem.js": "^1.0.10",
"emojibase-data": "^7.0.1",
Expand All @@ -63,8 +63,7 @@
"@babel/polyfill": "latest",
"@babel/preset-env": "latest",
"@types/leaflet": "^1.7.6",
"@utrecht/component-library-css": "3.0.1-alpha.0",
"@utrecht/components": "3.0.1-alpha.0",
"@utrecht/components": "5.0.1",
"autoprefixer": "^9.0.0",
"babel-loader": "^8.2.5",
"chai": "latest",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@

<div class="accessibility-header" role="complementary">
<ul class="accessibility-header__list" aria-label="{% trans "Toegankelijkheidshulp" %}">
<li class="accessibility-header__list-item">
{% trans "Doorgaan naar hoofdinhoud" as link_text %}
{% link href="#content" icon="south" text=link_text extra_classes="skip-link" %}
</li>

<li class="accessibility-header__list-item">
{% trans "Lees voor" as link_text %}
{% trans "Pauzeer" as alt_link_text %}
Expand All @@ -22,7 +17,11 @@
<li class="accessibility-header__list-item">
{% trans "Dyslexie" as link_text %}
{% trans "Normaal lettertype" as alt_link_text %}
{% link href="#" icon="font_download" text=link_text extra_classes="accessibility--change-font" data_text=link_text data_alt_text=alt_link_text %}
{% if desktop %}
{% link href="#" icon="font_download" text=link_text extra_classes="accessibility--change-font" data_text=link_text data_alt_text=alt_link_text %}
{% else %}
{% link href="#" icon="text_format" text=link_text extra_classes="accessibility--change-font" data_text=link_text data_alt_text=alt_link_text icon_outlined=True %}
{% endif %}
</li>

{% if help_text %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% load i18n link_tags %}

<p class="utrecht-paragraph">
{% trans "Doorgaan naar hoofdinhoud" as link_text %}
<a href="#content" class="utrecht-skip-link utrecht-skip-link--visible-on-focus utrecht-skip-link--focus-visible" aria-label="{{ link_text }}" title="{{ link_text }}">
<span class="skip-link__text">{{ link_text }}</span>
<span aria-hidden="true" class="material-icons ">south</span>
</a>
</p>
141 changes: 78 additions & 63 deletions src/open_inwoner/components/templates/components/Header/Header.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

{% get_solo "configurations.SiteConfiguration" as config %}

{% accessibility_header request=request %}
{% accessibility_header request=request desktop=True %}

<header class="header" aria-label="Navigatie header">
<div class="header__container">
Expand Down Expand Up @@ -33,77 +33,92 @@
{# end of mobile header-menu with logo #}

<div class="header--mobile header__submenu">
{% if cms_apps.products and request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
<nav class="header__actions header__actions--open" aria-label="Zoek navigatie mobiel">
<form id="search-form-mobile-open" class="search-form-delegate form form--inline">
{% input search_form.query no_label=True %}
{% form_actions primary_icon="search" primary_text=_("Zoeken") hide_primary_text=True %}
</form>
</nav>
{% endif %}

<nav class="primary-navigation primary-navigation--mobile" aria-label="Hoofd navigatie">
<ul class="primary-navigation__list">

<li class="primary-navigation__list-item">
{% trans "Overzicht" as link_text %}
{% link text=link_text href="/" icon="grid_view" icon_position="before" %}
</li>

<div class="header--mobile__close">
{% button icon="close" text=_("Sluiten") hide_text=True icon_outlined=True transparent=True id="closeMobileNav" %}
</div>

{% if cms_apps.products %}
{% if request.user.is_authenticated or not config.hide_categories_from_anonymous_users %}
<li class="primary-navigation__list-item dropdown-nav__toggle">
<a href="#" class="link link--toggle link--icon link--icon-position-before" aria-label="{% trans "Onderwerpen" %}" title="{% trans "Onderwerpen" %}" aria-expanded="false">
<span >{% trans "Onderwerpen" %}</span>
<span aria-hidden="true" class="material-icons-outlined ">description</span>
{% icon icon="expand_more" icon_position="after" icon_outlined=True %}
</a>

{% if menu_categories %}
<ul class="primary-navigation__list subpage-list">
{% for category in menu_categories %}
<li class="primary-navigation__list-item">
{% url 'products:category_detail' slug=category.slug as category_href %}
{% link text=category.name href=category_href %}
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}
<nav class="primary-navigation primary-navigation--mobile" aria-label="Hoofd navigatie">
<ul class="primary-navigation__list">

<li class="primary-navigation__list-item">
{% trans "Homepage" as link_text %}
{% link text=link_text href="/" icon="home" icon_position="before" icon_outlined=True %}
</li>

{% if cms_apps.products %}
{% if request.user.is_authenticated or not config.hide_categories_from_anonymous_users %}
<li class="primary-navigation__list-item dropdown-nav__toggle">
<a href="#" class="link link--toggle link--icon link--icon-position-before" aria-label="{% trans "Onderwerpen" %}" title="{% trans "Onderwerpen" %}" aria-expanded="false">
<span >{% trans "Onderwerpen" %}</span>
<span aria-hidden="true" class="material-icons-outlined ">source</span>
{% icon icon="expand_more" icon_position="after" icon_outlined=True %}
</a>

{% if menu_categories %}
<ul class="primary-navigation__list subpage-list">
{% for category in menu_categories %}
<li class="primary-navigation__list-item">
{% url 'products:category_detail' slug=category.slug as category_href %}
{% link text=category.name href=category_href %}
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}
{% endif %}

{{ rendered_cms_menu__home }}
{{ rendered_cms_menu__home }}

{% if has_general_faq_questions %}
<li class="primary-navigation__list-item">
{% link text=_('FAQ') href='general_faq' icon="help_outline" icon_position="before" icon_outlined=True %}
</li>
{% endif %}
</ul>
</nav>
{% if has_general_faq_questions %}
<li class="primary-navigation__list-item">
{% link text=_('Veelgestelde vragen') href='general_faq' icon="question_answer" icon_position="before" icon_outlined=True %}
</li>
{% endif %}
</ul>
</nav>

<section class="header__actions" aria-label="Navigatie mobiel voor inloggen en uitloggen">
<div class="header__text-actions">
<section class="header__actions" aria-label="Navigatie mobiel voor inloggen en uitloggen">
<div class="header__text-actions">

{% if request.user.is_authenticated %}
<p class="utrecht-paragraph">
{% icon icon="person" icon_position="before" outlined=True %}{% trans "Ingelogd als" %} {{ request.user.display_name }}
</p>
<ul class="header__list">
{% if request.user.is_authenticated %}
<ul class="header__list">
<li class="header__list-item">
{% trans "Logout" as logout %}
{% link text=logout href=request.user.get_logout_url icon="login" icon_position="before" primary=True %}
</li>
{% if cms_apps.products and request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
<li class="header__list-item">
{% trans "Logout" as logout %}
{% link text=logout href=request.user.get_logout_url icon="arrow_forward" icon_position="before" secondary=True %}
{% trans "Zoeken" as search %}
{% link text=search href="/search" icon="search" icon_position="before" %}
</li>
</ul>
{% elif config.login_show %}
<p></p>
{% endif %}
</div>
</section>
{% endif %}
</ul>
{% elif config.login_show %}
<ul class="header__list">
<li class="header__list-item">
{% url 'login' as login_url %}
{% trans "Log in" as loginmobile %}
{% link text=loginmobile title=loginmobile href=login_url icon="account_circle" icon_position="before" primary=True icon_outlined=True %}
</li>
<li class="header__list-item">
{% trans "Zoeken" as search %}
{% link text=search href="/search" icon="search" icon_position="before" %}
</li>
</ul>
{% endif %}
</div>
</section>

</div>
{# end of submenu items #}
<section class="accessibility-header__mobilenav">
<p class="utrecht-paragraph">Toegankelijkheid:</p>
{% accessibility_header request=request desktop=False %}
<span class="spacer"></span>
</section>

</div>
{# end of submenu items #}

{% firstof config.logo.default_alt_text config.name as logo_alt_text %}
<div class="logo__desktop">{% include "components/Logo/Logo.html" with src=config.logo.file.url alt=logo_alt_text svg_height=75 only %}</div>
Expand Down
1 change: 1 addition & 0 deletions src/open_inwoner/components/templatetags/link_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def link(href, text, **kwargs):
- extra_classes: str | Extra classes
- hide_text: bool | whether to hide the text and use aria attribute instead.
- icon: str | The icon that should be displayed.
- icon_outlined: bool | Whether the icon needs to be filled or only show line-art
- icon_position: str | "before" or "after".
- primary: bool | If the primary styling should be used
- secondary: bool | If the secondary styling should be used
Expand Down
32 changes: 25 additions & 7 deletions src/open_inwoner/components/tests/test_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,23 +161,41 @@ def test_search_bar_hidden_from_anonymous_users(self):
config.save()

response = self.client.get("/")

doc = PyQuery(response.content)

search_buttons = doc.find("[title='Zoeken']")
search_forms = [
form
for form in doc.find("form").items()
if form.find("button[title='Zoeken']")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick I guess, but: can't we simply do something like doc.find("form:has(> button[title='Zoeken'])")?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did at first! But then I got the error "cssselect.parser.SelectorSyntaxError: Expected an argument, got <DELIM '[' at 15>..." and it seems due to cssselect, which doesn’t support all the same selectors as the jQuery-like PyQuery. Specifically, it seems to not support :has() with attribute selectors directly.

To get around this limitation, I tried an alternative approach: first find all forms on the page, then filter them programmatically to check if they contain a button[title='Zoeken'] with a simple CSS attribute selector that would work in all browser engines.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shame that the selector support appears to be limited, but no worries, thanks for the explanation!

]

self.assertEqual(len(search_buttons), 0)
self.assertEqual(
len(search_forms), 0, "Search form should be hidden for anonymous users."
)

def test_search_bar_not_hidden_from_anonymous_users(self):
config = SiteConfiguration.get_solo()
config.hide_search_from_anonymous_users = False
config.save()

response = self.client.get("/")

doc = PyQuery(response.content)

search_buttons = doc.find("[title='Zoeken']")
search_forms = [
form
for form in doc.find("form").items()
if form.find("button[title='Zoeken']")
]

self.assertGreater(
len(search_forms), 0, "Search form should be visible for anonymous users."
)

for button in search_buttons:
self.assertEqual(button.tag, "button")
# Check each search form for the expected input element
for search_form in search_forms:
search_input = search_form.find("input[type='text'][name='query']")
self.assertEqual(
len(search_input),
1,
"Each search form should have a single text input named 'query'.",
)
Loading
Loading