All files / packages/sds-subsystems/.storybook/addons/theme-builder/src/components AccordionPanel.jsx

0% Statements 0/16
0% Branches 0/22
0% Functions 0/3
0% Lines 0/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122                                                                                                                                                                                                                                                   
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import SvgIcon from './SvgIcon';
 
 
/**
 * Lightning Design System Accordion Panel Component
 * A React 19 compatible implementation following SLDS patterns
 */
const AccordionPanel = ({ 
  id,
  summary,
  children,
  expanded = false,
  onTogglePanel,
  className = '',
  disabled = false,
  assistiveText = {},
  headerTabIndex = -1,
  onHeaderKeyDown,
  setHeaderButtonRef,
  ...otherProps 
}) => {
  const handleToggle = useCallback((event) => {
    if (disabled) return;
    
    if (onTogglePanel) {
      onTogglePanel(event, { id, expanded: !expanded });
    }
  }, [disabled, onTogglePanel, id, expanded]);
 
  const handleKeyDown = useCallback((event) => {
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault();
      handleToggle(event);
    }
  }, [handleToggle]);
 
  const panelClasses = `slds-accordion__list-item ${className}`.trim();
  const sectionClasses = `slds-accordion__section ${expanded ? 'slds-is-open' : ''}`.trim();
  const buttonClasses = `slds-accordion__summary-action slds-button slds-button_reset ${disabled ? 'slds-is-disabled' : ''}`.trim();
  const contentClasses = `slds-accordion__content ${expanded ? 'slds-show' : 'slds-hide'}`.trim();
 
  // Assistive text defaults
  const defaultAssistiveText = {
    collapsePanel: 'Collapse panel',
    expandPanel: 'Expand panel',
  };
  
  const mergedAssistiveText = { ...defaultAssistiveText, ...assistiveText };
  const buttonAriaLabel = expanded ? mergedAssistiveText.collapsePanel : mergedAssistiveText.expandPanel;
 
  return (
    <li className={panelClasses} {...otherProps}>
      <section className={sectionClasses}>
        <div className="slds-accordion__summary">
          <h3 className="slds-accordion__summary-heading">
            <button
              type="button"
              className={buttonClasses}
              aria-expanded={expanded}
              aria-controls={`${id}-content`}
              aria-label={`${buttonAriaLabel}: ${summary}`}
              id={`${id}-summary`}
              tabIndex={headerTabIndex}
              onClick={handleToggle}
              onKeyDown={(e) => {
                // First allow parent Accordion to handle arrow navigation
                if (onHeaderKeyDown) onHeaderKeyDown(e);
                // Then handle local toggle keys (Enter/Space)
                handleKeyDown(e);
              }}
              disabled={disabled}
              ref={setHeaderButtonRef}
            >
              {/* <img src={ expanded ? switchIcon : chevronRightIcon} alt="switch" className='slds-button__icon slds-button__icon_left slds-icon slds-icon-text-default slds-icon_x-small'/> */}
              <SvgIcon symbol={ expanded ? 'switch' : 'chevronright'} className="slds-button__icon slds-button__icon_left slds-icon slds-icon-text-default slds-icon_x-small"/>
              <span className="slds-accordion__summary-content">
                {summary}
              </span>
            </button>
          </h3>
        </div>
        <div 
          id={`${id}-content`}
          className={contentClasses}
          role="region"
          aria-labelledby={`${id}-summary`}
        >
          {expanded && children}
        </div>
      </section>
    </li>
  );
};
 
AccordionPanel.propTypes = {
  id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  summary: PropTypes.node.isRequired,
  children: PropTypes.node,
  expanded: PropTypes.bool,
  onTogglePanel: PropTypes.func,
  className: PropTypes.string,
  disabled: PropTypes.bool,
  assistiveText: PropTypes.shape({
    collapsePanel: PropTypes.string,
    expandPanel: PropTypes.string,
  }),
  headerTabIndex: PropTypes.number,
  onHeaderKeyDown: PropTypes.func,
  setHeaderButtonRef: PropTypes.func,
};
 
AccordionPanel.defaultProps = {
  expanded: false,
  className: '',
  disabled: false,
  assistiveText: {},
};
 
export default AccordionPanel;