Skip to content

Commit

Permalink
Merge pull request #342 from springload/feature/react-18-useid
Browse files Browse the repository at this point in the history
Preparing for React 18 (useId)
  • Loading branch information
Matthew Holloway authored Apr 19, 2022
2 parents c9aded3 + 8cd999a commit b555698
Show file tree
Hide file tree
Showing 20 changed files with 2,584 additions and 2,106 deletions.
12 changes: 6 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2
jobs:
install-job:
docker:
- image: circleci/node:dubnium
- image: circleci/node:erbium
working_directory: ~/repo
steps:
- checkout
Expand All @@ -24,7 +24,7 @@ jobs:

test-job:
docker:
- image: circleci/node:dubnium
- image: circleci/node:erbium

working_directory: ~/repo

Expand All @@ -36,7 +36,7 @@ jobs:

lint-job:
docker:
- image: circleci/node:dubnium
- image: circleci/node:erbium

working_directory: ~/repo

Expand All @@ -48,7 +48,7 @@ jobs:

build-job:
docker:
- image: circleci/node:dubnium
- image: circleci/node:erbium

working_directory: ~/repo

Expand All @@ -60,7 +60,7 @@ jobs:

coverage-job:
docker:
- image: circleci/node:dubnium
- image: circleci/node:erbium

working_directory: ~/repo

Expand All @@ -73,7 +73,7 @@ jobs:

integration-job:
docker:
- image: circleci/node:dubnium-browsers
- image: circleci/node:erbium-browsers

working_directory: ~/repo

Expand Down
21 changes: 11 additions & 10 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
module.exports = {
parser: "@typescript-eslint/parser",
parser: '@typescript-eslint/parser',
parserOptions: {
jsx: true,
},
plugins: ["react", "@typescript-eslint", "jsx-a11y"],
plugins: ['react', '@typescript-eslint', 'jsx-a11y'],
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jsx-a11y/recommended",
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:jsx-a11y/recommended',
],
settings: {
react: {
pragma: "React",
version: "detect",
pragma: 'React',
version: 'detect',
},
},
rules: {
"@typescript-eslint/no-non-null-assertion": "off",
"react/prop-types": "off",
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'react/prop-types': 'off',
},
};
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
lts/dubnium
lts/erbium
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,35 @@
> All notable changes to this project are documented in this file. This project
> adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [[v5.0.0]](https://github.com/springload/react-accessible-accordion/releases/tag/v5.0.0)

React Accessible Accordion now supports React 18 with its out-of-order streaming
feature.

The new out-of-order streaming feature required using React 18's
[`useId`](https://reactjs.org/blog/2022/03/29/react-v18.html#useid) hook. This
affects the DOM ids that RAA generates, changing from `accordion__heading-raa-0`
(React 16 and 17) to `accordion__heading-:r0:` (React 18). Although this change
shouldn't affect most users, if you have any code that selects ids with DOM APIs
such as `document.querySelector()` then the `:` characters will need escaping
with `\\` eg. `document.querySelector('#accordion__heading-\\:r0\\:')`.

When using older versions of React 16 or 17 the same DOM ids will be generated.

Because of this change in behaviour this is a major version upgrade.

## [[v4.0.0]](https://github.com/springload/react-accessible-accordion/releases/tag/v4.0.0)

Making `role="region"` optional on panels.

The new behaviour has no `role="region"` by default, and developers can opt-in
using the `region` prop as `<AccordionItemPanel region>`.

The previous behaviour had every panel as a `role="region"` which created an
excessive amount of regions for the screen reader.

Because of this change in behaviour this is a major version upgrade.

## [[v3.3.0]](https://github.com/springload/react-accessible-accordion/releases/tag/v3.3.0)

### Changed
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ to get in touch via our
## FAQs
### React 18?
RAA supports React 18, and the new out-of-order streaming feature. See the
CHANGELOG for details.
### Which design patterns does this component aim to solve?
Those described by the WAI ARIA spec's description of an 'accordion':
Expand All @@ -225,8 +230,8 @@ description, as written above. By "accordion-like", we mean components which
have collapsible items but require bespoke interactive mechanisms in order to
expand, collapse and 'disable' them. This includes (but is not limited to)
multi-step forms, like those seen in many cart/checkout flows, which we believe
require (other) complex markup in order to be considered 'accessible'.
This also includes disclosure widgets.
require (other) complex markup in order to be considered 'accessible'. This also
includes disclosure widgets.
### How do I disable an item?
Expand Down
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-accessible-accordion",
"version": "4.0.0",
"version": "5.0.0",
"description": "Accessible Accordion component for React",
"main": "dist/umd/index.js",
"module": "dist/es/index.js",
Expand Down Expand Up @@ -89,12 +89,12 @@
"@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.1.0",
"@testing-library/react": "^8.0.4",
"@testing-library/react": "12",
"@types/jest": "^24.0.15",
"@types/react": "^16.8.22",
"@types/react-dom": "^16.8.4",
"@types/react": "^18.0.5",
"@types/react-dom": "^18.0.1",
"@types/react-syntax-highlighter": "^11.0.4",
"@types/react-test-renderer": "^16.8.2",
"@types/react-test-renderer": "^18.0.0",
"@types/uuid": "^3.4.4",
"@typescript-eslint/eslint-plugin": "^3.6.0",
"@typescript-eslint/parser": "^3.6.0",
Expand All @@ -115,8 +115,8 @@
"mini-css-extract-plugin": "^0.7.0",
"prettier": "^2.0.5",
"puppeteer": "2.0.0",
"react": "16.8.0",
"react-dom": "16.8.0",
"react": "17",
"react-dom": "17",
"react-syntax-highlighter": "^12.2.1",
"react-test-renderer": "^16.8.6",
"rimraf": "^2.6.3",
Expand All @@ -133,8 +133,8 @@
"webpack-dev-server": "^3.2.1"
},
"peerDependencies": {
"react": "^16.3.2 || ^17.0.0",
"react-dom": "^16.3.3 || ^17.0.0"
"react": "^16.3.2 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.3.3 || ^17.0.0 || ^18.0.0"
},
"husky": {
"hooks": {
Expand Down
6 changes: 3 additions & 3 deletions src/components/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as React from 'react';
import { DivAttributes } from '../helpers/types';
import { Provider } from './AccordionContext';
import { UUID } from './ItemContext';
import { ID } from './ItemContext';

type AccordionProps = Pick<
DivAttributes,
Exclude<keyof DivAttributes, 'onChange'>
> & {
className?: string;
preExpanded?: UUID[];
preExpanded?: ID[];
allowMultipleExpanded?: boolean;
allowZeroExpanded?: boolean;
onChange?(args: UUID[]): void;
onChange?(args: ID[]): void;
};

const Accordion = ({
Expand Down
28 changes: 14 additions & 14 deletions src/components/AccordionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ import AccordionStore, {
InjectedHeadingAttributes,
InjectedPanelAttributes,
} from '../helpers/AccordionStore';
import { UUID } from './ItemContext';
import { ID } from './ItemContext';

export interface ProviderProps {
preExpanded?: UUID[];
preExpanded?: ID[];
allowMultipleExpanded?: boolean;
allowZeroExpanded?: boolean;
children?: React.ReactNode;
onChange?(args: UUID[]): void;
onChange?(args: ID[]): void;
}

type ProviderState = AccordionStore;

export interface AccordionContext {
allowMultipleExpanded: boolean;
allowZeroExpanded: boolean;
toggleExpanded(uuid: UUID): void;
isItemDisabled(uuid: UUID): boolean;
isItemExpanded(uuid: UUID): boolean;
toggleExpanded(uuid: ID): void;
isItemDisabled(uuid: ID): boolean;
isItemExpanded(uuid: ID): boolean;
getPanelAttributes(
uuid: UUID,
uuid: ID,
dangerouslySetExpanded?: boolean,
): InjectedPanelAttributes;
getHeadingAttributes(uuid: UUID): InjectedHeadingAttributes;
getHeadingAttributes(uuid: ID): InjectedHeadingAttributes;
getButtonAttributes(
uuid: UUID,
uuid: ID,
dangerouslySetExpanded?: boolean,
): InjectedButtonAttributes;
}
Expand All @@ -52,7 +52,7 @@ export class Provider extends React.PureComponent<
allowZeroExpanded: this.props.allowZeroExpanded,
});

toggleExpanded = (key: UUID): void => {
toggleExpanded = (key: ID): void => {
this.setState(
(state: Readonly<ProviderState>) => state.toggleExpanded(key),
() => {
Expand All @@ -63,16 +63,16 @@ export class Provider extends React.PureComponent<
);
};

isItemDisabled = (key: UUID): boolean => {
isItemDisabled = (key: ID): boolean => {
return this.state.isItemDisabled(key);
};

isItemExpanded = (key: UUID): boolean => {
isItemExpanded = (key: ID): boolean => {
return this.state.isItemExpanded(key);
};

getPanelAttributes = (
key: UUID,
key: ID,
dangerouslySetExpanded?: boolean,
): InjectedPanelAttributes => {
return this.state.getPanelAttributes(key, dangerouslySetExpanded);
Expand All @@ -84,7 +84,7 @@ export class Provider extends React.PureComponent<
};

getButtonAttributes = (
key: UUID,
key: ID,
dangerouslySetExpanded?: boolean,
): InjectedButtonAttributes => {
return this.state.getButtonAttributes(key, dangerouslySetExpanded);
Expand Down
8 changes: 4 additions & 4 deletions src/components/AccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import * as React from 'react';
import { useState } from 'react';
import DisplayName from '../helpers/DisplayName';
import { DivAttributes } from '../helpers/types';
import { assertValidHtmlId, nextUuid } from '../helpers/uuid';
import { assertValidHtmlId, useNextId } from '../helpers/id';
import {
Consumer as ItemConsumer,
ItemContext,
Provider as ItemProvider,
UUID,
ID,
} from './ItemContext';

type Props = DivAttributes & {
uuid?: UUID;
uuid?: ID;
activeClassName?: string;
dangerouslySetExpanded?: boolean;
};
Expand All @@ -23,7 +23,7 @@ const AccordionItem = ({
activeClassName,
...rest
}: Props): JSX.Element => {
const [instanceUuid] = useState<UUID>(nextUuid());
const [instanceUuid] = useState<ID>(useNextId());
const uuid = customUuid ?? instanceUuid;

const renderChildren = (itemContext: ItemContext): JSX.Element => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/AccordionItemButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '../helpers/focus';
import keycodes from '../helpers/keycodes';
import { DivAttributes } from '../helpers/types';
import { assertValidHtmlId } from '../helpers/uuid';
import { assertValidHtmlId } from '../helpers/id';

import { Consumer as ItemConsumer, ItemContext } from './ItemContext';

Expand Down Expand Up @@ -91,7 +91,7 @@ type WrapperProps = Pick<
Exclude<keyof DivAttributes, keyof InjectedButtonAttributes>
>;

const AccordionItemButtonWrapper: React.SFC<WrapperProps> = (
const AccordionItemButtonWrapper: React.FC<WrapperProps> = (
props: WrapperProps,
): JSX.Element => (
<ItemConsumer>
Expand Down
4 changes: 2 additions & 2 deletions src/components/AccordionItemHeading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import { InjectedHeadingAttributes } from '../helpers/AccordionStore';
import DisplayName from '../helpers/DisplayName';
import { DivAttributes } from '../helpers/types';
import { assertValidHtmlId } from '../helpers/uuid';
import { assertValidHtmlId } from '../helpers/id';

import { Consumer as ItemConsumer, ItemContext } from './ItemContext';

Expand Down Expand Up @@ -71,7 +71,7 @@ type WrapperProps = Pick<
Exclude<keyof DivAttributes, keyof InjectedHeadingAttributes>
>;

const AccordionItemHeadingWrapper: React.SFC<DivAttributes> = (
const AccordionItemHeadingWrapper: React.FC<DivAttributes> = (
props: WrapperProps,
): JSX.Element => (
<ItemConsumer>
Expand Down
8 changes: 6 additions & 2 deletions src/components/AccordionItemPanel.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ describe('AccordionItem', () => {
</Accordion>,
);
expect(
getByRole('region').getAttribute('aria-labelledby'),
getByRole('region', { hidden: true }).getAttribute(
'aria-labelledby',
),
).toBeTruthy();
});

Expand All @@ -101,7 +103,9 @@ describe('AccordionItem', () => {
const { getByText, queryByRole } = render(
<Accordion>
<AccordionItem>
<AccordionItemPanel region={false}>Hello World</AccordionItemPanel>
<AccordionItemPanel region={false}>
Hello World
</AccordionItemPanel>
</AccordionItem>
</Accordion>,
);
Expand Down
Loading

0 comments on commit b555698

Please sign in to comment.