Skip to content

Commit

Permalink
Merge pull request #269 from springload/feature/manual-state-override
Browse files Browse the repository at this point in the history
Add manual state with dangerouslySetExpanded
  • Loading branch information
synecdokey authored Jul 1, 2020
2 parents 76a515e + d1ea367 commit 80e21c8
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 58 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ Allow the only remaining expanded item to be collapsed.
#### preExpanded: `string[]` [_optional_, default: `[]`]
Accepts an array of strings and any `AccordionItem` whose `uuid` prop matches any one
of these strings will be expanded on mount.
Accepts an array of strings and any `AccordionItem` whose `uuid` prop matches
any one of these strings will be expanded on mount.
#### className : `string` [*optional*, default: `'accordion'`]
Expand All @@ -121,6 +121,12 @@ Class(es) to apply to element.
Recommended for use with `onChange`. Will be auto-generated if not provided.
#### dangerouslySetExpanding: `boolean` [*optional*]
Enables external control of the expansion.
> Warning: This may impact accessibility negatively, use at your own risk
---
### AccordionItemHeading
Expand Down
5 changes: 4 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ module.exports = api => {
'@babel/preset-typescript',
];

const plugins = ['@babel/plugin-proposal-class-properties'];
const plugins = [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-nullish-coalescing-operator',
];

return {
presets,
Expand Down
37 changes: 37 additions & 0 deletions demo/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,43 @@ const App = (): JSX.Element => (
</AccordionItem>
))}
</Accordion>

<h2 className="u-margin-top">Manual state</h2>

<p>
When you use the <strong>onChange</strong> prop, you can get
feedback about which items are expanded.
</p>

<p>
In this example, we are simply logging the uuids of the expanded
items to the console. Have a click around then check your console to
see this in action.
</p>

<Accordion>
{placeholders.map((placeholder: Placeholder, i: number) => {
const isExpanded = i < 2;

return (
<AccordionItem
key={placeholder.heading}
uuid={placeholder.uuid}
// Warning: This can impact accessibility negatively
dangerouslySetExpanded={isExpanded}
>
<AccordionItemHeading>
<AccordionItemButton>
{placeholder.heading}
</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
{placeholder.panel}
</AccordionItemPanel>
</AccordionItem>
);
})}
</Accordion>
</>
);

Expand Down
12 changes: 12 additions & 0 deletions integration/__snapshots__/wai-aria.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,26 @@ Object {
"name": "Heading One",
"role": "button",
},
Object {
"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.",
"role": "text",
},
Object {
"name": "Heading Two",
"role": "button",
},
Object {
"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.",
"role": "text",
},
Object {
"name": "Heading Three",
"role": "button",
},
Object {
"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.",
"role": "text",
},
],
"name": "React Accessible Accordion - Integration Test Sandbox",
"role": "WebArea",
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/plugin-proposal-class-properties": "^7.4.4",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0",
Expand All @@ -102,7 +103,7 @@
"jest": "^24.5.0",
"lint-staged": "^8.1.5",
"mini-css-extract-plugin": "^0.7.0",
"prettier": "^1.16.3",
"prettier": "^2.0.5",
"puppeteer": "2.0.0",
"react": "16.3.2",
"react-dom": "16.3.3",
Expand All @@ -114,12 +115,12 @@
"rollup-plugin-node-resolve": "^5.1.0",
"rollup-plugin-replace": "^2.1.1",
"style-loader": "^0.23.1",
"tslint": "^5.14.0",
"tslint": "^6.1.2",
"tslint-config-prettier": "^1.18.0",
"tslint-microsoft-contrib": "^6.1.0",
"tslint-plugin-prettier": "^2.0.1",
"tslint-react": "^4.0.0",
"typescript": "^3.5.2",
"tslint-microsoft-contrib": "^6.2.0",
"tslint-plugin-prettier": "^2.3.0",
"tslint-react": "^5.0.0",
"typescript": "^3.9.5",
"uuid": "^3.3.2",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
Expand Down
24 changes: 18 additions & 6 deletions src/components/AccordionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ export interface AccordionContext {
toggleExpanded(uuid: UUID): void;
isItemDisabled(uuid: UUID): boolean;
isItemExpanded(uuid: UUID): boolean;
getPanelAttributes(uuid: UUID): InjectedPanelAttributes;
getPanelAttributes(
uuid: UUID,
dangerouslySetExpanded?: boolean,
): InjectedPanelAttributes;
getHeadingAttributes(uuid: UUID): InjectedHeadingAttributes;
getButtonAttributes(uuid: UUID): InjectedButtonAttributes;
getButtonAttributes(
uuid: UUID,
dangerouslySetExpanded?: boolean,
): InjectedButtonAttributes;
}

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

getPanelAttributes = (key: UUID): InjectedPanelAttributes => {
return this.state.getPanelAttributes(key);
getPanelAttributes = (
key: UUID,
dangerouslySetExpanded?: boolean,
): InjectedPanelAttributes => {
return this.state.getPanelAttributes(key, dangerouslySetExpanded);
};

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

getButtonAttributes = (key: UUID): InjectedButtonAttributes => {
return this.state.getButtonAttributes(key);
getButtonAttributes = (
key: UUID,
dangerouslySetExpanded?: boolean,
): InjectedButtonAttributes => {
return this.state.getButtonAttributes(key, dangerouslySetExpanded);
};

render(): JSX.Element {
Expand Down
8 changes: 6 additions & 2 deletions src/components/AccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
type Props = DivAttributes & {
uuid?: UUID;
activeClassName?: string;
dangerouslySetExpanded?: boolean;
};

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

render(): JSX.Element {
const { uuid = this.instanceUuid } = this.props;
const { uuid = this.instanceUuid, dangerouslySetExpanded } = this.props;

return (
<ItemProvider uuid={uuid}>
<ItemProvider
uuid={uuid}
dangerouslySetExpanded={dangerouslySetExpanded}
>
<ItemConsumer>{this.renderChildren}</ItemConsumer>
</ItemProvider>
);
Expand Down
16 changes: 12 additions & 4 deletions src/components/ItemContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type ProviderProps = {
children?: React.ReactNode;
uuid: UUID;
accordionContext: AccordionContext;
dangerouslySetExpanded?: boolean;
};

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

renderChildren = (accordionContext: AccordionContext): JSX.Element => {
const { uuid } = this.props;
const { uuid, dangerouslySetExpanded } = this.props;

const expanded = accordionContext.isItemExpanded(uuid);
const expanded =
dangerouslySetExpanded ?? accordionContext.isItemExpanded(uuid);
const disabled = accordionContext.isItemDisabled(uuid);
const panelAttributes = accordionContext.getPanelAttributes(uuid);
const panelAttributes = accordionContext.getPanelAttributes(
uuid,
dangerouslySetExpanded,
);
const headingAttributes = accordionContext.getHeadingAttributes(uuid);
const buttonAttributes = accordionContext.getButtonAttributes(uuid);
const buttonAttributes = accordionContext.getButtonAttributes(
uuid,
dangerouslySetExpanded,
);

return (
<Context.Provider
Expand Down
6 changes: 4 additions & 2 deletions src/helpers/AccordionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ export default class AccordionStore {

public readonly getPanelAttributes = (
uuid: UUID,
dangerouslySetExpanded?: boolean,
): InjectedPanelAttributes => {
const expanded = this.isItemExpanded(uuid);
const expanded = dangerouslySetExpanded ?? this.isItemExpanded(uuid);

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

public readonly getButtonAttributes = (
uuid: UUID,
dangerouslySetExpanded?: boolean,
): InjectedButtonAttributes => {
const expanded = this.isItemExpanded(uuid);
const expanded = dangerouslySetExpanded ?? this.isItemExpanded(uuid);
const disabled = this.isItemDisabled(uuid);

return {
Expand Down
1 change: 0 additions & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"typedef": [
true,
"call-signature",
"arrow-call-signature",
"parameter",
"arrow-parameter",
"property-declaration",
Expand Down
Loading

0 comments on commit 80e21c8

Please sign in to comment.