Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
533c1f2
a11y: #4220 counter tag for unique id for aria
StephDriver Dec 2, 2025
6047138
a11y: #4220 olh featured article links add aria markup
StephDriver Sep 26, 2025
3174798
a11y: #4220 box link aria
StephDriver Dec 2, 2025
25ac2c6
a11y: olh carousel add orbit bullets
StephDriver Sep 29, 2025
c347db4
a11y: olh carousel set autoplay=false
StephDriver Sep 29, 2025
26845b0
a11y: olh carousel caption colour contrast
StephDriver Sep 29, 2025
62c5f96
a11y: #4225 olh nav line formatting for ease of editing
StephDriver Sep 30, 2025
28cd137
a11y: #4225 olh nav .is_dropdown_submenu_parent to is_dropdown_submen…
StephDriver Sep 30, 2025
c2fdb3b
a11y: #4225 olh nav add aria markup to dropdowns
StephDriver Sep 30, 2025
643aee4
a11y: #4225 olh nav suport aria-expanded
StephDriver Sep 30, 2025
597e659
a11y: #4225 olh nav make narrow alignment consistent
StephDriver Sep 30, 2025
a01fe9f
a11y: #4225 olh nav remove duplicate </nav>
StephDriver Sep 30, 2025
56ecfc7
a11y: #4225 olh improve article text options button
StephDriver Sep 30, 2025
d3fd4b7
a11y: #4225 olh make article text options keyboard navigable
StephDriver Sep 30, 2025
097a9db
a11y: #4225 olh make article text options widescreen style updates
StephDriver Sep 30, 2025
6157ab7
a11y: #4225 olh fix article text option dropdown linebreak
StephDriver Sep 30, 2025
226b5e1
a11y: #4225 olh keyboard navigation focus-visible
StephDriver Sep 30, 2025
9f2a59e
Revert "a11y: #4220 counter tag for unique id for aria"
StephDriver Dec 4, 2025
c4a942b
a11y: #4220 use uuid tag instead of counter tag
StephDriver Dec 4, 2025
8ffcc56
a11y olh carousel add orbit bullets fix rebase duplicates
StephDriver Dec 4, 2025
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
34 changes: 34 additions & 0 deletions src/themes/OLH/assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,40 @@ $(document).on('click', '[data-toggle]', function() {
$button.attr('aria-expanded', !currentExpanded);
});

// Accessibility: Handle Nav aria-expanded on keyboard navigation
$(document).on('click', '[aria-expanded]', function() {
var $button = $(this);
var currentExpanded = $button.attr('aria-expanded') === 'true';
$button.attr('aria-expanded', !currentExpanded);
});

function toggleAriaExpanded(submenu, expanded) {
var $parent = submenu.parent('li.is-dropdown-submenu-parent');
var $button = $parent.find('a[aria-expanded]');
$button.attr('aria-expanded', expanded);
}

// Accessibility: Listen for Foundation menu events to update aria-expanded
$(document).ready(function() {
// dropdown menu (wide screen)
$(document).on('show.zf.dropdownmenu', function(event, $sub) {
toggleAriaExpanded($sub, true);
});

$(document).on('hide.zf.dropdownmenu', function(event, $sub) {
$('a[aria-expanded="true"]').attr('aria-expanded', 'false');
});

// drilldown menu (narrow screen)
$(document).on('open.zf.drilldown', function(event, $elem) {
toggleAriaExpanded($elem, true);
});

$(document).on('hide.zf.drilldown', function(event, $elem) {
$('a[aria-expanded="true"]').attr('aria-expanded', 'false');
});
});

$(".search-toggle").click(function() {
var $searchMenu = $("#search-menu");
if ($searchMenu.is(':visible')) {
Expand Down
102 changes: 101 additions & 1 deletion src/themes/OLH/assets/scss/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -614,12 +614,42 @@ div.caption span.label {
li {
a {
color: $dark-gray;
padding: 0.5rem 0;
display: block;
text-decoration: none;

@include breakpoint(medium) {
padding: 0.5rem 1rem;
}
}
button {
color: $dark-gray;
background: none;
border: none;
padding: 0.5rem 0;
font: inherit;
cursor: pointer;
text-decoration: none;
text-align: left;
display: block;
width: 100%;

@include breakpoint(medium) {
padding: 0.5rem 1rem;
}
}
&:hover {
background: $medium-gray;
}
i {
margin-top: rem-calc(-5px);
margin-right: 0.5rem;
vertical-align: middle;
}

// Dropdown menu items should stay on single line
.menu.vertical li {
white-space: nowrap;
}
}
}
Expand Down Expand Up @@ -1552,4 +1582,74 @@ span + .btn-background {
section.invisible-landmark{
padding: 0;
margin: 0;
}
}

// carousel style overrides
.orbit-bullets button{
min-width: 24px;
min-height: 24px;
}

.orbit-caption{
color: var(--primary-light-color);
background-color: color-mix(in srgb, var(--primary-dark-color) 90%, transparent);
}

/*
* WCAG 2.4.7 Focus Visible - Two-Color Focus Indicator (Technique C40)
* Requires at least 1:9 contrast ratio between the two focus colours.
*/
:root {
--focus-light: #F9F9F9;
--focus-dark: #193146;
--focus-ring-size: 4px;
}

/* Prevent layout shifts */
/* Inline links override to prevent layout shifts without affecting typography */
p a,
span a,
li a {
margin: calc(-1 * var(--focus-ring-size));
padding: var(--focus-ring-size);
box-sizing: border-box;
}

p a,
span a {
display: inline-block;
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't believe this is needed, since outline does not add any margin or padding or size to the element. I commented it out and tested it, and I did not get a layout shift when tabbing through.

It is also causing a bit of a visible gap between the focus ring and the element. Do you think we can remove it safely, or is there another reason for it I'm not seeing?

Copy link
Member Author

@StephDriver StephDriver Nov 14, 2025

Choose a reason for hiding this comment

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

This was how I got the links that were within other text to remain stationary rather than move around when receiving/losing focus. The main culprit was where text had flowed such that the link had been split across two lines, for some links, this reflow ended up changing when focused. Using this style prevented that. This was a style choice born of experimenting until something worked rather than theory.

Copy link
Member Author

Choose a reason for hiding this comment

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

inline_block.mov

Copy link
Member

Choose a reason for hiding this comment

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

There is something wrong with the .mov file above that is keeping me from watching it, but that sounds fine--i just wanted to make sure this was needed.



/* General */
*:focus-visible {
outline: 2px var(--focus-light) solid;
outline-offset: 0;
box-shadow: 0 0 0 var(--focus-ring-size) var(--focus-dark);
}

/* focus bounding boxes */
a:focus-visible {
outline: 2px var(--focus-light) solid;
outline-offset: 0;
box-shadow: 0 0 0 var(--focus-ring-size) var(--focus-dark);
display: inline-block;
white-space: normal;
}

input[type="text"]:focus-visible ,
input[type="textarea"].tinymce:focus-visible ,
input[type="email"]:focus-visible ,
input[type="password"]:focus-visible ,
input[type="search"]:focus-visible ,
input[type="number"]:focus-visible ,
input[type="date"]:focus-visible ,
input[type="datetime-local"]:focus-visible ,
input[type="file"]:focus-visible ,
input[type="submit"]:focus-visible {
outline: 2px var(--focus-light) solid;
outline-offset: 0;
box-shadow: 0 0 0 var(--focus-ring-size) var(--focus-dark);
}

/* end of WCAG 2.4.7 Focus Visible - Two-Color Focus Indicator (Technique C40) */
190 changes: 140 additions & 50 deletions src/themes/OLH/templates/core/nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,96 +6,186 @@
<nav>
<div class="top-bar" id="main-menu" style="display: block;">
<ul class="menu vertical medium-horizontal" data-responsive-menu="drilldown medium-dropdown">
{% if request.journal.nav_home %}<li><a href="{% url 'website_index' %}">{% trans 'Home' %}</a></li>{% endif %}
{% if request.journal.nav_news %}<li><a href="{% url 'core_news_list' %}">{{ journal_settings.news.news_title }}</a></li>{% endif %}
{% for item in navigation_items %}
{% if item.has_sub_nav %}
<li class=".is-dropdown-submenu-parent"><a href="#"
data-options="is_hover:true; hover_timeout:5000">{{ item.link_name }}</a>
<ul class="menu vertical medium-horizontal">
{% if item.link %}<li><a href="{{ item.url }}">{{ item.link_name }}</a></li>{% endif %}
{% for subnav in item.sub_nav_items %}
<li><a href="{{ subnav.url }}">{{ subnav.link_name }}</a></li>
{% endfor %}
</ul>
{% if request.journal.nav_home %}
<li>
<a href="{% url 'website_index' %}">{% trans 'Home' %}</a>
</li>
{% elif not item.for_footer %}
<li><a href="{{ item.url }}">{{ item.link_name }}</a></li>
{% endif %}

{% if request.journal.nav_news %}
<li>
<a href="{% url 'core_news_list' %}">{{ journal_settings.news.news_title }}</a>
</li>
{% endif %}

{% for item in navigation_items %}
{% if item.has_sub_nav %}
<li class="is-dropdown-submenu-parent">
<a href="#" data-options="is_hover:true; hover_timeout:5000"
role="button"
aria-expanded="false"
aria-controls="menu-nav-item-{{ item.counter }}"
>
{{ item.link_name }}
</a>
<ul class="menu vertical medium-horizontal" id="menu-nav-item-{{ item.counter }}">
{% if item.link %}
<li>
<a href="{{ item.url }}">{{ item.link_name }}</a>
</li>
{% endif %}
{% for subnav in item.sub_nav_items %}
<li>
<a href="{{ subnav.url }}">{{ subnav.link_name }}</a>
</li>
{% endfor %}
</ul>
</li>
{% elif not item.for_footer %}
<li>
<a href="{{ item.url }}">{{ item.link_name }}</a>
</li>
{% endif %}
{% endfor %}
{% if request.journal.nav_articles %}<li><a href="{% url 'journal_articles' %}">{% trans 'Articles' %}</a></li>{% endif %}
{% if request.journal.nav_issues %}<li><a href="{% url 'journal_issues' %}">{% trans 'Issues' %}</a></li>{% endif %}

{% if request.journal.nav_articles %}
<li>
<a href="{% url 'journal_articles' %}">{% trans 'Articles' %}</a>
</li>
{% endif %}

{% if request.journal.nav_issues %}
<li>
<a href="{% url 'journal_issues' %}">{% trans 'Issues' %}</a>
</li>
{% endif %}

{% if journal_settings.general.enable_editorial_display %}
{% if journal_settings.general.multi_page_editorial %}
<li class=".is-dropdown-submenu-parent">
<a href="#" data-options="is_hover:true; hover_timeout:5000">{{ journal_settings.styling.editorial_group_page_name }}</a>
<ul class="menu vertical medium-horizontal">
{% for group in request.journal.editorial_groups %}
<li><a href="{% url 'editorial_team_group' group.pk %}">{{ group.name }}</a></li>
{% endfor %}
</ul>
</li>
<li class="is-dropdown-submenu-parent">
<a href="#" data-options="is_hover:true; hover_timeout:5000"
role="button"
aria-expanded="false"
aria-controls="menu-nav-journal"
>
{{ journal_settings.styling.editorial_group_page_name }}
</a>
<ul class="menu vertical medium-horizontal" id="menu-nav-journal">
{% for group in request.journal.editorial_groups %}
<li>
<a href="{% url 'editorial_team_group' group.pk %}">{{ group.name }}</a>
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li><a href="{% url 'editorial_team' %}">{{ journal_settings.styling.editorial_group_page_name }}</a></li>
<li>
<a href="{% url 'editorial_team' %}">{{ journal_settings.styling.editorial_group_page_name }}</a>
</li>
{% endif %}
{% endif %}
{% if request.journal.nav_sub %}<li><a href="{% url 'journal_submissions' %}">{% trans 'Submission' %}</a></li>{% endif %}
{% if request.journal.nav_contact %}<li><a href="{% url 'contact' %}">{% trans 'Contact' %}</a></li>{% endif %}

{% if request.journal.nav_sub %}
<li>
<a href="{% url 'journal_submissions' %}">{% trans 'Submission' %}</a>
</li>
{% endif %}

{% if request.journal.nav_contact %}
<li>
<a href="{% url 'contact' %}">{% trans 'Contact' %}</a>
</li>
{% endif %}

{% hook 'nav_block' %}
{% if request.journal.nav_start and not journal_settings.general.disable_journal_submission %}

{% if request.journal.nav_start and not journal_settings.general.disable_journal_submission %}
<li>
<a href="{% url 'submission_start' %}" class="button">
<a href="{% url 'submission_start' %}" >
<i aria-hidden="true" class="fa fa-cloud-upload"></i> {% trans 'Start Submission' %}
</a>
</li>
{% endif %}

{% if request.journal.nav_review %}
<li>
<a href="{% url 'become_reviewer' %}" class="button">
<a href="{% url 'become_reviewer' %}" >
<i aria-hidden="true" class="fa fa-trophy"></i>
{% trans 'Become a Reviewer' %}
</a>
</li>
{% endif %}

<li class=".is-dropdown-submenu-parent show-for-small-only">
<a href="#" data-options="is_hover:true; hover_timeout:5000">{% trans 'Account' %}</a>
<ul class="menu vertical medium-horizontal">
<li class="is-dropdown-submenu-parent show-for-small-only">
<a href="#" data-options="is_hover:true; hover_timeout:5000"
role="button"
aria-expanded="false"
aria-controls="menu-nav-account"
>
{% trans 'Account' %}
</a>
<ul class="menu vertical medium-horizontal" id="menu-nav-account">
{% if request.user.is_authenticated %}
<li><a href="{% url 'core_dashboard' %}">{% trans 'Dashboard' %}</a></li>
<li>
<a href="{% url 'core_dashboard' %}">{% trans 'Dashboard' %}</a>
</li>
<li class="divider"></li>
{% if not journal_settings.general.disable_journal_submission %}<li><a href="{% url 'submission_start' %}">{% trans 'Submit' %}</a></li>{% endif %}

{% if not journal_settings.general.disable_journal_submission %}
<li>
<a href="{% url 'submission_start' %}">{% trans 'Submit' %}</a>
</li>
{% endif %}

{% user_has_role request 'editor' as user_is_editor %}
{% if user_is_editor or request.user.is_staff%}
{% if user_is_editor or request.user.is_staff %}
<li class="divider"></li>
<li><a href="{% url 'kanban' %}">{% trans 'Kanban' %}</a></li>
<li><a href="{% url 'core_manager_index' %}">{% trans 'Manager' %}</a></li>
<li>
<a href="{% url 'kanban' %}">{% trans 'Kanban' %}</a>
</li>
<li>
<a href="{% url 'core_manager_index' %}">{% trans 'Manager' %}</a>
</li>
{% if request.resolver_match.url_name and request.resolver_match.url_name == 'article_view' and article %}
<li><a href="{% url 'manage_archive_article' article.pk %}">{% trans 'Edit Article' %}</a></li>
<li>
<a href="{% url 'manage_archive_article' article.pk %}">{% trans 'Edit Article' %}</a>
</li>
{% endif %}
{% if request.resolver_match.url_name and request.resolver_match.url_name == 'journal_issue' and issue %}
<li><a href="{% url 'manage_issues_id' issue.pk %}">{% trans 'Edit Issue' %}</a></li>
<li>
<a href="{% url 'manage_issues_id' issue.pk %}">{% trans 'Edit Issue' %}</a>
</li>
{% endif %}
{% if request.resolver_match.url_name and request.resolver_match.url_name == 'core_news_item' and news_item %}
<li><a href="{% url 'core_manager_edit_news' news_item.pk %}">{% trans 'Edit News Item' %}</a></li>
<li>
<a href="{% url 'core_manager_edit_news' news_item.pk %}">{% trans 'Edit News Item' %}</a>
</li>
{% endif %}
{% endif %}

{% if request.user.is_staff %}
<li><a href="/admin/">{% trans 'Admin' %}</a></li>
<li>
<a href="/admin/">{% trans 'Admin' %}</a>
</li>
{% endif %}

<li class="divider"></li>
<li><a href="{% url 'core_edit_profile' %}">{% trans 'Profile' %}</a></li>
<li><a href="{% url 'core_logout' %}">{% trans 'Logout' %}</a></li>
<li>
<a href="{% url 'core_edit_profile' %}">{% trans 'Profile' %}</a>
</li>
<li>
<a href="{% url 'core_logout' %}">{% trans 'Logout' %}</a>
</li>
{% else %}
<li>
<a href="{% url 'core_login' %}">
{% trans "Log in" %}
</a>
<a href="{% url 'core_login' %}">
{% trans "Log in" %}
</a>
</li>
<li>
<a href="{% url 'core_register' %}">
{% trans "Register" %}
</a>
<a href="{% url 'core_register' %}">
{% trans "Register" %}
</a>
</li>
{% endif %}
</ul>
Expand Down
Loading