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

feat: allow multiple opaque identifiers in HTML attributes #18594

Closed
eps1lon opened this issue Apr 13, 2020 · 10 comments
Closed

feat: allow multiple opaque identifiers in HTML attributes #18594

eps1lon opened this issue Apr 13, 2020 · 10 comments

Comments

@eps1lon
Copy link
Collaborator

eps1lon commented Apr 13, 2020

react version: #17322
Original: #17322 (comment)

Currently only a single value from useOpaqueIdentifier (unreleased) can be passed to HTML attributes. However, there are HTML attributes which support multiple ids (IDREFS) like aria-labelledby. This can be used to implement various patterns such as:

export default function App() {
  const taxpayerId = React.unstable_useOpaqueIdentifier();
  const spouseId = React.unstable_useOpaqueIdentifier();
  const w2GrossId = React.unstable_useOpaqueIdentifier();
  const dividendsId = React.unstable_useOpaqueIdentifier();
  return (
    <table>
      <tbody>
        <tr>
          <td />
          <th id={taxpayerId}>Taxpayer</th>
          <th id={spouseId}>Spouse</th>
        </tr>

        <tr>
          <th id={w2GrossId}>W2 Gross</th>
          <td>
            <input type="text" aria-labelledby={[taxpayerId, w2GrossId]} />
          </td>
          <td>
            <input type="text" aria-labelledby={[spouseId, w2GrossId]} />
          </td>
        </tr>

        <tr>
          <th id={dividendsId}>Dividends</th>
          <td>
            <input type="text" aria-labelledby={[taxpayerId, dividendsId]} />
          </td>
          <td>
            <input type="text" aria-labelledby={[spouseId, dividendsId]} />
          </td>
        </tr>
      </tbody>
    </table>
  );
}

-- https://codesandbox.io/s/useopaqueidentifier-for-idrefs-ocnm4

This example is from https://www.w3.org/WAI/GL/wiki/Using_aria-labelledby_to_concatenate_a_label_from_several_text_nodes

This currently almost works but it concatenates the ids with "," (default toString of arrays) instead of " ".

<button aria-labelledby={[opaqueIdentifier1, opaqueIdentifier1]} /> is to me the most intuitive one since we're passing a list of ids.

Edit:
Removed the collapsible listbox example since that pattern has some a11y issue.

@aweary
Copy link
Contributor

aweary commented Apr 13, 2020

I like the API of using an array of opaque identifiers. You could make the argument that React should always join arrays passed to DOM attributes with a space, since the HTML spec defines the space as the list delimiter. This would be a breaking change though.

One alternative would be iterating through every array passed to an attribute and checking that each item is an opaque identifier, but that's a lot of potentially wasted work.

Maybe a special value like React.createIdentifierList that React could check for and serialize differently?

@aweary
Copy link
Contributor

aweary commented Apr 13, 2020

@eps1lon I believe you can safely get around this for now by using a custom class that extends Array and overrides toString.

@eps1lon
Copy link
Collaborator Author

eps1lon commented Apr 13, 2020

Maybe a special value like React.createIdentifierList that React could check for and serialize differently?

Which also has the upside that it won't trigger jsx-a11y/aria-proptypes or TypeScript type errors (we would need to claim that opaque identifiers are strings for TS to accept it. On the other hand we need to change types anyway for useOpaqueIdentifier) .

Having the array shorthand is definitely nice but I think having an explicit createIdentifierList is safer long term.

@eps1lon
Copy link
Collaborator Author

eps1lon commented May 3, 2020

@aweary Seems like your approach only works for .render. It throws during hydration (using .hydrate with

The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.

-- https://codesandbox.io/s/serverless-tdd-7ltt5

@stale
Copy link

stale bot commented Aug 2, 2020

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Aug 2, 2020
@diegohaz
Copy link

diegohaz commented Aug 2, 2020

Bump

@stale stale bot removed the Resolution: Stale Automatically closed due to inactivity label Aug 2, 2020
@stale
Copy link

stale bot commented Dec 25, 2020

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Dec 25, 2020
@diegohaz
Copy link

Bump

@gaearon
Copy link
Collaborator

gaearon commented Mar 24, 2021

I’ve added a label to revisit so that stale bot stops trying to close this.

@eps1lon
Copy link
Collaborator Author

eps1lon commented Dec 8, 2021

Implemented with useId in #22644

@eps1lon eps1lon closed this as completed Dec 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants