Skip to content

Commit 80e21c8

Browse files
authored
Merge pull request #269 from springload/feature/manual-state-override
Add manual state with dangerouslySetExpanded
2 parents 76a515e + d1ea367 commit 80e21c8

File tree

11 files changed

+179
-58
lines changed

11 files changed

+179
-58
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ Allow the only remaining expanded item to be collapsed.
9797
9898
#### preExpanded: `string[]` [_optional_, default: `[]`]
9999
100-
Accepts an array of strings and any `AccordionItem` whose `uuid` prop matches any one
101-
of these strings will be expanded on mount.
100+
Accepts an array of strings and any `AccordionItem` whose `uuid` prop matches
101+
any one of these strings will be expanded on mount.
102102
103103
#### className : `string` [*optional*, default: `'accordion'`]
104104
@@ -121,6 +121,12 @@ Class(es) to apply to element.
121121
122122
Recommended for use with `onChange`. Will be auto-generated if not provided.
123123
124+
#### dangerouslySetExpanding: `boolean` [*optional*]
125+
126+
Enables external control of the expansion.
127+
128+
> Warning: This may impact accessibility negatively, use at your own risk
129+
124130
---
125131
126132
### AccordionItemHeading

babel.config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ module.exports = api => {
1616
'@babel/preset-typescript',
1717
];
1818

19-
const plugins = ['@babel/plugin-proposal-class-properties'];
19+
const plugins = [
20+
'@babel/plugin-proposal-class-properties',
21+
'@babel/plugin-proposal-nullish-coalescing-operator',
22+
];
2023

2124
return {
2225
presets,

demo/src/index.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,43 @@ const App = (): JSX.Element => (
193193
</AccordionItem>
194194
))}
195195
</Accordion>
196+
197+
<h2 className="u-margin-top">Manual state</h2>
198+
199+
<p>
200+
When you use the <strong>onChange</strong> prop, you can get
201+
feedback about which items are expanded.
202+
</p>
203+
204+
<p>
205+
In this example, we are simply logging the uuids of the expanded
206+
items to the console. Have a click around then check your console to
207+
see this in action.
208+
</p>
209+
210+
<Accordion>
211+
{placeholders.map((placeholder: Placeholder, i: number) => {
212+
const isExpanded = i < 2;
213+
214+
return (
215+
<AccordionItem
216+
key={placeholder.heading}
217+
uuid={placeholder.uuid}
218+
// Warning: This can impact accessibility negatively
219+
dangerouslySetExpanded={isExpanded}
220+
>
221+
<AccordionItemHeading>
222+
<AccordionItemButton>
223+
{placeholder.heading}
224+
</AccordionItemButton>
225+
</AccordionItemHeading>
226+
<AccordionItemPanel>
227+
{placeholder.panel}
228+
</AccordionItemPanel>
229+
</AccordionItem>
230+
);
231+
})}
232+
</Accordion>
196233
</>
197234
);
198235

integration/__snapshots__/wai-aria.spec.js.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,26 @@ Object {
77
"name": "Heading One",
88
"role": "button",
99
},
10+
Object {
11+
"name": "Sunt in reprehenderit cillum ex proident qui culpa fugiat pariatur aliqua nostrud consequat consequat enim quis sit consectetur ad aute ea ex eiusmod id esse culpa et pariatur ad amet pariatur pariatur dolor quis.",
12+
"role": "text",
13+
},
1014
Object {
1115
"name": "Heading Two",
1216
"role": "button",
1317
},
18+
Object {
19+
"name": "Velit tempor dolore commodo voluptate id do nulla do ut proident cillum ad cillum voluptate deserunt fugiat ut sed cupidatat ut consectetur consequat incididunt sed in culpa do labore ea incididunt ea in eiusmod.",
20+
"role": "text",
21+
},
1422
Object {
1523
"name": "Heading Three",
1624
"role": "button",
1725
},
26+
Object {
27+
"name": "Lorem ipsum esse occaecat voluptate duis incididunt amet eiusmod sunt commodo sunt enim anim ea culpa ut tempor dolore fugiat exercitation aliquip commodo dolore elit esse est ullamco velit et deserunt.",
28+
"role": "text",
29+
},
1830
],
1931
"name": "React Accessible Accordion - Integration Test Sandbox",
2032
"role": "WebArea",

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
"@babel/cli": "^7.4.4",
8181
"@babel/core": "^7.4.5",
8282
"@babel/plugin-proposal-class-properties": "^7.4.4",
83+
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
8384
"@babel/polyfill": "^7.4.4",
8485
"@babel/preset-env": "^7.4.5",
8586
"@babel/preset-react": "^7.0.0",
@@ -102,7 +103,7 @@
102103
"jest": "^24.5.0",
103104
"lint-staged": "^8.1.5",
104105
"mini-css-extract-plugin": "^0.7.0",
105-
"prettier": "^1.16.3",
106+
"prettier": "^2.0.5",
106107
"puppeteer": "2.0.0",
107108
"react": "16.3.2",
108109
"react-dom": "16.3.3",
@@ -114,12 +115,12 @@
114115
"rollup-plugin-node-resolve": "^5.1.0",
115116
"rollup-plugin-replace": "^2.1.1",
116117
"style-loader": "^0.23.1",
117-
"tslint": "^5.14.0",
118+
"tslint": "^6.1.2",
118119
"tslint-config-prettier": "^1.18.0",
119-
"tslint-microsoft-contrib": "^6.1.0",
120-
"tslint-plugin-prettier": "^2.0.1",
121-
"tslint-react": "^4.0.0",
122-
"typescript": "^3.5.2",
120+
"tslint-microsoft-contrib": "^6.2.0",
121+
"tslint-plugin-prettier": "^2.3.0",
122+
"tslint-react": "^5.0.0",
123+
"typescript": "^3.9.5",
123124
"uuid": "^3.3.2",
124125
"webpack": "^4.29.6",
125126
"webpack-cli": "^3.3.0",

src/components/AccordionContext.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ export interface AccordionContext {
2424
toggleExpanded(uuid: UUID): void;
2525
isItemDisabled(uuid: UUID): boolean;
2626
isItemExpanded(uuid: UUID): boolean;
27-
getPanelAttributes(uuid: UUID): InjectedPanelAttributes;
27+
getPanelAttributes(
28+
uuid: UUID,
29+
dangerouslySetExpanded?: boolean,
30+
): InjectedPanelAttributes;
2831
getHeadingAttributes(uuid: UUID): InjectedHeadingAttributes;
29-
getButtonAttributes(uuid: UUID): InjectedButtonAttributes;
32+
getButtonAttributes(
33+
uuid: UUID,
34+
dangerouslySetExpanded?: boolean,
35+
): InjectedButtonAttributes;
3036
}
3137

3238
const Context = React.createContext(null as AccordionContext | null);
@@ -65,16 +71,22 @@ export class Provider extends React.PureComponent<
6571
return this.state.isItemExpanded(key);
6672
};
6773

68-
getPanelAttributes = (key: UUID): InjectedPanelAttributes => {
69-
return this.state.getPanelAttributes(key);
74+
getPanelAttributes = (
75+
key: UUID,
76+
dangerouslySetExpanded?: boolean,
77+
): InjectedPanelAttributes => {
78+
return this.state.getPanelAttributes(key, dangerouslySetExpanded);
7079
};
7180

7281
getHeadingAttributes = (key: UUID): InjectedHeadingAttributes => {
7382
return this.state.getHeadingAttributes(key);
7483
};
7584

76-
getButtonAttributes = (key: UUID): InjectedButtonAttributes => {
77-
return this.state.getButtonAttributes(key);
85+
getButtonAttributes = (
86+
key: UUID,
87+
dangerouslySetExpanded?: boolean,
88+
): InjectedButtonAttributes => {
89+
return this.state.getButtonAttributes(key, dangerouslySetExpanded);
7890
};
7991

8092
render(): JSX.Element {

src/components/AccordionItem.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
type Props = DivAttributes & {
1313
uuid?: UUID;
1414
activeClassName?: string;
15+
dangerouslySetExpanded?: boolean;
1516
};
1617

1718
const defaultProps = {
@@ -40,10 +41,13 @@ export default class AccordionItem extends React.Component<Props> {
4041
};
4142

4243
render(): JSX.Element {
43-
const { uuid = this.instanceUuid } = this.props;
44+
const { uuid = this.instanceUuid, dangerouslySetExpanded } = this.props;
4445

4546
return (
46-
<ItemProvider uuid={uuid}>
47+
<ItemProvider
48+
uuid={uuid}
49+
dangerouslySetExpanded={dangerouslySetExpanded}
50+
>
4751
<ItemConsumer>{this.renderChildren}</ItemConsumer>
4852
</ItemProvider>
4953
);

src/components/ItemContext.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type ProviderProps = {
1717
children?: React.ReactNode;
1818
uuid: UUID;
1919
accordionContext: AccordionContext;
20+
dangerouslySetExpanded?: boolean;
2021
};
2122

2223
export type ProviderWrapperProps = Pick<
@@ -42,13 +43,20 @@ class Provider extends React.Component<ProviderProps> {
4243
};
4344

4445
renderChildren = (accordionContext: AccordionContext): JSX.Element => {
45-
const { uuid } = this.props;
46+
const { uuid, dangerouslySetExpanded } = this.props;
4647

47-
const expanded = accordionContext.isItemExpanded(uuid);
48+
const expanded =
49+
dangerouslySetExpanded ?? accordionContext.isItemExpanded(uuid);
4850
const disabled = accordionContext.isItemDisabled(uuid);
49-
const panelAttributes = accordionContext.getPanelAttributes(uuid);
51+
const panelAttributes = accordionContext.getPanelAttributes(
52+
uuid,
53+
dangerouslySetExpanded,
54+
);
5055
const headingAttributes = accordionContext.getHeadingAttributes(uuid);
51-
const buttonAttributes = accordionContext.getButtonAttributes(uuid);
56+
const buttonAttributes = accordionContext.getButtonAttributes(
57+
uuid,
58+
dangerouslySetExpanded,
59+
);
5260

5361
return (
5462
<Context.Provider

src/helpers/AccordionStore.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ export default class AccordionStore {
8383

8484
public readonly getPanelAttributes = (
8585
uuid: UUID,
86+
dangerouslySetExpanded?: boolean,
8687
): InjectedPanelAttributes => {
87-
const expanded = this.isItemExpanded(uuid);
88+
const expanded = dangerouslySetExpanded ?? this.isItemExpanded(uuid);
8889

8990
return {
9091
role: this.allowMultipleExpanded ? undefined : 'region',
@@ -105,8 +106,9 @@ export default class AccordionStore {
105106

106107
public readonly getButtonAttributes = (
107108
uuid: UUID,
109+
dangerouslySetExpanded?: boolean,
108110
): InjectedButtonAttributes => {
109-
const expanded = this.isItemExpanded(uuid);
111+
const expanded = dangerouslySetExpanded ?? this.isItemExpanded(uuid);
110112
const disabled = this.isItemDisabled(uuid);
111113

112114
return {

tslint.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"typedef": [
1717
true,
1818
"call-signature",
19-
"arrow-call-signature",
2019
"parameter",
2120
"arrow-parameter",
2221
"property-declaration",

0 commit comments

Comments
 (0)