Changeset 83b8b8f in Klonkt


Ignore:
Timestamp:
06/20/2026 02:04:32 PM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
999aad2
Parents:
2149f5a
Message:

feat(i18n): styled language dropdown in the header (instead of native select)

Custom dropdown (details/summary, like the user menu): toggle = globe + code +
chevron; menu = full names with code, accent on the active language, clean
shadow/border. Closes on outside click (handler extended). style.css?v=28.

Co-Authored-By: Claude <noreply@…>

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/assets/css/style.css

    r2149f5a r83b8b8f  
    15041504}
    15051505
    1506 /* Taal-keuze in de header-nav (NL/EN/DE). Past bij de pill-knoppen ernaast. */
    1507 .nav-lang {
    1508     background: transparent; color: var(--ink);
    1509     border: 1px solid var(--rule); border-radius: 999px;
    1510     padding: .35rem .5rem; font-size: .8rem; font-weight: 600;
    1511     font-family: inherit; cursor: pointer; line-height: 1;
    1512 }
    1513 .nav-lang:hover { border-color: var(--accent); }
    1514 .nav-lang option { background: var(--paper); color: var(--ink); }
     1506/* Taal-keuze in de header-nav (NL/EN/DE) — eigen gestylede dropdown. */
     1507.lang-menu { position: relative; }
     1508.lang-menu > summary {
     1509    list-style: none; cursor: pointer;
     1510    display: inline-flex; align-items: center; gap: .3rem;
     1511    padding: .35rem .55rem; border-radius: 999px;
     1512    border: 1px solid var(--rule); background: transparent; color: var(--ink);
     1513}
     1514.lang-menu > summary::-webkit-details-marker { display: none; }
     1515.lang-menu > summary:hover { border-color: var(--accent); }
     1516.lang-toggle .lang-code { font-size: .8rem; font-weight: 700; letter-spacing: .02em; }
     1517.lang-toggle .icon { width: 16px; height: 16px; opacity: .8; }
     1518.lang-caret { width: 12px; height: 12px; opacity: .7; transition: transform .15s; }
     1519.lang-menu[open] .lang-caret { transform: rotate(180deg); }
     1520.lang-dropdown {
     1521    position: absolute; top: calc(100% + 8px); right: 0;
     1522    min-width: 170px; z-index: 60;
     1523    background: var(--paper); border: 1px solid var(--rule);
     1524    border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.22);
     1525    padding: .35rem; display: flex; flex-direction: column;
     1526}
     1527.lang-item {
     1528    display: flex; align-items: center; gap: .6rem;
     1529    padding: .5rem .65rem; border-radius: 8px;
     1530    color: var(--ink); text-decoration: none; font-size: .9rem;
     1531}
     1532.lang-item:hover { background: var(--paper-2); }
     1533.lang-item.is-active { color: var(--accent); font-weight: 600; }
     1534.lang-item-code {
     1535    font-size: .7rem; font-weight: 700; opacity: .6;
     1536    min-width: 1.6em;
     1537}
    15151538@media (max-width: 400px) {
    15161539    .masthead { padding: calc(.5rem + var(--safe-top)) 0 .5rem; }
  • src/views/partials/topnav.ejs

    r2149f5a r83b8b8f  
    8282      </button>
    8383
    84       <% if (typeof langs !== 'undefined' && langs && langs.length > 1) { %>
    85         <select class="nav-lang" aria-label="<%= t('nav.language') %>" title="<%= t('nav.language') %>"
    86                 onchange="location.href='/lang/'+this.value+'?r='+encodeURIComponent(location.pathname+location.search)">
    87           <% langs.forEach(function(l){ %><option value="<%= l.code %>"<%= l.active ? ' selected' : '' %>><%= l.code.toUpperCase() %></option><% }); %>
    88         </select>
     84      <% if (typeof langs !== 'undefined' && langs && langs.length > 1) {
     85           var _curLang = (langs.find(function(l){ return l.active; }) || { code: 'nl' }).code;
     86           var _langR = (typeof currentPath !== 'undefined' && currentPath) ? currentPath : '/';
     87      %>
     88        <details class="lang-menu">
     89          <summary class="nav-btn lang-toggle" aria-label="<%= t('nav.language') %>" title="<%= t('nav.language') %>">
     90            <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
     91            <span class="lang-code"><%= _curLang.toUpperCase() %></span>
     92            <svg class="lang-caret" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
     93          </summary>
     94          <div class="lang-dropdown" role="menu">
     95            <% langs.forEach(function(l){ %>
     96              <a class="lang-item<%= l.active ? ' is-active' : '' %>" role="menuitem" href="/lang/<%= l.code %>?r=<%= encodeURIComponent(_langR) %>"><span class="lang-item-code"><%= l.code.toUpperCase() %></span><%= l.name %></a>
     97            <% }); %>
     98          </div>
     99        </details>
    89100      <% } %>
    90101
     
    210221    if (e.target.closest('#search-toggle')) { openSearch(); return; }
    211222    if (e.target.closest('#search-close')) { closeSearch(); return; }
    212     // Gebruikersmenu sluiten bij klik erbuiten.
    213     var open = document.querySelector('.user-menu[open]');
    214     if (open && !open.contains(e.target)) open.removeAttribute('open');
     223    // Open dropdowns (gebruikersmenu + taalkeuze) sluiten bij klik erbuiten.
     224    document.querySelectorAll('.user-menu[open], .lang-menu[open]').forEach(function(d) {
     225      if (!d.contains(e.target)) d.removeAttribute('open');
     226    });
    215227  });
    216228
  • src/views/shell.ejs

    r2149f5a r83b8b8f  
    163163
    164164<!-- v9 stylesheet (full palette system) -->
    165 <link rel="stylesheet" href="/assets/css/style.css?v=27">
     165<link rel="stylesheet" href="/assets/css/style.css?v=28">
    166166
    167167<!-- Audio player styles: loaded on every page so the mini-player works
Note: See TracChangeset for help on using the changeset viewer.