scss Twig / SASS / JS中的可访问下拉菜单(Wordpress / Timber-oriented)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scss Twig / SASS / JS中的可访问下拉菜单(Wordpress / Timber-oriented)相关的知识,希望对你有一定的参考价值。
<?php
/* Returns an array with various PHP/Timber data for inserting into JS
*/
function script_data() {
$script_data = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'mainmenu_icon_submenu' => Timber::compile_string("{% include 'partials/image-svg-sprite.twig' with {'id': 'arrow_down_med', 'classes': ['u-svg-arrow_down_med-size', 'c-main-menu__link-submenu-icon'], 'theme_link': theme_link} %}", array('theme_link' => get_template_directory_uri())),
'mainmenu_icon_hamburger' => Timber::compile_string("{% include 'partials/image-svg-sprite.twig' with {'id': 'hamburger', 'classes': ['u-svg-hamburger-size', 'c-header__togglebutton-icon'], 'theme_link': theme_link} %}", array('theme_link' => get_template_directory_uri())),
);
return $script_data;
}
{
"name": "package",
"version": "1.0.0",
"dependencies": {
"focus-trap": "^2.3.0",
}
}
{#
Item classes legend:
__item — all items
__subitem — all items on 2nd and deeper levels
__level-x-item -- all items on specific level
#}
{% if menu %}
{% spaceless %}
{% set listclass = [] %}
{% if is_submenu is defined and is_submenu == true %}
{% set listclass = listclass|merge([ baseclass ~ '__submenu' ]) %}
{% set first_subitem = menu|first %}
{% set listclass = listclass|merge([ baseclass ~ '__menu_level-' ~ (first_subitem.level + 1) ]) %}
{% else %}
{% set listclass = listclass|merge([ baseclass ~ '__list', baseclass ~ '__menu_level-1' ]) %}
{% endif %}
<ul class="{{ listclass | join(' ') }}">
{% for item in menu %}
{# {% set itemclasses = item.classes %} #}
{% set itemclasses = [] %}
{% if is_submenu is defined and is_submenu == true %}
{% set itemclasses = itemclasses|merge([ baseclass ~ '__item', baseclass ~ '__subitem', baseclass ~ '__item_level-' ~ (item.level + 1) ]) %}
{% else %}
{% set itemclasses = itemclasses|merge([ baseclass ~ '__item', baseclass ~ '__item_level-1' ]) %}
{% if item_level_1_classes is defined %}
{% set itemclasses = itemclasses|merge([item_level_1_classes]) %}
{% endif %}
{% endif %}
{% if item.current %}
{% set itemclasses = itemclasses|merge([ baseclass ~ '__item_current' ]) %}
{% endif %}
{% if item.current_item_parent %}
{% set itemclasses = itemclasses|merge([ baseclass ~ '__item_current-parent' ]) %}
{% endif %}
{% if item.get_children %}
{% set itemclasses = itemclasses|merge([ baseclass ~ '__item_has-submenu' ]) %}
{% endif %}
<li class="{{ itemclasses | join(' ') }}">
<a class="{{ baseclass }}__link"{{ item.get_children ? ' aria-haspopup="true"' }} href="{{item.get_link}}">{{item.title}}</a>
{% include 'partials/menu.twig' with {'menu':item.get_children, is_submenu:true } %}
</li>
{% endfor %}
</ul>
{% endspaceless %}
{% endif %}
'use strict';
/**
* Main menu
*/
function init() {
// !Set vars
var overlay_sel = '[data-overlay]';
var focus_trap = require('../../node_modules/focus-trap');
// initiate focus trap for the overlay
var focus_trap_overlay = focus_trap(overlay_sel, {
clickOutsideDeactivates:true,
escapeDeactivates:false
});
var menu_sets = [
{
nav_class:'c-main-menu',
header_class:'c-header',
container_outer_class:'c-header__menu-container-outer',
container_inner_class:'c-header__menu-container-inner'
}
];
$.each(menu_sets, function(i, cl) {
if ($('.' + cl.nav_class).length) {
$('.' + cl.nav_class).each(function() {
var $nav = $(this);
var $header = $('.' + cl.header_class);
var $menus_outer = $('.' + cl.container_outer_class);
var $menus_inner = $('.' + cl.container_inner_class);
// !Append HTML
$menus_outer.append(`
<button class="state-togglebutton-hamburger ${cl.header_class}__togglebutton" aria-haspopup="true" aria-expanded="false">` +
script_data.mainmenu_icon_hamburger +
`</span>
</button>
`);
$nav.find(`.${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu > .${cl.nav_class}__link`).each(function() {
$(this).wrapInner(`<span class="${cl.nav_class}__link-inner"></span>`);
});
// add submenu icon
$nav.find(`.${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu > .${cl.nav_class}__link`).append(script_data.mainmenu_icon_submenu);
var $nav_button = $header.find(`.${cl.header_class}__togglebutton`);
$menus_inner.attr('aria-hidden', 'true');
// the component may be styled now!
$nav.addClass('js-component-ready');
// !Events
// close by clicking elsewhere
$(document).on('click touchstart', function(e) {
if ($menus_outer.is('.is-menu-overlay-open')) {
if (
!$(e.target).closest($menus_inner).length &&
!$(e.target).closest(`.${cl.header_class}__togglebutton`).length
) {
e.preventDefault();
toggle_overlay($nav_button, $menus_outer, $menus_inner, 'close');
}
}
});
// toggle by clicking hamburger button
$menus_outer.on('click', `.${cl.header_class}__togglebutton`, function() {
if ($(this).hasClass('state-togglebutton-hamburger')) {
toggle_overlay($nav_button, $menus_outer, $menus_inner, 'open');
} else if ($(this).hasClass('state-togglebutton-close')) {
toggle_overlay($nav_button, $menus_outer, $menus_inner, 'close');
}
});
// open submenus with click when mobile
$header.on('click', `
.is-menu-overlay-open
.${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu
> .${cl.nav_class}__link
`, function(e) {
if (!$(e.target).closest(`.${cl.nav_class}__link-inner`).length) {
e.preventDefault();
if ($(this).parent().hasClass(`${cl.nav_class}__item_has-submenu-displayed`)) {
$(this).parent().removeClass(`${cl.nav_class}__item_has-submenu-displayed`);
} else {
$nav.find(`.${cl.nav_class}__item_has-submenu-displayed`).removeClass(`${cl.nav_class}__item_has-submenu-displayed`);
$(this).parent().addClass(`${cl.nav_class}__item_has-submenu-displayed`);
}
}
});
// open submenus with hover/focus when desktop
var menu_desktop_sel = `.${cl.container_outer_class}:not(.is-menu-overlay-open)`;
var toggle_class = `${cl.nav_class}__item_has-submenu-displayed`;
var link_with_submenu_sel = `${menu_desktop_sel}
.${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu
> .${cl.nav_class}__link`;
var submenu_sel = `${menu_desktop_sel}
.${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu
> .${cl.nav_class}__submenu`;
var open_items_sel = `${menu_desktop_sel}
.${cl.nav_class}__item_has-submenu-displayed`;
$header.on('mouseenter focusin', link_with_submenu_sel, function(e) {
$header.find(open_items_sel).removeClass(`${toggle_class}`);
$(this).parent().addClass(`${toggle_class}`);
});
$header.on('mouseleave', link_with_submenu_sel, function(e) {
$(this).parent().removeClass(`${toggle_class}`);
});
$header.on('mouseenter', submenu_sel, function(e) {
$(this).parent().addClass(`${toggle_class}`);
});
$header.on('mouseleave', submenu_sel, function(e) {
$(this).parent().removeClass(`${toggle_class}`);
});
$header.on('focusin', submenu_sel, function(e) {
$(this).parent().addClass(`${toggle_class}`);
});
// close overlay with Esc key
$(document).on('keyup', function(e) {
if (
e.which === 27 &&
$menus_outer.hasClass('is-menu-overlay-open')
){
toggle_overlay($nav_button, $menus_outer, $menus_inner, 'close');
}
});
});
}
});
// !Functions
function toggle_overlay($nav_button, $menus_outer, $menus_inner, action) {
switch(action) {
case 'open':
$menus_outer.addClass('is-menu-overlay-open');
$menus_inner.attr('aria-hidden', 'false');
$nav_button
.attr('aria-expanded', 'true')
.addClass('state-togglebutton-close').removeClass('state-togglebutton-hamburger');
focus_trap_overlay.activate();
break;
case 'close':
$menus_outer.removeClass('is-menu-overlay-open');
$menus_inner.attr('aria-hidden', 'true');
$nav_button
.attr('aria-expanded', 'false')
.addClass('state-togglebutton-hamburger').removeClass('state-togglebutton-close');
focus_trap_overlay.deactivate();
break;
}
}
// !Append HTML
// !Events
// !Functions
}
module.exports = {
init: init
};
// @z-index space: 110-120
@mixin c-main-menu($base:&) {
$local-item-spacing-x:28px;
$local-menu-desktop-shift-y:17px;
& {
@include mq($until: mainmenu-horizontalized) {
padding-top:36px;
}
@include mq($from: mainmenu-horizontalized) {
padding-top:15px;
}
@include mq($from: xlarge) {
padding-top:30px;
}
}
@at-root {
#{$base}__item_level-1 {
& > #{$base}__link {
}
#{$base}__submenu {
display:none;
}
}
// never display 3rd, 4th etc menu levels
#{$base}__item_level-2 {
#{$base}__submenu {
display:none;
}
& > #{$base}__link {
}
}
#{$base}__item_has-submenu-displayed {
& > #{$base}__submenu {
display:block;
}
}
#{$base}__link {
display:block;
}
// mobile
@include mq($until: mainmenu-horizontalized) {
#{$base}__link-submenu-icon {
position:absolute;
}
#{$base}__item_level-1#{$base}__item_has-submenu {
& > #{$base}__link {
&:hover {
text-decoration:none;
}
& > #{$base}__link-inner {
&:hover {
text-decoration:underline;
}
}
}
}
#{$base}__item_has-submenu-displayed {
#{$base}__link-submenu-icon {
transform:scaleY(-1);
}
}
#{$base}__menu_level-2 {
}
#{$base}__item_level-2 {
@include u-spacing-y(8px);
& > #{$base}__link {
&:focus {
outline:white 1px dotted;
}
}
}
}
// desktop
@include mq($from: mainmenu-horizontalized) {
#{$base}__item_current,
#{$base}__item_current-parent {
& > #{$base}__link {
color:$color-link;
}
}
#{$base}__link-submenu-icon {
position:absolute;
}
#{$base}__list {
@include u-spacing-x(-$local-item-spacing-x, margin);
}
#{$base}__item_level-1 {
flex:1 1 auto;
& > #{$base}__link {
@include u-spacing-x($local-item-spacing-x);
padding-top:26px;
padding-bottom:28px;
white-space:nowrap;
}
}
#{$base}__menu_level-2 {
text-align:left;
position:absolute;
min-width:200px;
max-width:300px;
z-index:112;
}
#{$base}__item_has-submenu-displayed {
& > #{$base}__link {
box-shadow:$box-shadow;
background-color:white;
z-index:111;
}
}
#{$base}__item_level-2 {
& > #{$base}__link {
border-top:#f2f2f2 1px solid;
@include u-spacing-y(20px);
font-weight:normal;
}
&:first-child > #{$base}__link {
border-top:none;
}
}
}
}
}
// @z-index space: 100-110
.c-header {
$local-spacing-top:10px;
@include t-page-wrapper;
padding-top:$local-spacing-top;
display:flex;
&__logo {
@include mq($until: mainmenu-horizontalized) {
@include u-spacing-x(auto, margin);
}
@include mq($from: mainmenu-horizontalized) {
flex:0 1 auto;
}
@include mq($from: large, $until: xlarge) {
padding-top:14px;
}
&-image {
width:177px;
@include mq($from: medium) {
width:239px;
}
@include mq($from: large) {
width:170px;
}
@include mq($from: xlarge) {
width:250px;
}
display:block;
max-width:100%;
height:auto;
}
}
&__menu {
@include mq($from: mainmenu-horizontalized) {
margin-left:5.4%;
flex:1 1 100%;
}
}
&__menu-container-outer {
@include mq($from: mainmenu-horizontalized) {
flex:1 1 100%;
}
}
&__menu-container-inner {
display:none;
.is-menu-overlay-open & {
display:block;
}
@include mq($until: mainmenu-horizontalized) {
background-color:white;
width:span(7);
text-align:center;
position:fixed;
overflow-y:auto;
-webkit-overflow-scrolling: touch;
height:100%;
right:0;
top:0;
box-shadow:-10px 0 20px 0 rgba(0, 0, 0, 0.2);
z-index:100;
}
@include mq($until: small) {
width:100%;
}
@include mq($from: mainmenu-horizontalized) {
display:block;
}
}
&__togglebutton {
@include u-remove-button-styling;
z-index:101;
fill:$color-sand-brown;
display:none;
@include mq($until: mainmenu-horizontalized) {
display:block;
position:absolute;
right:17px;
&.state-togglebutton-close {
position:fixed;
top:$local-spacing-top;
}
}
}
&__togglebutton-icon {
display:block;
}
}
以上是关于scss Twig / SASS / JS中的可访问下拉菜单(Wordpress / Timber-oriented)的主要内容,如果未能解决你的问题,请参考以下文章
将 json 数据作为 .scss 文件中的 sass 变量导入 Nuxt
Vue 融入flexible.js scss(sass)文件 添加scss文件 sass