Passed
Push — task/hygrogen-react-components ( c486f0 )
by Yonathan
07:32
created

resources/assets/js/components/H2Components/Accordion.tsx   A

Complexity

Total Complexity 1
Complexity/F 0

Size

Lines of Code 98
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 1
eloc 79
mnd 1
bc 1
fnc 0
dl 0
loc 98
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
import * as React from "react";
2
import { useIntl, defineMessages } from "react-intl";
3
import { h2ComponentAccordionAddTriggerEvent } from "@hydrogen-design-system/system/dist/import/latest/components/accordion/scripts/accordion";
4
import Button, { ButtonProps } from "./Button";
5
6
const messages = defineMessages({
7
  expand: {
8
    id: "hydrogen.accordion.expand",
9
    defaultMessage: "Click to view...",
10
    description: " Accessibility text for the accordion expand button.",
11
  },
12
});
13
14
interface AccordionContext {
15
  triggerIconPos?: "left" | "right";
16
}
17
18
const AccordionContext = React.createContext<AccordionContext>({});
19
20
const useAccordion = (): {} => {
21
  const context = React.useContext(AccordionContext);
22
  if (!context) {
23
    throw new Error(
24
      "This component must be used within a <Accordion> component.",
25
    );
26
  }
27
  return context;
28
};
29
30
interface BtnProps extends ButtonProps {
31
  addIcon?: React.ReactElement | string;
32
  removeIcon?: React.ReactElement | string;
33
}
34
35
const Btn: React.FunctionComponent<BtnProps> = (props) => {
36
  useAccordion();
37
  const { addIcon, removeIcon, styling, type, onClick, children } = props;
38
  const intl = useIntl();
39
  return (
40
    <Button
41
      styling={styling}
42
      type={type}
43
      aria-expanded="false"
44
      data-h2-accordion-trigger
45
      tabIndex={0}
46
      onClick={onClick}
47
      {...props}
48
    >
49
      <span data-h2-accordion-trigger-label>
50
        {intl.formatMessage(messages.expand)}
51
      </span>
52
      <span aria-hidden="true" data-h2-accordion-add-icon>
53
        {addIcon || <i className="fas fa-plus" />}
54
      </span>
55
      <span aria-hidden="true" data-h2-accordion-remove-icon>
56
        {removeIcon || <i className="fas fa-minus" />}
57
      </span>
58
      <div data-h2-accordion-trigger-content>{children}</div>
59
    </Button>
60
  );
61
};
62
63
const Content: React.FunctionComponent = (props) => {
64
  useAccordion();
65
  const { children } = props;
66
  return (
67
    <div aria-hidden="true" data-h2-accordion-content>
68
      {children}
69
    </div>
70
  );
71
};
72
73
interface AccordionComposition {
74
  Btn: React.FunctionComponent<BtnProps>;
75
  Content: React.FunctionComponent;
76
}
77
78
const Accordion: React.FunctionComponent<AccordionContext> &
79
  AccordionComposition = (props) => {
80
  const { triggerIconPos, children } = props;
81
  const ref = React.useRef(null);
82
  React.useEffect((): void => {
83
    h2ComponentAccordionAddTriggerEvent("latest", ref.current);
84
  });
85
  return (
86
    <AccordionContext.Provider value={props}>
87
      <div ref={ref} data-h2-accordion={triggerIconPos || "left"} {...props}>
88
        {children}
89
      </div>
90
    </AccordionContext.Provider>
91
  );
92
};
93
94
Accordion.Btn = Btn;
95
Accordion.Content = Content;
96
97
export default Accordion;
98