Skip to content

Conversation

@AdrianRomanski
Copy link

@AdrianRomanski AdrianRomanski commented Jan 25, 2026

Disclosure Pattern

feat(aria/disclosure): add disclosure pattern 

Implements the WAI-ARIA Disclosure pattern with two directives.

DisclosureTrigger (ngDisclosureTrigger) is a toggle button that controls content visibility with keyboard support (Enter, Space) and ARIA attributes (aria-expanded, aria-controls).

DisclosureContent (ngDisclosureContent) is a content panel that shows/hides based on trigger state.

Updated .ng-dev/commit-message.mts with aria/disclosure scope.

  • Tests for the changes have been added (for bug fixes / features)

Yes, both are tested

  • private pattern - src/aria/private/disclosure/disclosure.spec.ts

  • public directives - src/aria/disclosure/disclosure.spec.ts

  • Docs have been added / updated (for bug fixes / features)

I’ve added documentation throughout the feature and also included a GUIDE file.

  • guides/aria-disclosure.md

PR Type

What kind of change does this PR introduce?

  • Feature

What is the current behavior?

The @angular/aria library currently lacks a Disclosure (Show/Hide) pattern implementation.

What is the new behavior?

Implements the Disclosure Pattern with two directives:

DisclosureTrigger (ngDisclosureTrigger)

  • Toggle button that controls content visibility
  • Keyboard support: Enter and Space to toggle
  • Two-way binding with [(expanded)]
  • Supports disabled and alwaysExpanded states
  • ARIA attributes: role="button", aria-expanded, aria-controls, aria-disabled

DisclosureContent (ngDisclosureContent)

  • Content panel that shows/hides based on trigger state
  • Integrates with DeferredContentAware for lazy rendering
  • Supports preserveContent to keep DOM when collapsed
  • Automatic hidden attribute management

Architecture

Follows the two-layer pattern established in @angular/aria:

  • Private layer: DisclosurePattern class in src/aria/private/disclosure/
  • Public layer: Angular directives in src/aria/disclosure/

Testing

  • Unit tests organized by POUR accessibility principles
  • Tests cover: Perceivable, Operable, Understandable, Robust
  • Accessibility checks (axe) via runAccessibilityChecks()

Documentation

  • Guide: guides/aria-disclosure.md with usage examples (Im not sure about location of this one, as they are not other patterns in this directory, but i could not find a better place)
  • Comparison between Disclosure and Accordion patterns (They can be confusing so i have added this section to make it cleaerer)
  • API reference for all inputs, outputs, and methods

Does this PR introduce a breaking change?

  • Yes
  • No

Local Testing

Tested locally by linking packages via file: protocol:

{
  "@angular/cdk": "file:/home/adrian-romanski/projects/components/dist/releases/cdk",
  "@angular/aria": "file:/home/adrian-romanski/projects/components/dist/releases/aria",
  "@angular/material": "file:/home/adrian-romanski/projects/components/dist/releases/material"
}

Verified:

  • Keyboard navigation (Enter, Space to toggle)
  • Accessibility tree
  • ARIA attributes (aria-expanded, aria-controls, aria-disabled)
  • Two-way binding with [(expanded)]
  • Disabled state behavior
  • alwaysExpanded constraint
  • Content visibility (hidden attribute)

Build & Tests:

bazel build //src/aria/disclosure
bazel test //src/aria/disclosure:unit_tests
bazel test //src/aria/private/disclosure:unit_tests
  • Build successful
  • All tests pass (Chromium + Firefox)

Other information

When to use Disclosure vs Accordion

Feature Disclosure Accordion
Grouping Independent items Grouped with ngAccordionGroup
Keyboard navigation Enter/Space only Arrow keys, Home/End
Expansion mode Always independent Configurable (multiExpandable)
Focus management None Roving tabindex

Example Usage

<button 
  ngDisclosureTrigger 
  #trigger="ngDisclosureTrigger"
  [(expanded)]="isExpanded"
  [controls]="'content-id'">
  {{ isExpanded() ? 'Hide' : 'Show' }} Details
</button>

<div 
  id="content-id" 
  ngDisclosureContent 
  [trigger]="trigger">
  <p>Collapsible content here.</p>
</div>

@google-cla
Copy link

google-cla bot commented Jan 25, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@angular-robot angular-robot bot added detected: feature PR contains a feature commit area: docs Related to the documentation area: build & ci Related the build and CI infrastructure of the project labels Jan 25, 2026
@AdrianRomanski AdrianRomanski changed the title feat(aria): add disclosure pattern feat(aria/disclosure): add disclosure pattern Jan 25, 2026
Implements the WAI-ARIA Disclosure pattern with two directives.

DisclosureTrigger (ngDisclosureTrigger) is a toggle button that controls content visibility with keyboard support (Enter, Space) and ARIA attributes (aria-expanded, aria-controls).

DisclosureContent (ngDisclosureContent) is a content panel that shows/hides based on trigger state.
@AdrianRomanski AdrianRomanski force-pushed the feature-aria-disclosure branch from 7dc2925 to b44abf2 Compare January 25, 2026 14:45
Copy link
Member

@crisbeto crisbeto left a comment

Choose a reason for hiding this comment

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

Will leave it up for discussion, but I'm not sure we need directives for this pattern specifically, considering that it's basically an @if statement.

@ok7sai
Copy link
Member

ok7sai commented Jan 27, 2026

Thanks for the contribution! There is <details>/<summary> for native disclosure support, or like @crisbeto mentioned you can simply implement one with @if for more controls. Making it a UI pattern can be too complex for what it actually does.

@AdrianRomanski
Copy link
Author

AdrianRomanski commented Jan 28, 2026

@crisbeto @ok7sai

Thank you for the replies and for explaining the topic. I learned a lot while working on this feature, so the time was definitely not wasted 😄
Next time, I’ll make sure to create an issue before jumping into another feature implementation.
What I enjoyed most while learning was how clearly the separation between patterns and public directives was presented. Bazel also turned out to be much easier than I expected I was a bit intimidated at first since it was my first time building something with it.

If i could ask for little code check, what do you think about grouping tests based on POUR principles? Does it make sense to you?

src/aria/private/disclosure/disclosure.spec.ts
src/aria/disclosure/disclosure.spec.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build & ci Related the build and CI infrastructure of the project area: docs Related to the documentation detected: feature PR contains a feature commit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants