-
Notifications
You must be signed in to change notification settings - Fork 184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: ModalRoot/ModalPage/ModalCard #6759
base: master
Are you sure you want to change the base?
Conversation
size-limit report 📦
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit d567e6e:
|
e2e tests |
👀 Docs deployed
Commit d567e6e |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6759 +/- ##
==========================================
- Coverage 95.47% 93.92% -1.55%
==========================================
Files 380 389 +9
Lines 11325 11182 -143
Branches 3777 3699 -78
==========================================
- Hits 10812 10503 -309
- Misses 513 679 +166
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
4a0d455
to
7d03282
Compare
cd0da9c
to
c382b8f
Compare
c382b8f
to
fba65d5
Compare
c1453c5
to
a1c9447
Compare
481fc96
to
f07b8b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Грандиозная работа! 👏 👏 👏 💪
Здорово раскидал по компонентам!
Понравилось, что компоненты теперь функции как практически везде!
Офигенно как переведена анимация/перетаскивание на CSS Transition и контроллеры. (Там я, конечно, поплыл, но приятно видеть знакомое API с коллбэками и то, что всё сводится к установке css переменных)
Надо пристально пройтись по местам где коллбёки передаются в компоненты, а не напрямую в html элементы и обернуть их useCallback, и по местам, где объекты возвращаются из хуков или передаются в контекст, чтобы обернуть в useMemo и избежать лишних ререндеров.
По стайлгайду и сторибуку прошелся и так и на устройстве, ничего такого не заметил.
добавил мемоизацию там где можно, но во всех местах сильная завязка на пользователя, т.к. используются колбеки ( ждём React 19, где не нужно будет руками мемоизировать) |
cb1bd66
to
9473173
Compare
- `CustomSelect` жалуется на `renderOption` в 729 строке, что якобы идёт обращение к `ref.current`, но такого там нет; ```plain 729:51 error Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) react-compiler/react-compiler ``` - `ModalRootContext` и `useModalManager` переписываются в PR #6759.
eb4002f
to
2aeae94
Compare
2aeae94
to
45e4dff
Compare
87edb94
to
8132551
Compare
8132551
to
6654031
Compare
55d7a16
to
d567e6e
Compare
settlingHeight
в 0, минимальное значение ограничено до 25, а максимальное до 100)Проверить после
Описание
Переписаны компоненты ModalPage/ModalCard
ModalRoot
.ModalPage
/ModalCard
:open
;keepMounted
;onClose
изменён сVoidFunction
на(reason: ModalPageCloseReason, event?: UIEvent<HTMLElement>) => void
;noFocusToDialog
, приоритетней чемnoFocusToDialog
вModalRoot
;modalOverlayTestId
, приоритетней чемmodalOverlayTestId
вModalRoot
.ModalOutlet
;ModalOverlay
;ModalPageInternal
иModalCardInternal
, у них есть свойствоModalOverlay
;ModalContext
, который теперь используется в компонентахModalPageHeader
,Group
иPanelHeader
вместоModalRootContext
.ModalPage
:settlingHeight
теперь имеет значение по умолчанию50%
вместо75%
, обратил внимание, что в обычноBottomSheet
'ы открываются на половину экрана;footer
, а также создан компонентModalPageFooter
;ModalPageContent
– вынес, чтобы можно было в будущем перейти на сборModalPage
через композицию компонентов.lib/sheet
:В папке хранится логика отвечающая за взаимодействие с модалкой на мобильных экранах. Отдаёт хук
useBottomSheet()
.Переписан компонент ModalRoot
open
компонентовModalCard
иModalPage
в зависимости от ихid
/nav
и параметраactiveModal
, а также рендера общейModalOverlay
для всех модалок.ModalRoot
:onOpen
,onOpened
,onClosed
, которые всплывают отactiveModal
;PopoutRoot
удалёнPopoutRootModal
в пользуModalOutlet
уModalPage
иModalCard
.ModalRootContext
:onClose
нужно теперь обязательно передаватьid
модального окна;onOpen
,onOpened
,onClosed
, чтобы их могли вызыватьModalPage
иModalCard
;registerModal
теперь@deprecated
– не нужно отдельно регистрировать модальное окно.updateModalHeight
теперь@deprecated
– задача с обновлением высоты контента приdynamicContentHeight
решается через CSS;ModalRootOverlayContext
/VisuallyHiddenModalOverlay
:ModalOverlay
для всех модалок в контекстеModalRoot
, происходит подменаModalOverlay
вModalPage
иModalCard
наVisuallyHiddenModalOverlay
, который отвечает за приёмonClick
иmodalOverlayTestId
, а самModalOverlay
попадает в началоModalRoot
useModalManager()
:unmounted
состояние;ModalRoot
иModalPage
/ModalCard
;ModalOverlay
наVisuallyHiddenModalOverlay
.withModalRootContext
:updateModalHeight
HOC тоже@deprecated
.Изменения, которые нужно вынести в отдельные PR после первичного ревью
useKeyboard()
вuseVirtualKeyboardState()
Нюансы
Обратная совместимость
Постарался сделать так, чтобы миграция прошла бесследно.
Сломаются вот такой кейс:
который нужно будет править руками.
BottomSheet, анимации и свайп
Полное появление и полное скрытие происходит через
transform
, но анимация взаимодействия через свайп реализована черезheight
, т.к. это оказалось самым оптимальным способом для решения задач:ModalPageFooter
внизу;settlingHeight
меньше100
;dynamicContentHeight
.Нашёл решение допустимым, т.к. свайп используется либо для закрытия, либо для разворачивания/сворачивания модального окна на всю или на половину страницы. В первом случае сработает закрытие через
transform
, а во втором разворачивание/сворачивание произойдёт черезheight
.dynamicContentHeight
Обновление высоты происходит без анимации, т.к.
height: auto
не анимируется. Опустил анимирование, т.к. усложняет компонент. В теории можно прибегнуть кuseResizeObserver()
.Адативность
При
platform="vkcom"
и при разрешении экрана767px
компонент теперь превращается в BottomSheet, но при этом логику взаимодействия через тач не имеет, т.к.isDesktop
приplatform="vkcom"
всегдаtrue
вне зависимости от размера экрана.Решения
Выделение текста
С помощью функции
hasSelectionWithRangeType
определяем, что пользователь выделил текст и перестаём реагировать наtouchstart
иtouchmove
пока выделение не будет удалено.Вертикальный и горизонтальный скроллы
ModalPageContent
): проверяем наscrollTop !== 0
touchstart
достаём скроллируемый элемент черезevent.target
и проверяем на положениеscrollTop !== 0
и направление пальца вверхПлавающие элементы внутри модалки
Нужно рекомендовать использовать
forcePortal
– в коде проверяем, что идёт взаимодействие с элементом вне модалки.Или нужно рекомендовать добавлять в корневой элемент плавающего элемента атрибут
data-vkui-prevent-swipe
.Поля ввода
Наилучшего варианта не нашёл кроме как:
useVirtualKeyboardState()
узнавать, что пользователь работает с клавиатурой, и перебиватьsafe-area-inset-bottom
натот, что возвращает хук0 (попытка вычислять разницу высоты черезVisualViewport
, чтобы реагировать на смену размера клавиатуры, например, из-за панели эмодзи, не удалась);window
и сохранять его позицию наwindow.scrollTo(0, visualViewport.offsetTop)
.Так как иные решения приводят к другим проблемам (подробнее можно прочесть в JSDoc хука
useVirtualKeyboardState()
), следующие баги нужно закрыть:Референсы