Skip to content

feat(select): add alternate rendering strategy for improved accessibility #14430

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

Closed
wants to merge 1 commit into from

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Dec 8, 2018

Currently mat-select has some accessibility issues, because we don't keep the options in the DOM until the select is attached, making it harder for assistive technology to pick it up. These changes add an alternate, opt-in, rendering strategy that'll keep the options inside the DOM. The rendering strategy is controlled through the MAT_SELECT_RENDERING_STRATEGY injection token.

In order to facilitate the new rendering strategy, these changes introduce a new kind of portal called an InlinePortal. It is a portal whose content is transferred from one place in the DOM to another when it is attached/detached.

Another change that was necessary for the new rendering to work was being able to pass a portal to the CdkConnectedOverlay directive. If no portal is passed, the directive will fall back to the current behavior.

@crisbeto crisbeto added the target: minor This PR is targeted for the next minor release label Dec 8, 2018
@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Dec 8, 2018
@crisbeto
Copy link
Member Author

crisbeto commented Dec 8, 2018

@jelbourn a few things that are up in the air:

  • Should we target a patch or a minor?
  • I wasn't too sure about the naming of some of the new symbols (e.g. "rendering strategy", "inline portal"). I'm open to different suggestions.
  • Should this be opt-in or opt-out? Also should it have an input on the MatSelect, in addition to the injection token?
  • Should we be running the mat-select tests both against the default rendering strategy and the inline one? mat-select is already the component with the most tests and this would double them. We'd probably see a bit of an increase in CI time.

@ngbot
Copy link

ngbot bot commented Dec 20, 2018

Hi @crisbeto! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

1 similar comment
@ngbot
Copy link

ngbot bot commented Dec 20, 2018

Hi @crisbeto! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

@jelbourn
Copy link
Member

jelbourn commented Jan 8, 2019

Per open questions:

  • It should be minor since we're adding new APIs
  • It should be opt-in, since tons of people have unit tests that assume the select panel is absent when "closed"
  • We probably should do all the tests (except the ones that don't apply), even if it does increase the run time

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.

High level- I don't quite follow why the new type of portal is necessary. What's the rundown of this approach vs. just visually the existing overlay?

}

/** DOM node hosting the portal's content. */
get origin(): HTMLElement {
Copy link
Member

Choose a reason for hiding this comment

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

element?

[style.transformOrigin]="_transformOrigin"
[style.font-size.px]="_triggerFontSize"
(keydown)="_handleKeydown($event)">
<ng-content></ng-content>
Copy link
Member

Choose a reason for hiding this comment

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

Can we avoid doing the "ng-content inside ng-template` trick? It ends up always instantiating the content, even when it's not going to be attached.

Copy link
Member Author

Choose a reason for hiding this comment

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

We could make it work by allowing people to provide an ng-template as the content. The problem is that we need the content to be rendered, in order to know what the options inside the select are. We need to know the options for a lot of things like showing the selected value, knowing where to position the dropdown, supporting keyboard navigation while closed etc.

@crisbeto
Copy link
Member Author

crisbeto commented Jan 9, 2019

@jelbourn I'll go through the rest of the feedback. As for the reason why I introduced a new portal, it's because it makes it easier to switch between the two approaches and it's much more aligned with the rest of our setup. The alternative would be something like the approach in #11806 where we'd need to support multiple parallel code paths.

@crisbeto crisbeto force-pushed the select-a11y-rework branch from 141c534 to cabdc2b Compare January 9, 2019 19:40
@crisbeto
Copy link
Member Author

crisbeto commented Jan 9, 2019

@jelbourn all the feedback should be addressed now.

@crisbeto crisbeto force-pushed the select-a11y-rework branch from cabdc2b to f3ffda0 Compare January 9, 2019 20:17
@crisbeto
Copy link
Member Author

@jelbourn the changes that we've discussed should be implemented now, can you take another look?

@jelbourn jelbourn added the Accessibility This issue is related to accessibility (a11y) label Feb 26, 2019
@crisbeto crisbeto force-pushed the select-a11y-rework branch from f3ffda0 to 79bf5a9 Compare March 9, 2019 18:49
@crisbeto crisbeto force-pushed the select-a11y-rework branch 2 times, most recently from 77879e3 to a2fa363 Compare April 7, 2019 17:55
@mmalerba mmalerba added aaa and removed aaa labels Apr 25, 2019
@crisbeto crisbeto force-pushed the select-a11y-rework branch from a2fa363 to 223e2ff Compare May 23, 2019 18:48
crisbeto added a commit to crisbeto/material2 that referenced this pull request May 23, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
crisbeto added a commit to crisbeto/material2 that referenced this pull request May 23, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
…lity

Currently `mat-select` has some accessibility issues, because we don't keep the options in the DOM until the select is attached, making it harder for assistive technology to pick it up. These changes add an alternate, opt-in, rendering strategy that'll keep the options inside the DOM. The rendering strategy is controlled through the `MAT_SELECT_RENDERING_STRATEGY` injection token.

In order to facilitate the new rendering strategy, these changes introduce a new kind of portal called an `InlinePortal`. It is a portal whose content is transferred from one place in the DOM to another when it is attached/detached.

Another change that was necessary for the new rendering to work was being able to pass a portal to the `CdkConnectedOverlay` directive. If no portal is passed, the directive will fall back to the current behavior.
@crisbeto crisbeto force-pushed the select-a11y-rework branch from 223e2ff to aeaf07d Compare May 24, 2019 05:36
crisbeto added a commit to crisbeto/material2 that referenced this pull request May 27, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jun 24, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jun 24, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Jun 25, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
@Splaktar
Copy link
Contributor

There is no mention here about presubmit failures or issues, but #11083 (comment) mentions

Attempts at fixing this were all just too much of a breaking change, such that it was impossible to roll out to applications in Google already using MatSelect.

@jelbourn has this been presubmitted again after the May 2019 updates? If so, can you please confirm that this needs to be considered for closing due to too many presubmit failures?

@jelbourn
Copy link
Member

Right- this change was unfortunately too breaking to land for existing Google apps. The new plan is bake the improvements into the MDC-based select component.

@jelbourn jelbourn closed this Jul 19, 2019
crisbeto added a commit to crisbeto/material2 that referenced this pull request Sep 5, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Sep 5, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Sep 5, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for angular#14430.
jelbourn pushed a commit that referenced this pull request Sep 6, 2019
Adds a new type of portal called `DomPortal` which transfers the contents of a portal into the portal outlet and then restores them on destroy.

This was implemented initially for #14430.
@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 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Accessibility This issue is related to accessibility (a11y) 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.

5 participants