ux improvements: contrast, readability, accessibility, keyboard nav
This commit is contained in:
parent
cd3be4eba7
commit
13b5e6d1a9
6 changed files with 96 additions and 16 deletions
41
css/base.css
41
css/base.css
|
|
@ -3,7 +3,7 @@
|
|||
--surface-container-highest: #eae2d2;
|
||||
--surface: #fff8f0;
|
||||
--backdrop-blur: 24px;
|
||||
--primary: #8c4d50;
|
||||
--primary: #753a3d;
|
||||
--primary-container: #fcacaf;
|
||||
--on-background: #363227;
|
||||
--nav-height: 4rem;
|
||||
|
|
@ -33,8 +33,8 @@
|
|||
|
||||
body {
|
||||
background-color: var(--surface);
|
||||
font-family: "Plus Jakarta Sans", sans-serif;
|
||||
box-sizing: border-box;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h1,
|
||||
|
|
@ -91,7 +91,7 @@ h5 {
|
|||
|
||||
p {
|
||||
color: var(--on-background);
|
||||
line-height: 1.5rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
body > nav,
|
||||
|
|
@ -134,6 +134,41 @@ img {
|
|||
color: transparent;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--on-background);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.sr-only:focus {
|
||||
position: fixed;
|
||||
top: 0.5rem;
|
||||
left: 0.5rem;
|
||||
width: auto;
|
||||
height: auto;
|
||||
padding: 0.5rem 1rem;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
white-space: normal;
|
||||
background: var(--surface);
|
||||
color: var(--on-background);
|
||||
z-index: 1000;
|
||||
border-radius: var(--small-radius);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
main {
|
||||
transition: opacity 0.15s ease;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,10 +163,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
& h4 {
|
||||
& h3 {
|
||||
font-family:
|
||||
"Plus Jakarta Sans", sans-serif; /* Modern font for titles */
|
||||
"Plus Jakarta Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 0.95rem;
|
||||
margin-bottom: 0.5rem;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ templ Album(images []string, activePage string, pages []string) {
|
|||
<section>
|
||||
<div id="album-grid">
|
||||
for _, img := range images {
|
||||
<div>
|
||||
@AvifImage("album/"+img, "album", true)
|
||||
<div tabindex="0" role="button" aria-label={ img }>
|
||||
@AvifImage("album/"+img, img, true)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ templ layout(activePage string) {
|
|||
<script defer src="/album.js"></script>
|
||||
</head>
|
||||
<body hx-boost="true" hx-ext="preload" preload="mouseover">
|
||||
<nav>
|
||||
<a href="#main-content" class="sr-only">Przejdź do treści</a>
|
||||
<nav aria-label="Główna nawigacja">
|
||||
<div>
|
||||
<a href="/">
|
||||
<img src="/images/logo.svg" alt="logo"/>
|
||||
|
|
@ -32,11 +33,13 @@ templ layout(activePage string) {
|
|||
<a class="btn" href="#footer">Kontakt</a>
|
||||
</div>
|
||||
</nav>
|
||||
{ children... }
|
||||
<div id="main-content" tabindex="-1">
|
||||
{ children... }
|
||||
</div>
|
||||
<footer id="footer">
|
||||
<div>
|
||||
<div>
|
||||
<img src="/images/logo.svg" alt="logo" style="width: 14rem"/>
|
||||
<img src="/images/logo.svg" alt="" style="width: 14rem"/>
|
||||
<p>Pasja, natura i domowy smak w każdym kawałku ciasta.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -186,6 +189,9 @@ templ Link(activePage, targetPage, title string) {
|
|||
href={ fmt.Sprint("/", targetPage, "/") }
|
||||
}
|
||||
}
|
||||
if activePage == targetPage {
|
||||
aria-current="page"
|
||||
}
|
||||
>{ title }</a>
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +204,9 @@ templ GreenLink(activePage, targetPage, title string) {
|
|||
href={ fmt.Sprint("/", targetPage, "/") }
|
||||
}
|
||||
}
|
||||
if activePage == targetPage {
|
||||
aria-current="page"
|
||||
}
|
||||
class="btn-green"
|
||||
>{ title }</a>
|
||||
}
|
||||
|
|
@ -206,7 +215,7 @@ templ subnavHeader(title, description string) {
|
|||
<header class="subnav">
|
||||
<h1>{ title }</h1>
|
||||
<p>{ description }</p>
|
||||
<nav>
|
||||
<nav aria-label="Kategorie">
|
||||
{ children... }
|
||||
</nav>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -176,29 +176,29 @@ templ WyrobyTorty() {
|
|||
</header>
|
||||
<div>
|
||||
<div>
|
||||
<h4>Karmel-jogurt-migdały</h4>
|
||||
<h3>Karmel-jogurt-migdały</h3>
|
||||
<p>mus z karmelizowanej białej czekolady, chrupiąca warstwa migdałowa, ganache jogurtowy</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Mango-marakuja-truskawka</h4>
|
||||
<h3>Mango-marakuja-truskawka</h3>
|
||||
<p>
|
||||
spód migdałowy, galaretka mango-marakuja, żelka truskawkowa, krem diplomat
|
||||
kokosowo-waniliowy
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Czekolada-malina-jeżyna</h4>
|
||||
<h3>Czekolada-malina-jeżyna</h3>
|
||||
<p>
|
||||
biszkopt jogurtowy, chrupiąca warstwa czekoladowa, żelka jeżynowa, krem malinowy, mus
|
||||
czekoladowy
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Whisky-mango</h4>
|
||||
<h3>Whisky-mango</h3>
|
||||
<p>brownie, krem mango, ganache czekoladowe , mus whisky</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Kawa-orzech ziemny</h4>
|
||||
<h3>Kawa-orzech ziemny</h3>
|
||||
<p>biszkopt, karmelizowane orzeszki ziemne, namelaka z masłem orzechowym, kawowy mus</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
35
js/album.js
35
js/album.js
|
|
@ -9,8 +9,12 @@
|
|||
var items = Array.from(grid.children)
|
||||
if (!items.length) return
|
||||
|
||||
var lastFocus = null
|
||||
|
||||
var lb = document.createElement('div')
|
||||
lb.id = 'lightbox'
|
||||
lb.setAttribute('role', 'dialog')
|
||||
lb.setAttribute('aria-modal', 'true')
|
||||
lb.innerHTML =
|
||||
'<button id="lb-close" aria-label="Zamknij"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>' +
|
||||
'<button id="lb-prev" aria-label="Poprzednie"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg></button>' +
|
||||
|
|
@ -22,6 +26,7 @@
|
|||
var current = -1
|
||||
|
||||
function open(idx) {
|
||||
lastFocus = document.activeElement
|
||||
current = idx
|
||||
var img = items[current].querySelector('img')
|
||||
lbImg.removeAttribute('src')
|
||||
|
|
@ -29,11 +34,13 @@
|
|||
lb.classList.add('open')
|
||||
lbImg.src = img.src
|
||||
lbImg.alt = img.alt
|
||||
lb.querySelector('#lb-close').focus()
|
||||
}
|
||||
|
||||
function close() {
|
||||
lb.classList.remove('open')
|
||||
current = -1
|
||||
if (lastFocus) lastFocus.focus()
|
||||
}
|
||||
|
||||
function prev() {
|
||||
|
|
@ -46,8 +53,35 @@
|
|||
open((current + 1) % items.length)
|
||||
}
|
||||
|
||||
function trapFocus(e) {
|
||||
if (!lb.classList.contains('open')) return
|
||||
var focusable = lb.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
|
||||
if (!focusable.length) return
|
||||
var first = focusable[0]
|
||||
var last = focusable[focusable.length - 1]
|
||||
if (e.key === 'Tab') {
|
||||
if (e.shiftKey) {
|
||||
if (document.activeElement === first) {
|
||||
e.preventDefault()
|
||||
last.focus()
|
||||
}
|
||||
} else {
|
||||
if (document.activeElement === last) {
|
||||
e.preventDefault()
|
||||
first.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items.forEach(function (item, i) {
|
||||
item.addEventListener('click', function () { open(i) })
|
||||
item.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault()
|
||||
open(i)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
lb.querySelector('#lb-close').addEventListener('click', close)
|
||||
|
|
@ -61,6 +95,7 @@
|
|||
})
|
||||
|
||||
document.addEventListener('keydown', function (e) {
|
||||
trapFocus(e)
|
||||
if (!lb.classList.contains('open')) return
|
||||
if (e.key === 'Escape') { close(); e.preventDefault() }
|
||||
if (e.key === 'ArrowLeft') { prev(); e.preventDefault() }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue