diff --git a/common/changes/office-ui-fabric-react/magellan-focusableDisabledItems_2018-02-22-23-48.json b/common/changes/office-ui-fabric-react/magellan-focusableDisabledItems_2018-02-22-23-48.json new file mode 100644 index 00000000000000..43df507df1227e --- /dev/null +++ b/common/changes/office-ui-fabric-react/magellan-focusableDisabledItems_2018-02-22-23-48.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "office-ui-fabric-react", + "comment": "[ContextualMenu] Disabled buttons are focusable", + "type": "patch" + } + ], + "packageName": "office-ui-fabric-react", + "email": "law@microsoft.com" +} \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.test.tsx b/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.test.tsx index 3efa04c9d2991c..c9861234dc780d 100644 --- a/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.test.tsx +++ b/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.test.tsx @@ -239,13 +239,22 @@ describe('ContextualMenu', () => { expect(document.querySelector('.SubMenuClass')).toBeDefined(); }); - it('applies disabled property when `disabled` is true', () => { + it('can focus on disabled items', () => { const items: IContextualMenuItem[] = [ { name: 'TestText 1', key: 'TestKey1', + }, + { + name: 'TestText 2', + key: 'TestKey2', disabled: true, }, + { + name: 'TestText 3', + key: 'TestKey3', + isDisabled: true, + }, ]; ReactTestUtils.renderIntoDocument( @@ -254,17 +263,51 @@ describe('ContextualMenu', () => { /> ); - const menuItem = document.querySelector('button.ms-ContextualMenu-link') as HTMLButtonElement; + const menuItems = document.querySelectorAll('button.ms-ContextualMenu-link') as NodeListOf; + expect(menuItems.length).toEqual(3); + + menuItems[0].focus(); + expect(document.activeElement.textContent).toEqual('TestText 1'); + expect(document.activeElement.className.split(' ')).not.toContain('is-disabled'); - expect(menuItem.disabled).toBeTruthy(); + menuItems[1].focus(); + expect(document.activeElement.textContent).toEqual('TestText 2'); + expect(document.activeElement.className.split(' ')).toContain('is-disabled'); + + menuItems[2].focus(); + expect(document.activeElement.textContent).toEqual('TestText 3'); + expect(document.activeElement.className.split(' ')).toContain('is-disabled'); }); - it('applies disabled property when deprecated property `isDisabled` is true', () => { + it('cannot click on disabled items', () => { + const itemsClicked = [ + false, + false, + false + ]; const items: IContextualMenuItem[] = [ { name: 'TestText 1', key: 'TestKey1', + onClick: () => itemsClicked[0] = true + }, + { + name: 'TestText 2', + key: 'TestKey2', + disabled: true, + onClick: () => { + itemsClicked[1] = true; + fail('Disabled item should not be clickable'); + } + }, + { + name: 'TestText 3', + key: 'TestKey3', isDisabled: true, + onClick: () => { + itemsClicked[2] = true; + fail('Disabled item should not be clickable'); + } }, ]; @@ -274,9 +317,17 @@ describe('ContextualMenu', () => { /> ); - const menuItem = document.querySelector('button.ms-ContextualMenu-link') as HTMLButtonElement; + const menuItems = document.querySelectorAll('button.ms-ContextualMenu-link') as NodeListOf; + expect(menuItems.length).toEqual(3); + + menuItems[0].click(); + expect(itemsClicked[0]).toEqual(true); + + menuItems[1].click(); + expect(itemsClicked[1]).toEqual(false); - expect(menuItem.disabled).toBeTruthy(); + menuItems[2].click(); + expect(itemsClicked[2]).toEqual(false); }); it('renders headers properly', () => { diff --git a/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.tsx b/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.tsx index eb143facbc726f..a9a6de851776d2 100644 --- a/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.tsx +++ b/packages/office-ui-fabric-react/src/components/ContextualMenu/ContextualMenu.tsx @@ -290,7 +290,7 @@ export class ContextualMenu extends BaseComponent { title } } { (items && items.length) ? ( ); } @@ -492,11 +492,11 @@ export class ContextualMenu extends BaseComponent ); @@ -531,6 +531,10 @@ export class ContextualMenu extends BaseComponent this._onItemMouseDown(item, ev), onMouseMove: this._onItemMouseMove.bind(this, item), - disabled: this._isItemDisabled(item), href: item.href, title: item.title, 'aria-label': ariaLabel, @@ -556,10 +559,16 @@ export class ContextualMenu extends BaseComponent - + ); } @@ -617,7 +626,7 @@ export class ContextualMenu extends BaseComponent, + , ); } @@ -640,7 +649,7 @@ export class ContextualMenu extends BaseComponent this._onItemMouseDown(item, ev), onMouseMove: this._onItemMouseMove.bind(this, item) }), - + ); } @@ -821,6 +830,9 @@ export class ContextualMenu extends BaseComponent) { + if (item.disabled || item.isDisabled) { + return; + } if (item.onClick) { item.onClick(ev, item); } else if (this.props.onItemClick) { diff --git a/packages/office-ui-fabric-react/src/components/ContextualMenu/examples/ContextualMenu.Basic.Example.tsx b/packages/office-ui-fabric-react/src/components/ContextualMenu/examples/ContextualMenu.Basic.Example.tsx index 4fa1b5f774ef5f..318cefb3872fde 100644 --- a/packages/office-ui-fabric-react/src/components/ContextualMenu/examples/ContextualMenu.Basic.Example.tsx +++ b/packages/office-ui-fabric-react/src/components/ContextualMenu/examples/ContextualMenu.Basic.Example.tsx @@ -23,7 +23,8 @@ export class ContextualMenuBasicExample extends React.Component { items: [ { key: 'newItem', - name: 'New' + name: 'New', + onClick: () => console.log('New clicked') }, { key: 'divider_1', @@ -31,20 +32,24 @@ export class ContextualMenuBasicExample extends React.Component { }, { key: 'rename', - name: 'Rename' + name: 'Rename', + onClick: () => console.log('Rename clicked') }, { key: 'edit', - name: 'Edit' + name: 'Edit', + onClick: () => console.log('Edit clicked') }, { key: 'properties', - name: 'Properties' + name: 'Properties', + onClick: () => console.log('Properties clicked') }, { key: 'disabled', name: 'Disabled item', - disabled: true + disabled: true, + onClick: () => console.error('Disabled item should not be clickable.') } ] } } diff --git a/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.test.tsx b/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.test.tsx index ff04576a4f4e89..a02f86a9dc39c3 100644 --- a/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.test.tsx +++ b/packages/office-ui-fabric-react/src/components/DetailsList/DetailsList.test.tsx @@ -74,7 +74,6 @@ describe('DetailsList', () => { if (value === null || value === undefined) { value = ''; } - console.log('Rendered column'); return (
{ value } diff --git a/packages/office-ui-fabric-react/src/components/DetailsList/__snapshots__/DetailsList.test.tsx.snap b/packages/office-ui-fabric-react/src/components/DetailsList/__snapshots__/DetailsList.test.tsx.snap index 3781b2dbc69d23..d4d66656bcecad 100644 --- a/packages/office-ui-fabric-react/src/components/DetailsList/__snapshots__/DetailsList.test.tsx.snap +++ b/packages/office-ui-fabric-react/src/components/DetailsList/__snapshots__/DetailsList.test.tsx.snap @@ -62,16 +62,52 @@ exports[`DetailsList renders List correctly 1`] = ` role="checkbox" >
@@ -79,10 +115,27 @@ exports[`DetailsList renders List correctly 1`] = ` aria-hidden={true} className= ms-Check-check - undefined { display: inline-block; } + { + color: #c8c8c8; + font-size: 16px; + height: 18px; + left: .5px; + opacity: 0; + position: absolute; + text-align: center; + top: 0px; + vertical-align: middle; + width: 18px; + } + &:hover { + opacity: 1; + } + @media screen and (-ms-high-contrast: active){& { + -ms-high-contrast-adjust: none; + } data-icon-name="StatusCircleCheckmark" role="presentation" /> diff --git a/scripts/tasks/webpack-resources.js b/scripts/tasks/webpack-resources.js index 91adf80278493f..6bc227592c55ed 100644 --- a/scripts/tasks/webpack-resources.js +++ b/scripts/tasks/webpack-resources.js @@ -74,6 +74,7 @@ module.exports = { { devServer: { inline: true, + host: '10.121.24.189', port: 4322, },