Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toolbar component #5080

Merged
merged 22 commits into from
Oct 10, 2023
Merged

Toolbar component #5080

merged 22 commits into from
Oct 10, 2023

Conversation

snowystinger
Copy link
Member

@snowystinger snowystinger commented Sep 15, 2023

Closes

Update: Scope reduced, this only supports children of types: Button, Checkbox, Link, RSP ActionGroup

Guidance from accessibility:

ActionGroup should support role="group" so that you can have groups within a toolbar without nesting toolbars.

I've tested this out. If the toolbars are nested, then the outermost label is not read. If the inner toolbars are groups, then both labels are read as expected. This can be seen simply in this demo. I recommend popping out into a new window before using VO.
https://codesandbox.io/s/sleepy-northcutt-hfhwnr?file=/src/App.js

Implementing a subset of https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/examples/toolbar/

Open questions, do we need the RSP component?
Answer: Not at the moment, we don't want this held up by a design review.

  • extra info: I've created a basic version of it so that we can test interactions with ActionGroup, which is the currently the primary use case. What I've implemented is pretty much what anyone else would need to implement to use it in Spectrum.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

# Conflicts:
#	packages/react-aria-components/stories/index.stories.tsx
@rspbot
Copy link

rspbot commented Sep 15, 2023

@rspbot
Copy link

rspbot commented Sep 15, 2023

# Conflicts:
#	packages/react-aria-components/src/index.ts
#	packages/react-aria-components/stories/index.stories.tsx
@rspbot
Copy link

rspbot commented Sep 18, 2023

@rspbot
Copy link

rspbot commented Sep 18, 2023

@rspbot
Copy link

rspbot commented Sep 20, 2023

@rspbot
Copy link

rspbot commented Sep 20, 2023

// Any reason not to include ref? i feel like we've been sad about not including it down the line
// same with state...
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function useToolbar(props: ToolbarProps & {isInsideAToolbar: boolean}, ref: ForwardedRef<HTMLDivElement>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to put this in a @react-aria/toolbar package?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previously you and @dannify had been on the fence about it, happy to move it

packages/react-aria-components/src/Toolbar.tsx Outdated Show resolved Hide resolved
packages/react-aria-components/src/Toolbar.tsx Outdated Show resolved Hide resolved
<Radio className={styles.radio} value="right">Right</Radio>
</RadioGroup>
*/}
{/* disabled buttons do not work in toolbar yet, the buttons cannot be focused
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cannot be? isn't that correct?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based off the aria example, some of the disabled buttons are still focusable for screenreaders

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and specifically it says this a little further down the page

While they are HTML button elements, as described in the accessibility features section above, in order to remain focusable when disabled, they have aria-disabled instead of the HTML disabled attribute.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm that's very subjective. I would expect to skip over them by default, otherwise that is inconsistent with everything else we currently implement.

<Button isDisabled>Cut</Button>
</Toolbar>
*/}
{/* select does not work in toolbar yet, focus can't move "Right Arrow" past it
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if our listeners are capturing seems like it should?

Copy link
Member Author

@snowystinger snowystinger Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Determined what happened, I wasn't specifying to the focusmanager to move to the next tabbable element, so focus was going to the hidden select and then right back to the select button, forever

it brings up a bigger issue though, we have some components with non-tabble elements, radio group, which should be navigable by arrow key, and then we have some components with non-tabbable elements, select, which should not be navigable by arrow key (there is a hidden input)

I'm not sure how to distinguish between the two. Any thoughts?

I tried using our accept function in createFocusManager, but ActionGroup isn't implemented as a radiogroup all the time and its button can look very similar to NumberField's increment/decrement buttons...

I don't want to use the context I introduced here because I'm still hoping to find a way to get rid of it

Maybe we could use the FocusScope context to declare if a particular scope intends to control certain keys for navigation within the scope? Problematic that hooks don't have access to our context.

Or we could put a data-attribute on elements like the NumberField increment button that's like, data-reallyNotTabbable... so i'd have something to filter on, hahaha

</ListBox>
</Popover>
</Select>*/}
{/* numberfield does not work in toolbar yet, focus stops on the stepper buttons
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial review, will wrap up after lunch

EDIT: nothing else to comment on that hasn't been touched on by other reviews

packages/@react-types/actiongroup/src/index.d.ts Outdated Show resolved Hide resolved
packages/react-aria-components/src/Toolbar.tsx Outdated Show resolved Hide resolved
packages/react-aria-components/src/Toolbar.tsx Outdated Show resolved Hide resolved
packages/react-aria-components/src/Toolbar.tsx Outdated Show resolved Hide resolved
packages/react-aria-components/src/Toolbar.tsx Outdated Show resolved Hide resolved
@rspbot
Copy link

rspbot commented Sep 21, 2023

@rspbot
Copy link

rspbot commented Sep 25, 2023

@rspbot
Copy link

rspbot commented Sep 26, 2023

@@ -45,7 +45,8 @@ export interface FocusManagerOptions {
/** Whether focus should wrap around when it reaches the end of the scope. */
wrap?: boolean,
/** A callback that determines whether the given element is focused. */
accept?: (node: Element) => boolean
accept?: (node: Element) => boolean,
preview?: boolean
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed so i could use the same setup and determine where focus would move in both the tabbable and focusable case next before actually committing to it

@rspbot
Copy link

rspbot commented Sep 26, 2023

@rspbot
Copy link

rspbot commented Sep 27, 2023

@rspbot
Copy link

rspbot commented Sep 27, 2023

@rspbot
Copy link

rspbot commented Sep 27, 2023

@rspbot
Copy link

rspbot commented Sep 27, 2023

devongovett
devongovett previously approved these changes Oct 10, 2023
Copy link
Member

@devongovett devongovett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. let's get this into the next testing session.

toolbarProps: HTMLAttributes<HTMLElement>
}

// Any reason not to include state? i feel like we've been sad about not including a state arg in the past
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of what state a toolbar would have so probably ok. 🤷


export const ToolbarContext = createContext<ContextValue<ToolbarProps, HTMLDivElement>>({});

function Toolbar(props: ToolbarProps, ref: ForwardedRef<HTMLDivElement>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss whether we want to temporarily name this UNSTABLE_Toolbar before the next release.

# Conflicts:
#	packages/react-aria-components/package.json
@rspbot
Copy link

rspbot commented Oct 10, 2023

@rspbot
Copy link

rspbot commented Oct 10, 2023

## API Changes

unknown top level export { type: 'identifier', name: 'Column' }
unknown top level export { type: 'identifier', name: 'Column' }
unknown type { type: 'link' }
unknown type { type: 'link' }
unknown type { type: 'link' }
unknown type { type: 'link' }
unknown type { type: 'link' }
unknown type { type: 'link' }

@react-aria/toolbar

AriaToolbarProps

-
+AriaToolbarProps {
+  orientation?: Orientation = 'horizontal'
+}

it changed:

  • useToolbar

useToolbar

changed by:

  • AriaToolbarProps
-
+useToolbar {
+  props: AriaToolbarProps
+  ref: RefObject<HTMLDivElement>
+  returnVal: undefined
+}

Copy link
Member

@reidbarber reidbarber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed when using Up/Down arrow on horizontal, focus stays within the groups (and vice versa for vertical). Is this expected?

@snowystinger
Copy link
Member Author

I noticed when using Up/Down arrow on horizontal, focus stays within the groups (and vice versa for vertical). Is this expected?

This is expected https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/ it just happens that ActionGroups use the opposing direction to navigate as well and I just let the child component handle the keys I don't. It's hard to know enough about the children to do anything other than this. For instance, controlling a slider vs navigating a menu vs numberfield spin button. So I think this is an ok interpretation.

Copy link
Member

@reidbarber reidbarber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@snowystinger snowystinger merged commit 7427349 into main Oct 10, 2023
26 checks passed
@snowystinger snowystinger deleted the toolbar-component branch October 10, 2023 21:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants