From d8a6781586ce965da098219962ed749a37624575 Mon Sep 17 00:00:00 2001 From: YuanboXue-Amber Date: Wed, 31 May 2023 19:46:31 +0200 Subject: [PATCH 1/4] changes --- .../react-components/react-tags/package.json | 1 + .../src/components/TagGroup/useTagGroup.ts | 28 ++++++++++++++++--- .../react-tags/stories/Tag/TagDescription.md | 1 + .../TagButton/TagButtonBestPractices.md | 2 ++ .../stories/TagButton/TagButtonDescription.md | 1 + .../stories/TagGroup/TagGroupBestPractices.md | 4 +++ .../stories/TagGroup/TagGroupDescription.md | 1 + .../TagGroup/TagGroupDismiss.stories.tsx | 8 +++--- 8 files changed, 38 insertions(+), 8 deletions(-) diff --git a/packages/react-components/react-tags/package.json b/packages/react-components/react-tags/package.json index 0367f86414010d..6d5f811e615766 100644 --- a/packages/react-components/react-tags/package.json +++ b/packages/react-components/react-tags/package.json @@ -39,6 +39,7 @@ "@fluentui/react-avatar": "^9.5.5", "@fluentui/react-icons": "^2.0.196", "@fluentui/react-jsx-runtime": "9.0.0-alpha.6", + "@fluentui/react-shared-contexts": "^9.5.0", "@fluentui/react-tabster": "^9.7.5", "@fluentui/react-theme": "^9.1.8", "@fluentui/react-utilities": "^9.9.2", diff --git a/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts b/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts index 5da937f4212447..13077cf0d2931f 100644 --- a/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts +++ b/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts @@ -1,6 +1,8 @@ import * as React from 'react'; -import { getNativeElementProps, useEventCallback } from '@fluentui/react-utilities'; +import { getNativeElementProps, useEventCallback, useMergedRefs } from '@fluentui/react-utilities'; import type { TagGroupProps, TagGroupState } from './TagGroup.types'; +import { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster'; +import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts'; /** * Create the state required to render TagGroup. @@ -14,10 +16,27 @@ import type { TagGroupProps, TagGroupState } from './TagGroup.types'; export const useTagGroup_unstable = (props: TagGroupProps, ref: React.Ref): TagGroupState => { const { onDismiss, size = 'medium' } = props; + const innerRef = React.useRef(); + const { targetDocument } = useFluent(); + const { findNextFocusable, findFirstFocusable } = useFocusFinders(); + const handleTagDismiss = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, id: string) => { onDismiss?.(e, { dismissedTagValue: id }); - // TODO set focus after tag dismiss + // set focus after tag dismiss + const activeElement = targetDocument?.activeElement; + if (innerRef.current?.contains(activeElement as HTMLElement)) { + // focus on next tag only if the active element is within the current tag group + const next = + findNextFocusable(activeElement as HTMLElement, { container: innerRef.current }) ?? + findFirstFocusable(innerRef.current as HTMLElement); + next?.focus(); + } + }); + + const arrowNavigationProps = useArrowNavigationGroup({ + circular: true, + axis: 'both', }); return { @@ -30,9 +49,10 @@ export const useTagGroup_unstable = (props: TagGroupProps, ref: React.Ref { const defaultItems = [ - { value: '1', children: 'Tag 1' }, - { value: '2', children: 'Tag 2' }, - { value: 'tagButton-foo', children: 'Foo' }, - { value: 'tagButton-bar', children: 'Bar' }, + { value: '1', children: 'Tag 1', 'aria-label': 'Tag1, remove' }, + { value: '2', children: 'Tag 2', 'aria-label': 'Tag2, remove' }, + { value: 'tagButton-foo', children: 'Foo', dismissButton: { 'aria-label': 'Foo, remove' } }, + { value: 'tagButton-bar', children: 'Bar', dismissButton: { 'aria-label': 'Bar, remove' } }, ]; const [items, setItems] = React.useState>(defaultItems); From 040c0caa519d57caa0d37c16a376f34c815057af Mon Sep 17 00:00:00 2001 From: YuanboXue-Amber Date: Thu, 1 Jun 2023 10:39:03 +0200 Subject: [PATCH 2/4] mention picker --- .../react-tags/stories/TagGroup/TagGroupBestPractices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-components/react-tags/stories/TagGroup/TagGroupBestPractices.md b/packages/react-components/react-tags/stories/TagGroup/TagGroupBestPractices.md index 7746d597264369..0be386c6dd82ba 100644 --- a/packages/react-components/react-tags/stories/TagGroup/TagGroupBestPractices.md +++ b/packages/react-components/react-tags/stories/TagGroup/TagGroupBestPractices.md @@ -2,7 +2,7 @@ ### Do -- When using `TagGroup` with `Combobox` to display multiple selected values: +- A Picker component is planned for displaying multiple selected values using `TagGroup` with `Combobox`, and will be the recommended approach once it's available. But for now, when using `TagGroup` with `Combobox`: - Set the `listbox` role for `TagGroup` and the `option` role for each `Tag`. - If using `TagButton`, set the `option` role for the content and make the dismiss button not focusable. When content is focused, Enter/Space should invoke the primary action, and Backspace/Delete remove the tag. From 5978a1fb7d217a74202544176d66cc858d318566 Mon Sep 17 00:00:00 2001 From: YuanboXue-Amber Date: Mon, 5 Jun 2023 10:42:47 +0200 Subject: [PATCH 3/4] focus on prev tag when remove last tag in group --- .../react-tags/src/components/TagGroup/useTagGroup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts b/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts index 13077cf0d2931f..8cd7664ba60cb1 100644 --- a/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts +++ b/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts @@ -18,7 +18,7 @@ export const useTagGroup_unstable = (props: TagGroupProps, ref: React.Ref(); const { targetDocument } = useFluent(); - const { findNextFocusable, findFirstFocusable } = useFocusFinders(); + const { findNextFocusable, findPrevFocusable } = useFocusFinders(); const handleTagDismiss = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, id: string) => { onDismiss?.(e, { dismissedTagValue: id }); @@ -29,7 +29,7 @@ export const useTagGroup_unstable = (props: TagGroupProps, ref: React.Ref Date: Mon, 5 Jun 2023 12:36:00 +0200 Subject: [PATCH 4/4] fix --- .../src/components/TagGroup/useTagGroup.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts b/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts index 8cd7664ba60cb1..1cdf4937d92e36 100644 --- a/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts +++ b/packages/react-components/react-tags/src/components/TagGroup/useTagGroup.ts @@ -3,6 +3,7 @@ import { getNativeElementProps, useEventCallback, useMergedRefs } from '@fluentu import type { TagGroupProps, TagGroupState } from './TagGroup.types'; import { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster'; import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts'; +import { tagButtonClassNames } from '../TagButton/useTagButtonStyles.styles'; /** * Create the state required to render TagGroup. @@ -27,10 +28,20 @@ export const useTagGroup_unstable = (props: TagGroupProps, ref: React.Ref