Re: collapsible content

Hello!

I want to change the icon-caret on the collapsible content to the plus and minus icon. I use the following method to do so with collapsible rows, but I can’t figure out how to do it with collapsible content.

CSS to Hide Existing Caret Icon

I add this CSS to hide any existing caret icons with collapsible rows:

/* Hide the default caret SVG within the summary */
.product__accordion details summary .icon-caret {
display: none;
}

JavaScript to Manage Accordion State and Icons

I add this JS to show the plus and minus icons with collapsible rows:

// Define SVG icons
const plusIcon = ``;

const minusIcon = ``;

document.querySelectorAll('.product__accordion details').forEach((accordion) => {
const summary = accordion.querySelector('summary');
const titleDiv = summary.querySelector('.summary__title');

// Add plus icon initially to all closed accordions
if (!accordion.hasAttribute('open')) {
titleDiv.innerHTML += plusIcon;
} else {
titleDiv.innerHTML += minusIcon;
}

accordion.addEventListener('click', function(event) {
// Prevent default behavior to properly handle the state
event.preventDefault();

document.querySelectorAll('.product__accordion details').forEach((otherAccordion) => {
if (otherAccordion !== accordion) {
otherAccordion.removeAttribute('open');

// Replace minus icon with plus icon for other accordions
const otherSummary = otherAccordion.querySelector('summary');
const existingMinusSvg = otherSummary.querySelector('.minus-icon');
if (existingMinusSvg) {
existingMinusSvg.remove();
otherSummary.querySelector('.summary__title').innerHTML += plusIcon;
}
}
});

// Toggle the current accordion
const isOpen = !accordion.hasAttribute('open');
const svgIcon = summary.querySelector('.plus-icon, .minus-icon');
if (svgIcon) {
svgIcon.remove();
}

if (isOpen) {
accordion.setAttribute('open', '');
summary.querySelector('.summary__title').innerHTML += minusIcon;
} else {
accordion.removeAttribute('open');
summary.querySelector('.summary__title').innerHTML += plusIcon;
}
});
});

Any help getting the plus and minus icons to show on collapsible content without sharing my store link would be greatly appreciated!

Hello there!

I understand you want to change the icon-caret on the collapsible content to plus and minus icons. Let’s adapt your existing approach for collapsible content. Here’s how you can do it:

  1. First, add this CSS to hide the existing caret icon for collapsible content:
/* Hide the default caret SVG within the summary for collapsible content */
.collapsible-content summary .icon-caret {
  display: none;
}
  1. Now, add this JavaScript to manage the icons for collapsible content:
// Define SVG icons
const plusIcon = ``;

const minusIcon = ``;

document.querySelectorAll('.collapsible-content details').forEach((content) => {
  const summary = content.querySelector('summary');

  // Add plus icon initially to all closed collapsible content
  if (!content.hasAttribute('open')) {
    summary.innerHTML += plusIcon;
  } else {
    summary.innerHTML += minusIcon;
  }

  content.addEventListener('toggle', function() {
    const svgIcon = summary.querySelector('.plus-icon, .minus-icon');
    if (svgIcon) {
      svgIcon.remove();
    }

    if (this.hasAttribute('open')) {
      summary.innerHTML += minusIcon;
    } else {
      summary.innerHTML += plusIcon;
    }
  });
});
  1. Make sure your HTML structure for collapsible content looks like this:

  

The main differences from your original code for collapsible rows are:

  1. We’re now targeting .collapsible-content details instead of .product__accordion details.
  2. We’re using the ‘toggle’ event instead of ‘click’ to detect changes in the collapsible content state.
  3. We’re adding icons directly to the summary element instead of a .summary__title div.
  4. We’re not manually managing the open/closed state or closing other elements, as the
    element handles this natively.

These changes make the code work specifically for collapsible content while maintaining the functionality you had for collapsible rows. The plus and minus icons will now appear and change appropriately when you interact with the collapsible content.

If you need any further adjustments or have any questions, please let me know!

Note: If this solution doesn’t work, feel free to share your store link, and I’ll take a closer look to assist you further!

Thanks,
SV | Untechnickle

Hi, @TheUntechnickle

Thank you for the prompt reply. Unfortunately, it doesn’t seem to work. Maybe I am doing it wrong.

I added the CSS, which does correctly hide the caret icon. I tried adding the JavaScript to product-info.js, and theme-editor.js, but neither seem to make the plus or minus icons appear on the collapsible content.

@TheUntechnickle The JS code seems to work when I add it to the global.js file, but then the collapsible row plus and minus icons disappear.

Try this instead:

// Define SVG icons
const plusIcon = ``;

const minusIcon = ``;

// Function to handle icon placement
function placeIcon(element, isOpen) {
  const icon = isOpen ? minusIcon : plusIcon;
  const existingIcon = element.querySelector('.plus-icon, .minus-icon');
  if (existingIcon) {
    existingIcon.remove();
  }
  element.innerHTML += icon;
}

// Handle collapsible rows (product accordion)
document.querySelectorAll('.product__accordion details').forEach((accordion) => {
  const summary = accordion.querySelector('summary');
  const titleDiv = summary.querySelector('.summary__title');

  // Add initial icon
  placeIcon(titleDiv, accordion.hasAttribute('open'));

  accordion.addEventListener('click', function(event) {
    event.preventDefault();

    document.querySelectorAll('.product__accordion details').forEach((otherAccordion) => {
      if (otherAccordion !== accordion) {
        otherAccordion.removeAttribute('open');
        placeIcon(otherAccordion.querySelector('.summary__title'), false);
      }
    });

    const isOpen = !accordion.hasAttribute('open');
    if (isOpen) {
      accordion.setAttribute('open', '');
    } else {
      accordion.removeAttribute('open');
    }
    placeIcon(titleDiv, isOpen);
  });
});

// Handle collapsible content
document.querySelectorAll('.collapsible-content details').forEach((content) => {
  const summary = content.querySelector('summary');

  // Add initial icon
  placeIcon(summary, content.hasAttribute('open'));

  content.addEventListener('toggle', function() {
    placeIcon(summary, this.hasAttribute('open'));
  });
});

Also, make sure you have the following CSS to hide the default caret icons:

/* Hide the default caret SVG within the summary */
.product__accordion details summary .icon-caret,
.collapsible-content details summary .icon-caret {
  display: none;
}

This approach should maintain the functionality for your collapsible rows while adding support for the new collapsible content. The plus and minus icons should now appear and function correctly for both types of elements.

Feel free to DM or reply here if there’s anything else you need my help with :slightly_smiling_face:

Cheers!