Skip to content

Commit

Permalink
Merge pull request #115 from communitiesuk/nested-accordion
Browse files Browse the repository at this point in the history
Fix bug and enable nested accordion functionality
  • Loading branch information
Ellie-Brakoniecki committed Nov 30, 2023
2 parents 8d9121a + e981e4f commit 129c570
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 32 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "uk_gov_dash_components",
"version": "1.23.0",
"version": "1.24.0",
"description": "Dash components for Gov UK",
"repository": {
"type": "git",
Expand Down
90 changes: 59 additions & 31 deletions src/lib/fragments/Accordion.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,61 @@ const AccordionButtonClassName = "accordion-button govuk-accordion__section-butt
class Accordion extends Component {
constructor(props) {
super(props);
// Check if sectionsOpenDefault prop exists and is an array, otherwise generate a default array
const defaultSectionsOpen = Array.isArray(this.props.defaultSectionsOpen)
? this.props.defaultSectionsOpen
: Array.from({ length: this.props.accordionHeadings.length }, () => true);
// Check if sectionsOpenDefault prop exists and is an array, otherwise generate a default array
const defaultSectionsOpen = Array.isArray(this.props.defaultSectionsOpen)
? this.props.defaultSectionsOpen
: Array.from({ length: this.props.accordionHeadings.length }, () => true);

this.state = {
sectionsOpen: defaultSectionsOpen
this.state = {
sectionsOpen: defaultSectionsOpen
}

}
if (this.props.children.length > 1){
this.contentRefs = this.props.children.map(() => React.createRef());}
else{
this.contentRefs = [React.createRef()];
}
this.initializeContentRefs();
this.headerRefs = this.props.accordionHeadings.map(() => React.createRef());
}

initializeContentRefs = () => {
this.contentRefs = React.Children.map(this.props.children, () => React.createRef());
}

componentDidUpdate(prevProps) {
// check if number of children has changed
if (React.Children.count(prevProps.children) !== React.Children.count(this.props.children)) {
this.initializeContentRefs();
// reset the open state of sections
this.setState({
sectionsOpen: Array.from({ length: React.Children.count(this.props.children) }, () => false)
});
}
}


openOrCloseAccordionSection = (index) => {
this.setState(prevState => ({
sectionsOpen: prevState.sectionsOpen.map((isOpen, i) => i === index ? !isOpen : isOpen),
}));
this.setState(prevState => {
const newSectionsOpen = prevState.sectionsOpen.map((isOpen, i) =>
i === index ? !isOpen : isOpen
);

if (this.contentRefs[index] && this.contentRefs[index].current) {
this.contentRefs[index].current.style.display = newSectionsOpen[index] ? 'block' : 'none';
}

return { sectionsOpen: newSectionsOpen };
});
}

setInitialDisplayStyles = () => {
this.contentRefs.forEach((ref, index) => {
if (ref.current) {
ref.current.style.display = this.state.sectionsOpen[index] ? 'block' : 'none';
}
});
}

componentDidMount() {
this.setInitialDisplayStyles();
}

// This method handles the Up arrow key event for an accordion component
// depending on the origin of the event (Show All button, section heading, or section content).
handleUpArrow = (index, eventOrigin) => {
Expand Down Expand Up @@ -160,20 +192,17 @@ class Accordion extends Component {
return focusable[targetIndex] || null;
}

render() {
let accordionContent
const bannerSections = this.props.bannerSections;
if (this.props.children.length === 1 || xtype.type(this.props.children) !== 'array') {
accordionContent = this.renderAccordionSection(0, this.props.children, this.state.sectionsOpen[0])
}
else {
if (bannerSections) {
accordionContent = this.props.children.map((accordionSectionContent, index) => this.renderAccordionSection(index, accordionSectionContent, this.state.sectionsOpen[index], this.props.bannerSections[index]))
}
else {
accordionContent = this.props.children.map((accordionSectionContent, index) => this.renderAccordionSection(index, accordionSectionContent, this.state.sectionsOpen[index]))
}
}
render() {
const accordionContent = React.Children.map(this.props.children, (accordionSectionContent, index) => {
return this.renderAccordionSection(
index,
accordionSectionContent,
this.state.sectionsOpen[index],
this.props.bannerSections ? this.props.bannerSections[index] : null,
`accordion-section-${index}`
);
});

return (
<div className="js-enabled">
<div
Expand All @@ -190,8 +219,7 @@ class Accordion extends Component {
renderAccordionSection(index, accordionSectionContent, sectionIsOpen, bannerSection) {
const accordionHeading = this.props.accordionHeadings[index]
const bannerSectionHeading = this.props.accordionHeadings[bannerSection]
const contentId = `accordion-default-content-${index}`;

const contentId = `${this.props.id}-default-content-${index}`;


return (
Expand Down

0 comments on commit 129c570

Please sign in to comment.