Simplify code to have an off-canvas menu

While Foundations's off-canvas menu allows us to forget about writing
CSS, it also leads to complicated HTML.

Ideally Foundation would provide an easy way to simplify what we're
doing, but I haven't found anything in the documentation.

We could simplify the HTML a bit more if we used a CSS grid layout
instead of a flex one, but old browsers have better support for the
latter.

Note we're using `breakpoint(medium)` so we can group the CSS for small
screens and follow SCSS-Lint rules at the same time.

Also note behavior of the main area when the menu appears on small
screens is slightly different: it doesn't move the main content to the
right. I've done it this way so we don't have any overflow issues,
unlike the previous version.

There's a small issue using a label and a checkbox to enable/disable the
menu: sighted keyboard users with a small screen might not be able to
enable the menu. So we're adding the `:focus-within` pseudoclass so the
menu can be normally navigated using the keyboard. Even if old browsers
don't support this pseudoclass, we believe the probability of a sighted
user using a small screen, navigating with the keyboard and using an old
browser is really low, particularly in the admin area.

We're also adding the `aria-hidden` attribute on the label, since the
menu is never hidden for screen readers and so having a control to show
it could be confusing. Since the label is not focusable, we're complying
with the fourth ARIA rule:

> Do not use role="presentation" or aria-hidden="true" on a focusable
> element .
>
> Using either of these on a focusable element will result in some users
> focusing on 'nothing'.
This commit is contained in:
Javi Martín
2020-04-30 16:51:24 +02:00
parent 2363aa4c76
commit 125106f9c0
8 changed files with 453 additions and 452 deletions

View File

@@ -31,7 +31,6 @@
@include foundation-responsive-embed; @include foundation-responsive-embed;
@include foundation-label; @include foundation-label;
@include foundation-media-object; @include foundation-media-object;
@include foundation-off-canvas;
@include foundation-orbit; @include foundation-orbit;
@include foundation-pagination; @include foundation-pagination;
@include foundation-progress-bar; @include foundation-progress-bar;

View File

@@ -436,10 +436,6 @@ a {
display: table-cell; display: table-cell;
} }
.off-canvas-content {
box-shadow: none;
}
.uppercase { .uppercase {
text-transform: uppercase; text-transform: uppercase;
} }
@@ -450,22 +446,63 @@ a {
} }
.menu-and-content { .menu-and-content {
$side-menu-min-width: 250px;
@include breakpoint(medium) {
display: flex; display: flex;
> :first-child { > nav {
flex: 25%; flex: 25%;
min-width: 250px; min-width: $side-menu-min-width;
> :first-child { + * {
height: 100%;
}
}
> :last-child {
flex: 75%; flex: 75%;
overflow-x: auto;
padding: $line-height !important; padding: $line-height !important;
} }
}
[for="show_menu"] {
display: none;
}
}
@include breakpoint(small only) {
> nav {
height: 100%;
left: -$side-menu-min-width;
overflow-y: auto;
position: fixed;
top: 0;
transition: left 0.5s ease;
width: $side-menu-min-width;
z-index: 12;
+ * {
padding: $line-height !important;
}
}
[name="show_menu"]:checked + nav,
> nav:focus-within {
left: 0;
+ * {
overflow-x: hidden;
[for="show_menu"]::after {
@include reveal-overlay;
content: "";
cursor: pointer;
display: block;
z-index: 11;
}
}
}
}
[name="show_menu"] {
display: none;
}
} }
// 02. Header // 02. Header

View File

@@ -1,5 +1,4 @@
<div class="admin-sidebar"> <ul id="admin_menu" data-accordion-menu data-multi-open="true">
<ul id="admin_menu" data-accordion-menu data-multi-open="true">
<% if feature?(:proposals) %> <% if feature?(:proposals) %>
<li class="section-title"> <li class="section-title">
<%= link_to admin_proposals_path do %> <%= link_to admin_proposals_path do %>
@@ -277,5 +276,4 @@
</li> </li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div>

View File

@@ -7,35 +7,23 @@
</head> </head>
<body class="admin"> <body class="admin">
<div class="off-canvas-wrapper">
<div class="off-canvas-wrapper-inner" data-off-canvas-wrapper>
<div class="off-canvas position-left" id="offCanvas" data-off-canvas>
<div class="show-for-small-only">
<%= side_menu %>
</div>
</div>
<div class="off-canvas-content" data-off-canvas-content>
<%= render "layouts/admin_header" %> <%= render "layouts/admin_header" %>
<div class="menu-and-content no-margin-top"> <div class="menu-and-content no-margin-top">
<div id="side_menu" class="hide-for-small-only"> <%= check_box_tag :show_menu, nil, false, role: "switch" %>
<nav id="side_menu" class="admin-sidebar">
<%= side_menu %> <%= side_menu %>
</div> </nav>
<div class="admin-content"> <div class="admin-content">
<div class="show-for-small-only"> <%= label_tag :show_menu, t("admin.menu.admin"),
<button type="button" class="button hollow expanded" data-toggle="offCanvas"><%= t("admin.menu.admin") %></button> "aria-hidden": true, class: "button hollow expanded" %>
</div>
<%= render "layouts/flash" %> <%= render "layouts/flash" %>
<%= render "layouts/officing_booth" if controller.class.parent == Officing && session[:booth_id].present? %> <%= render "layouts/officing_booth" if controller.class.parent == Officing && session[:booth_id].present? %>
<%= yield %> <%= yield %>
</div> </div>
</div> </div>
</div>
</div>
</div>
</body> </body>
</html> </html>

View File

@@ -25,32 +25,18 @@
<h1 class="show-for-sr"><%= setting["org_name"] %></h1> <h1 class="show-for-sr"><%= setting["org_name"] %></h1>
<div class="off-canvas-wrapper">
<div class="off-canvas-wrapper-inner" data-off-canvas-wrapper>
<div class="off-canvas position-left" id="offCanvas" data-off-canvas>
<div class="show-for-small-only">
<div class="dashboard-sidebar">
<%= render "dashboard/menu" %>
</div>
</div>
</div>
<div class="off-canvas-content" data-off-canvas-content>
<%= render "layouts/header", with_subnavigation: false %> <%= render "layouts/header", with_subnavigation: false %>
<div class="menu-and-content no-margin-top"> <div class="menu-and-content no-margin-top">
<div id="side_menu" class="hide-for-small-only"> <%= check_box_tag :show_menu, nil, false, role: "switch" %>
<div class="dashboard-sidebar">
<nav id="side_menu" class="dashboard-sidebar">
<%= render "dashboard/menu" %> <%= render "dashboard/menu" %>
</div> </nav>
</div>
<div class="admin-content"> <div class="admin-content">
<div class="show-for-small-only"> <%= label_tag :show_menu, t("admin.menu.admin"),
<button type="button" class="button hollow expanded" data-toggle="offCanvas"> "aria-hidden": true, class: "button hollow expanded" %>
<%= t("admin.menu.admin") %>
</button>
</div>
<%= render "layouts/flash" %> <%= render "layouts/flash" %>
<%= render "layouts/dashboard/proposal_totals" %> <%= render "layouts/dashboard/proposal_totals" %>
@@ -58,8 +44,5 @@
<%= yield %> <%= yield %>
</div> </div>
</div> </div>
</div>
</div>
</div>
</body> </body>
</html> </html>

View File

@@ -46,7 +46,7 @@
</header> </header>
<main class="no-margin-top row expanded collapse"> <main class="no-margin-top row expanded collapse">
<div class="small-12 medium-3 column"> <div class="small-12 medium-3 column admin-sidebar">
<%= render "/management/menu" %> <%= render "/management/menu" %>
</div> </div>

View File

@@ -1,5 +1,4 @@
<div class="admin-sidebar"> <ul id="admin_menu" data-accordion-menu>
<ul id="admin_menu" data-accordion-menu>
<li class="section-title"> <li class="section-title">
<a href="#"> <a href="#">
<span class="icon-user"></span> <span class="icon-user"></span>
@@ -64,5 +63,4 @@
<%= t("management.menu.user_invites") %> <%= t("management.menu.user_invites") %>
<% end %> <% end %>
</li> </li>
</ul> </ul>
</div>

View File

@@ -1,5 +1,4 @@
<nav class="admin-sidebar"> <ul id="moderation_menu">
<ul id="moderation_menu">
<li> <li>
<%= link_to t("moderation.dashboard.index.title"), moderation_root_path %> <%= link_to t("moderation.dashboard.index.title"), moderation_root_path %>
</li> </li>
@@ -51,5 +50,4 @@
<%= t("moderation.menu.users") %> <%= t("moderation.menu.users") %>
<% end %> <% end %>
</li> </li>
</ul> </ul>
</nav>