Skip to content

Commit 905aeb5

Browse files
authored
fix(aria/menu): unable to set softDisabled (#33265)
Fixes the following issues in the Aria menu: 1. The menu didn't have a `softDisabled` input. 2. The menu bar had a `softDisabled` input, but it was being ignored. Fixes #33262.
1 parent e99ac3b commit 905aeb5

4 files changed

Lines changed: 33 additions & 4 deletions

File tree

goldens/aria/menu/index.api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ export class Menu<V> implements OnDestroy {
2525
ngOnDestroy(): void;
2626
readonly parent: _angular_core.WritableSignal<MenuTrigger<V> | MenuItem<V> | undefined>;
2727
readonly _pattern: MenuPattern<V>;
28+
readonly softDisabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
2829
readonly tabIndex: Signal<0 | -1>;
2930
readonly textDirection: _angular_core.WritableSignal<_angular_cdk_bidi.Direction>;
3031
readonly typeaheadDelay: _angular_core.InputSignal<number>;
3132
readonly visible: Signal<boolean>;
3233
readonly wrap: _angular_core.InputSignalWithTransform<boolean, unknown>;
3334
// (undocumented)
34-
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Menu<any>, "[ngMenu]", ["ngMenu"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "expansionDelay": { "alias": "expansionDelay"; "required": false; "isSignal": true; }; }, { "itemSelected": "itemSelected"; }, never, never, true, [{ directive: typeof DeferredContentAware; inputs: { "preserveContent": "preserveContent"; }; outputs: {}; }]>;
35+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Menu<any>, "[ngMenu]", ["ngMenu"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "expansionDelay": { "alias": "expansionDelay"; "required": false; "isSignal": true; }; }, { "itemSelected": "itemSelected"; }, never, never, true, [{ directive: typeof DeferredContentAware; inputs: { "preserveContent": "preserveContent"; }; outputs: {}; }]>;
3536
// (undocumented)
3637
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Menu<any>, never>;
3738
}

src/aria/menu/menu-bar.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ export class MenuBar<V> implements OnDestroy {
113113
...this,
114114
items: this._itemPatterns,
115115
multi: () => false,
116-
softDisabled: () => true,
117116
focusMode: () => 'roving',
118117
orientation: () => 'horizontal',
119118
selectionMode: () => 'explicit',

src/aria/menu/menu.spec.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,32 @@ describe('Standalone Menu Pattern', () => {
498498
expect(item?.getAttribute('aria-label')).toBe('Apple item label');
499499
});
500500

501+
describe('softDisabled', () => {
502+
it('should skip disabled items during navigation when softDisabled is false', () => {
503+
setupMenu();
504+
fixture.componentInstance.softDisabled.set(false);
505+
fixture.detectChanges();
506+
507+
const apple = getItem('Apple')!;
508+
const berries = getItem('Berries');
509+
510+
keydown(apple, 'ArrowUp');
511+
expect(document.activeElement).toBe(berries);
512+
});
513+
514+
it('should focus disabled items during navigation when softDisabled is true', () => {
515+
setupMenu();
516+
fixture.componentInstance.softDisabled.set(true);
517+
fixture.detectChanges();
518+
519+
const apple = getItem('Apple')!;
520+
const cherry = getItem('Cherry');
521+
522+
keydown(apple!, 'ArrowUp');
523+
expect(document.activeElement).toBe(cherry);
524+
});
525+
});
526+
501527
describe('structural validations', () => {
502528
let consoleSpy: jasmine.Spy;
503529

@@ -1077,7 +1103,7 @@ describe('Menu Bar Pattern', () => {
10771103

10781104
@Component({
10791105
template: `
1080-
<div ngMenu [expansionDelay]="0" (itemSelected)="itemSelected($event)">
1106+
<div ngMenu [softDisabled]="softDisabled()" [expansionDelay]="0" (itemSelected)="itemSelected($event)">
10811107
<ng-template ngMenuContent>
10821108
<div
10831109
ngMenuItem
@@ -1104,6 +1130,7 @@ describe('Menu Bar Pattern', () => {
11041130
})
11051131
class StandaloneMenuExample {
11061132
firstItemAriaLabel = signal<string | null>(null);
1133+
softDisabled = signal(true);
11071134

11081135
itemSelected(value: string) {}
11091136
}

src/aria/menu/menu.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ export class Menu<V> implements OnDestroy {
114114
/** A reference to the parent menu item or menu trigger. */
115115
readonly parent = signal<MenuTrigger<V> | MenuItem<V> | undefined>(undefined);
116116

117+
/** Whether the menu is soft disabled. */
118+
readonly softDisabled = input(true, {transform: booleanAttribute});
119+
117120
/** The menu ui pattern instance. */
118121
readonly _pattern: MenuPattern<V>;
119122

@@ -152,7 +155,6 @@ export class Menu<V> implements OnDestroy {
152155
parent: computed(() => this.parent()?._pattern),
153156
items: this._itemPatterns,
154157
multi: () => false,
155-
softDisabled: () => true,
156158
focusMode: () => 'roving',
157159
orientation: () => 'vertical',
158160
selectionMode: () => 'explicit',

0 commit comments

Comments
 (0)