Контроль раскрытия панелей

В библиотеке MUI (Material-UI) управление раскрытием панелей реализуется с помощью компонента Accordion. Этот компонент предоставляет удобный способ создания разворачивающихся блоков контента, где пользователь может открывать и закрывать секции для отображения дополнительной информации. Контроль раскрытия панелей может быть реализован как неуправляемый компонент (состояние внутреннее), так и управляемый компонент (состояние контролируется извне).


Основные свойства Accordion

Accordion имеет следующие ключевые свойства:

  • expanded – булево значение, определяющее, раскрыта ли панель. Используется для управляемого компонента.
  • onChange – функция-обработчик, вызываемая при изменении состояния панели.
  • disabled – блокирует раскрытие панели.
  • TransitionProps – свойства для управления анимацией раскрытия.

Пример простого контролируемого Accordion:

import React, { useState } from 'react';
import Accordion from '@mui/material/Accordion';
import AccordionSummary from '@mui/material/AccordionSummary';
import AccordionDetails from '@mui/material/AccordionDetails';
import Typography from '@mui/material/Typography';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';

function ControlledAccordion() {
  const [expanded, setExpanded] = useState(false);

  const handleChange = (panel) => (event, isExpanded) => {
    setExpanded(isExpanded ? panel : false);
  };

  return (
    <div>
      <Accordion expanded={expanded === 'panel1'} onCha nge={handleChange('panel1')}>
        <AccordionSummary expandIcon={<ExpandMoreIcon />}>
          <Typography>Панель 1</Typography>
        </AccordionSummary>
        <AccordionDetails>
          <Typography>Контент панели 1</Typography>
        </AccordionDetails>
      </Accordion>

      <Accordion expanded={expanded === 'panel2'} onCha nge={handleChange('panel2')}>
        <AccordionSummary expandIcon={<ExpandMoreIcon />}>
          <Typography>Панель 2</Typography>
        </AccordionSummary>
        <AccordionDetails>
          <Typography>Контент панели 2</Typography>
        </AccordionDetails>
      </Accordion>
    </div>
  );
}

В данном примере expanded задаёт активную панель, а handleChange переключает состояние раскрытия. Используется логика «только одна панель открыта одновременно», что часто требуется в интерфейсах.


Множественное раскрытие панелей

Если нужно разрешить пользователю открывать сразу несколько панелей, состояние можно хранить в виде объекта или массива:

const [expandedPanels, setExpandedPanels] = useState([]);

const handleMultiChange = (panel) => (event, isExpanded) => {
  setExpandedPanels(prev =>
    isExpanded
      ? [...prev, panel]
      : prev.filter(p => p !== panel)
  );
};

Каждая панель проверяет, присутствует ли её идентификатор в массиве expandedPanels:

<Accordion
  expanded={expandedPanels.includes('panel1')}
  onCha nge={handleMultiChange('panel1')}
>

Такой подход позволяет реализовать интерфейсы с множественными раскрытиями, например, FAQ или сложные фильтры.


Анимация и кастомизация

MUI использует компонент Collapse для анимации раскрытия. Через свойство TransitionProps можно настраивать длительность и тип анимации:

<Accordion
  TransitionProps={{ timeout: 500 }}
>

Также можно полностью контролировать и кастомизировать иконку раскрытия через свойство expandIcon в AccordionSummary:

<AccordionSummary expandIcon={<CustomIcon />}>

Для стилизации отдельных частей панели применяются классы и sx-параметры:

  • sx позволяет писать инлайн-стили в формате системы MUI.
  • classes используется для точечной замены стандартных стилей, например, root, expanded, summary, details.

Пример:

<Accordion
  sx={{
    border: '1px solid #ccc',
    borderRadius: 2,
    '&.Mui-expanded': {
      backgroundColor: '#f0f0f0',
    }
  }}
>

Контроль состояния извне

Часто требуется полностью контролировать состояние раскрытия панелей из родительского компонента, например, для синхронизации с сервером или локальным хранилищем. В этом случае expanded и onChange используют пропсы, передаваемые извне:

<Accordion
  expanded={props.expandedPanels.includes('panel1')}
  onCha nge={props.handlePanelChange('panel1')}
>

Такое решение обеспечивает единый источник правды для состояния, что особенно важно в крупных приложениях с множественными компонентами.


Динамическое создание панелей

Если количество панелей заранее неизвестно, удобно создавать их динамически через массив объектов:

const panels = [
  { id: 'panel1', title: 'Панель 1', content: 'Контент 1' },
  { id: 'panel2', title: 'Панель 2', content: 'Контент 2' },
];

panels.map(panel => (
  <Accordion
    key={panel.id}
    expanded={expanded === panel.id}
    onCha nge={handleChange(panel.id)}
  >
    <AccordionSummary expandIcon={<ExpandMoreIcon />}>
      <Typography>{panel.title}</Typography>
    </AccordionSummary>
    <AccordionDetails>
      <Typography>{panel.content}</Typography>
    </AccordionDetails>
  </Accordion>
));

Такой подход повышает масштабируемость интерфейса и упрощает поддержку кода.


Выводы по контролю раскрытия

  • Управляемый Accordion позволяет полностью контролировать раскрытие через expanded и onChange.
  • Множественные раскрытия реализуются с использованием массивов состояния.
  • Анимация и стилизация настраиваются через TransitionProps, sx и classes.
  • Динамическое создание панелей облегчает масштабирование интерфейсов.

Контроль раскрытия панелей в MUI сочетает простоту использования с гибкостью, обеспечивая полный контроль над поведением компонентов и внешним видом.