Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Material UI dependencies from Accordion and Accordion Group #1267

Merged
merged 13 commits into from Sep 22, 2022
Merged
28 changes: 27 additions & 1 deletion lib/src/accordion-group/AccordionGroup.stories.tsx
Expand Up @@ -80,6 +80,32 @@ export const Chromatic = () => (
</DxcAccordionGroup.Accordion>
</DxcAccordionGroup>
</ExampleContainer>
<ExampleContainer pseudoState="pseudo-focus">
<Title title="Focused" theme="light" level={4} />
<DxcAccordionGroup defaultIndexActive={2}>
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex
ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
</div>
</DxcAccordionGroup.Accordion>
<DxcAccordionGroup.Accordion label="Accordion2" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</div>
</DxcAccordionGroup.Accordion>
<DxcAccordionGroup.Accordion label="Accordion2" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</div>
</DxcAccordionGroup.Accordion>
</DxcAccordionGroup>
</ExampleContainer>
<Title title="Margins" theme="light" level={2} />
<ExampleContainer>
<Title title="Xxsmall" theme="light" level={4} />
Expand Down Expand Up @@ -222,4 +248,4 @@ export const Chromatic = () => (
</DxcAccordionGroup>
</ExampleContainer>
</>
);
);
60 changes: 8 additions & 52 deletions lib/src/accordion-group/AccordionGroup.test.js
Expand Up @@ -3,44 +3,6 @@ import { render, fireEvent } from "@testing-library/react";
import DxcAccordionGroup from "./AccordionGroup";

describe("Accordion component tests", () => {
test("Uncontrolled accordion group renders with children", () => {
const { getByText, getAllByRole } = render(
<DxcAccordionGroup>
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</div>
</DxcAccordionGroup.Accordion>
<DxcAccordionGroup.Accordion label="Accordion2" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</div>
</DxcAccordionGroup.Accordion>
</DxcAccordionGroup>
);

expect(getByText("Accordion1")).toBeTruthy();
expect(getByText("Accordion2")).toBeTruthy();
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("false");
expect(getAllByRole("button")[1].getAttribute("aria-expanded")).toBe("false");
});
test("Uncontrolled accordion group renders with only one children", () => {
const { getByText, getAllByRole } = render(
<DxcAccordionGroup>
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</div>
</DxcAccordionGroup.Accordion>
</DxcAccordionGroup>
);

expect(getByText("Accordion1")).toBeTruthy();
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("false");
});
test("Uncontrolled accordion group calls correct function on click", () => {
const onActiveChange = jest.fn();
const { getByText, getAllByRole } = render(
Expand All @@ -67,31 +29,25 @@ describe("Accordion component tests", () => {
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("true");
expect(getAllByRole("button")[1].getAttribute("aria-expanded")).toBe("false");
});
test("Uncontrolled accordion group renders initially with an accordion expanded", () => {
const { getByText, getAllByRole } = render(
test("Uncontrolled accordion group renders initially with an accordion expanded using defaultIndexActive", () => {
const { queryByText, getByText, getAllByRole } = render(
<DxcAccordionGroup defaultIndexActive={1}>
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</div>
<div>First accordion</div>
</DxcAccordionGroup.Accordion>
<DxcAccordionGroup.Accordion label="Accordion2" padding="medium">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</div>
<div>Second accordion</div>
</DxcAccordionGroup.Accordion>
</DxcAccordionGroup>
);
expect(getByText("Accordion1")).toBeTruthy();
expect(getByText("Accordion2")).toBeTruthy();
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("false");
expect(getAllByRole("button")[1].getAttribute("aria-expanded")).toBe("true");
expect(getByText("Second accordion")).toBeTruthy();
expect(queryByText("First accordion")).toBeFalsy();
});
test("Controlled accordion with indexActive change", () => {
const onActiveChange = jest.fn();
const { getByText, getAllByRole, rerender } = render(
const { queryByText, getByText, getAllByRole, rerender } = render(
<DxcAccordionGroup margin="large" indexActive={1} onActiveChange={onActiveChange}>
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium" margin="large">
<div>Text1</div>
Expand All @@ -101,7 +57,7 @@ describe("Accordion component tests", () => {
</DxcAccordionGroup.Accordion>
</DxcAccordionGroup>
);
expect(getByText("Text1")).toBeTruthy();
expect(queryByText("Text1")).toBeFalsy();
expect(getByText("Text2")).toBeTruthy();
fireEvent.click(getByText("Accordion1"));
fireEvent.click(getByText("Accordion2"));
Expand Down
85 changes: 23 additions & 62 deletions lib/src/accordion-group/AccordionGroup.tsx
@@ -1,19 +1,12 @@
// @ts-nocheck
import React, { createContext, useCallback, useContext, useMemo, useState } from "react";
import styled, { ThemeProvider } from "styled-components";
import DxcAccordion from "../accordion/Accordion";
import { getMargin } from "../common/utils.js";
import { spaces } from "../common/variables.js";
import useTheme from "../useTheme";
import AccordionGroupPropsType, { AccordionPropsType } from "./types";
import AccordionGroupPropsType, { AccordionGroupAccordionContextProps, AccordionPropsType, Margin, Space } from "./types";

type AccordionGroupAccordionContext = {
activeIndex: number;
handlerActiveChange: (index: number) => void;
disabled: boolean;
index: number;
};
const AccordionGroupAccordionContext = createContext<AccordionGroupAccordionContext | null>(null);
const AccordionGroupAccordionContext = createContext<AccordionGroupAccordionContextProps | null>(null);

const AccordionGroupAccordion = ({ ...childProps }: AccordionPropsType): JSX.Element => {
const { activeIndex, handlerActiveChange, disabled, index } = useContext(AccordionGroupAccordionContext);
Expand Down Expand Up @@ -73,79 +66,47 @@ DxcAccordionGroup.Accordion = AccordionGroupAccordion;

const calculateWidth = (margin) => `calc(100% - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})`;

const AccordionGroupContainer = styled.div`
display: inline-block;
const AccordionGroupContainer = styled.div<{ margin: Space | Margin; disabled: boolean }>`
GomezIvann marked this conversation as resolved.
Show resolved Hide resolved
width: ${(props) => calculateWidth(props.margin)};

margin: ${({ margin }) => (margin && typeof margin !== "object" ? spaces[margin] : "0px")};
margin-top: ${({ margin }) => (margin && typeof margin === "object" && margin.top ? spaces[margin.top] : "")};
margin-right: ${({ margin }) => (margin && typeof margin === "object" && margin.right ? spaces[margin.right] : "")};
margin-bottom: ${({ margin }) =>
margin && typeof margin === "object" && margin.bottom ? spaces[margin.bottom] : ""};
margin-left: ${({ margin }) => (margin && typeof margin === "object" && margin.left ? spaces[margin.left] : "")};

cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};

& > :not(div:last-child) {
& > div:first-child {
> div:not(:last-of-type):not(:only-of-type) {
border-bottom: ${(props) =>
`${props.theme.accordionGroupSeparatorBorderThickness} ${props.theme.accordionGroupSeparatorBorderStyle}`};
border-color: ${(props) => props.theme.accordionGroupSeparatorBorderColor};
}
> div:not(:first-of-type):not(:last-of-type):not(:only-of-type) {
border-radius: 0;
& > h3 > button {
border-radius: 0;
border-bottom: ${(props) =>
`${props.theme.accordionGroupSeparatorBorderThickness} ${props.theme.accordionGroupSeparatorBorderStyle}`};
border-color: ${(props) => props.theme.accordionGroupSeparatorBorderColor};

& > .Mui-expanded {
border-radius: 0;
}
& > .MuiButtonBase-root {
border-radius: 0;
}
}
}
> div:first-of-type:not(:only-of-type) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-top-left-radius: ${(props) => props.theme.borderRadius};
border-top-right-radius: ${(props) => props.theme.borderRadius};

& > div:first-child {
& > div:first-child {
& > h3 > button {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-top-left-radius: ${(props) => props.theme.borderRadius};
border-top-right-radius: ${(props) => props.theme.borderRadius};
border-bottom: ${(props) =>
`${props.theme.accordionGroupSeparatorBorderThickness} ${props.theme.accordionGroupSeparatorBorderStyle}`};
border-color: ${(props) => props.theme.accordionGroupSeparatorBorderColor};

& > .Mui-expanded {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-top-left-radius: ${(props) => props.theme.borderRadius};
border-top-right-radius: ${(props) => props.theme.borderRadius};
}
& > .MuiButtonBase-root {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-top-left-radius: ${(props) => props.theme.borderRadius};
border-top-right-radius: ${(props) => props.theme.borderRadius};
}
}
}
> div:last-of-type:not(:only-of-type) {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: ${(props) => props.theme.borderRadius};
border-bottom-right-radius: ${(props) => props.theme.borderRadius};

& > div:last-child {
& > div:first-child {
border-bottom-left-radius: ${(props) => props.theme.borderRadius};
border-bottom-right-radius: ${(props) => props.theme.borderRadius};
& > h3 > button {
border-top-left-radius: 0;
border-top-right-radius: 0;

& > .Mui-expanded {
border-bottom-left-radius: ${(props) => props.theme.borderRadius};
border-bottom-right-radius: ${(props) => props.theme.borderRadius};
border-top-left-radius: 0;
border-top-right-radius: 0;
}
& > .MuiButtonBase-root {
border-bottom-left-radius: ${(props) => props.theme.borderRadius};
border-bottom-right-radius: ${(props) => props.theme.borderRadius};
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}
`;
Expand Down
11 changes: 9 additions & 2 deletions lib/src/accordion-group/types.ts
@@ -1,5 +1,5 @@
type Space = "xxsmall" | "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge";
type Margin = {
export type Space = "xxsmall" | "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge";
export type Margin = {
top?: Space;
bottom?: Space;
left?: Space;
Expand Down Expand Up @@ -71,4 +71,11 @@ type Props = {
children: React.ReactElement<AccordionPropsType>[] | React.ReactElement<AccordionPropsType>;
};

export type AccordionGroupAccordionContextProps = {
activeIndex: number;
handlerActiveChange: (index: number) => void;
disabled: boolean;
index: number;
};

export default Props;
3 changes: 1 addition & 2 deletions lib/src/accordion/Accordion.stories.tsx
Expand Up @@ -133,13 +133,12 @@ export const Chromatic = () => (
icon={folderIcon}
padding="medium"
>
<div style={{ display: "flex", flexDirection: "column" }}>
<div style={{ display: "flex", flexDirection: "column", gap: "36px" }}>
<DxcTextInput
label="Label"
helperText="HelperText"
placeholder="Placeholder"
size="fillParent"
margin={{ bottom: "medium" }}
/>
<DxcButton label="Submit" size="medium" />
</div>
Expand Down
17 changes: 11 additions & 6 deletions lib/src/accordion/Accordion.test.js
Expand Up @@ -3,13 +3,18 @@ import { render, fireEvent } from "@testing-library/react";
import DxcAccordion from "./Accordion";

describe("Accordion component tests", () => {
test("Accordion renders with correct text", () => {
const onChange = jest.fn();
const { getByText } = render(<DxcAccordion label="Accordion" assistiveText="Assistive text" onChange={onChange} />);
expect(getByText("Accordion")).toBeTruthy();
expect(getByText("Assistive text")).toBeTruthy();
test("Renders with correct aria accessibility attributes", () => {
const { getByRole } = render(
<DxcAccordion label="Accordion" defaultIsExpanded>
<div>test-expanded</div>
</DxcAccordion>
);
const accordion = getByRole("button");
const panel = getByRole("region");
expect(accordion.getAttribute("aria-controls")).toBe(panel.id);
expect(panel.getAttribute("aria-labelledBy")).toBe(accordion.id);
});
test("Accordion renders expanded by default when it is uncontrolled", () => {
test("Renders expanded by default when it is uncontrolled", () => {
const { getByRole } = render(
<DxcAccordion label="Accordion" defaultIsExpanded>
<div>test-expanded</div>
Expand Down