microsoft / microsoft/fluentui

[Feature]: sharing IDREF between compound components

Open
#24,163 12 comments 0 reactions 1 assignee View on GitHub

@bsunderhus is already working on this.

Since Aug 1, 2022.

Component: Dialog Component: Menu Fluent UI react-components (v9) Resolution: Soft Close Type: Feature
Dominant language
TypeScript
Stars
20.3k
Forks
2.9k
Avg merge
2d 9h
Merged PRs (30d)
46

Description

Library

React Components / v9 (@fluentui/react-components)

Describe the feature that you would like added

Current behavior

Most of v9 components introduce a default ID by context and passing it down the line to its compound component to consume.

// MenuGroup

export function useMenuGroup_unstable(props: MenuGroupProps, ref: React.Ref<HTMLElement>): MenuGroupState {
  const headerId = useId('menu-group');

  return {
    components: {
      root: 'div',
    },
    root: getNativeElementProps('div', {
      ref,
      'aria-labelledby': headerId, // adds aria attribute with header id
      role: 'group',
      ...props,
    }),
    headerId: headerId, // passes header id to be added through context
  };
}

// MenuGroupHeader

export function useMenuGroupHeader_unstable(
  props: MenuGroupHeaderProps,
  ref: React.Ref<HTMLElement>,
): MenuGroupHeaderState {
  const { headerId: id } = useMenuGroupContext_unstable(); // consumes headerId from MenuGroup provided context

  return {
    components: {
      root: 'div',
    },
    root: getNativeElementProps('div', {
      ref,
      id,
      ...props,
    }),
  };
}

Problem Statement

Some ARIA Patterns require Id references being shared between compound components through Context to ensure functionality, for example: aria-labelledby, aria-describedby, aria-controls, etc,.

In the example usage above of MenuGroup and MenuGroupHeader, If the user provides its own id to MenuGroupHeader, and stops using the one provided by context, then MenuGroup would start pointing aria-labelledby to the wrong place. Current solution is documenting this problem and stating for the user that it is its own job to re-introduce the proper aria-labelledby attribute on its own:

export const GroupingItems = () => (
  <Menu>
    <MenuTrigger>
      <Button>Toggle menu</Button>
    </MenuTrigger>

    <MenuPopover>
      <MenuList>
        {/* aria-labelledby should be re-introduced here, otherwise MenuGroup would point to a unused id */}
        <MenuGroup aria-labelledby="custom-id">
          <MenuGroupHeader id="custom-id">Section header</MenuGroupHeader>
          <MenuItem icon={<CutIcon />}>Cut</MenuItem>
          <MenuItem icon={<PasteIcon />}>Paste</MenuItem>
          <MenuItem icon={<EditIcon />}>Edit</MenuItem>
        </MenuGroup>
        <MenuDivider />
      </MenuList>
    </MenuPopover>
  </Menu>
);

Feature Request

To solve this problem, some sort of context mechanism to add IDREF between compound components is required.

One problem with this is the extra render this would require in the case a child component updates its id reference to its parent, but so far, I can't think of a better solution.

THIS IS STILL OPEN FOR DEBATE

Have you discussed this feature with our team

teams-prague

Additional context

No response

Validations
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.