Skip to content

Commit bfeb2b0

Browse files
authored
Merge pull request #917 from dxc-technology/gomezivann-accordionGroup-default
New prop `defaultIndexActive` for Accordion Group
2 parents 0d4367e + e7dc9bb commit bfeb2b0

File tree

8 files changed

+78
-41
lines changed

8 files changed

+78
-41
lines changed

docs/src/pages/components/cdk-components/accordion-group/AccordionGroup.jsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ function AccordionGroup() {
1414
return (
1515
<ComponentDoc>
1616
<ComponentHeader title="Accordion Group" status="ready"></ComponentHeader>
17-
1817
<Section>
1918
<DxcHeading level={3} text="Props" margin={{ bottom: "small" }} />
2019
<AccordionGroupPropsTable />
@@ -47,14 +46,14 @@ function AccordionGroup() {
4746
</Section>
4847
<Section>
4948
<DxcHeading level={3} text="Examples" margin={{ bottom: "small" }} />
50-
<Example
51-
title="Uncontrolled Accordion Group"
52-
example={uncontrolledAccordionGroup}
53-
></Example>
5449
<Example
5550
title="Controlled Accordion Group"
5651
example={controlledAccordionGroup}
5752
></Example>
53+
<Example
54+
title="Uncontrolled Accordion Group"
55+
example={uncontrolledAccordionGroup}
56+
></Example>
5857
<Example title="Disabled Accordion Group" example={disabled}></Example>
5958
</Section>
6059
</ComponentDoc>

docs/src/pages/components/cdk-components/accordion-group/api.jsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,45 @@ const AccordionGroupPropsTable = () => {
99
<th>Default</th>
1010
<th>Description</th>
1111
</tr>
12+
<tr>
13+
<td>defaultIndexActive: number</td>
14+
<td></td>
15+
<td>Initially active accordion, only when it is uncontrolled.</td>
16+
</tr>
1217
<tr>
1318
<td>indexActive: number</td>
1419
<td></td>
15-
<td>The index of the active accordion. If undefined, the component will be uncontrolled and the active accordion will be managed internally by the component. If null, the component will be controlled and all accordions will be closed.</td>
20+
<td>
21+
The index of the active accordion. If undefined, the component will be
22+
uncontrolled and the active accordion will be managed internally by
23+
the component. If null, the component will be controlled and all
24+
accordions will be closed.
25+
</td>
1626
</tr>
1727
<tr>
18-
<td>disabled: boolean</td>
19-
<td><code>false</code></td>
20-
<td>If true, the component will be disabled.</td>
28+
<td>disabled: boolean</td>
29+
<td>
30+
<code>false</code>
31+
</td>
32+
<td>If true, the component will be disabled.</td>
2133
</tr>
2234
<tr>
23-
<td>onActiveChange: function</td>
24-
<td></td>
25-
<td>This function will be called when the user clicks on an accordion. The index of the clicked accordion will be passed as a parameter.</td>
35+
<td>onActiveChange: function</td>
36+
<td></td>
37+
<td>
38+
This function will be called when the user clicks on an accordion. The
39+
index of the clicked accordion will be passed as a parameter.
40+
</td>
2641
</tr>
27-
<tr>
28-
<td>margin: string | object</td>
29-
<td></td>
30-
<td>Size of the margin to be applied to the component ('xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge'). You can pass an object with 'top', 'bottom', 'left' and 'right' properties in order to specify different margin sizes.</td>
42+
<tr>
43+
<td>margin: string | object</td>
44+
<td></td>
45+
<td>
46+
Size of the margin to be applied to the component ('xxsmall' |
47+
'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge'). You
48+
can pass an object with 'top', 'bottom', 'left' and 'right' properties
49+
in order to specify different margin sizes.
50+
</td>
3151
</tr>
3252
</DxcTable>
3353
);

docs/src/pages/components/cdk-components/accordion-group/examples/controlledAccordionGroup.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { useState } from "react";
44
const code = `() => {
55
const [indexAccordion, setIndexAccordion] = useState(0);
66
7-
const onActiveChange = (i) => {
8-
setIndexAccordion((prevValue) => prevValue === i ? null : i);
7+
const onActiveChange = (index) => {
8+
setIndexAccordion((currentIndex) => currentIndex === index ? -1 : index);
99
};
1010
1111
return (

docs/src/pages/components/cdk-components/accordion-group/examples/uncontrolledAccordionGroup.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DxcAccordionGroup } from "@dxc-technology/halstack-react";
33
const code = `() => {
44
return (
55
<div>
6-
<DxcAccordionGroup margin="medium">
6+
<DxcAccordionGroup margin="medium" defaultIndexActive={0}>
77
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium">
88
<div>
99
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
@@ -24,7 +24,7 @@ const code = `() => {
2424
}`;
2525

2626
const scope = {
27-
DxcAccordionGroup
27+
DxcAccordionGroup,
2828
};
2929

3030
export default { code, scope };

lib/src/accordion-group/AccordionGroup.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const Chromatic = () => (
3636
</ExampleContainer>
3737
<ExampleContainer>
3838
<Title title="Expanded" theme="light" level={4} />
39-
<DxcAccordionGroup indexActive={1}>
39+
<DxcAccordionGroup defaultIndexActive={1}>
4040
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium">
4141
<div>
4242
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et

lib/src/accordion-group/AccordionGroup.test.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ describe("Accordion component tests", () => {
2626
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("false");
2727
expect(getAllByRole("button")[1].getAttribute("aria-expanded")).toBe("false");
2828
});
29-
3029
test("Uncontrolled accordion group renders with only one children", () => {
3130
const { getByText, getAllByRole } = render(
3231
<DxcAccordionGroup>
@@ -42,7 +41,6 @@ describe("Accordion component tests", () => {
4241
expect(getByText("Accordion1")).toBeTruthy();
4342
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("false");
4443
});
45-
4644
test("Uncontrolled accordion group calls correct function on click", () => {
4745
const onActiveChange = jest.fn();
4846
const { getByText, getAllByRole } = render(
@@ -69,7 +67,28 @@ describe("Accordion component tests", () => {
6967
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("true");
7068
expect(getAllByRole("button")[1].getAttribute("aria-expanded")).toBe("false");
7169
});
72-
70+
test("Uncontrolled accordion group renders initially with an accordion expanded", () => {
71+
const { getByText, getAllByRole } = render(
72+
<DxcAccordionGroup defaultIndexActive={1}>
73+
<DxcAccordionGroup.Accordion label="Accordion1" padding="medium">
74+
<div>
75+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
76+
leo lobortis eget.
77+
</div>
78+
</DxcAccordionGroup.Accordion>
79+
<DxcAccordionGroup.Accordion label="Accordion2" padding="medium">
80+
<div>
81+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
82+
leo lobortis eget.
83+
</div>
84+
</DxcAccordionGroup.Accordion>
85+
</DxcAccordionGroup>
86+
);
87+
expect(getByText("Accordion1")).toBeTruthy();
88+
expect(getByText("Accordion2")).toBeTruthy();
89+
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("false");
90+
expect(getAllByRole("button")[1].getAttribute("aria-expanded")).toBe("true");
91+
});
7392
test("Controlled accordion with indexActive change", () => {
7493
const onActiveChange = jest.fn();
7594
const { getByText, getAllByRole, rerender } = render(
@@ -105,7 +124,6 @@ describe("Accordion component tests", () => {
105124
expect(getAllByRole("button")[0].getAttribute("aria-expanded")).toBe("true");
106125
expect(getAllByRole("button")[1].getAttribute("aria-expanded")).toBe("false");
107126
});
108-
109127
test("Disabled uncontrolled accordion group", () => {
110128
const onActiveChange = jest.fn();
111129
const { getByText } = render(

lib/src/accordion-group/AccordionGroup.tsx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// @ts-nocheck
2-
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
2+
import React, { createContext, useCallback, useContext, useMemo, useState } from "react";
33
import styled, { ThemeProvider } from "styled-components";
44
import DxcAccordion from "../accordion/Accordion";
55
import { getMargin } from "../common/utils.js";
@@ -8,19 +8,19 @@ import useTheme from "../useTheme";
88
import AccordionGroupPropsType, { AccordionPropsType } from "./types";
99

1010
type AccordionGroupAccordionContext = {
11-
innerIsExpanded: number;
11+
activeIndex: number;
1212
handlerActiveChange: (index: number) => void;
1313
disabled: boolean;
1414
index: number;
1515
};
1616
const AccordionGroupAccordionContext = createContext<AccordionGroupAccordionContext | null>(null);
1717

1818
const AccordionGroupAccordion = ({ ...childProps }: AccordionPropsType): JSX.Element => {
19-
const { innerIsExpanded, handlerActiveChange, disabled, index } = useContext(AccordionGroupAccordionContext);
19+
const { activeIndex, handlerActiveChange, disabled, index } = useContext(AccordionGroupAccordionContext);
2020

2121
return (
2222
<DxcAccordion
23-
isExpanded={innerIsExpanded === index}
23+
isExpanded={activeIndex === index}
2424
onChange={() => {
2525
handlerActiveChange(index);
2626
}}
@@ -33,38 +33,34 @@ const AccordionGroupAccordion = ({ ...childProps }: AccordionPropsType): JSX.Ele
3333
};
3434

3535
const DxcAccordionGroup = ({
36+
defaultIndexActive,
3637
indexActive,
3738
disabled = false,
3839
onActiveChange,
3940
margin,
4041
children,
4142
}: AccordionGroupPropsType): JSX.Element => {
4243
const colorsTheme = useTheme();
43-
44-
const [innerIsExpanded, setInnerIsExpanded] = useState(0);
44+
const [innerIndexActive, setInnerIndexActive] = useState(defaultIndexActive ?? -1);
4545
const handlerActiveChange = useCallback(
4646
(index) => {
47-
indexActive === undefined
48-
? setInnerIsExpanded((prev) => (index === prev ? -1 : index))
49-
: setInnerIsExpanded(indexActive);
50-
47+
indexActive ?? setInnerIndexActive((prev) => (index === prev ? -1 : index));
5148
!disabled && onActiveChange?.(index);
5249
},
5350
[disabled, indexActive, onActiveChange]
5451
);
55-
const value = useMemo(() => ({ innerIsExpanded, handlerActiveChange, disabled }), [innerIsExpanded, disabled]);
56-
57-
useEffect(() => {
58-
setInnerIsExpanded(indexActive);
59-
}, [indexActive]);
52+
const contextValue = useMemo(
53+
() => ({ activeIndex: indexActive ?? innerIndexActive, handlerActiveChange, disabled }),
54+
[indexActive, innerIndexActive, handlerActiveChange, disabled]
55+
);
6056

6157
return (
6258
<ThemeProvider theme={colorsTheme.accordion}>
6359
<AccordionGroupContainer margin={margin} disabled={disabled}>
6460
{(Array.isArray(children) ? children : [children])
6561
.filter((child) => child.type === AccordionGroupAccordion)
6662
.map((accordion, index) => (
67-
<AccordionGroupAccordionContext.Provider value={{ index, ...value }}>
63+
<AccordionGroupAccordionContext.Provider value={{ index, ...contextValue }}>
6864
{accordion}
6965
</AccordionGroupAccordionContext.Provider>
7066
))}

lib/src/accordion-group/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ export type AccordionPropsType = {
4343
};
4444

4545
type Props = {
46+
/**
47+
* Initially active accordion, only when it is uncontrolled.
48+
*/
49+
defaultIndexActive?: number;
4650
/**
4751
* The index of the active accordion. If undefined, the component will be uncontrolled and the active accordion will be managed internally by the component.
4852
* If null, the component will be controlled and all accordions will be closed.

0 commit comments

Comments
 (0)