Compare commits

...

1 Commits

Author SHA1 Message Date
Step35
5cb71b666c [a11y] V2: Add aria-label to Explore filter/sort radios + search (WCAG 3.3.2) — #546
Some checks failed
Architecture Lint / Linter Tests (pull_request) Successful in 20s
Smoke Test / smoke (pull_request) Failing after 20s
Validate Config / YAML Lint (pull_request) Failing after 15s
Validate Config / JSON Validate (pull_request) Successful in 18s
Validate Config / Python Syntax & Import Check (pull_request) Failing after 57s
Validate Config / Python Test Suite (pull_request) Has been skipped
Validate Config / Shell Script Lint (pull_request) Failing after 59s
Validate Config / Cron Syntax Check (pull_request) Successful in 12s
Validate Config / Deploy Script Dry Run (pull_request) Successful in 15s
Validate Config / Playbook Schema Validation (pull_request) Successful in 31s
Architecture Lint / Lint Repository (pull_request) Failing after 23s
PR Checklist / pr-checklist (pull_request) Successful in 5m17s
Add a11y overrides for Explore/Repositories page form inputs that
lacked programmatic labels:
- Search input: aria-label="Search repositories"
- 11 filter radio buttons (clear, archived, fork, mirror, template, private)
- 12 sort radio buttons (newest, oldest, alphabetically, etc.)

Fixes 25 unlabeled inputs identified in accessibility audit.

Deployment: deploy/gitea-a11y/deploy-gitea-a11y.sh

Closes #546
2026-04-26 17:27:05 -04:00
3 changed files with 67 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ Applied fixes identified by the accessibility audit (#492):
| R2 | #552 | 3.3.1 | `aria-required="true"` on required form fields |
| R3 | #553 | 4.1.2 | `aria-label` on star/fork count links ("2 stars", "0 forks") |
| R4 | #554 | 1.3.1 | `<time datetime="...">` elements for relative timestamps |
| V2 | #546 | 3.3.2 | `aria-label` on search input and filter/sort radio buttons (25 inputs) |
## Structure

View File

@@ -0,0 +1,64 @@
<div class="ui small secondary filter menu">
<form id="repo-search-form" class="ui form ignore-dirty tw-flex-1 tw-flex tw-items-center tw-gap-x-2">
{{if .Language}}<input type="hidden" name="language" value="{{.Language}}">{{end}}
{{if .PageIsExploreRepositories}}<input type="hidden" name="only_show_relevant" value="{{.OnlyShowRelevant}}">{{end}}
{{if .TabName}}<input type="hidden" name="tab" value="{{.TabName}}">{{end}}
{{if .TopicOnly}}<input type="hidden" name="topic" value="{{.TopicOnly}}">{{end}}
<div class="ui small fluid action input tw-flex-1">
{{template "shared/search/input" dict "Value" .Keyword "Placeholder" (ctx.Locale.Tr "search.repo_kind")}}
{{template "shared/search/button"}}
</div>
<!-- Filter -->
<div class="item ui small dropdown jump">
<span class="text">{{ctx.Locale.Tr "filter"}}</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu flex-items-menu">
<label class="item"><input type="radio" name="clear-filter" aria-label="{{ctx.Locale.Tr "filter.clear"}}"> {{ctx.Locale.Tr "filter.clear"}}</label>
<div class="divider"></div>
<label class="item"><input type="radio" name="archived" {{if .IsArchived.Value}}checked{{end}} value="1" aria-label="{{ctx.Locale.Tr "filter.is_archived"}}"> {{ctx.Locale.Tr "filter.is_archived"}}</label>
<label class="item"><input type="radio" name="archived" {{if (not (.IsArchived.ValueOrDefault true))}}checked{{end}} value="0" aria-label="{{ctx.Locale.Tr "filter.not_archived"}}"> {{ctx.Locale.Tr "filter.not_archived"}}</label>
<div class="divider"></div>
<label class="item"><input type="radio" name="fork" {{if .IsFork.Value}}checked{{end}} value="1" aria-label="{{ctx.Locale.Tr "filter.is_fork"}}"> {{ctx.Locale.Tr "filter.is_fork"}}</label>
<label class="item"><input type="radio" name="fork" {{if (not (.IsFork.ValueOrDefault true))}}checked{{end}} value="0" aria-label="{{ctx.Locale.Tr "filter.not_fork"}}"> {{ctx.Locale.Tr "filter.not_fork"}}</label>
<div class="divider"></div>
<label class="item"><input type="radio" name="mirror" {{if .IsMirror.Value}}checked{{end}} value="1" aria-label="{{ctx.Locale.Tr "filter.is_mirror"}}"> {{ctx.Locale.Tr "filter.is_mirror"}}</label>
<label class="item"><input type="radio" name="mirror" {{if (not (.IsMirror.ValueOrDefault true))}}checked{{end}} value="0" aria-label="{{ctx.Locale.Tr "filter.not_mirror"}}"> {{ctx.Locale.Tr "filter.not_mirror"}}</label>
<div class="divider"></div>
<label class="item"><input type="radio" name="template" {{if .IsTemplate.Value}}checked{{end}} value="1" aria-label="{{ctx.Locale.Tr "filter.is_template"}}"> {{ctx.Locale.Tr "filter.is_template"}}</label>
<label class="item"><input type="radio" name="template" {{if (not (.IsTemplate.ValueOrDefault true))}}checked{{end}} value="0" aria-label="{{ctx.Locale.Tr "filter.not_template"}}"> {{ctx.Locale.Tr "filter.not_template"}}</label>
<div class="divider"></div>
<label class="item"><input type="radio" name="private" {{if .IsPrivate.Value}}checked{{end}} value="1" aria-label="{{ctx.Locale.Tr "filter.private"}}"> {{ctx.Locale.Tr "filter.private"}}</label>
<label class="item"><input type="radio" name="private" {{if (not (.IsPrivate.ValueOrDefault true))}}checked{{end}} value="0" aria-label="{{ctx.Locale.Tr "filter.public"}}"> {{ctx.Locale.Tr "filter.public"}}</label>
</div>
</div>
<!-- Sort -->
<div class="item ui small dropdown jump">
<span class="text">{{ctx.Locale.Tr "repo.issues.filter_sort"}}</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<label class="{{if eq .SortType "newest"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "newest"}}checked{{end}} value="newest" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</label>
<label class="{{if eq .SortType "oldest"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "oldest"}}checked{{end}} value="oldest" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</label>
<label class="{{if eq .SortType "alphabetically"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "alphabetically"}}checked{{end}} value="alphabetically" aria-label="{{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</label>
<label class="{{if eq .SortType "reversealphabetically"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "reversealphabetically"}}checked{{end}} value="reversealphabetically" aria-label="{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</label>
<label class="{{if eq .SortType "recentupdate"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "recentupdate"}}checked{{end}} value="recentupdate" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</label>
<label class="{{if eq .SortType "leastupdate"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "leastupdate"}}checked{{end}} value="leastupdate" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</label>
{{if not .DisableStars}}
<label class="{{if eq .SortType "moststars"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "moststars"}}checked{{end}} value="moststars" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.moststars"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.moststars"}}</label>
<label class="{{if eq .SortType "feweststars"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "feweststars"}}checked{{end}} value="feweststars" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.feweststars"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.feweststars"}}</label>
{{end}}
<label class="{{if eq .SortType "mostforks"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "mostforks"}}checked{{end}} value="mostforks" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.mostforks"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.mostforks"}}</label>
<label class="{{if eq .SortType "fewestforks"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "fewestforks"}}checked{{end}} value="fewestforks" aria-label="{{ctx.Locale.Tr "repo.issues.filter_sort.fewestforks"}}"> {{ctx.Locale.Tr "repo.issues.filter_sort.fewestforks"}}</label>
<label class="{{if eq .SortType "size"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "size"}}checked{{end}} value="size" aria-label="{{ctx.Locale.Tr "repo.issues.label.filter_sort.by_size"}}"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.by_size"}}</label>
<label class="{{if eq .SortType "reversesize"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "reversesize"}}checked{{end}} value="reversesize" aria-label="{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_by_size"}}"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_by_size"}}</label>
</div>
</div>
</form>
</div>
{{if and .PageIsExploreRepositories .OnlyShowRelevant}}
<div class="ui message">
<span data-tooltip-content="{{ctx.Locale.Tr "explore.relevant_repositories_tooltip"}}">
{{ctx.Locale.Tr "explore.relevant_repositories" (printf "?only_show_relevant=0&sort=%s&q=%s&language=%s" $.SortType (QueryEscape $.Keyword) (QueryEscape $.Language))}}
</span>
</div>
{{end}}
<div class="divider"></div>

View File

@@ -0,0 +1,2 @@
{{/* a11y V2 fix: add aria-label for search on explore page */}}
<input type="search" name="q"{{with .Value}} value="{{.}}"{{end}} maxlength="255" spellcheck="false" placeholder="{{with .Placeholder}}{{.}}{{else}}{{ctx.Locale.Tr "search.search"}}{{end}}"{{if .Disabled}} disabled{{end}}{{if .PageIsExploreRepositories}} aria-label="{{ctx.Locale.Tr "search.repo_kind"}}"{{end}}>