-
Notifications
You must be signed in to change notification settings - Fork 185
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: reduce motion #6979
refactor: reduce motion #6979
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. |
e2e tests |
👀 Docs deployed
Commit 2fa4fbb |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6979 +/- ##
==========================================
+ Coverage 83.46% 83.49% +0.03%
==========================================
Files 353 351 -2
Lines 10570 10499 -71
Branches 3510 3473 -37
==========================================
- Hits 8822 8766 -56
+ Misses 1748 1733 -15
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
3bc5b30
to
809fb94
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.
Доброе дело!
Офигенная работа проделана 💪 |
Заодно поправим здесь? Спиннер нужно медленнее крутить?) |
5cdb6fd
to
c89d7d1
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.
Грандиозная работа! 👏
Нашел пару моментов, на которые стоит обратить внимание.
И в целом мысли по анимациям.
Давай где-нибудь пропишем результаты твоего ресерча по анимациям, чтобы всегда можно было на это сослаться в будущем! в Contribution, например, со ссылкой на этот PR. (в комментарию к самому файлу Contribution я подробнее расписал). Чтобы контрибьютеру было понятно как дальше с ними быть. Что вот такое мы завернём ещё и в медиа выражение, а вот такое просто оставим как есть.
Будем плюсом ещё добавить ссылку на файл по хэшу комита, где ты по фэн шую разруливаешь сложные анимации с помощью css переменных (например, Root), опять же, чтобы было место на которое всегда можно сослаться в качестве рекомендуемой практики. И ссылку на Removable, например, где есть простая анимация не требующая ничего более и которую в медиа выражение заворачивать не надо.
packages/vkui/src/components/PanelHeaderContext/PanelHeaderContext.module.css
Outdated
Show resolved
Hide resolved
- удалён хук `useTimeout()` и везде заменён на ручной запуск и очистку – этот хук больше усложняет код, чем упрощает; - удалён `lib/supportEvents.ts`, т.к. все браузеры из текущего `.browserslistrc` поддерживают событие [transitionend](https://developer.mozilla.org/ru/docs/Web/API/Element/transitionend_event#%D1%81%D0%BE%D0%B2%D0%BC%D0%B5%D1%81%D1%82%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D1%8C_%D1%81_%D0%B1%D1%80%D0%B0%D1%83%D0%B7%D0%B5%D1%80%D0%B0%D0%BC%D0%B8); - удалён хук `useReducedMotion()` – на текущий момент больше не используется, т.к. оказывается `(prefers-reduced-motion: reduce)` не предполагает полное отключение всех анимаций, а лишь говорит, что надо их упростить. Эти изменения привели к следующему: - `useWaitTransitionFinish()` – теперь и возвращает сразу функцию не оборачивая его в объект; - в следующих компонентах для анимаций теперь используется `useCSSKeyframesAnimationController()`: - `ActionSheet` - `Alert` - `PanelHeaderContext` – заодно `useGlobalEventListener()` заменён на `useGlobalOnClickOutside()`. И теперь, если `visible === false`, то компонент не остаётся в DOM. - `PopoutWrapper` теперь неконтролируемый – показывается/скрывается в зависимости от параметра `closing`; - создан хук `useDocumentVisibilityState()` – в этом коммите используется в `Gallery`. h2. Типы - добавлен `TimeoutId`, чтобы не приходилось каждый раз писать `ReturnType<typeof setTimeout> | null;`. h2. Тесты - применён `waitCSSKeyframeAnimationEnd()` там, где раньше была завязка на `setTimeout`; - добавлена утилита `waitCSSTransitionEnd()`; - добавлен мок для `TransitionEvent`.
Заодно поправил устаревшую информацию.
Co-authored-by: Victoria Zhizhonkova <indarklight@gmail.com>
…useReducedMotion()`
…le.tsx Co-authored-by: Andrey Medvedev <andr.medv.spb@gmail.com>
acedc77
to
0ad1433
Compare
8a9fc8f
to
a18db43
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.
🔥
💯
💅
В #6979 для теста менял на `2s` и случайно закоммитил.
Была проблема, что до #6979: 1. переменная `prevSwipeBackResult` использовалась в `React.useEffect()`, из-за чего она была всегда актуальная, т.к. обращались мы к ней после окончания рендера. В #6979 она переместилась в **render prop**, где мы обращаемся к переменной до окончания рендера, поэтому и получалось так, что свайп бёк срабатывал в первый раз, пока `prevSwipeBackResult` являлся `null`, а во второй раз уже не срабатывал, т.к. `prevSwipeBackResult` имел предыдущее состояние. Изучил, что проверку на `prevSwipeBackResult` в целом можно удалить. 2. Событие `transitionend` навешивалось в обход **React**, а также был фолбек на `setTimeout()`. В #6979 события навешиваются через **React** – `onTransitionEnd`. Иногда обработчик не вызывался. Чтобы исправить это, перенёс навешивания события на текущий элемент (`isSwipeBackPrev`) вместо последующего (`isSwipeBackNext`). Поправил тесты под это изменение. **Изменения** - удалил `React.useCallback()` на обработчике события `onAnimationEnd`, т.к. это обычный `<div />` и мемоизация ни к чему - заодно отрефакторил `calcPanelSwipeStyles()` и `calcPanelSwipeBackOverlayStyles()`;
h2. Описание Была проблема, что до #6979: 1. переменная `prevSwipeBackResult` использовалась в `React.useEffect()`, из-за чего она была всегда актуальная, т.к. обращались мы к ней после окончания рендера. В #6979 она переместилась в **render prop**, где мы обращаемся к переменной до окончания рендера, поэтому и получалось так, что свайп бёк срабатывал в первый раз, пока `prevSwipeBackResult` являлся `null`, а во второй раз уже не срабатывал, т.к. `prevSwipeBackResult` имел предыдущее состояние. Изучил, что проверку на `prevSwipeBackResult` в целом можно удалить. 2. Событие `transitionend` навешивалось в обход **React**, а также был фолбек с `setTimeout()`. В #6979 события навешиваются через **React** – `onTransitionEnd`. Иногда обработчик не вызывался. Чтобы исправить это, перенёс навешивания события на текущий элемент (`isSwipeBackPrev`) вместо последующего (`isSwipeBackNext`). Поправил тесты под это изменение. h2. Изменения - удалил `React.useCallback()` на обработчике события `onAnimationEnd`, т.к. это обычный `<div />` и мемоизация ни к чему; - заодно отрефакторил `calcPanelSwipeStyles()` и `calcPanelSwipeBackOverlayStyles()`.
h2. Описание Была проблема, что до #6979: 1. переменная `prevSwipeBackResult` использовалась в `React.useEffect()`, из-за чего она была всегда актуальная, т.к. обращались мы к ней после окончания рендера. В #6979 она переместилась в **render prop**, где мы обращаемся к переменной до окончания рендера, поэтому и получалось так, что свайп бёк срабатывал в первый раз, пока `prevSwipeBackResult` являлся `null`, а во второй раз уже не срабатывал, т.к. `prevSwipeBackResult` имел предыдущее состояние. Изучил, что проверку на `prevSwipeBackResult` в целом можно удалить. 2. Событие `transitionend` навешивалось в обход **React**, а также был фолбек с `setTimeout()`. В #6979 события навешиваются через **React** – `onTransitionEnd`. Иногда обработчик не вызывался. Чтобы исправить это, перенёс навешивания события на текущий элемент (`isSwipeBackPrev`) вместо последующего (`isSwipeBackNext`). Поправил тесты под это изменение. h2. Изменения - удалил `React.useCallback()` на обработчике события `onAnimationEnd`, т.к. это обычный `<div />` и мемоизация ни к чему; - заодно отрефакторил `calcPanelSwipeStyles()` и `calcPanelSwipeBackOverlayStyles()`.
preferes-reduced-motion
#2703, [Feature] Анимации у выпадающих меню #2250Описание
В CSS файлах применил медиа-выражение
@media screen and (prefers-reduced-motion: reduce)
там, где необходимо. Попутно рефакторил некоторые из них. Например, примененил токен--vkui--animation_duration_m
где это возможно.Note
Упрощал основываясь на поведении iOS и приложений под него. При включении параметра Уменьшение движения + Предпочтение перекрёстным наплывам (Настройки -> Универсальный доступ -> Движение) переходы, зачастую, заменяются на анимацию через смену прозрачности.
Затронутые анимации:
Note
Длительность и изинги НЕ трогал, только подменял изменение размеров и/или передвижения.
ActionSheet
--vkui_internal--*
;useCSSKeyframesAnimationController()
.Alert
--vkui_internal--*
;useCSSKeyframesAnimationController()
.Button
@media screen and (prefers-reduced-motion: no-preference)
, т.к. допустимая анимация.PanelHeaderContext
--vkui_internal--*
;useCSSKeyframesAnimationController()
.useGlobalEventListener()
заменён наuseGlobalOnClickOutside()
. И теперь, еслиvisible === false
, то компонент не остаётся в DOM;visible === false
возвращаемnull
.Removable
@media screen and (prefers-reduced-motion: no-preference)
, т.к. допустимая анимация.Root
Skeleton
Snackbar
Switch
@media screen and (prefers-reduced-motion: no-preference)
, т.к. допустимая анимация.View
PanelHeader
.animationFades.module.css
@media screen and (prefers-reduced-motion: no-preference)
, т.к. допустимая анимация.focusVisible.module.css
@media screen and (prefers-reduced-motion: no-preference)
на@media screen and (prefers-reduced-motion: reduce)
Что не затронул?
Не трогал мобильный
ModalRoot
дабы не сломать его. Лучше сделать в рамках #2449.Остальные изменения
docs/CONTRIBUTING.md
добавил информацию про a11y (заодно немного освежил документ);useTimeout()
и везде заменён на ручной запуск и очистку – этот хук больше усложняет код, чем упрощает;lib/supportEvents.ts
, т.к. все браузеры из текущего.browserslistrc
поддерживают событие transitionend;- удалён хук(UPD вернул в рамках ⚡ c89d7d1).useReducedMotion()
– на текущий момент больше не используется, т.к. оказывается(prefers-reduced-motion: reduce)
не предполагает полное отключение всех анимаций, а лишь говорит, что надо их упростить.Эти изменения привели к следующему:
useWaitTransitionFinish()
– теперь и возвращает сразу функцию не оборачивая его в объект;PopoutWrapper
– теперь компонент неконтролируемый – показывается/скрывается в зависимости от параметраclosing
.Типы
TimeoutId
, чтобы не приходилось каждый раз писатьReturnType<typeof setTimeout> | null;
.Тесты
waitCSSKeyframeAnimationEnd()
там, где раньше была завязка наsetTimeout
;waitCSSTransitionEnd()
;TransitionEvent
.