Closed KingOfTac closed 5 months ago
I don't how I missed #5469 when looking for existing issues tracking this.
Thanks for this! One immediate thought that I have here is that I think the current RFC details two implementations. What I mean by that is that I think this illustrates both the foundation implementation, as well as what I would expect from the CLI. Specifically, I wonder about the "universal" applicability of menu-width
, menu-height
, and menu-offset
. I really like these for the "FAST CLI" starter implementation, where those can be driven by tokens, but I don't think there are necessary for every menu button (foundational). Thoughts on that distinction @KingofTac? Again, I really like those, but they aren't necessary for an implementation where I may have a menu button with a menu that is holistically controlled by CSS as one example.
From a foundation point of view, I agree they aren't needed.
Getting into the implementation specifics, I would say if floating-ui is used by the foundation class, it would be pretty easy for implementations to provide their own version of computePosition
and add the specific middewares and positioning details that they want. So with that in mind the CLI starter could very well add the menu-width
and menu-height
as tokens and override the foundation MenuButton
's computePosition
and pass it the size middleware using those tokens.
From a foundation point of view, I agree they aren't needed.
Getting into the implementation specifics, I would say if floating-ui is used by the foundation class, it would be pretty easy for implementations to provide their own version of
computePosition
and add the specific middewares and positioning details that they want. So with that in mind the CLI starter could very well add themenu-width
andmenu-height
as tokens and override the foundationMenuButton
'scomputePosition
and pass it the size middleware using those tokens.
This was exactly the consideration I had when working to incorporate Floating-UI into a couple of our components as part of #6186. My thought was that while it might make for a robust API, exposing everything would make for a very "cluttered" API by default. Instead, I figured a better way might be to have a public method that could be overridden to provide a more custom and bespoke implementation of computePosition (something like setMenuPosition()
).
A couple of follow-up thoughts/questions here:
Ideally I'd like to be able to use menu, because that's a not-insignificant portion of code that does represent a menu. As noted, it doesn't represent all types of menu, but we can look to pick that work up either as part of menu or by creating a more common navigation "menu" approach (list w/ links) for example...
If we have labelledby in the shadow dom for the menu, but the role of menu is on a slotted element, does that do what we expect accessibility wise? I'm not sure it's going to pick it up as expected.
Do you have an example of the implementation/prototype that was causing issues w/ NVDA (is that in the WIP examples)?
I think using Menu
is perfectly doable. The challenges with it are, like you said it doesn't represent all menus.
This comment made me realize I missed adding the menu role in the anatomy section, so I went and updated that above. I think you're right that labelledby
won't cross the shadow boundary so that's why I intended the menu element to be a part of MenuButton
's anatomy. I can see cases where you would want to slot in a custom menu element, so thoughts/
feedback here would be great.
I'll have to find where I have that prototype since that implementation was from several months ago. I'll link here when I find it.
@chrisdholt Not a fully functioning menu button, but this shows the Behavior I was seeing with NVDA and using Button
https://stackblitz.com/edit/typescript-lh92fh?file=index.ts
When the menu button receives focus, it will announce that it is clickable more than once
@chrisdholt I'm just circling back to this. If you want, I can update the spec to be focused on the foundation implementation with notes on extending and implementing custom versions.
@chrisdholt I'm just circling back to this. If you want, I can update the spec to be focused on the foundation implementation with notes on extending and implementing custom versions.
I think that would be great. Having the spec focus on Foundation and then illustrate extensibility as examples will transition well for the CLI and documentation IMO. I'd love if our documentation broadened to open up examples of extending classes to address common scenarios
Sounds good. I'll get a new version up this weekend.
Hi, I'm interested in building a split button and dropdown button components for FAST. What's the status of this project? Obviously you've got the spec here, but has any work been done to implement this?
I see two other issues asking for similar stuff:
Also, there was a (discarded?) PR to add a split button in the past.
So stepping back a moment, two questions:
Hi, I'm interested in building a split button and dropdown button components for FAST. What's the status of this project? Obviously you've got the spec here, but has any work been done to implement this?
I see two other issues asking for similar stuff:
Also, there was a (discarded?) PR to add a split button in the past.
So stepping back a moment, two questions:
For @KingOfTac what's the status of this menu button? Has code been written yet?
For @chrisdholt, I'm hesitant to contribute here for fear my work would be discarded. Would FAST welcome a MenuButton, SplitButton, and NavBar? Or is this something you guys don't want, or would rather build yourselves?
This spec is still rather new. It needs more work and there are still a few unknowns around whether or not to compose existing components into this one or not. I have been working on a new version of the spec that I hope we'll be able to start implementing.
Another reason why there hasn't been much new component work is that most of the team has been focused on the next major release of FAST which is turning out to be one of the largest with many new features and breaking changes. For this reason I have been hesitant to start implementation until vNext is closer to release in order to reduce refactoring due to breaking changes in fast-element and fast-foundation.
Ah, interesting indeed. Well, I'm beginning to question whether I should wait to contribute then. Thanks for the heads up.
@chrisdholt want to weigh in? Would it be wise to wait to contribute until FAST vNext is released?
Hi, I'm interested in building a split button and dropdown button components for FAST. What's the status of this project? Obviously you've got the spec here, but has any work been done to implement this?
I see two other issues asking for similar stuff:
It appears there was a (discarded?) PR to add a split button in the past.
This all makes me a bit hesitant to contribute here
Well, first - we'd welcome a contribution here. Specific to the split button work, the hope was to bring that into a more well rounded menu button approach, perhaps via a slot (noted here: https://github.com/microsoft/fast/pull/4083#issuecomment-1030250715) because it lends itself better to our goals. The biggest concern with serving both menu button (as represented in this issue) and split button are that our primary method of approach is composition. A year or two ago there was a good amount of discussion around split buttons and their patterns - one big thing that landed was that they are two tab stops. They are both buttons, one being a normal button and one following the menu button pattern (still a button). So when exploring split button, I tend to ask how those things "compose", considering this is two buttons and we value composition, the most intuitive template for a composable split button is either one or two slots and the class itself likely doesn't need any logic because the element just organizes slotted content. Given that context, it was proposed in the spec review that perhaps split button as a construct is better served by being slotted in with a menu button. This would allow slotting the second via the light DOM for full control, etc. We decided we wanted to explore that route rather than deliver something that was a generic wrapper for buttons - Brook was going to pick that back up, but he ended up moving on to a different project and the need for that component fell off (until now). There is more to that backstory, but hopefully that gives at least some insight into why that was closed and nothing materialized from it.
I think the key here is that we'd love a contribution to FAST for any number of things component-wise and we certainly don't need to be the ones to build it ourselves. With that said though, I think any contribution directly to fast-foundation
for instance needs to go through some kind of spec review to ensure that we're aligned in our approach, goals are being met, etc. We'd happily take a navbar, or navigation menu (we don't have that...basically a list w/ anchors), or other things - but I think the expectation for it bubbling into foundation is that it's aligned with our current approach and values - hopefully that makes sense. An example would be - if your concept for a menu is to forgo slots and composition in favor of taking in item data from an array; that's certainly doable but it doesn't align with our current approach of "composition first". We'll gladly take contributions (and we do quite often), but in order for us to provide consistent experience we need to ensure that the approach is consistent with our goals. With that said, if you're up for it, we'd welcome a contribution and we're happy to help work through certain nuances. Additionally, perhaps you have an idea for how we can approach composition while providing a great DX out of the box - we'd love to hear that and see how our approach might evolve.
Ah, interesting indeed. Well, I'm beginning to question whether I should wait to contribute then. Thanks for the heads up.
@chrisdholt want to weigh in? Would it be wise to wait to contribute until FAST vNext is released?
Eh....I say no :). It depends though, I know that could be a bit chaotic.
We're exploring a few things that I think are really exciting right now, but due to gaps I haven't put together an RFC on the direction. Even then, I don't think it would impact the work you'd be contributing in super significant ways...perhaps some light refactoring but I don't see it significantly changing approaches for instance.
@EisenbergEffect may have thoughts here too but in terms of creating new components, I think most of the breaks that would be most painful have already been made on the FAST Element side of things.
In terms of component building, I think you can use the v2 stuff in master with the v1 documentation. There aren't really breaking changes in how components are built and we've made the primary organizational changes in foundation. So, I think you're good to go.
We'd happily take a navbar, or navigation menu (we don't have that...basically a list w/ anchors), or other things - but I think the expectation for it bubbling into foundation is that it's aligned with our current approach and values - hopefully that makes sense. An example would be - if your concept for a menu is to forgo slots and composition in favor of taking in item data from an array; that's certainly doable but it doesn't align with our current approach of "composition first".
Alright, that does make sense.
I'd be doing this contribution as part of Microsoft's Fix / Hack / Learn (FHL) week, meaning I have limited time to do this. Probably not enough time to build a well-rounded spec and component that conforms to W3C specs, but maybe enough to get started.
If anything, I could start a spec and create a proof-of-concept component(s) during FHL week, then get feedback from you all and iterate on that in my spare time.
We'd happily take a navbar, or navigation menu (we don't have that...basically a list w/ anchors), or other things - but I think the expectation for it bubbling into foundation is that it's aligned with our current approach and values - hopefully that makes sense. An example would be - if your concept for a menu is to forgo slots and composition in favor of taking in item data from an array; that's certainly doable but it doesn't align with our current approach of "composition first".
Alright, that does make sense.
I'd be doing this contribution as part of Microsoft's Fix / Hack / Learn (FHL) week, meaning I have limited time to do this. Probably not enough time to build a well-rounded spec and component that conforms to W3C specs, but maybe enough to get started.
If anything, I could start a spec and create a proof-of-concept component(s) during FHL week, then get feedback from you all and iterate on that in my spare time.
Sounds good - and it doesn't have to be exhaustive. I'd provide as much content as needed and no more - we are pretty open to be iterative, etc. The big thing we're looking for is to identify any gaps in assumption or understanding and provide feedback up front to avoid someone going in an opposite direction or one that misses a few gotchas, requirements, etc.
Also, for some context here, the reason I'm interested in contributing these components is because I work on apps.microsoft.com, and we're looking to rewrite our front-end using web components. It's currently in React + old FAST (before Web Components!), but we're considering migrating to newer tech, and one option is modern FAST.
Looking at modern FAST and doing some quick tech spikes, I noticed it was missing some components we need, such as nav bar with collapsible menus on mobile, split buttons, and menu buttons. Hence why I'm interested in contributing. 🙂
Contributions welcome - rising tide raises all ships and whatnot :)
@chrisdholt @EisenbergEffect @JudahGabriel
New MenuButton
spec that explores supporting split buttons. Per comments above, this merely positions the buttons and does not incorporate logic specific to split buttons.
Some basic exploratory examples here. https://stackblitz.com/edit/typescript-zg9qwx?file=index.html
As defined by the W3C:
A menu button is a button that opens a menu. It is often styled as a typical push button with a downward pointing arrow or triangle to hint that activating the button will display a menu.
A common request in the FAST community is how to make dropdowns, either for action menus or navigation. It is also a very common pattern amongst UI libraries, and while it is something that can produced using a combination of components that already exist in FAST it still a difficult pattern to implement correctly when accessibility becomes involved.
Expanded/Collapsed Indicator: An indicator (usually down/up chevrons) that visually indicates the expanded/collapsed state of the menu, as well as indicating that the button opens a menu.
MenuPosition: Provides a way to set the position of the menu relative to the reference button.
SplitButton compisition via start/end slots When a button is slotted into either the start or end slot or both, the menu button becomes a split button.
Menu
which reduces the amount of logic for focus and keyboard navigation, however in order to fully align with the ARIA patterns for MenuButton
s Menu
will need to be updated to support a roving tabindex.Component Name:
fast-menu-button
Attributes & Properties:
menu-position
- enum that contains all of the valid positions for the menu. Defaults to bottom-start
;expanded
- boolean that indicates whether or not the menu button is in its expanded state. This attribute is not used for AT as the internal Button
element has the aria-expanded
attribute. This attribute is meant to enable easier ergonomics for styling the MenuButton
via light-dom based on its current state.auto-update
- boolean to enable auto updating the menu's position as the MenuButton
moves around on the page.Events
expand
- fires when the menu is expanded.collapse
- fires when the menu is collapsed.
an alternative worth exploring is a single
expanded-change
event that fires in both scenarios. This aligns better with the custom events spec where custom event names need a hyphen in them, as well as aligning with other Foundation component's events.
Notes: When the host element gets connected to the DOM, it will need to setup a click handler on the document in order to trigger the light dismiss of the menu.
MenuButtonOptions
collapsedIcon
- Auther definable icon for the collapsed state.expandedIcon
- Auther definable icon for the expanded state.<div part="control">
<slot name="start"></slot>
<fast-button
aria-haspopup="true"
aria-expanded="{expanded || null}"
>
<slot></slot>
{
options
? expanded
? options.expandedIcon
: options.collapsedIcon
: ''
}
</fast-button>
<slot name="end"></slot>
</div>
<fast-menu
role="menu"
part="menu"
>
<slot name="item">
Menu items / dividers and other presentation content go here.
Anything that is not `role=menuitem` is ignored by keyboard navigation
</slot>
</fast-menu>
Slot Names
Notes: I'm on the fence on whether the default slot should be the internal button's content or the menu items. On the one hand you don't need to wrap the button's text with an element to slot it, but then you need to specify
slot="item"
on every item which becomes tedious and adds clutter to the markup.
default
- use the default slot for the button content.start
- can be used for icons and text. If another button is slotted here then the MenuButton
turns into a SplitButton
.end
- can be used for icons and text. If another button is slotted here then the MenuButton
turns into a SplitButton
.item
- The menu items.CSS Parts
control
- The container around the button and start/end slots.menu
- The menu element.expanded
- If the menu is visibleMenuButton
transitions into a split button. In this scenario additional tab stops need to be handled for the extra button(s).The MenuButton will need to reverse the start and end slots, as well as the indicator for users in an RTL setting. The menu positions for start and end will also need to reverse.
Potentially floating-ui, if FAST ends up moving in that direction
If floating-ui is not used, then AnchoredRegion
or another utility if AnchoredRegion
is deprecated.
Menu
Button
Button
in MenuButton
. While prototyping with Button
NVDA announces that the menu button is clickable twice, while using a native button does not have this behavior. I suspect this has something to do with Button
delegating focus, but haven't thoroughly tested this yet. Setting role="none"
on the Button
could be a temporary workaround until a better solution is found.W3C Spec for Menu, Menubar, and MenuButton W3C Accessible MenuButton Example
Unfortunately @microsoft/fast-foundation
is being deprecated, refer to #6955.
MenuButton
Overview
As defined by the W3C:
Background
A common request in the FAST community is how to make dropdowns, either for action menus or navigation. It is also a very common pattern amongst UI libraries, and while it is something that can produced using a combination of components that already exist in FAST it still a difficult pattern to implement correctly when accessibility becomes involved.
Use Cases
Features
Expanded/Collapsed Indicator: An indicator (usually down/up chevrons) that visually indicates the expanded/collapsed state of the menu, as well as indicating that the button opens a menu.
MenuPosition: Provides a way to set the position of the menu relative to the reference button.
Risks and Challenges
Should
Menu
be used, or should a custom menu that uses the styling fromMenu
be used? (similiar to howSelect
's andCombobox
's listboxes are built.)If
Menu
is used, will it need to be updated to supportAnchor
s with a role ofmenuitem
.Menu
already supports slotting elements with amenuitem
role, but this poses a styling challenge.MenuItem
be updated to support the capabilities ofAnchor
or should a purpose built element exist for menu items that are used for navigation?Could
MenuButton
also be used for a split button?Prior Art/Examples
Design
API
Component Name:
fast-menu-button
Attributes & Properties:
menu-position
- enum that contains all of the valid positions for the menu.viewport-lock
- boolean that enables the menu to stay within the view.menu-width
- enum with options for auto, reference width, and content widthmenu-height
- enum with options for auto, reference height, and content heightmenu-offset
- number. This could be an attribute, but leaning more towards a design token since this tends be something shared amongst popups that have a reference element in other design systems, i.e. Fluent UI'sSelect
&Combobox
.Events
expand
- fires when the menu is expandedcollapse
- fires when the menu is collapsedAnatomy
Notes:
When the host element gets connected to the DOM, it will need to setup a click handler on the document in order to trigger the light dismiss of the menu.
Some design systems add an arrow element to the menu that points at the button element. This can either be handled through component anatomy, or if floating-ui is used for the positioning, its arrow middleware can be used.
Slot Names
default
- use the default slot for the button contentstart
- the start slot before the button's content slotend
- the end slot after the button's content and before the indicator slotsexpanded-icon
- the icon to show the expanded state of the menucollapsed-icon
- the icon to show the collapsed state of the menuitem
- the menu itemsCSS Parts
control
- the button elementindicator
- the wrapper element around the expanded-icon & collapsed-icon slotsmenu
- the menu elementImplementation
States
expanded
- if the menu is visibleAccessibility
The MenuButton should align to the patterns provided by the W3C: https://www.w3.org/WAI/ARIA/apg/patterns/menubutton/
Globalization
The MenuButton will need to reverse the start and end slots, as well as the indicator for users in an RTL setting. The menu positions for start and end will also need to reverse as well.
Dependencies
Potentially floating-ui, if FAST ends up moving in that direction
If floating-ui is not used, then
AnchoredRegion
Could use
Button
,Menu
, andMenuItem
if the implementation uses composition in favor of custom anatomy that is styled like these components.Button
inMenuButton
. While prototyping withButton
NVDA announces that the menu button is clickable twice, while using a native button does not have this behavior.Appendix
Resources
W3C Spec for Menu, Menubar, and MenuButton W3C Accessible MenuButton Example