Skip to content

feat(cdk-experimental/menu): add ability to open menus from a standalone trigger #20363

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

Merged
merged 1 commit into from
Aug 28, 2020

Conversation

andy9775
Copy link
Contributor

Adds the ability to open a menu from a menu trigger placed outside of a menu or menubar.

@andy9775 andy9775 requested a review from jelbourn as a code owner August 19, 2020 15:11
@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Aug 19, 2020
@andy9775 andy9775 requested a review from teflonwaffles August 19, 2020 15:12
/** Injection token for CloseDecider function. */
export const CLOSE_DECIDER = new InjectionToken<CloseDecider>('cdk-menu-close-decider');

@Injectable({providedIn: 'root'})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have some documentation, especially since I'm a little unclear whether the client developer will call this directly, or whether it will only be internally invoked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andy9775 andy9775 force-pushed the cdk-menu-standalone-trigger branch from 19b3e57 to ef73bff Compare August 19, 2020 19:36
* out. It is provided alongside the MenuStack to the BackgroundClickService and is called on each
* background click event.
*/
export type CloseDecider = (target: Element | null) => boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export type CloseDecider = (target: Element | null) => boolean;
export type ClosePredicate = (target: Element | null) => boolean;

https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)

* set of menus is closed out resulting in only having a single set of open menus at any given time.
*/
@Injectable({providedIn: 'root'})
export class BackgroundClickService implements OnDestroy {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't totally follow why this service is necessary. Why can't we use the outsidePointerEvents stream on OverlayRef for most of this, filtering the stream to the events that we care about for each type of overlay? I tried doing roughly what I had in mind here: jelbourn@584265c

What am I missing with this approach?

Copy link
Contributor Author

@andy9775 andy9775 Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed offline to update the Overlay logic to listen to contextmenu events (#20373) and to exclude buttons with a cdk-menu-trigger class in the predicate function.

@andy9775 andy9775 force-pushed the cdk-menu-standalone-trigger branch from ef73bff to f55bcec Compare August 21, 2020 22:37
@andy9775
Copy link
Contributor Author

@jelbourn @teflonwaffles feedback should be addressed however we're still blocked on the issue in #20377

@andy9775 andy9775 added the blocked This issue is blocked by some external factor, such as a prerequisite PR label Aug 22, 2020
Comment on lines 43 to 44
const isOpenTrigger =
coerceBooleanProperty(target.getAttribute('aria-expanded')) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const isOpenTrigger =
coerceBooleanProperty(target.getAttribute('aria-expanded')) &&
const isTriggerOpen = target.getAttribute('aria-expanded') === 'true';

I would use a direct comparison to 'true' here since coerceBooleanProperty will treat the empty string as true since it's intended to match the behavior of HTML boolean attributes

const isOpenTrigger =
coerceBooleanProperty(target.getAttribute('aria-expanded')) &&
target.classList.contains('cdk-menu-trigger');
const isNoninlineMenu =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const isNoninlineMenu =
const isOverlayMenu =

.outsidePointerEvents()
.pipe(takeUntil(this._stopOutsideClicksListener))
.subscribe(event => {
if (event.target instanceof Element && !isClickInsideMenuOverlay(event.target)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the instanceof check necessary because of something that might happen at run-time, or is it just to satisfy typescript that event.target is an element? If the latter, you can just do isClickInsideMenuOverlay(event.target as Element) since we know that something has to be an element to receive a click

@andy9775 andy9775 force-pushed the cdk-menu-standalone-trigger branch from f55bcec to 880309d Compare August 25, 2020 19:20
@andy9775
Copy link
Contributor Author

@jelbourn feedback should be addressed.

@andy9775 andy9775 force-pushed the cdk-menu-standalone-trigger branch from 880309d to 82bc091 Compare August 25, 2020 19:21
…one trigger

Adds the ability to open a menu from a menu trigger placed outside of a menu or menubar.
@andy9775 andy9775 removed the blocked This issue is blocked by some external factor, such as a prerequisite PR label Aug 28, 2020
@andy9775 andy9775 force-pushed the cdk-menu-standalone-trigger branch from 82bc091 to fca424b Compare August 28, 2020 15:14
@andy9775
Copy link
Contributor Author

@jelbourn confirmed that this is now working now that #20377 has been merged in

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jelbourn jelbourn added action: merge The PR is ready for merge by the caretaker target: minor This PR is targeted for the next minor release merge safe labels Aug 28, 2020
@jelbourn jelbourn merged commit de98466 into angular:master Aug 28, 2020
annieyw pushed a commit to annieyw/components that referenced this pull request Aug 31, 2020
…one trigger (angular#20363)

Adds the ability to open a menu from a menu trigger placed outside of a menu or menubar.
mmalerba pushed a commit to mmalerba/components that referenced this pull request Sep 5, 2020
…one trigger (angular#20363)

Adds the ability to open a menu from a menu trigger placed outside of a menu or menubar.
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 28, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants