Миграция с v7 на v8


Удалена функция withModalRootContext из ModalRoot.


Удалено свойство baseClassName у компонента VisuallyHidden. Используйте стандартное свойство className.


  • Свойство onClose переименовано в onClosed.
  • Добавлена поддержка slotProps.iosCloseItem для упрощения локализации кнопки “Отмена” на iOS.

Кнопка отмены на iOS рендерится отдельно от списка действий (вне ActionSheetItem). Теперь можно передавать свойства напрямую в ActionSheetDefaultIosCloseItem через slotProps.iosCloseItem без необходимости создавать обёртку.

Миграция
<ActionSheet
- onClose={() => {}}
+ onClosed={() => {}}
  title="Заголовок"
>
  <ActionSheetItem>Действие</ActionSheetItem>
</ActionSheet>

Пример использования slotProps.iosCloseItem для локализации:

<ActionSheet
  onClosed={() => setPopout(null)}
  slotProps={{
    iosCloseItem: {
      children: i18n("cancel"),
    },
  }}
>
  <ActionSheetItem onClick={handleAction}>Действие</ActionSheetItem>
</ActionSheet>

Свойство onClose переименовано в onClosed.

Миграция
<Alert
  title="Подтвердите действие"
  description="Вы уверены?"
- onClose={() => setPopout(null)}
+ onClosed={() => setPopout(null)}
/>

Свойство onClose переименовано в onClosed.

Миграция
<Snackbar
- onClose={() => setSnackbar(null)}
+ onClosed={() => setSnackbar(null)}
>
  Сообщение
</Snackbar>

Свойство fixed удалено. Вместо него используйте свойство strategy.

Миграция
<PopoutWrapper
- fixed
/>
 
<PopoutWrapper
- fixed={true}
/>
 
<PopoutWrapper
- fixed={false}
+ strategy="none"
/>

Изменена реализация fixed — вместо position: fixed используется position: sticky. Это потребовало изменения раскладки всей страницы — height: 100% на <html> и <body> удалён в пользу display: flex, и теперь высота страницы зависит от содержимого.

Что может сломаться
  • Получение области видимости через document.body.clientHeight или его потомков с height: 100%. Необходимо заменить либо на document.documentElement.clientHeight, либо на window.innerHeight.

    - document.body.clientHeight
    + document.documentElement.clientHeight
    // или
    + window.innerHeight
  • Чтобы какой-то из элементов растягивался на высоту области видимости, используйте единицы измерения vh или dvh вместо %.

    - height: 100%
    + height: 100dvh
  • Для SplitCol с fixed: чтобы растянуть потомок на всю колонку, используйте flex-grow: 1 на этом потомке.


Внутренние отступы синхронизированы с другими элементами форм. Компонент стал компактнее.


Изменена структура компонента и уменьшена минимальная высота.

Структурные изменения:

  • Свойство after теперь всегда рендерится справа от компонента (вне основного контента), независимо от значения afterAlign.
  • Добавлены новые свойства meta и submeta для отображения текста справа от основного контента внутри блока.
  • Если вы использовали after с afterAlign="start", замените его на meta и submeta.

Изменение минимальной высоты:

Режимv7v8
regular64px48px
compact60px44px
Миграция

Если вы использовали after с afterAlign="start" (или не указывали afterAlign), замените на meta и submeta:

<RichCell
  before={<Avatar size={48} />}
  overTitle="онлайн"
  subtitle="Санкт-Петербург"
- after="Текст"
- afterCaption="Подтекст"
- afterAlign="start"
+ meta="Текст"
+ submeta="Подтекст"
>
  Имя пользователя
</RichCell>

Если вы использовали after с afterAlign="center" или afterAlign="end", поведение остаётся прежним:

<RichCell
  before={<Avatar size={48} />}
  subtitle="Санкт-Петербург"
  after={<Icon28Like />}
  afterAlign="center"
>
  Имя пользователя
</RichCell>

Свойство imageTheme теперь по умолчанию имеет значение "auto" вместо "dark". При значении "auto" тема изображения определяется автоматически на основе цветовой схемы приложения.

Миграция

Если вам нужно сохранить прежнее поведение, укажите imageTheme="dark":

<Banner
  mode="image"
+ imageTheme="dark"
  background={<div style={{ backgroundImage: 'url(...)' }} />}
>
  Контент
</Banner>

Изменены цвета при appearance="neutral":

mode=“primary”:

  • Было: текст --color_text_primary, фон --color_background_secondary
  • Стало: текст --color_text_contrast, фон --color_icon_secondary

mode=“secondary”:

  • Было: текст --color_text_subhead, фон --color_background_secondary
  • Стало: текст --color_text_primary, фон --color_background_secondary_alpha

Свойство accessible теперь по умолчанию имеет значение true.


Изменён тип свойства onChange:

- onChange?: (value?: Date) => void
+ onChange?: (value: Date) => void

Проверка значения на undefined больше не требуется.

Миграция
<Calendar
- onChange={(value: Date | undefined) => {
-   if (value) {
-     setValue(value);
-   }
- }}
+ onChange={(value: Date) => setValue(value)}
/>

Изменён тип свойства onChange:

- onChange?: (value?: Date) => void
+ onChange?: (value: Date | null) => void

Значение null означает, что поле очищено. Значение undefined не используется, так как оно зарезервировано для неконтролируемого состояния компонента.


В ряде компонентов изменено поведение передачи дополнительных свойств (restProps). Теперь restProps применяются к корневому элементу, а для передачи свойств во внутренние элементы используется slotProps.

Свойства getRef, data-* и aria-* атрибуты теперь нужно передавать через slotProps.input.

Миграция
<Input
- getRef={inputRef}
- data-testid="my-input"
- aria-label="Введите текст"
+ slotProps={{
+   input: {
+     getRootRef: inputRef,
+     "data-testid": "my-input",
+     "aria-label": "Введите текст"
+   }
+ }}
/>

Свойства getRef, data-* и aria-* атрибуты теперь нужно передавать через slotProps.textarea.

Миграция
<Textarea
- getRef={textareaRef}
- data-testid="my-textarea"
+ slotProps={{
+   textarea: {
+     getRootRef: textareaRef,
+     "data-testid": "my-textarea"
+   }
+ }}
/>

Свойства getRef, data-*, aria-* атрибуты и специфичные для input свойства (кроме checked, disabled, readOnly, required, name, value) теперь нужно передавать через slotProps.input.

Миграция
<Checkbox
- getRef={checkboxRef}
- data-testid="my-checkbox"
- aria-describedby="hint"
+ slotProps={{
+   input: {
+     getRootRef: checkboxRef,
+     "data-testid": "my-checkbox",
+     "aria-describedby": "hint"
+   }
+ }}
>
  Согласен
</Checkbox>
 
<Switch
- getRef={switchRef}
- data-testid="my-switch"
+ slotProps={{
+   input: {
+     getRootRef: switchRef,
+     "data-testid": "my-switch"
+   }
+ }}
/>
 
<Radio
- getRef={radioRef}
+ slotProps={{
+   input: {
+     getRootRef: radioRef
+   }
+ }}
>
  Вариант
</Radio>

Свойства getRef, data-* и aria-* атрибуты теперь нужно передавать через slotProps.input.

Миграция
<File
- getRef={fileRef}
- data-testid="file-input"
+ slotProps={{
+   input: {
+     getRootRef: fileRef,
+     "data-testid": "file-input"
+   }
+ }}
>
  Выбрать файл
</File>

Свойства restProps теперь применяются к корневому элементу, а не к внутреннему input. Для передачи свойств во внутренний input используйте slotProps.input.

Миграция
<CustomSelect
- data-testid="select"
- aria-label="Выберите значение"
+ slotProps={{
+   input: {
+     "data-testid": "select",
+     "aria-label": "Выберите значение"
+   }
+ }}
  options={options}
  value={value}
  onChange={onChange}
/>

Свойства для внутреннего input теперь передаются через slotProps.input.

Миграция
<ChipsSelect
- getRef={inputRef}
- data-testid="chips-select"
- aria-describedby="hint"
+ slotProps={{
+   input: {
+     getRootRef: inputRef,
+     "data-testid": "chips-select",
+     "aria-describedby": "hint"
+   }
+ }}
  value={value}
  onChange={onChange}
/>

Свойства restProps теперь применяются к корневому элементу, а не к внутреннему контейнеру content. Для передачи свойств в контейнер используйте slotProps.content.

Миграция
<SplitLayout
- className="my-layout"
- data-testid="layout"
+ slotProps={{
+   content: {
+     className: "my-layout",
+     "data-testid": "layout"
+   }
+ }}
  header={<PanelHeader />}
>
  <SplitCol>Контент</SplitCol>
</SplitLayout>

Следующие API помечены как устаревшие и будут удалены в будущих версиях.

Свойства sizeX и sizeY теперь @deprecated, используйте density вместо sizeY, viewWidth={ViewWidth.MOBILE} вместо sizeX="compact" и viewWidth={ViewWidth.SMALL_TABLET} вместо sizeX="regular"

Пример миграции
- <AdaptivityProvider sizeX="compact">
+ <AdaptivityProvider viewWidth={ViewWidth.MOBILE}>
 
- <AdaptivityProvider sizeX="regular">
+ <AdaptivityProvider viewWidth={ViewWidth.SMALL_TABLET}>
 
- <AdaptivityProvider sizeY="compact">
+ <AdaptivityProvider density="compact">
 
- <AdaptivityProvider sizeY="regular">
+ <AdaptivityProvider density="regular">
 
- <AdaptivityProvider sizeX="compact" sizeY="compact">
+ <AdaptivityProvider viewWidth={ViewWidth.MOBILE} density="compact">
 
- <AdaptivityProvider sizeX="regular" sizeY="regular">
+ <AdaptivityProvider viewWidth={ViewWidth.SMALL_TABLET} density="regular">
 
- <AppRootProvider sizeX="regular" sizeY="compact">
+ <AppRootProvider viewWidth={ViewWidth.SMALL_TABLET} density="compact">
 
- <AppRootProvider sizeX="compact" sizeY="regular">
+ <AppRootProvider viewWidth={ViewWidth.MOBILE} density="regular">

Компонент ModalRoot помечен как @deprecated. Используйте хук useModalManager для императивного управления модальными окнами.

Миграция
- const [activeModal, setActiveModal] = useState(null);
-
- <ModalRoot activeModal={activeModal} onClose={() => setActiveModal(null)}>
-   <ModalPage id="modal" onClose={() => setActiveModal(null)}>
-     Контент
-   </ModalPage>
- </ModalRoot>
 
+ const [modalApi, modalHolder] = useModalManager();
+
+ // Открытие модального окна
+ modalApi.openModalPage({
+   children: <div>Контент</div>,
+ });
+
+ // В JSX
+ {modalHolder}

Компонент FixedLayout помечен как @deprecated и будет удалён в v10. Используйте вместо него Box со свойствами position="sticky" и insetBlockStart/insetBlockEnd.

Миграция
- <FixedLayout vertical="top">
+ <Box position="sticky" insetBlockStart={0}>
    Content
- </FixedLayout>
+ </Box>
 
- <FixedLayout vertical="bottom">
+ <Box position="sticky" insetBlockEnd={0}>
    Content
- </FixedLayout>
+ </Box>

Подкомпонент Flex.Item помечен как @deprecated. Используйте стандартные CSS свойства или свойства компонента Box для управления дочерними элементами.


Свойство afterCaption помечено как @deprecated. Используйте вместо него свойство submeta.

Миграция
<RichCell
- afterCaption="Подтекст"
+ submeta="Подтекст"
>
  Контент
</RichCell>

Свойства mode="cancel" и isCancelItem отмечены как устаревшие.

Вместо использования ActionSheetItem с mode="cancel" или isCancelItem в качестве iosCloseItem, используйте:

  • slotProps.iosCloseItem в ActionSheet для передачи свойств в кнопку отмены
  • или свойство iosCloseItem с компонентом ActionSheetDefaultIosCloseItem для полной кастомизации
Миграция
<ActionSheet
  onClosed={() => setPopout(null)}
  title="Выберите действие"
- iosCloseItem={
-   <ActionSheetItem mode="cancel" onClick={() => setPopout(null)}>
-     Отмена
-   </ActionSheetItem>
- }
+ slotProps={{
+    iosCloseItem: {
+      children: "Отмена",
+      onClick: () => setPopout(null)
+    }
+  }}
+>
+  <ActionSheetItem onClick={handleAction}>Действие</ActionSheetItem>
</ActionSheet>

Альтернативный вариант с использованием ActionSheetDefaultIosCloseItem напрямую:

<ActionSheet
  onClosed={() => setPopout(null)}
  title="Выберите действие"
- iosCloseItem={
-   <ActionSheetItem mode="cancel" onClick={() => setPopout(null)}>
-     Отмена
-   </ActionSheetItem>
- }
+ iosCloseItem={
+   <ActionSheetDefaultIosCloseItem onClick={() => setPopout(null)}>
+     Отмена
+   </ActionSheetDefaultIosCloseItem>
+ }
>
  <ActionSheetItem onClick={handleAction}>Действие</ActionSheetItem>
</ActionSheet>

Свойство accessible помечено как @deprecated, так как теперь оно имеет значение true по умолчанию.