-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create dropdown menu component #16631
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some further cleanup required:
menu/definition
directory - please put all things into one file, they are all mostly used only by the factory util, with I thing just one exception. Remove "definition" factory and move the singular file intomenu/
directory.- Change the factory class name and file name to something like
DropdownMenuFactory
-- it does not create a definition, it creates a menu. - Drop everything related to "tree" utils, the whole directory. From what I checked, everything that is in there comes down to
.menus
getter. AFAICS, these utils are not used anywhere else (there istree
property too but it isn't used anywhere outside.menus
, and there is.walk()
which isn't used anywhere).- To build
.menus
I am pretty sure we can do it with a simple tree-search algorithm that useswhile
and anarray
to store results. We won't need to use several utils, types and files. preloadAllMenus()
seems not to be used anywhere besides tests (at least that what my IDE tells me).- Same with
getCurrentlyVisibleMenusElements()
.
- To build
I wrote that maybe some of the utils may stay. I meant just menus
, but I thought that menus
include both menu views and button views. tree
is not necessary. But we may need something like items
(or buttons
) -- all leaf items in the structure, flattened. So that we can operate on them when the editor state (e.g. selection) changes.
For items
entries, we may need a "path" to them, i.e. an array of menus in which an item is. But I think that will be needed for the search only, and I purposely don't mention any search related things when discussing what should be dropped from this PR. As I mentioned multiple times, this PR should be only about the nested menus functionality.
packages/ckeditor5-ui/src/dropdown/menu/utils/dropdownmenubehaviors.ts
Outdated
Show resolved
Hide resolved
packages/ckeditor5-ui/src/dropdown/menu/utils/dropdownmenubehaviors.ts
Outdated
Show resolved
Hide resolved
packages/ckeditor5-ui/src/dropdown/menu/utils/dropdownmenubehaviors.ts
Outdated
Show resolved
Hide resolved
👍🏻 done
👍🏻 done
At this moment, it's kinda crucial to get all DOM elements that belong to the menu. Without such helper, it's impossible to render dropdown menu inside dropdown. Check this place for additional PR that implements AI support: https://github.com/cksource/ckeditor5-commercial/pull/6213/files#diff-c3e2cfc5f2b64e23fc4bb25cdb3e76e1615a85a1fd0fac616a71d2271cb1456cR165
As we discussed, it's used in search implementation right here. 👍🏻 I moved this code to search PR.
While I agree that this solution is good enough in terms of making the tree flat, or simply iteration over such tree, it makes it difficult to perform search using such approach. We need to know when we enter to the node, when we leave, to construct a proper search tree. Please check this file. I used API that is quite similar to
It's used especially in testing, and AI integration to enable or disable menu entries of specific type. It's used here.
❌ It is necessary, and it's not only my opinion. It was originally added in the menu bar (here) for testing purposes. It allows us to compare tree structures created by definition quickly. At the same time, I agree that there are a lot of other, simpler approaches, to do that but I believe that it's the only one that is the most elegant one because filtering, flattening, and other tree-things can be done using the most common algorithms that are basically copy & paste from other implementations. |
Feature (ui): Create dropdown menu component.
Part of #16311.
Other PRs
Focus change PR: #16642
Search integration PR: #16314
AI Integration PR: https://github.com/cksource/ckeditor5-commercial/pull/6213
Screens
Example usage
Changes performed on menubar implementation
menus
property dynamically instead of storing it as array class member. It is possible to register already createdDropdownMenuView
instance that was created outside of menu. Such instance might have items added or deleted depending on external integration logic (for example, adding button menu entry).Example:
tree
getter that allows to traverse through whole menu that allows for lookup for specific menu entries in tests, filtering menu or creating another instance of dropdown menu with mapped definition. The one nice side effect of such approach is the ability to createdump()
functionality, which allows to easily serialize whole menu to simple pseudo-HTML form, which is super easy to test in other integrations.groups
menu attributes has been removed. Now it is possible to passListSeparatorView
manually.ck-body-wrapper
.Drawbacks
It is fixed by adding optional lazy initialization of menus.tree
/menus
getter calls might be expensive for huge menus (> 500 entries). It's not real case and at this moment there are no actions required to be performed in this scope.Scrolling in large sub-menus is missing.Useful links and discussions