-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Observed element hooks (#28291)
* feat: Observed element hooks Implements hooks that enable the use of `observedElement` API in react-tabster Fixes #28030 * changefiles * fix md * Add tabster documentation * add useModalAttribute docs * improve observable examples * improve focusable group examples * improve arrow navigation group * add focus finders * Update packages/react-components/react-components/stories/Concepts/FocusManagement/useFocusFinders/FindPrevious.stories.tsx * fix type check * improve styles * improve docs * Add utilities section
- Loading branch information
Showing
37 changed files
with
1,534 additions
and
0 deletions.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-components-c657e5d0-310f-4d2d-a635-1b8e3f8030bc.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"type": "minor", | ||
"comment": "feat: Observed element hooks", | ||
"packageName": "@fluentui/react-components", | ||
"email": "[email protected]", | ||
"dependentChangeType": "patch" | ||
} |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-tabster-ba4d3383-0449-4ed9-837f-486329ef158a.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"type": "minor", | ||
"comment": "feat: Observed element hooks", | ||
"packageName": "@fluentui/react-tabster", | ||
"email": "[email protected]", | ||
"dependentChangeType": "patch" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
...react-components/stories/Concepts/FocusManagement/useArrowNavigationGoup/Axis.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import * as React from 'react'; | ||
import { | ||
TextBoldRegular, | ||
TextUnderlineRegular, | ||
TextItalicRegular, | ||
TextAlignLeftRegular, | ||
TextAlignCenterRegular, | ||
TextAlignRightRegular, | ||
CopyRegular, | ||
ClipboardPasteRegular, | ||
CutRegular, | ||
} from '@fluentui/react-icons'; | ||
import { | ||
Button, | ||
useArrowNavigationGroup, | ||
Field, | ||
RadioGroup, | ||
Radio, | ||
UseArrowNavigationGroupOptions, | ||
makeStyles, | ||
shorthands, | ||
mergeClasses, | ||
} from '@fluentui/react-components'; | ||
|
||
const useStyles = makeStyles({ | ||
container: { | ||
display: 'flex', | ||
...shorthands.gap('5px'), | ||
}, | ||
|
||
vertical: { | ||
flexDirection: 'column', | ||
}, | ||
|
||
both: {}, | ||
horizontal: {}, | ||
grid: { | ||
display: 'grid', | ||
gridTemplateColumns: 'repeat(3, max-content)', | ||
}, | ||
['grid-linear']: { | ||
display: 'grid', | ||
gridTemplateColumns: 'repeat(3, max-content)', | ||
}, | ||
}); | ||
|
||
export const Axis = () => { | ||
const styles = useStyles(); | ||
const [axis, setAxis] = React.useState<UseArrowNavigationGroupOptions['axis']>('horizontal'); | ||
const atributes = useArrowNavigationGroup({ axis }); | ||
|
||
return ( | ||
<> | ||
<Field label="Select an axis"> | ||
<RadioGroup value={axis} onChange={(e, data) => setAxis(data.value as UseArrowNavigationGroupOptions['axis'])}> | ||
<Radio label="Horizontal" value="horizontal" /> | ||
<Radio label="Vertical" value="vertical" /> | ||
<Radio label="Both" value="both" /> | ||
<Radio label="Grid" value="grid" /> | ||
<Radio label="Linear Grid" value="grid-linear" /> | ||
</RadioGroup> | ||
</Field> | ||
<div | ||
aria-label="Editor toolbar example" | ||
role="toolbar" | ||
{...atributes} | ||
className={mergeClasses(styles.container, axis && styles[axis])} | ||
> | ||
<Button aria-label="Bold" icon={<TextBoldRegular />} /> | ||
<Button aria-label="Underline" icon={<TextUnderlineRegular />} /> | ||
<Button aria-label="Italic" icon={<TextItalicRegular />} /> | ||
<Button aria-label="Align Left" icon={<TextAlignLeftRegular />} /> | ||
<Button aria-label="Align Center" icon={<TextAlignCenterRegular />} /> | ||
<Button aria-label="Align Right" icon={<TextAlignRightRegular />} /> | ||
<Button aria-label="Copy" icon={<CopyRegular />} /> | ||
<Button aria-label="Cut" icon={<CutRegular />} /> | ||
<Button aria-label="Paste" icon={<ClipboardPasteRegular />} /> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
Axis.parameters = { | ||
docs: { | ||
description: { | ||
story: [ | ||
'Keyboard navigation can be configured for different axis:', | ||
'- horizontal - navigation with left/right keys', | ||
'- vertical - navigation with up/downkeys', | ||
'- both - navigation with all arrow keys, left/down and right/up will navigate in the same direction', | ||
'- grid - bidirectional navigation in a 2D grid', | ||
'- grid-liear - same as grid navigation, but horizontal focus will continue to flow to the next row', | ||
].join('\n'), | ||
}, | ||
}, | ||
}; |
53 changes: 53 additions & 0 deletions
53
...ts/stories/Concepts/FocusManagement/useArrowNavigationGoup/CircularNavigation.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import * as React from 'react'; | ||
import { | ||
TextBoldRegular, | ||
TextUnderlineRegular, | ||
TextItalicRegular, | ||
TextAlignLeftRegular, | ||
TextAlignCenterRegular, | ||
TextAlignRightRegular, | ||
CopyRegular, | ||
ClipboardPasteRegular, | ||
CutRegular, | ||
} from '@fluentui/react-icons'; | ||
import { Button, useArrowNavigationGroup, makeStyles, shorthands, Checkbox } from '@fluentui/react-components'; | ||
|
||
const useStyles = makeStyles({ | ||
container: { | ||
display: 'flex', | ||
...shorthands.gap('5px'), | ||
}, | ||
}); | ||
|
||
export const CircularNavigation = () => { | ||
const styles = useStyles(); | ||
const [checked, setChecked] = React.useState(true); | ||
const attributes = useArrowNavigationGroup({ axis: 'horizontal', circular: checked }); | ||
|
||
return ( | ||
<> | ||
<Checkbox label="Circular" checked={checked} onChange={(e, data) => setChecked(data.checked as boolean)} /> | ||
<div aria-label="Editor toolbar example" role="toolbar" {...attributes} className={styles.container}> | ||
<Button aria-label="Bold" icon={<TextBoldRegular />} /> | ||
<Button aria-label="Underline" icon={<TextUnderlineRegular />} /> | ||
<Button aria-label="Italic" icon={<TextItalicRegular />} /> | ||
<Button aria-label="Align Left" icon={<TextAlignLeftRegular />} /> | ||
<Button aria-label="Align Center" icon={<TextAlignCenterRegular />} /> | ||
<Button aria-label="Align Right" icon={<TextAlignRightRegular />} /> | ||
<Button aria-label="Copy" icon={<CopyRegular />} /> | ||
<Button aria-label="Cut" icon={<CutRegular />} /> | ||
<Button aria-label="Paste" icon={<ClipboardPasteRegular />} /> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
CircularNavigation.parameters = { | ||
docs: { | ||
description: { | ||
story: [ | ||
'Circular navigation means that focus will keep circling around the collection of focusable elements.', | ||
].join('\n'), | ||
}, | ||
}, | ||
}; |
39 changes: 39 additions & 0 deletions
39
...ct-components/stories/Concepts/FocusManagement/useArrowNavigationGoup/Default.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from 'react'; | ||
import { | ||
TextBoldRegular, | ||
TextUnderlineRegular, | ||
TextItalicRegular, | ||
TextAlignLeftRegular, | ||
TextAlignCenterRegular, | ||
TextAlignRightRegular, | ||
CopyRegular, | ||
ClipboardPasteRegular, | ||
CutRegular, | ||
} from '@fluentui/react-icons'; | ||
import { Button, useArrowNavigationGroup, makeStyles, shorthands } from '@fluentui/react-components'; | ||
|
||
const useStyles = makeStyles({ | ||
container: { | ||
display: 'flex', | ||
...shorthands.gap('5px'), | ||
}, | ||
}); | ||
|
||
export const Default = () => { | ||
const styles = useStyles(); | ||
const attributes = useArrowNavigationGroup({ axis: 'horizontal' }); | ||
|
||
return ( | ||
<div aria-label="Editor toolbar example" role="toolbar" {...attributes} className={styles.container}> | ||
<Button aria-label="Bold" icon={<TextBoldRegular />} /> | ||
<Button aria-label="Underline" icon={<TextUnderlineRegular />} /> | ||
<Button aria-label="Italic" icon={<TextItalicRegular />} /> | ||
<Button aria-label="Align Left" icon={<TextAlignLeftRegular />} /> | ||
<Button aria-label="Align Center" icon={<TextAlignCenterRegular />} /> | ||
<Button aria-label="Align Right" icon={<TextAlignRightRegular />} /> | ||
<Button aria-label="Copy" icon={<CopyRegular />} /> | ||
<Button aria-label="Cut" icon={<CutRegular />} /> | ||
<Button aria-label="Paste" icon={<ClipboardPasteRegular />} /> | ||
</div> | ||
); | ||
}; |
50 changes: 50 additions & 0 deletions
50
...t-components/stories/Concepts/FocusManagement/useArrowNavigationGoup/Memorize.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import * as React from 'react'; | ||
import { | ||
TextBoldRegular, | ||
TextUnderlineRegular, | ||
TextItalicRegular, | ||
TextAlignLeftRegular, | ||
TextAlignCenterRegular, | ||
TextAlignRightRegular, | ||
CopyRegular, | ||
ClipboardPasteRegular, | ||
CutRegular, | ||
} from '@fluentui/react-icons'; | ||
import { Button, useArrowNavigationGroup, makeStyles, shorthands } from '@fluentui/react-components'; | ||
|
||
const useStyles = makeStyles({ | ||
container: { | ||
display: 'flex', | ||
...shorthands.gap('5px'), | ||
}, | ||
}); | ||
|
||
export const Memorize = () => { | ||
const styles = useStyles(); | ||
const attributes = useArrowNavigationGroup({ axis: 'horizontal', circular: true, memorizeCurrent: true }); | ||
|
||
return ( | ||
<div aria-label="Editor toolbar example" role="toolbar" {...attributes} className={styles.container}> | ||
<Button aria-label="Bold" icon={<TextBoldRegular />} /> | ||
<Button aria-label="Underline" icon={<TextUnderlineRegular />} /> | ||
<Button aria-label="Italic" icon={<TextItalicRegular />} /> | ||
<Button aria-label="Align Left" icon={<TextAlignLeftRegular />} /> | ||
<Button aria-label="Align Center" icon={<TextAlignCenterRegular />} /> | ||
<Button aria-label="Align Right" icon={<TextAlignRightRegular />} /> | ||
<Button aria-label="Copy" icon={<CopyRegular />} /> | ||
<Button aria-label="Cut" icon={<CutRegular />} /> | ||
<Button aria-label="Paste" icon={<ClipboardPasteRegular />} /> | ||
</div> | ||
); | ||
}; | ||
|
||
Memorize.parameters = { | ||
docs: { | ||
description: { | ||
story: [ | ||
'When a users tabs out out of the collection of focusable elements, ', | ||
'users will tab back into the last focused element.', | ||
].join('\n'), | ||
}, | ||
}, | ||
}; |
19 changes: 19 additions & 0 deletions
19
...eact-components/stories/Concepts/FocusManagement/useArrowNavigationGoup/index.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useArrowNavigationGroup } from '@fluentui/react-components'; | ||
import descriptionMd from './useArrowNavigationGroupDescription.md'; | ||
|
||
export { Default } from './Default.stories'; | ||
export { Axis } from './Axis.stories'; | ||
export { CircularNavigation } from './CircularNavigation.stories'; | ||
export { Memorize } from './Memorize.stories'; | ||
|
||
export default { | ||
title: 'Utilities/Focus Management/useArrowNavigationGroup', | ||
component: useArrowNavigationGroup, | ||
parameters: { | ||
docs: { | ||
description: { | ||
component: [descriptionMd].join('\n'), | ||
}, | ||
}, | ||
}, | ||
}; |
6 changes: 6 additions & 0 deletions
6
...ts/FocusManagement/useArrowNavigationGoup/useArrowNavigationGroupDescription.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
This hook enables keyboard navigation using the arrow keys (up/down/left/right), among a collection of | ||
focusable elements. This hook is powered using the [Mover API in tabster](http://tabster.io/docs/mover/). | ||
In addition to the arrow keys, Home and End keys will navigate to the first and last focusable element in the collection | ||
respectively. | ||
|
||
> NOTE: Elements with `tabindex="-1"` are considered unfocusable by tabster and will be skipped. |
Oops, something went wrong.