From 143e71b4b102178b7f9c7ec48c72cc51c22e1971 Mon Sep 17 00:00:00 2001 From: Sofiya Huts Date: Wed, 24 Oct 2018 15:22:49 +0200 Subject: [PATCH 1/4] Make Grid keyboard navigable by adding Grid Behavior --- ...GridExampleKeyboardNavigable.shorthand.tsx | 108 ++++++++++++++++++ .../GridExampleKeyboardNavigable.tsx | 107 +++++++++++++++++ .../components/Grid/Variations/index.tsx | 5 + src/components/Grid/Grid.tsx | 10 +- src/index.ts | 1 + .../Behaviors/Grid/gridBehavior.ts | 16 +++ src/lib/accessibility/index.ts | 1 + 7 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx create mode 100644 docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx create mode 100644 src/lib/accessibility/Behaviors/Grid/gridBehavior.ts diff --git a/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx new file mode 100644 index 0000000000..672b94be08 --- /dev/null +++ b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx @@ -0,0 +1,108 @@ +import React from 'react' +import { Grid, Image, Button, gridBehavior } from '@stardust-ui/react' +import _ from 'lodash' + +const images = [ + { + key: 'ade', + }, + { + key: 'chris', + }, + { + key: 'christian', + }, + { + key: 'daniel', + }, + { + key: 'elliot', + }, + { + key: 'helen', + }, + { + key: 'jenny', + }, + { + key: 'joe', + }, + { + key: 'justen', + }, + { + key: 'laura', + }, + { + key: 'matt', + }, + { + key: 'nan', + }, + { + key: 'nom', + }, + { + key: 'stevie', + }, + { + key: 'steve', + }, + { + key: 'tom', + }, + { + key: 'veronika', + }, +] + +const imageButtonStyles = { + minWidth: '72px', + maxWidth: '72px', + height: '72px', + padding: '0', + margin: '0', + background: '#fff', +} +const renderImages = () => { + return _.map(images, image => ( + + )) +} + +const renderImageButtons = () => { + return _.map(images, image => ( + + )) +} + +const gridStyles = { + gridColumnGap: '10px', + gridRowGap: '10px', +} + +const GridExample = () => ( +
+ Grid with images, which are not natively focusable elements. Set 'data-is-focusable=true' to + each item to make grid items focusable and navigable. + +
+ Grid with images, wrapped with buttons, which are natively focusable elements. No need to add + 'data-is-focusable'='true'. + +
+) + +export default GridExample diff --git a/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx new file mode 100644 index 0000000000..d1ee3295dd --- /dev/null +++ b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx @@ -0,0 +1,107 @@ +import React from 'react' +import { Grid, Image, Button, gridBehavior } from '@stardust-ui/react' +import _ from 'lodash' + +const images = [ + { + key: 'ade', + }, + { + key: 'chris', + }, + { + key: 'christian', + }, + { + key: 'daniel', + }, + { + key: 'elliot', + }, + { + key: 'helen', + }, + { + key: 'jenny', + }, + { + key: 'joe', + }, + { + key: 'justen', + }, + { + key: 'laura', + }, + { + key: 'matt', + }, + { + key: 'nan', + }, + { + key: 'nom', + }, + { + key: 'stevie', + }, + { + key: 'steve', + }, + { + key: 'tom', + }, + { + key: 'veronika', + }, +] + +const imageButtonStyles = { + minWidth: '72px', + maxWidth: '72px', + height: '72px', + padding: '0', + margin: '0', + background: '#fff', +} +const renderImages = () => { + return _.map(images, image => ( + + )) +} + +const renderImageButtons = () => { + return _.map(images, image => ( + + )) +} + +const gridStyles = { + gridColumnGap: '10px', + gridRowGap: '10px', +} + +const GridExample = () => ( +
+ Grid with images, which are not natively focusable elements. Set 'data-is-focusable=true' to + each item to make grid items focusable and navigable. + + {renderImages()} + +
+ Grid with images, wrapped with button components, which are natively focusable elements. No need + to add 'data-is-focusable'='true' + + {renderImageButtons()} + +
+) + +export default GridExample diff --git a/docs/src/examples/components/Grid/Variations/index.tsx b/docs/src/examples/components/Grid/Variations/index.tsx index d5ca43fa71..cc7f38ad1b 100644 --- a/docs/src/examples/components/Grid/Variations/index.tsx +++ b/docs/src/examples/components/Grid/Variations/index.tsx @@ -19,6 +19,11 @@ const Variations = () => ( description="We can specify a certain amount of columns and rows or the explicit columns and rows for a grid." examplePath="components/Grid/Variations/GridExampleColumnsAndRows" /> + ) diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index 3d4249395b..6f60b991db 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -3,10 +3,14 @@ import * as React from 'react' import { UIComponent, childrenExist, customPropTypes, RenderResultConfig } from '../../lib' import { ComponentVariablesInput, ComponentSlotStyle } from '../../themes/types' import { Extendable, ShorthandValue, ReactChildren } from '../../../types/utils' +import { Accessibility } from '../../lib/accessibility/types' +import { defaultBehavior } from '../../lib/accessibility' + import ReactNode = React.ReactNode export interface GridProps { as?: any + accessibility?: Accessibility className?: string children?: ReactChildren columns?: string | number @@ -59,10 +63,14 @@ class Grid extends UIComponent, any> { /** Override for theme site variables to allow modifications of component styling via themes. */ variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), + + /** Accessibility behavior if overridden by the user. */ + accessibility: PropTypes.func, } - public static defaultProps = { + public static defaultProps: GridProps = { as: 'div', + accessibility: defaultBehavior, } public renderComponent({ ElementType, classes, rest }: RenderResultConfig): ReactNode { diff --git a/src/index.ts b/src/index.ts index dbed4569fc..aab5404448 100644 --- a/src/index.ts +++ b/src/index.ts @@ -118,6 +118,7 @@ export { export { default as chatMessageEnterEscBehavior, } from './lib/accessibility/Behaviors/Chat/chatMessageEnterEscBehavior' +export { default as gridBehavior } from './lib/accessibility/Behaviors/Grid/gridBehavior' // // Utilities diff --git a/src/lib/accessibility/Behaviors/Grid/gridBehavior.ts b/src/lib/accessibility/Behaviors/Grid/gridBehavior.ts new file mode 100644 index 0000000000..ab2cb0b74b --- /dev/null +++ b/src/lib/accessibility/Behaviors/Grid/gridBehavior.ts @@ -0,0 +1,16 @@ +import { Accessibility, FocusZoneMode } from '../../types' + +/** + * @description + * Wraps component in FocusZone allowing arrow key navigation through the children of the component. + */ +const gridBehavior: Accessibility = (props: any) => ({ + focusZone: { + mode: FocusZoneMode.Wrap, + props: { + isCircularNavigation: true, + }, + }, +}) + +export default gridBehavior diff --git a/src/lib/accessibility/index.ts b/src/lib/accessibility/index.ts index a993f06c49..878b7184dd 100644 --- a/src/lib/accessibility/index.ts +++ b/src/lib/accessibility/index.ts @@ -26,3 +26,4 @@ export { default as chatMessageBehavior } from './Behaviors/Chat/chatMessageBeha export { default as chatMessageEnterEscBehavior, } from './Behaviors/Chat/chatMessageEnterEscBehavior' +export { default as gridBehavior } from './Behaviors/Grid/gridBehavior' From 2044595812987700a793583a9a798f5fa001b959 Mon Sep 17 00:00:00 2001 From: Sofiya Huts Date: Wed, 24 Oct 2018 16:06:32 +0200 Subject: [PATCH 2/4] Small enhancement to examples --- ...GridExampleKeyboardNavigable.shorthand.tsx | 82 ++++++------------- .../GridExampleKeyboardNavigable.tsx | 82 ++++++------------- 2 files changed, 48 insertions(+), 116 deletions(-) diff --git a/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx index 672b94be08..36d7f11398 100644 --- a/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx +++ b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.shorthand.tsx @@ -2,58 +2,24 @@ import React from 'react' import { Grid, Image, Button, gridBehavior } from '@stardust-ui/react' import _ from 'lodash' -const images = [ - { - key: 'ade', - }, - { - key: 'chris', - }, - { - key: 'christian', - }, - { - key: 'daniel', - }, - { - key: 'elliot', - }, - { - key: 'helen', - }, - { - key: 'jenny', - }, - { - key: 'joe', - }, - { - key: 'justen', - }, - { - key: 'laura', - }, - { - key: 'matt', - }, - { - key: 'nan', - }, - { - key: 'nom', - }, - { - key: 'stevie', - }, - { - key: 'steve', - }, - { - key: 'tom', - }, - { - key: 'veronika', - }, +const imageNames = [ + 'ade', + 'chris', + 'christian', + 'daniel', + 'elliot', + 'helen', + 'jenny', + 'joe', + 'justen', + 'laura', + 'matt', + 'nan', + 'nom', + 'stevie', + 'steve', + 'tom', + 'veronika', ] const imageButtonStyles = { @@ -65,20 +31,20 @@ const imageButtonStyles = { background: '#fff', } const renderImages = () => { - return _.map(images, image => ( + return _.map(imageNames, imageName => ( )) } const renderImageButtons = () => { - return _.map(images, image => ( - )) } diff --git a/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx index d1ee3295dd..58979fa171 100644 --- a/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx +++ b/docs/src/examples/components/Grid/Variations/GridExampleKeyboardNavigable.tsx @@ -2,58 +2,24 @@ import React from 'react' import { Grid, Image, Button, gridBehavior } from '@stardust-ui/react' import _ from 'lodash' -const images = [ - { - key: 'ade', - }, - { - key: 'chris', - }, - { - key: 'christian', - }, - { - key: 'daniel', - }, - { - key: 'elliot', - }, - { - key: 'helen', - }, - { - key: 'jenny', - }, - { - key: 'joe', - }, - { - key: 'justen', - }, - { - key: 'laura', - }, - { - key: 'matt', - }, - { - key: 'nan', - }, - { - key: 'nom', - }, - { - key: 'stevie', - }, - { - key: 'steve', - }, - { - key: 'tom', - }, - { - key: 'veronika', - }, +const imageNames = [ + 'ade', + 'chris', + 'christian', + 'daniel', + 'elliot', + 'helen', + 'jenny', + 'joe', + 'justen', + 'laura', + 'matt', + 'nan', + 'nom', + 'stevie', + 'steve', + 'tom', + 'veronika', ] const imageButtonStyles = { @@ -65,20 +31,20 @@ const imageButtonStyles = { background: '#fff', } const renderImages = () => { - return _.map(images, image => ( + return _.map(imageNames, imageName => ( )) } const renderImageButtons = () => { - return _.map(images, image => ( - )) } From 051a9a51668ef7b2586a2e9ac967d02f68aa6cdd Mon Sep 17 00:00:00 2001 From: Sofiya Huts Date: Wed, 24 Oct 2018 16:07:27 +0200 Subject: [PATCH 3/4] Small enhancement to examples From f9b9c4cefe5d6d7a0288a27caaf1dc0c2a5e6869 Mon Sep 17 00:00:00 2001 From: Sofiya Huts Date: Fri, 2 Nov 2018 13:45:44 +0100 Subject: [PATCH 4/4] Fix tests --- src/lib/accessibility/Behaviors/Grid/gridBehavior.ts | 3 ++- test/specs/behaviors/behavior-test.tsx | 2 ++ test/specs/behaviors/testDefinitions.ts | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/accessibility/Behaviors/Grid/gridBehavior.ts b/src/lib/accessibility/Behaviors/Grid/gridBehavior.ts index ab2cb0b74b..9958a11c60 100644 --- a/src/lib/accessibility/Behaviors/Grid/gridBehavior.ts +++ b/src/lib/accessibility/Behaviors/Grid/gridBehavior.ts @@ -2,13 +2,14 @@ import { Accessibility, FocusZoneMode } from '../../types' /** * @description - * Wraps component in FocusZone allowing arrow key navigation through the children of the component. + * Wraps component in FocusZone allowing circular arrow key navigation through the children of the component. */ const gridBehavior: Accessibility = (props: any) => ({ focusZone: { mode: FocusZoneMode.Wrap, props: { isCircularNavigation: true, + preventDefaultWhenHandled: true, }, }, }) diff --git a/test/specs/behaviors/behavior-test.tsx b/test/specs/behaviors/behavior-test.tsx index 5fbb6cf857..63a4f5af15 100644 --- a/test/specs/behaviors/behavior-test.tsx +++ b/test/specs/behaviors/behavior-test.tsx @@ -24,6 +24,7 @@ import { toggleButtonBehavior, toolbarBehavior, toolbarButtonBehavior, + gridBehavior, } from 'src/lib/accessibility' import { TestHelper } from './testHelper' import definitions from './testDefinitions' @@ -51,5 +52,6 @@ testHelper.addBehavior('tabListBehavior', tabListBehavior) testHelper.addBehavior('toolbarBehavior', toolbarBehavior) testHelper.addBehavior('toggleButtonBehavior', toggleButtonBehavior) testHelper.addBehavior('toolbarButtonBehavior', toolbarButtonBehavior) +testHelper.addBehavior('gridBehavior', gridBehavior) testHelper.run(behaviorMenuItems) diff --git a/test/specs/behaviors/testDefinitions.ts b/test/specs/behaviors/testDefinitions.ts index c00bafcae4..3c30aa4c9c 100644 --- a/test/specs/behaviors/testDefinitions.ts +++ b/test/specs/behaviors/testDefinitions.ts @@ -200,9 +200,9 @@ definitions.push({ }, }) -// Wraps component in FocusZone allowing arrow key navigation through the children of the component. +// [Circular navigation] Wraps component in FocusZone allowing circular arrow key navigation through the children of the component. definitions.push({ - regexp: /Wraps component in FocusZone allowing arrow key navigation through the children of the component.\.+/g, + regexp: /Wraps component in FocusZone allowing circular arrow key navigation through the children of the component\.+/g, testMethod: (parameters: TestMethod) => { const property = { isCircularNavigation: undefined,