Skip to content

Commit 2e0c334

Browse files
committed
Merge branch 'master' of https://github.com/joaojmendes/sp-dev-fx-controls-react into joaojmendes-master
2 parents fe819a7 + c004e8c commit 2e0c334

27 files changed

+1619
-190
lines changed
387 KB
Loading

docs/documentation/docs/controls/FilePicker.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ The FilePicker component can be configured with the following properties:
5959
| label | string | no | Specifies the text describing the file picker. |
6060
| buttonLabel | string | no | Specifies the label of the file picker button. |
6161
| buttonIcon | string | no | In case it is provided the file picker will be rendered as an action button. |
62+
buttonIconProps | IIconProps | no | In case it is provided the file picker will be rendered as an Icon the and all can define Properties for Icon |
6263
| onSave | (filePickerResult: IFilePickerResult) => void | yes | Handler when the file has been selected and picker has been closed. |
6364
| onChange | (filePickerResult: IFilePickerResult) => void | no | Handler when the file selection has been changed. |
6465
| context | ExtensionContext \| WebPartContext | yes | Current context. |
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Accessible Accordion
2+
3+
This control allows you to render an accordion control. Is a Implementation based on React Accessible Accordion Control, that was customize UI to be more Fluent.
4+
5+
Here is an example of the control in action:
6+
7+
![Accessible Accordion control](../assets/AccessibleAccordion.gif)
8+
9+
## How to use this control in your solutions
10+
11+
- Check that you installed the `@pnp/spfx-controls-react` dependency. Check out the [getting started](../../#getting-started) page for more information about installing the dependency.
12+
- In your component file, import the `Accordion` control as follows:
13+
14+
```TypeScript
15+
import {
16+
Accordion,
17+
AccordionItem,
18+
AccordionItemHeading,
19+
AccordionItemButton,
20+
AccordionItemPanel,
21+
} from "@pnp/spfx-controls-react/lib/AccessibleAccordion";
22+
23+
```
24+
25+
- Use the `Accordion` control in your code as follows:
26+
27+
```TypeScript
28+
<Accordion>
29+
<AccordionItem>
30+
<AccordionItemHeading>
31+
<AccordionItemButton>
32+
What harsh truths do you prefer to ignore?
33+
</AccordionItemButton>
34+
</AccordionItemHeading>
35+
<AccordionItemPanel>
36+
<p>
37+
Exercitation in fugiat est ut ad ea cupidatat ut in
38+
cupidatat occaecat ut occaecat consequat est minim minim
39+
esse tempor laborum consequat esse adipisicing eu
40+
reprehenderit enim.
41+
</p>
42+
</AccordionItemPanel>
43+
</AccordionItem>
44+
<AccordionItem>
45+
<AccordionItemHeading>
46+
<AccordionItemButton>
47+
Is free will real or just an illusion?
48+
</AccordionItemButton>
49+
</AccordionItemHeading>
50+
<AccordionItemPanel>
51+
<p>
52+
In ad velit in ex nostrud dolore cupidatat consectetur
53+
ea in ut nostrud velit in irure cillum tempor laboris
54+
sed adipisicing eu esse duis nulla non.
55+
</p>
56+
</AccordionItemPanel>
57+
</AccordionItem>
58+
</Accordion>
59+
}
60+
```
61+
62+
## Implementation
63+
64+
The `Accordion` control can be configured with the following properties:
65+
66+
67+
### Accordion
68+
69+
#### allowMultipleExpanded : `boolean` [*optional*, default: `false`]
70+
71+
Don't autocollapse items when expanding other items.
72+
73+
#### allowZeroExpanded : `boolean` [*optional*, default: `false`]
74+
75+
Allow the only remaining expanded item to be collapsed.
76+
77+
#### preExpanded: `string[]` [_optional_, default: `[]`]
78+
79+
Accepts an array of strings and any `AccordionItem` whose `uuid` prop matches
80+
any one of these strings will be expanded on mount.
81+
82+
#### className : `string` [*optional*, default: `'accordion'`]
83+
84+
Class(es) to apply to element.
85+
86+
#### onChange : `(string[]) => void` [*optional*]
87+
88+
Callback which is invoked when items are expanded or collapsed. Gets passed
89+
`uuid`s of the currently expanded `AccordionItem`s.
90+
91+
---
92+
93+
### AccordionItem
94+
95+
#### className : `string` [*optional*, default: `accordion__item`]
96+
97+
Class(es) to apply to element.
98+
99+
#### uuid : `string|number` [*optional*]
100+
101+
Recommended for use with `onChange`. Will be auto-generated if not provided.
102+
103+
#### dangerouslySetExpanded: `boolean` [*optional*]
104+
105+
Enables external control of the expansion.
106+
107+
> Warning: This may impact accessibility negatively, use at your own risk
108+
109+
---
110+
111+
### AccordionItemHeading
112+
113+
#### className : `string` [*optional*, default: `'accordion__heading'`]
114+
115+
Class(es) to apply to the 'heading' element.
116+
117+
#### aria-level : `number` [*optional*, default: `3`]
118+
119+
Semantics to apply to the 'heading' element. A value of `1` would make your
120+
heading element hierarchically equivalent to an `<h1>` tag, and likewise a value
121+
of `6` would make it equivalent to an `<h6>` tag.
122+
123+
### AccordionItemButton
124+
125+
#### className : `string` [*optional*, default: `'accordion__button'`]
126+
127+
Class(es) to apply to the 'button' element.
128+
129+
---
130+
131+
### AccordionItemPanel
132+
133+
#### className : `string` [*optional*, default: `'accordion__panel'`]
134+
135+
Class(es) to apply to element.
136+
137+
---
138+
139+
### AccordionItemState
140+
141+
#### children : `({ expanded: boolean, disabled: boolean }): JSX.Element` [**required**]
142+
143+
---
144+
145+
## Helpers
146+
147+
### resetNextUuid : `(): void`
148+
149+
Resets the internal counter for Accordion items' identifiers (including `id`
150+
attributes). For use in test suites and isomorphic frameworks.
151+
152+
---
153+
154+
155+
![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/AccessibleAccordion)

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"lodash": "4.17.13",
3737
"office-ui-fabric-react": "6.214.0",
3838
"react": "16.8.5",
39+
"react-accessible-accordion": "^3.3.3",
3940
"react-dom": "16.8.5",
4041
"react-quill": "1.3.5"
4142
},

src/AccessibleAccordion.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './controls/accessibleAccordion';
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import "../css/AccordionStylesOverride.css";
2+
3+
import * as React from "react";
4+
5+
import { DivAttributes } from "../helpers/types";
6+
import { Provider } from "./AccordionContext";
7+
import { UUID } from "./ItemContext";
8+
9+
type AccordionProps = Pick<
10+
DivAttributes,
11+
Exclude<keyof DivAttributes, 'onChange'>
12+
> & {
13+
className?: string;
14+
preExpanded?: UUID[];
15+
allowMultipleExpanded?: boolean;
16+
allowZeroExpanded?: boolean;
17+
onChange?(args: UUID[]): void;
18+
};
19+
20+
const Accordion = ({
21+
className = 'accordion',
22+
allowMultipleExpanded,
23+
allowZeroExpanded,
24+
onChange,
25+
preExpanded,
26+
...rest
27+
}: AccordionProps): JSX.Element => {
28+
return (
29+
<Provider
30+
preExpanded={preExpanded}
31+
allowMultipleExpanded={allowMultipleExpanded}
32+
allowZeroExpanded={allowZeroExpanded}
33+
onChange={onChange}
34+
>
35+
<div
36+
data-accordion-component="Accordion"
37+
className={className}
38+
{...rest}
39+
/>
40+
</Provider>
41+
);
42+
};
43+
44+
export default Accordion;
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// tslint:disable:max-classes-per-file
2+
3+
import "../css/AccordionStylesOverride.css";
4+
5+
import * as React from "react";
6+
7+
import AccordionStore, {
8+
InjectedButtonAttributes,
9+
InjectedHeadingAttributes,
10+
InjectedPanelAttributes
11+
} from "../helpers/AccordionStore";
12+
import { UUID } from "./ItemContext";
13+
14+
export interface ProviderProps {
15+
preExpanded?: UUID[];
16+
allowMultipleExpanded?: boolean;
17+
allowZeroExpanded?: boolean;
18+
children?: React.ReactNode;
19+
onChange?(args: UUID[]): void;
20+
}
21+
22+
type ProviderState = AccordionStore;
23+
24+
export interface AccordionContext {
25+
allowMultipleExpanded: boolean;
26+
allowZeroExpanded: boolean;
27+
toggleExpanded(uuid: UUID): void;
28+
isItemDisabled(uuid: UUID): boolean;
29+
isItemExpanded(uuid: UUID): boolean;
30+
getPanelAttributes(
31+
uuid: UUID,
32+
dangerouslySetExpanded?: boolean,
33+
): InjectedPanelAttributes;
34+
getHeadingAttributes(uuid: UUID): InjectedHeadingAttributes;
35+
getButtonAttributes(
36+
uuid: UUID,
37+
dangerouslySetExpanded?: boolean,
38+
): InjectedButtonAttributes;
39+
}
40+
41+
const Context = React.createContext(null as AccordionContext | null);
42+
43+
export class Provider extends React.PureComponent<
44+
ProviderProps,
45+
ProviderState
46+
> {
47+
public static defaultProps: ProviderProps = {
48+
allowMultipleExpanded: false,
49+
allowZeroExpanded: false,
50+
};
51+
52+
public state: ProviderState = new AccordionStore({
53+
expanded: this.props.preExpanded,
54+
allowMultipleExpanded: this.props.allowMultipleExpanded,
55+
allowZeroExpanded: this.props.allowZeroExpanded,
56+
});
57+
58+
private toggleExpanded = (key: UUID): void => {
59+
this.setState(
60+
(state: Readonly<ProviderState>) => state.toggleExpanded(key),
61+
() => {
62+
if (this.props.onChange) {
63+
this.props.onChange(this.state.expanded);
64+
}
65+
},
66+
);
67+
}
68+
69+
private isItemDisabled = (key: UUID): boolean => {
70+
return this.state.isItemDisabled(key);
71+
}
72+
73+
private isItemExpanded = (key: UUID): boolean => {
74+
return this.state.isItemExpanded(key);
75+
}
76+
77+
private getPanelAttributes = (
78+
key: UUID,
79+
dangerouslySetExpanded?: boolean,
80+
): InjectedPanelAttributes => {
81+
return this.state.getPanelAttributes(key, dangerouslySetExpanded);
82+
}
83+
84+
private getHeadingAttributes = (): InjectedHeadingAttributes => {
85+
// uuid: UUID
86+
return this.state.getHeadingAttributes();
87+
}
88+
89+
private getButtonAttributes = (
90+
key: UUID,
91+
dangerouslySetExpanded?: boolean,
92+
): InjectedButtonAttributes => {
93+
return this.state.getButtonAttributes(key, dangerouslySetExpanded);
94+
}
95+
96+
public render(): JSX.Element {
97+
const { allowZeroExpanded, allowMultipleExpanded } = this.state;
98+
99+
return (
100+
<Context.Provider
101+
value={{
102+
allowMultipleExpanded,
103+
allowZeroExpanded,
104+
toggleExpanded: this.toggleExpanded,
105+
isItemDisabled: this.isItemDisabled,
106+
isItemExpanded: this.isItemExpanded,
107+
getPanelAttributes: this.getPanelAttributes,
108+
getHeadingAttributes: this.getHeadingAttributes,
109+
getButtonAttributes: this.getButtonAttributes,
110+
}}
111+
>
112+
{this.props.children || null}
113+
</Context.Provider>
114+
);
115+
}
116+
}
117+
118+
export class Consumer extends React.PureComponent<{
119+
children(container: AccordionContext): React.ReactNode;
120+
}> {
121+
private renderChildren = (container: AccordionContext | null): React.ReactNode => {
122+
return container ? this.props.children(container) : null;
123+
}
124+
125+
public render(): JSX.Element {
126+
return <Context.Consumer>{this.renderChildren}</Context.Consumer>;
127+
}
128+
}

0 commit comments

Comments
 (0)