Compare commits

..

2 Commits

Author SHA1 Message Date
jordi fita mas e34ef4f458 Remove the “sales” box from the dashboard
There are no sales yet in Numerus, and having that summary there
confuses people.

He left the space there, without any text or background color, to
maintain the position of the rest.

Closes #87.
2023-11-13 14:46:57 +01:00
jordi fita mas 31a655ae7f Add aria-current attribute to links in the top menu
This is mainly to be able to stylize them using CSS; the current style
i set i just a placeholder to check that it works as expected.

Most of these links needs to check for the URI’s prefix, because they
are links to a whole section, but the first link must check for the
exact match, otherwise it would match every other URI, as all of them
start with /company/{uuid}.

The server does not return the markup for the top navigation when usin
HTMx, though, hence i have to change the current class using JavaScript.

I am not sure if the correct value for aria-current is “page” when the
link is not for the actual page the user is currently in, like when is
in the new quote page, but it seems to be the most appropriate value
from the enumeration given in the specifications, except, perhaps, for
the “location” value, but i was unable to find any example of that value
anywhere.

Part of #89.
2023-11-13 14:42:27 +01:00
5 changed files with 33 additions and 14 deletions

View File

@ -10,6 +10,7 @@ import (
"math" "math"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"time" "time"
) )
@ -30,6 +31,12 @@ func mustRenderTemplate(wr io.Writer, r *http.Request, layout string, filename s
"currentLocale": func() string { "currentLocale": func() string {
return locale.Language.String() return locale.Language.String()
}, },
"requestURIMatches": func(uri string) bool {
return r.RequestURI == uri
},
"requestURIHasPrefix": func(uri string) bool {
return strings.HasPrefix(r.RequestURI, uri)
},
"companyURI": func(uri string) string { "companyURI": func(uri string) string {
return companyURI(company, uri) return companyURI(company, uri)
}, },

View File

@ -562,10 +562,12 @@ ul[role="menu"].action-menu li i[class^='ri-'] {
text-decoration: underline; text-decoration: underline;
} }
body > nav a[aria-current] {
background-color: yellow;
}
/* menu tauler final */ /* menu tauler final */
main > nav { main > nav {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -1038,10 +1040,6 @@ div[x-data="snackbar"] div[role="alert"].enter.end, div[x-data="snackbar"] div[r
min-width: 33rem; min-width: 33rem;
} }
#income-statement div:first-child {
background-color: var(--numerus--color--yellow);
}
#income-statement div:nth-child(2) { #income-statement div:nth-child(2) {
background-color: var(--numerus--color--green); background-color: var(--numerus--color--green);
} }

View File

@ -713,7 +713,7 @@ htmx.on('closeModal', () => {
htmx.on(document, 'alpine:init', () => { htmx.on(document, 'alpine:init', () => {
document.body.classList.remove('filters-visible'); document.body.classList.remove('filters-visible');
Alpine.data('snackbar', () => ({ Alpine.data('snackbar', () => ({
show: false, toast: "", toasts: [], timeoutId: null, init() { show: false, toast: "", toasts: [], timeoutId: null, init() {
htmx.on('htmx:error', (error) => { htmx.on('htmx:error', (error) => {
@ -753,3 +753,19 @@ htmx.on(document, 'alpine:init', () => {
}, },
})); }));
}); });
function updateCurrentMenuItem() {
const path = window.location.pathname;
const items = document.querySelectorAll('body > nav a');
items.forEach((item, i) => {
const matches = path === item.pathname;
if (matches || (i !== 0 && path.startsWith(item.pathname))) {
item.setAttribute('aria-current', 'page');
} else {
item.removeAttribute('aria-current');
}
});
}
htmx.on('htmx:pushedIntoHistory', updateCurrentMenuItem);
htmx.on('htmx:replacedInHistory', updateCurrentMenuItem);

View File

@ -50,12 +50,12 @@
</header> </header>
<nav aria-label="{{( pgettext "Main" "title" )}}" data-hx-target="main" data-hx-boost="true"> <nav aria-label="{{( pgettext "Main" "title" )}}" data-hx-target="main" data-hx-boost="true">
<ul> <ul>
<li><a href="{{ companyURI "/" }}">{{( pgettext "Dashboard" "nav" )}}</a></li> <li><a{{if requestURIMatches (companyURI "/") }} aria-current="page"{{ end }} href="{{ companyURI "/" }}">{{( pgettext "Dashboard" "nav" )}}</a></li>
<li><a href="{{ companyURI "/quotes" }}">{{( pgettext "Quotations" "nav" )}}</a></li> <li><a{{if requestURIHasPrefix (companyURI "/quotes") }} aria-current="page"{{ end }} href="{{ companyURI "/quotes" }}">{{( pgettext "Quotations" "nav" )}}</a></li>
<li><a href="{{ companyURI "/invoices" }}">{{( pgettext "Invoices" "nav" )}}</a></li> <li><a{{if requestURIHasPrefix (companyURI "/invoices") }} aria-current="page"{{ end }} href="{{ companyURI "/invoices" }}">{{( pgettext "Invoices" "nav" )}}</a></li>
<li><a href="{{ companyURI "/expenses" }}">{{( pgettext "Expenses" "nav" )}}</a></li> <li><a{{if requestURIHasPrefix (companyURI "/expenses") }} aria-current="page"{{ end }} href="{{ companyURI "/expenses" }}">{{( pgettext "Expenses" "nav" )}}</a></li>
<li><a href="{{ companyURI "/products" }}">{{( pgettext "Products" "nav" )}}</a></li> <li><a{{if requestURIHasPrefix (companyURI "/products") }} aria-current="page"{{ end }} href="{{ companyURI "/products" }}">{{( pgettext "Products" "nav" )}}</a></li>
<li><a href="{{ companyURI "/contacts" }}">{{( pgettext "Contacts" "nav" )}}</a></li> <li><a{{if requestURIHasPrefix (companyURI "/contacts") }} aria-current="page"{{ end }} href="{{ companyURI "/contacts" }}">{{( pgettext "Contacts" "nav" )}}</a></li>
</ul> </ul>
</nav> </nav>
<main> <main>

View File

@ -26,8 +26,6 @@
</div> </div>
<dl id="income-statement"> <dl id="income-statement">
<div> <div>
<dt>{{ (pgettext "Sales" "term") }}</dt>
<dd>{{ formatPriceSpan .Sales }}</dd>
</div> </div>
<div> <div>
<dt>{{ (pgettext "Income" "term") }}</dt> <dt>{{ (pgettext "Income" "term") }}</dt>