mirror of
https://github.com/go-gitea/gitea.git
synced 2026-03-22 14:34:54 -05:00
Reintegrate the dropdown patch using fomantic hooks and template changes #7640
Closed
opened 2025-11-02 07:32:08 -06:00 by GiteaMirror
·
11 comments
No Branch/Tag Specified
main
release/v1.25
release/v1.24
release/v1.23
release/v1.22
release/v1.21
release/v1.20
release/v1.19
release/v1.18
release/v1.17
release/v1.16
release/v1.15
release/v1.14
release/v1.13
release/v1.12
release/v1.11
release/v1.10
release/v1.9
release/v1.8
v1.25.3
v1.25.2
v1.25.1
v1.25.0
v1.24.7
v1.25.0-rc0
v1.26.0-dev
v1.24.6
v1.24.5
v1.24.4
v1.24.3
v1.24.2
v1.24.1
v1.24.0
v1.23.8
v1.24.0-rc0
v1.25.0-dev
v1.23.7
v1.23.6
v1.23.5
v1.23.4
v1.23.3
v1.23.2
v1.23.1
v1.23.0
v1.23.0-rc0
v1.24.0-dev
v1.22.6
v1.22.5
v1.22.4
v1.22.3
v1.22.2
v1.22.1
v1.22.0
v1.23.0-dev
v1.22.0-rc1
v1.21.11
v1.22.0-rc0
v1.21.10
v1.21.9
v1.21.8
v1.21.7
v1.21.6
v1.21.5
v1.21.4
v1.21.3
v1.21.2
v1.20.6
v1.21.1
v1.21.0
v1.21.0-rc2
v1.21.0-rc1
v1.20.5
v1.22.0-dev
v1.21.0-rc0
v1.20.4
v1.20.3
v1.20.2
v1.20.1
v1.20.0
v1.19.4
v1.21.0-dev
v1.20.0-rc2
v1.20.0-rc1
v1.20.0-rc0
v1.19.3
v1.19.2
v1.19.1
v1.19.0
v1.19.0-rc1
v1.20.0-dev
v1.19.0-rc0
v1.18.5
v1.18.4
v1.18.3
v1.18.2
v1.18.1
v1.18.0
v1.17.4
v1.18.0-rc1
v1.19.0-dev
v1.18.0-rc0
v1.17.3
v1.17.2
v1.17.1
v1.17.0
v1.17.0-rc2
v1.16.9
v1.17.0-rc1
v1.18.0-dev
v1.16.8
v1.16.7
v1.16.6
v1.16.5
v1.16.4
v1.16.3
v1.16.2
v1.16.1
v1.16.0
v1.15.11
v1.17.0-dev
v1.16.0-rc1
v1.15.10
v1.15.9
v1.15.8
v1.15.7
v1.15.6
v1.15.5
v1.15.4
v1.15.3
v1.15.2
v1.15.1
v1.14.7
v1.15.0
v1.15.0-rc3
v1.14.6
v1.15.0-rc2
v1.14.5
v1.16.0-dev
v1.15.0-rc1
v1.14.4
v1.14.3
v1.14.2
v1.14.1
v1.14.0
v1.13.7
v1.14.0-rc2
v1.13.6
v1.13.5
v1.14.0-rc1
v1.15.0-dev
v1.13.4
v1.13.3
v1.13.2
v1.13.1
v1.13.0
v1.12.6
v1.13.0-rc2
v1.14.0-dev
v1.13.0-rc1
v1.12.5
v1.12.4
v1.12.3
v1.12.2
v1.12.1
v1.11.8
v1.12.0
v1.11.7
v1.12.0-rc2
v1.11.6
v1.12.0-rc1
v1.13.0-dev
v1.11.5
v1.11.4
v1.11.3
v1.10.6
v1.12.0-dev
v1.11.2
v1.10.5
v1.11.1
v1.10.4
v1.11.0
v1.11.0-rc2
v1.10.3
v1.11.0-rc1
v1.10.2
v1.10.1
v1.10.0
v1.9.6
v1.9.5
v1.10.0-rc2
v1.11.0-dev
v1.10.0-rc1
v1.9.4
v1.9.3
v1.9.2
v1.9.1
v1.9.0
v1.9.0-rc2
v1.10.0-dev
v1.9.0-rc1
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.8.0-rc3
v1.7.6
v1.8.0-rc2
v1.7.5
v1.8.0-rc1
v1.9.0-dev
v1.7.4
v1.7.3
v1.7.2
v1.7.1
v1.7.0
v1.7.0-rc3
v1.6.4
v1.7.0-rc2
v1.6.3
v1.7.0-rc1
v1.7.0-dev
v1.6.2
v1.6.1
v1.6.0
v1.6.0-rc2
v1.5.3
v1.6.0-rc1
v1.6.0-dev
v1.5.2
v1.5.1
v1.5.0
v1.5.0-rc2
v1.5.0-rc1
v1.5.0-dev
v1.4.3
v1.4.2
v1.4.1
v1.4.0
v1.4.0-rc3
v1.4.0-rc2
v1.3.3
v1.4.0-rc1
v1.3.2
v1.3.1
v1.3.0
v1.3.0-rc2
v1.3.0-rc1
v1.2.3
v1.2.2
v1.2.1
v1.2.0
v1.2.0-rc3
v1.2.0-rc2
v1.1.4
v1.2.0-rc1
v1.1.3
v1.1.2
v1.1.1
v1.1.0
v1.0.2
v1.0.1
v1.0.0
v0.9.99
Labels
Clear labels
$20
$250
$50
$500
backport/done
💎 Bounty
docs-update-needed
good first issue
hacktoberfest
issue/bounty
issue/confirmed
issue/critical
issue/duplicate
issue/needs-feedback
issue/not-a-bug
issue/regression
issue/stale
issue/workaround
lgtm/need 2
modifies/api
modifies/translation
outdated/backport/v1.18
outdated/theme/markdown
outdated/theme/timetracker
performance/bigrepo
performance/cpu
performance/memory
performance/speed
pr/breaking
proposal/accepted
proposal/rejected
pr/wip
pull-request
reviewed/wontfix
💰 Rewarded
skip-changelog
status/blocked
topic/accessibility
topic/api
topic/authentication
topic/build
topic/code-linting
topic/commit-signing
topic/content-rendering
topic/deployment
topic/distribution
topic/federation
topic/gitea-actions
topic/issues
topic/lfs
topic/mobile
topic/moderation
topic/packages
topic/pr
topic/projects
topic/repo
topic/repo-migration
topic/security
topic/theme
topic/ui
topic/ui-interaction
topic/ux
topic/webhooks
topic/wiki
type/bug
type/deprecation
type/docs
type/enhancement
type/feature
type/miscellaneous
type/proposal
type/question
type/refactoring
type/summary
type/testing
type/upstream
Mirrored from GitHub Pull Request
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/gitea#7640
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @zeripath on GitHub (Jul 30, 2021).
Description
The dropdown patch from #8638 is somewhat of a blackbox with little shared understanding as to how it works and why. However, looking again at it I think there are ways that some of its work could be done using hooks already present in fomantic and with template changes.
I would like to use this issue to discuss parts of the patch and the reasoning for these
I hope @Jookia would be able to help explain this patch.
@zeripath commented on GitHub (Jul 30, 2021):
First of all I'm going to provide the original patch in its entirety:
Original Patch
@zeripath commented on GitHub (Jul 30, 2021):
The patch in #16576 differs in that these sections of the patch have been deleted:
These have been removed because with the updated JQuery these prevent the dropdown from ever losing focus.
Now, the second and third of these don't appear to be different from
module.event.item.click.call(...)but I'm not certain. The first however, does have a difference in that the the 3rd argument tomodule.event.item.click.callprevents the dropdown from recapturing focus and it is this third argument that will be missed when you replace it with a jQueryclick.So I guess the question is what was the aim of this?
@zeripath commented on GitHub (Jul 30, 2021):
module.aria.setupThis part of the patch calls
module.aria.setup()at the end of setup of dropdown.Looking
module.aria.setupthis first of all callsguessRolewhich does some heurisitic checking:and if so it will set
aria-busy=true, then add some aria attributes to the dropdown, before unsetting thearia-busy:role="menu"was discouraged except were it definitely represents a menu.idscould be autogenerated using js if they're really necessary.@zeripath commented on GitHub (Jul 30, 2021):
Set items tabindex -1
This sets the tabindex to -1 on all of the items - to match roving tabindex and to make the dropdown feel a lot more a select I guess - but I'm not sure if this is really all that necessary as tabbing works fine without it at present.
Is this really necessary? It could actually be set in onShow though.
@zeripath commented on GitHub (Jul 30, 2021):
setExpanded and refreshDescendant
First of all both of these functions appear to be being called straight after
onShowandonHidewhich are programmable hooks for dropdown and otherwise unused in Gitea so they should/could just be integrated there.Essentially these functions appear to keep track of the
aria-activedescendantand thearia-haspopupattributes on the dropdown.onShowandonHidefunctions?@Jookia commented on GitHub (Jul 30, 2021):
So the best way to look at this patch is to look through my mindset of what I could do to immediately make things a little better without putting load on maintainers to actually fix things, since it didn't seem like maintainers wanted to spend time refactoring HTML or learning ARIA in order to fix things properly. I was also learning ARIA at the time specifically to make this patch, and getting pretty burned out in the process. In the end I was looking at the specific solution of getting some menus working so my blind friend could use Gitea better.
For what it's worth, I had a lot of explanations in git commit messages but these got squashed and removed I think. I was grumpy about this for this exact reason.
Gitea uses dropdowns everywhere. Not just for menus, but also for search boxes, tag selection, branch selection, everywhere. These widgets range from 'listbox' to 'combobox' to other fancy widgets that do multiple things such as manage entries in a list and letting you add new entries by searching in the entry list and adding new tags. Sometimes there's even listboxes that have buttons to open the listbox with an arrow, and those are marked as icons. All of these use Fomantic's 'dropdown' UI.
So the first thing to really do is try and find some actual listboxes (which I incorrectly refer to as menu):
The criteria here is that:
That seems like it's MAYBE a dropdown. The correct solution here would be to go through every dropdown in Gitea's source code and categorize what it is and how to actually handle it, because for each dropdown Fomantic also adds some kind of Javascript, even on the little dropdown icons people are supposed to click.
The next step is to decide what ARIA widget this is and start implementing its role, as a contract between us and any assistive technology. I chose 'menubar' because I wasn't sure what to pick, but in retrospect it should've been 'listbox'. In any case, I did this wrong since I was trying to fit a square in to a round hole.
The next thing to think about is focus management. This is what most dropdowns on the Internet get wrong. When you use a keyboard to access ARIA widgets, you don't want to use tab, you want to just arrows and specific keys mandated by ARIA. This means for example that you can tab past listboxes without tabbing through each element in the listbox. If a person wants to use the dropdown, they'll open it and use the arrows.
It's also important to note that assistive technology have a thing called 'browse mode'- this is where the browser allows assistive technology to capture all key presses on a website. This is so a user can navigate a page using the keyboard arrows to step through each line of text, or jump to headings. This is much faster than tabbing through every element on a page, but it's also something that only really comes in to play for screen readers as far as I can tell. So people unable to use a mouse still have to tab through everything, but people with screen readers can skip it.
Quoting https://www.w3.org/TR/wai-aria-1.2/#application :
The lack of focus of individual elements means the assistive technology can no longer track and read out what items are selected, which is why we need to hint it:
I think widgets should manage their own focus since it provides a less confusing experiences- you can't accidentally focus subelements using tab when you're not supposed to and get in to an invalid and confusing state.
With that in mind, we set the tabindex to -1 so NOTHING inside the dropdown is focusable:
We also should be setting the icon next to the menu to tabindex -1 so we don't have to tab past it:
But that might not have been upstreamed or something.
We set aria-expanded when that changes:
Then whenever anything changes, we update the aria-activedescent attribute to point to the selected item:
This does not work for listboxes that let you select multiple things, only one or no elements.
Calls to these hooks are peppers basically whenever input happens or the dropdown is shown. This is because I didn't wanted to dig in the dropdown spaghetti and wanted to instead make sure it worked each time.
Now, when it's time to select an element, the dropdown code calls
module.event.item.click.call. This doesn't actually call onclick() handlers all the time. Instead you have to directly call click(). I noted this in my now squashed commit message:I had to revert this in one case later:
@zeripath commented on GitHub (Jul 30, 2021):
Remaining
refreshDescendantcallsThis adds a
refreshDescendantcall when you close a submenu using the left arrow key..And adds one when you open a submenu using the right arrow key.
When you move using the up arrow key.
And down with the down arrow key.
Finally this one is when we scroll by letter.
I think we could get away with using onChange and/or onLabelSelect to fire these.
@zeripath commented on GitHub (Jul 30, 2021):
Thanks @Jookia
I can imagine how burning out it felt - there's a reason why I never got round to fixing this myself. The documentation is highly confusing and its not clear how to map things on to Gitea's UI (or most UI TBH.)
I wouldn't assume that anyone doesn't want to learn ARIA - we just have other things to do and if someone appears to know things better most of us are happy to defer.
Your experience of getting burnt out by learning ARIA is precisely my feeling of when I tried looking into it - especially as I could not get orca to work at all.
Honestly - as I said I'd be very happy to copy patterns that work but finding any consistency in the documentation I last found when I looked in to this stuff was impossible.
Ah this is the issue with squash merging. Honestly if you ever feel like giving us another PR - and I hope you can - code comments and comments in issues are a better way of describing things.
Yup - it's a very versatile element. Especially with the searching.
Agreed - this is the correct solution.
Whilst not a solution that can be done for 1.15 - this can and should be done for 1.16 and would definitely receive positive reviews.
This explains my slight confusion with the
aria-role="menu"choice. I also think that in a lot of cases that we have a listbox we may be able to just switch to use<select>which as I understand it even with JS is handled better for screenreaders(?).My impression of fomantic-ui was that this was the one thing that it does right - but it doesn't set the active-descendent - which could be solved using a selection hook.
OK, I guess this really only applies if we have
<a>in the dropdown menu items - as<div>are not tabable by default. This should really be at the template levelI guess also a template level thing - but should probably not apply to searching dropdowns.
Yeah I'm not certain what happened there - may have been conflicted away.
This would require aria-multipleselected, aria-selected and focusing for the elements in the drop down IIRC?
but I don't understand why you want the onclick call exactly?
I think this is the one that I've noticed here .and had to add a fix in against.
@Jookia commented on GitHub (Jul 30, 2021):
I didn't know about multipleselected/aria-selected, etc.
The onClick call is because some Gitea code uses onClick elements and don't account for keyboard focus.
@zeripath commented on GitHub (Jul 31, 2021):
OK I think we should change those to use the select callback.
@Jookia commented on GitHub (Jul 31, 2021):
On Sat, Jul 31, 2021 at 02:15:13AM -0700, zeripath wrote:
Well, yeah. But who's going to spelunk the code to find them all?