Skip to content

Commit b555698

Browse files
author
Matthew Holloway
authored
Merge pull request #342 from springload/feature/react-18-useid
Preparing for React 18 (useId)
2 parents c9aded3 + 8cd999a commit b555698

20 files changed

+2584
-2106
lines changed

.circleci/config.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2
22
jobs:
33
install-job:
44
docker:
5-
- image: circleci/node:dubnium
5+
- image: circleci/node:erbium
66
working_directory: ~/repo
77
steps:
88
- checkout
@@ -24,7 +24,7 @@ jobs:
2424

2525
test-job:
2626
docker:
27-
- image: circleci/node:dubnium
27+
- image: circleci/node:erbium
2828

2929
working_directory: ~/repo
3030

@@ -36,7 +36,7 @@ jobs:
3636

3737
lint-job:
3838
docker:
39-
- image: circleci/node:dubnium
39+
- image: circleci/node:erbium
4040

4141
working_directory: ~/repo
4242

@@ -48,7 +48,7 @@ jobs:
4848

4949
build-job:
5050
docker:
51-
- image: circleci/node:dubnium
51+
- image: circleci/node:erbium
5252

5353
working_directory: ~/repo
5454

@@ -60,7 +60,7 @@ jobs:
6060

6161
coverage-job:
6262
docker:
63-
- image: circleci/node:dubnium
63+
- image: circleci/node:erbium
6464

6565
working_directory: ~/repo
6666

@@ -73,7 +73,7 @@ jobs:
7373

7474
integration-job:
7575
docker:
76-
- image: circleci/node:dubnium-browsers
76+
- image: circleci/node:erbium-browsers
7777

7878
working_directory: ~/repo
7979

.eslintrc.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
module.exports = {
2-
parser: "@typescript-eslint/parser",
2+
parser: '@typescript-eslint/parser',
33
parserOptions: {
44
jsx: true,
55
},
6-
plugins: ["react", "@typescript-eslint", "jsx-a11y"],
6+
plugins: ['react', '@typescript-eslint', 'jsx-a11y'],
77
extends: [
8-
"eslint:recommended",
9-
"plugin:react/recommended",
10-
"plugin:@typescript-eslint/recommended",
11-
"plugin:jsx-a11y/recommended",
8+
'eslint:recommended',
9+
'plugin:react/recommended',
10+
'plugin:@typescript-eslint/recommended',
11+
'plugin:jsx-a11y/recommended',
1212
],
1313
settings: {
1414
react: {
15-
pragma: "React",
16-
version: "detect",
15+
pragma: 'React',
16+
version: 'detect',
1717
},
1818
},
1919
rules: {
20-
"@typescript-eslint/no-non-null-assertion": "off",
21-
"react/prop-types": "off",
20+
'@typescript-eslint/ban-ts-comment': 'off',
21+
'@typescript-eslint/no-non-null-assertion': 'off',
22+
'react/prop-types': 'off',
2223
},
2324
};

.nvmrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
lts/dubnium
1+
lts/erbium

CHANGELOG.md

+29
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,35 @@
33
> All notable changes to this project are documented in this file. This project
44
> adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
55
6+
## [[v5.0.0]](https://github.com/springload/react-accessible-accordion/releases/tag/v5.0.0)
7+
8+
React Accessible Accordion now supports React 18 with its out-of-order streaming
9+
feature.
10+
11+
The new out-of-order streaming feature required using React 18's
12+
[`useId`](https://reactjs.org/blog/2022/03/29/react-v18.html#useid) hook. This
13+
affects the DOM ids that RAA generates, changing from `accordion__heading-raa-0`
14+
(React 16 and 17) to `accordion__heading-:r0:` (React 18). Although this change
15+
shouldn't affect most users, if you have any code that selects ids with DOM APIs
16+
such as `document.querySelector()` then the `:` characters will need escaping
17+
with `\\` eg. `document.querySelector('#accordion__heading-\\:r0\\:')`.
18+
19+
When using older versions of React 16 or 17 the same DOM ids will be generated.
20+
21+
Because of this change in behaviour this is a major version upgrade.
22+
23+
## [[v4.0.0]](https://github.com/springload/react-accessible-accordion/releases/tag/v4.0.0)
24+
25+
Making `role="region"` optional on panels.
26+
27+
The new behaviour has no `role="region"` by default, and developers can opt-in
28+
using the `region` prop as `<AccordionItemPanel region>`.
29+
30+
The previous behaviour had every panel as a `role="region"` which created an
31+
excessive amount of regions for the screen reader.
32+
33+
Because of this change in behaviour this is a major version upgrade.
34+
635
## [[v3.3.0]](https://github.com/springload/react-accessible-accordion/releases/tag/v3.3.0)
736

837
### Changed

README.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ to get in touch via our
207207
208208
## FAQs
209209
210+
### React 18?
211+
212+
RAA supports React 18, and the new out-of-order streaming feature. See the
213+
CHANGELOG for details.
214+
210215
### Which design patterns does this component aim to solve?
211216
212217
Those described by the WAI ARIA spec's description of an 'accordion':
@@ -225,8 +230,8 @@ description, as written above. By "accordion-like", we mean components which
225230
have collapsible items but require bespoke interactive mechanisms in order to
226231
expand, collapse and 'disable' them. This includes (but is not limited to)
227232
multi-step forms, like those seen in many cart/checkout flows, which we believe
228-
require (other) complex markup in order to be considered 'accessible'.
229-
This also includes disclosure widgets.
233+
require (other) complex markup in order to be considered 'accessible'. This also
234+
includes disclosure widgets.
230235
231236
### How do I disable an item?
232237

package.json

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-accessible-accordion",
3-
"version": "4.0.0",
3+
"version": "5.0.0",
44
"description": "Accessible Accordion component for React",
55
"main": "dist/umd/index.js",
66
"module": "dist/es/index.js",
@@ -89,12 +89,12 @@
8989
"@babel/preset-env": "^7.4.5",
9090
"@babel/preset-react": "^7.0.0",
9191
"@babel/preset-typescript": "^7.1.0",
92-
"@testing-library/react": "^8.0.4",
92+
"@testing-library/react": "12",
9393
"@types/jest": "^24.0.15",
94-
"@types/react": "^16.8.22",
95-
"@types/react-dom": "^16.8.4",
94+
"@types/react": "^18.0.5",
95+
"@types/react-dom": "^18.0.1",
9696
"@types/react-syntax-highlighter": "^11.0.4",
97-
"@types/react-test-renderer": "^16.8.2",
97+
"@types/react-test-renderer": "^18.0.0",
9898
"@types/uuid": "^3.4.4",
9999
"@typescript-eslint/eslint-plugin": "^3.6.0",
100100
"@typescript-eslint/parser": "^3.6.0",
@@ -115,8 +115,8 @@
115115
"mini-css-extract-plugin": "^0.7.0",
116116
"prettier": "^2.0.5",
117117
"puppeteer": "2.0.0",
118-
"react": "16.8.0",
119-
"react-dom": "16.8.0",
118+
"react": "17",
119+
"react-dom": "17",
120120
"react-syntax-highlighter": "^12.2.1",
121121
"react-test-renderer": "^16.8.6",
122122
"rimraf": "^2.6.3",
@@ -133,8 +133,8 @@
133133
"webpack-dev-server": "^3.2.1"
134134
},
135135
"peerDependencies": {
136-
"react": "^16.3.2 || ^17.0.0",
137-
"react-dom": "^16.3.3 || ^17.0.0"
136+
"react": "^16.3.2 || ^17.0.0 || ^18.0.0",
137+
"react-dom": "^16.3.3 || ^17.0.0 || ^18.0.0"
138138
},
139139
"husky": {
140140
"hooks": {

src/components/Accordion.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import * as React from 'react';
22
import { DivAttributes } from '../helpers/types';
33
import { Provider } from './AccordionContext';
4-
import { UUID } from './ItemContext';
4+
import { ID } from './ItemContext';
55

66
type AccordionProps = Pick<
77
DivAttributes,
88
Exclude<keyof DivAttributes, 'onChange'>
99
> & {
1010
className?: string;
11-
preExpanded?: UUID[];
11+
preExpanded?: ID[];
1212
allowMultipleExpanded?: boolean;
1313
allowZeroExpanded?: boolean;
14-
onChange?(args: UUID[]): void;
14+
onChange?(args: ID[]): void;
1515
};
1616

1717
const Accordion = ({

src/components/AccordionContext.tsx

+14-14
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,31 @@ import AccordionStore, {
66
InjectedHeadingAttributes,
77
InjectedPanelAttributes,
88
} from '../helpers/AccordionStore';
9-
import { UUID } from './ItemContext';
9+
import { ID } from './ItemContext';
1010

1111
export interface ProviderProps {
12-
preExpanded?: UUID[];
12+
preExpanded?: ID[];
1313
allowMultipleExpanded?: boolean;
1414
allowZeroExpanded?: boolean;
1515
children?: React.ReactNode;
16-
onChange?(args: UUID[]): void;
16+
onChange?(args: ID[]): void;
1717
}
1818

1919
type ProviderState = AccordionStore;
2020

2121
export interface AccordionContext {
2222
allowMultipleExpanded: boolean;
2323
allowZeroExpanded: boolean;
24-
toggleExpanded(uuid: UUID): void;
25-
isItemDisabled(uuid: UUID): boolean;
26-
isItemExpanded(uuid: UUID): boolean;
24+
toggleExpanded(uuid: ID): void;
25+
isItemDisabled(uuid: ID): boolean;
26+
isItemExpanded(uuid: ID): boolean;
2727
getPanelAttributes(
28-
uuid: UUID,
28+
uuid: ID,
2929
dangerouslySetExpanded?: boolean,
3030
): InjectedPanelAttributes;
31-
getHeadingAttributes(uuid: UUID): InjectedHeadingAttributes;
31+
getHeadingAttributes(uuid: ID): InjectedHeadingAttributes;
3232
getButtonAttributes(
33-
uuid: UUID,
33+
uuid: ID,
3434
dangerouslySetExpanded?: boolean,
3535
): InjectedButtonAttributes;
3636
}
@@ -52,7 +52,7 @@ export class Provider extends React.PureComponent<
5252
allowZeroExpanded: this.props.allowZeroExpanded,
5353
});
5454

55-
toggleExpanded = (key: UUID): void => {
55+
toggleExpanded = (key: ID): void => {
5656
this.setState(
5757
(state: Readonly<ProviderState>) => state.toggleExpanded(key),
5858
() => {
@@ -63,16 +63,16 @@ export class Provider extends React.PureComponent<
6363
);
6464
};
6565

66-
isItemDisabled = (key: UUID): boolean => {
66+
isItemDisabled = (key: ID): boolean => {
6767
return this.state.isItemDisabled(key);
6868
};
6969

70-
isItemExpanded = (key: UUID): boolean => {
70+
isItemExpanded = (key: ID): boolean => {
7171
return this.state.isItemExpanded(key);
7272
};
7373

7474
getPanelAttributes = (
75-
key: UUID,
75+
key: ID,
7676
dangerouslySetExpanded?: boolean,
7777
): InjectedPanelAttributes => {
7878
return this.state.getPanelAttributes(key, dangerouslySetExpanded);
@@ -84,7 +84,7 @@ export class Provider extends React.PureComponent<
8484
};
8585

8686
getButtonAttributes = (
87-
key: UUID,
87+
key: ID,
8888
dangerouslySetExpanded?: boolean,
8989
): InjectedButtonAttributes => {
9090
return this.state.getButtonAttributes(key, dangerouslySetExpanded);

src/components/AccordionItem.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ import * as React from 'react';
22
import { useState } from 'react';
33
import DisplayName from '../helpers/DisplayName';
44
import { DivAttributes } from '../helpers/types';
5-
import { assertValidHtmlId, nextUuid } from '../helpers/uuid';
5+
import { assertValidHtmlId, useNextId } from '../helpers/id';
66
import {
77
Consumer as ItemConsumer,
88
ItemContext,
99
Provider as ItemProvider,
10-
UUID,
10+
ID,
1111
} from './ItemContext';
1212

1313
type Props = DivAttributes & {
14-
uuid?: UUID;
14+
uuid?: ID;
1515
activeClassName?: string;
1616
dangerouslySetExpanded?: boolean;
1717
};
@@ -23,7 +23,7 @@ const AccordionItem = ({
2323
activeClassName,
2424
...rest
2525
}: Props): JSX.Element => {
26-
const [instanceUuid] = useState<UUID>(nextUuid());
26+
const [instanceUuid] = useState<ID>(useNextId());
2727
const uuid = customUuid ?? instanceUuid;
2828

2929
const renderChildren = (itemContext: ItemContext): JSX.Element => {

src/components/AccordionItemButton.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from '../helpers/focus';
99
import keycodes from '../helpers/keycodes';
1010
import { DivAttributes } from '../helpers/types';
11-
import { assertValidHtmlId } from '../helpers/uuid';
11+
import { assertValidHtmlId } from '../helpers/id';
1212

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

@@ -91,7 +91,7 @@ type WrapperProps = Pick<
9191
Exclude<keyof DivAttributes, keyof InjectedButtonAttributes>
9292
>;
9393

94-
const AccordionItemButtonWrapper: React.SFC<WrapperProps> = (
94+
const AccordionItemButtonWrapper: React.FC<WrapperProps> = (
9595
props: WrapperProps,
9696
): JSX.Element => (
9797
<ItemConsumer>

src/components/AccordionItemHeading.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import { InjectedHeadingAttributes } from '../helpers/AccordionStore';
33
import DisplayName from '../helpers/DisplayName';
44
import { DivAttributes } from '../helpers/types';
5-
import { assertValidHtmlId } from '../helpers/uuid';
5+
import { assertValidHtmlId } from '../helpers/id';
66

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

@@ -71,7 +71,7 @@ type WrapperProps = Pick<
7171
Exclude<keyof DivAttributes, keyof InjectedHeadingAttributes>
7272
>;
7373

74-
const AccordionItemHeadingWrapper: React.SFC<DivAttributes> = (
74+
const AccordionItemHeadingWrapper: React.FC<DivAttributes> = (
7575
props: WrapperProps,
7676
): JSX.Element => (
7777
<ItemConsumer>

src/components/AccordionItemPanel.spec.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ describe('AccordionItem', () => {
7979
</Accordion>,
8080
);
8181
expect(
82-
getByRole('region').getAttribute('aria-labelledby'),
82+
getByRole('region', { hidden: true }).getAttribute(
83+
'aria-labelledby',
84+
),
8385
).toBeTruthy();
8486
});
8587

@@ -101,7 +103,9 @@ describe('AccordionItem', () => {
101103
const { getByText, queryByRole } = render(
102104
<Accordion>
103105
<AccordionItem>
104-
<AccordionItemPanel region={false}>Hello World</AccordionItemPanel>
106+
<AccordionItemPanel region={false}>
107+
Hello World
108+
</AccordionItemPanel>
105109
</AccordionItem>
106110
</Accordion>,
107111
);

0 commit comments

Comments
 (0)