Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 Yesterday 23:01:06

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 5,291
Website GitHub

Putting an active class on a menu item if a submenu item is selected?

I’ve got myself tied up in a knot again here and wonder if you clever folks can help me make sense of it.

  • I have a regular main menu populated with a list of sections.
  • Some of those sections have submenus.
  • The submenus are a mix of articles and sections, so a simple article_custom list based off the section doesn’t work here.

What I’ve done instead is:

  • create a link category that matches the section name.
  • If the current section matches one of the link category names, output the submenu items as a linklist.
  • I’ve also managed to output an aria-current="page" show on a submenu item.

All of that already works well.

What I’m trying to do is attach an active class to the button that triggers the submenu. This is the pattern I have, which corresponds to the new-ish popover pattern where a button triggers a popover menu:

<button class="menu-item" popovertarget="submenu-<txp:section />">
    <txp:section title />
</button>
<div id="submenu-<txp:section />" class="submenu-popover" popover>
    <txp:linklist category='<txp:section />' wraptag="ul" break="li" class="submenu" role="list">
        <a href="<txp:link_url />"<txp:evaluate query='"<txp:link_url />" = "/<txp:variable name="this_section" />/"'> aria-current="page"</txp:evaluate>>
            <txp:link_name wraptag="span" />
        </a>
    </txp:linklist>
</div>

I had originally hoped to use css and :has, but that the button is not a container but an adjacent sibling. I’d need to do:

.menu-item:has(+ .submenu-popover:has([aria-current="page"]))

but you are not allowed to nest a :has(…) in a :has(…).(doing just the has current-page or just the has an adjacent sibling both work, but not in combination).

My second attempt was to create a variable if the current page is found, then to put that variable – leveraging the process order trick – in the button class above it. But, as in my earlier attempts at using the processing order, I’ve not mastered the switch in levels. I’ve tried <txp:variable[1] … > outside and inside the linklist without any luck.

This is what I have (just showing the principle not the complete code), but it doesn’t work:

<!-- this doesn't work -->
<button class="menu-item<txp:variable name="has-active" />"…>…</button>

<txp:linklist ...>
    <txp:evaluate test="evaluate">
        <txp:variable name="has-active"> active</txp:variable>
        <txp:evaluate query='"<txp:link_url />" = "/<txp:variable name="this_section" />/"'> aria-current="page"</txp:evaluate>
    </txp:evaluate>
</txp:linklist>
<!-- this works: <txp:variable name="has-active" /> -->

Any ideas, or maybe alternative approaches?


TXP Builders – finely-crafted code, design and txp

Offline

#2 Today 01:26:28

phiw13
Plugin Author
From: South-Western Japan
Registered: 2004-02-27
Posts: 3,680
Website

Re: Putting an active class on a menu item if a submenu item is selected?

Not sure if I follow your code correctly, at present your has-active variable is created after and at level below the place where you call the value.

Can’t you leverage the <txp:variable name="this_section" /> to set the ‘active’ value on the button?


Where is that emoji for a solar powered submarine when you need it ?
Sand space – admin theme for Textpattern
phiw13 on Codeberg

Offline

#3 Today 10:31:35

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 5,291
Website GitHub

Re: Putting an active class on a menu item if a submenu item is selected?

Thanks. You’re right, the section only variant is easier, but it gets more complex when individual articles are in the list too.

I’ve worked around it in the end by doing my “is the current page in this submenu” check beforehand and storing it in a variable. There’s a bit of code repetition and an extra query as a result, so not the most elegant solution. The following is an excerpt of the form that builds the menu:

<txp:variable name="this_section"><txp:section /></txp:variable>
<txp:section_list sections="menu,sections,list" … >

<txp:variable name="submenu_state" value="" />
<txp:linklist variable="submenu_item_urls" category='<txp:section />' break=","><txp:link_url /></txp:linklist>
<txp:variable name="current_page_url">/<txp:variable name="this_section" />/<txp:if_individual_article><txp:article_url_title /></txp:if_individual_article></txp:variable>
<txp:if_variable name="submenu_item_urls" value='<txp:variable name="current_page_url" />' match="any"><txp:variable name="submenu_state">active</txp:variable></txp:if_variable>

…

<li<txp:if_variable name="submenu_state" value="active"> class="active"</txp:if_variable>>
    <!-- menu link or button + submenu -->
</li>

</txp:section_list>

Essentially, this makes a comma-separated list of the link_urls in this submenu, stores the current page’s url and compares whether it matches one of the list entries. If it does, mark the submenu as active.


TXP Builders – finely-crafted code, design and txp

Offline

Board footer

Powered by FluxBB