fix some accessibility issues in preferences form

* link label with input using explicit labels
* use separate fieldset for form section
This commit is contained in:
Gaël Berthaud-Müller 2023-08-30 20:08:01 +02:00
parent d62db384fe
commit 74daa21fdd
5 changed files with 49 additions and 53 deletions

View File

@ -83,7 +83,6 @@ a {
fieldset { fieldset {
border: 0; border: 0;
padding: 0; padding: 0;
margin-top: -0.6em;
} }
legend { legend {
@ -96,6 +95,10 @@ legend {
margin-bottom: 8px; margin-bottom: 8px;
} }
.preferences > form:first-of-type {
margin-top: -.6em;
}
.preferences .note { .preferences .note {
border-top: 1px solid var(--border_grey); border-top: 1px solid var(--border_grey);
border-bottom: 1px solid var(--border_grey); border-bottom: 1px solid var(--border_grey);

View File

@ -88,22 +88,6 @@ input::-webkit-datetime-edit-year-field:focus {
} }
} }
.checkbox {
position: absolute;
top: 1px;
right: 0;
height: 17px;
width: 17px;
background-color: var(--bg_elements);
border: 1px solid var(--accent_border);
&:after {
content: "";
position: absolute;
display: none;
}
}
.checkbox-container { .checkbox-container {
display: block; display: block;
position: relative; position: relative;
@ -114,31 +98,38 @@ input::-webkit-datetime-edit-year-field:focus {
input { input {
position: absolute; position: absolute;
opacity: 0; right: 0;
cursor: pointer; height: 19px;
height: 0; width: 19px;
width: 0; background-color: var(--bg_elements);
border: 1px solid var(--accent_border);
appearance: none;
box-sizing: border-box;
cursor: inherit;
&:checked ~ .checkbox:after { &:after {
left: 2px;
bottom: 0;
font-size: 13px;
font-family: $font_4;
content: '\e803';
position: absolute;
display: none;
bottom: 2px;
}
&:checked:after {
display: block; display: block;
} }
} }
&:hover input ~ .checkbox { &:hover input {
border-color: var(--accent); border-color: var(--accent);
} }
&:active input ~ .checkbox { &:active input {
border-color: var(--accent_light); border-color: var(--accent_light);
} }
.checkbox:after {
left: 2px;
bottom: 0;
font-size: 13px;
font-family: $font_4;
content: '\e803';
}
} }
.pref-group { .pref-group {

View File

@ -64,13 +64,14 @@
margin-left: 23px; margin-left: 23px;
} }
.checkbox { input[type=checkbox] {
right: unset; right: unset;
left: -22px; left: -22px;
top: 1px;
} }
.checkbox-container .checkbox:after { .checkbox-container input[type=checkbox]:after {
top: -4px; top: 1px;
} }
} }

View File

@ -10,7 +10,8 @@ macro renderPrefs*(): untyped =
ident("buildHtml"), ident("tdiv"), nnkStmtList.newTree()) ident("buildHtml"), ident("tdiv"), nnkStmtList.newTree())
for header, options in prefList: for header, options in prefList:
result[2].add nnkCall.newTree( var prefGroup = nnkCall.newTree(ident("fieldset"), nnkStmtList.newTree())
prefGroup[1].add nnkCall.newTree(
ident("legend"), ident("legend"),
nnkStmtList.newTree( nnkStmtList.newTree(
nnkCommand.newTree(ident("text"), newLit(header)))) nnkCommand.newTree(ident("text"), newLit(header))))
@ -30,20 +31,21 @@ macro renderPrefs*(): untyped =
else: else:
stmt[0].add newLit(pref.options) stmt[0].add newLit(pref.options)
result[2].add stmt prefGroup[1].add stmt
result[2].add prefGroup
proc renderPreferences*(prefs: Prefs; path: string; themes: seq[string]): VNode = proc renderPreferences*(prefs: Prefs; path: string; themes: seq[string]): VNode =
buildHtml(tdiv(class="overlay-panel")): buildHtml(tdiv(class="overlay-panel preferences")):
fieldset(class="preferences"): form(`method`="post", action="/saveprefs", autocomplete="off"):
form(`method`="post", action="/saveprefs", autocomplete="off"): refererField path
refererField path
renderPrefs() renderPrefs()
h4(class="note"): h4(class="note"):
text "Preferences are stored client-side using cookies without any personal information." text "Preferences are stored client-side using cookies without any personal information."
button(`type`="submit", class="pref-submit"): button(`type`="submit", class="pref-submit"):
text "Save preferences" text "Save preferences"
buttonReferer "/resetprefs", "Reset preferences", path, class="pref-reset" buttonReferer "/resetprefs", "Reset preferences", path, class="pref-reset"

View File

@ -57,22 +57,21 @@ proc buttonReferer*(action, text, path: string; class=""; `method`="post"): VNod
text text text text
proc genCheckbox*(pref, label: string; state: bool): VNode = proc genCheckbox*(pref, label: string; state: bool): VNode =
buildHtml(label(class="pref-group checkbox-container")): buildHtml(tdiv(class="pref-group checkbox-container")):
text label label(`for`=pref): text label
input(name=pref, `type`="checkbox", checked=state) input(id=pref, name=pref, `type`="checkbox", checked=state)
span(class="checkbox")
proc genInput*(pref, label, state, placeholder: string; class=""; autofocus=true): VNode = proc genInput*(pref, label, state, placeholder: string; class=""; autofocus=true): VNode =
let p = placeholder let p = placeholder
buildHtml(tdiv(class=("pref-group pref-input " & class))): buildHtml(tdiv(class=("pref-group pref-input " & class))):
if label.len > 0: if label.len > 0:
label(`for`=pref): text label label(`for`=pref): text label
input(name=pref, `type`="text", placeholder=p, value=state, autofocus=(autofocus and state.len == 0)) input(id=pref, name=pref, `type`="text", placeholder=p, value=state, autofocus=(autofocus and state.len == 0))
proc genSelect*(pref, label, state: string; options: seq[string]): VNode = proc genSelect*(pref, label, state: string; options: seq[string]): VNode =
buildHtml(tdiv(class="pref-group pref-input")): buildHtml(tdiv(class="pref-group pref-input")):
label(`for`=pref): text label label(`for`=pref): text label
select(name=pref): select(id=pref, name=pref):
for opt in options: for opt in options:
option(value=opt, selected=(opt == state)): option(value=opt, selected=(opt == state)):
text opt text opt