Skip to content
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

Remove react-transition-group dependency #2391

Merged
merged 34 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d543d87
🛫
r100-stack Jan 6, 2025
182b4a8
🛫
r100-stack Jan 6, 2025
c2fe3b4
modified repo for the new year (2025)
smmr-dn Jan 6, 2025
1e43853
revert App.tsx
smmr-dn Jan 6, 2025
f2dd813
📈
r100-stack Jan 6, 2025
87a1663
Merge remote-tracking branch 'origin/uyen/modified-new-year-repo' int…
r100-stack Jan 6, 2025
2880bad
Merge branch 'r/themeprovider-children-state-loss-fix' into r/react-t…
r100-stack Jan 6, 2025
eb344b3
Merge branch 'main' into r/react-transition-group-removal
r100-stack Jan 8, 2025
0454c60
Dialog unit test fixes
r100-stack Jan 9, 2025
0a4bc2e
Merge branch 'main' into r/react-transition-group-removal
r100-stack Jan 9, 2025
e28fc35
Fix toast
r100-stack Jan 9, 2025
eff3128
Add JS animations
r100-stack Jan 10, 2025
22e06cd
Fix unit tests
r100-stack Jan 10, 2025
96ff004
Merge branch 'main' into r/react-transition-group-removal
r100-stack Jan 21, 2025
26a1172
Comments
r100-stack Jan 21, 2025
99c9bd6
Separate hook
r100-stack Jan 21, 2025
8b891a7
Testing without mocks
r100-stack Jan 21, 2025
6942306
Cleaner custom hook
r100-stack Jan 21, 2025
76bede6
Cleanup
r100-stack Jan 21, 2025
4197180
`animate?.()`
r100-stack Jan 21, 2025
1455427
Merge branch 'main' into r/react-transition-group-removal
r100-stack Jan 22, 2025
cbac390
Remove duplicate animateOutToRef
r100-stack Jan 22, 2025
b4876c8
onExit called before onClose
r100-stack Jan 23, 2025
8112a64
Merge branch 'main' into r/react-transition-group-removal
r100-stack Jan 23, 2025
630e7c9
Leftover
r100-stack Jan 23, 2025
ec56aaa
Fix Dialog subcomponents cannot self exist
r100-stack Jan 23, 2025
4344c56
Fix a few more tests
r100-stack Jan 23, 2025
14b84cf
Separate DialogMain context
r100-stack Jan 24, 2025
8ee4f16
Minimize diff
r100-stack Jan 24, 2025
de24f21
Leftover
r100-stack Jan 24, 2025
e4a0688
Changeset
r100-stack Jan 24, 2025
e33e1a1
Copyright
r100-stack Jan 24, 2025
0afd50e
Merge branch 'main' into r/react-transition-group-removal
r100-stack Jan 28, 2025
24783fb
Comments
r100-stack Jan 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rude-books-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@itwin/itwinui-css': minor
---

Animation related classes are made now deprecated: `.iui-enter`, `.iui-enter-active`, `.iui-exit`, `.iui-exit-active`.
mayank99 marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 5 additions & 0 deletions .changeset/tidy-geckos-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@itwin/itwinui-react': minor
---

Removed dependency on `react-transition-group`.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
mayank99 marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions apps/react-workshop/src/Toasts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ describe('Toasts', () => {
cy.get('#ladle-root').within(() => {
cy.get('button').first().click();
});

// Wait for entry animation to complete
cy.wait(240);
cy.compareSnapshot(testName);
});
});
Expand Down
31 changes: 0 additions & 31 deletions packages/itwinui-css/src/mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,6 @@
}
}

/// Classes for react-transition-group
/// Used for expand/collapse transitions. Needs height/width to be set in JS.
@mixin iui-transition-group {
$transition-rule:
opacity var(--iui-duration-1) ease-out,
width var(--iui-duration-1) ease-out,
height var(--iui-duration-1) ease-out;

&.iui-enter {
opacity: 0;
}

&.iui-enter-active {
opacity: 1;
@media (prefers-reduced-motion: no-preference) {
transition: $transition-rule;
}
}

&.iui-exit {
opacity: 1;
}

&.iui-exit-active {
opacity: 0;
@media (prefers-reduced-motion: no-preference) {
transition: $transition-rule;
}
}
}

@mixin safari-only {
@supports (-apple-pay-button-style: inherit) {
@content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,6 @@ $iui-side-navigation-icon-margins: calc(1.5 * var(--iui-size-m));
background-color: var(--iui-color-background);
border-inline-end: 1px solid var(--iui-color-border);

@include mixins.iui-transition-group;

&.iui-enter-active,
&.iui-exit-active {
display: flex;
}

&-content {
padding-block: 0 var(--iui-size-s);
padding-inline: var(--iui-size-s);
Expand Down
1 change: 0 additions & 1 deletion packages/itwinui-css/src/table/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@
border-inline-end: 1px solid transparent;
border-block-end: 1px solid var(--iui-color-border);
flex-shrink: 0;
@include mixins.iui-transition-group;
}

// #region Selection
Expand Down
4 changes: 1 addition & 3 deletions packages/itwinui-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@
"@tanstack/react-virtual": "^3.8.2",
"classnames": "^2.3.2",
"jotai": "^2.8.0",
"react-table": "^7.8.0",
"react-transition-group": "^4.4.5"
"react-table": "^7.8.0"
},
"devDependencies": {
"@swc/cli": "^0.5.1",
Expand All @@ -121,7 +120,6 @@
"@types/node": "*",
"@types/react": "*",
"@types/react-dom": "*",
"@types/react-transition-group": "^4.4.10",
"@vitest/coverage-v8": "^1.2.1",
"eslint": "^8",
"eslint-config-prettier": "^8.8.0",
Expand Down
74 changes: 43 additions & 31 deletions packages/itwinui-react/src/core/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { DialogButtonBar } from './DialogButtonBar.js';
import { DialogMain } from './DialogMain.js';
import { useMergedRefs, Box, Portal } from '../../utils/index.js';
import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
import { Transition } from 'react-transition-group';

type DialogProps = {
/**
Expand Down Expand Up @@ -42,37 +41,50 @@ const DialogComponent = React.forwardRef((props, ref) => {
} = props;

const dialogRootRef = React.useRef<HTMLDivElement>(null);
const mergedRefs = useMergedRefs(ref, dialogRootRef);

return (
<Transition in={isOpen} timeout={{ exit: 600 }} mountOnEnter unmountOnExit>
<DialogContext.Provider
value={{
isOpen,
onClose,
closeOnEsc,
closeOnExternalClick,
isDismissible,
preventDocumentScroll,
trapFocus,
setFocus,
isDraggable,
isResizable,
relativeTo,
dialogRootRef,
placement,
}}
>
<Portal portal={portal}>
<Box
className={cx('iui-dialog-wrapper', className)}
data-iui-relative={relativeTo === 'container'}
ref={useMergedRefs(ref, dialogRootRef)}
{...rest}
/>
</Portal>
</DialogContext.Provider>
</Transition>
);
const [shouldBeMounted, setShouldBeMounted] = React.useState(isOpen);

React.useEffect(() => {
if (isOpen) {
setShouldBeMounted(true);
}
// Wait for DialogMain to receive the isOpen=false to properly handle its exit. E.g. move focus to trigger.
else {
setTimeout(() => {
setShouldBeMounted(false);
}, 600);
}
}, [isOpen]);
mayank99 marked this conversation as resolved.
Show resolved Hide resolved

return shouldBeMounted ? (
<DialogContext.Provider
value={{
isOpen,
onClose,
closeOnEsc,
closeOnExternalClick,
isDismissible,
preventDocumentScroll,
trapFocus,
setFocus,
isDraggable,
isResizable,
relativeTo,
dialogRootRef,
placement,
}}
>
<Portal portal={portal}>
<Box
className={cx('iui-dialog-wrapper', className)}
data-iui-relative={relativeTo === 'container'}
ref={mergedRefs}
{...rest}
/>
</Portal>
</DialogContext.Provider>
) : null;
}) as PolymorphicForwardRefComponent<'div', DialogProps>;
if (process.env.NODE_ENV === 'development') {
DialogComponent.displayName = 'Dialog';
Expand Down
78 changes: 47 additions & 31 deletions packages/itwinui-react/src/core/Dialog/DialogMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
import { useDialogContext } from './DialogContext.js';
import type { DialogContextProps } from './DialogContext.js';
import { Transition } from 'react-transition-group';
import { DialogDragContext } from './DialogDragContext.js';
import { useDragAndDrop } from '../../utils/hooks/useDragAndDrop.js';

Expand Down Expand Up @@ -203,36 +202,53 @@ export const DialogMain = React.forwardRef((props, ref) => {
</Box>
);

return (
<Transition
in={isOpen}
appear={true}
timeout={{ exit: 600 }}
// Focuses dialog when opened
onEntered={() => {
previousFocusedElement.current = dialogRef.current?.ownerDocument
.activeElement as HTMLElement;
setFocus && dialogRef.current?.focus({ preventScroll: true });
}}
// Brings back focus to the previously focused element when closed
onExit={() => {
if (
dialogRef.current?.contains(
dialogRef.current?.ownerDocument.activeElement,
)
) {
previousFocusedElement.current?.focus();
}
}}
unmountOnExit={true}
nodeRef={dialogRef}
>
<DialogDragContext.Provider value={{ onPointerDown: handlePointerDown }}>
{trapFocus && <FocusTrap>{content}</FocusTrap>}
{!trapFocus && content}
</DialogDragContext.Provider>
</Transition>
);
/** Focuses dialog when opened. */
const onEnter = React.useCallback(() => {
previousFocusedElement.current = dialogRef.current?.ownerDocument
.activeElement as HTMLElement;
setFocus && dialogRef.current?.focus({ preventScroll: true });
}, [setFocus]);

/** Brings back focus to the previously focused element when closed. */
const onExit = React.useCallback(() => {
if (
dialogRef.current?.contains(
dialogRef.current?.ownerDocument.activeElement,
)
) {
previousFocusedElement.current?.focus();
}
}, []);

const [prevIsOpen, setPrevIsOpen] = React.useState<typeof isOpen>(false);
const [shouldBeMounted, setShouldBeMounted] = React.useState(isOpen);

if (prevIsOpen !== isOpen) {
setPrevIsOpen(isOpen);

if (isOpen) {
// Mount *before* handling dialog entry.
queueMicrotask(() => {
onEnter();
});

setShouldBeMounted(true);
} else {
onExit();

// Wait for the animation to end
setTimeout(() => {
setShouldBeMounted(false);
}, 600);
}
}
mayank99 marked this conversation as resolved.
Show resolved Hide resolved

return shouldBeMounted ? (
<DialogDragContext.Provider value={{ onPointerDown: handlePointerDown }}>
{trapFocus && <FocusTrap>{content}</FocusTrap>}
{!trapFocus && content}
</DialogDragContext.Provider>
) : null;
}) as PolymorphicForwardRefComponent<'div', DialogMainProps>;
if (process.env.NODE_ENV === 'development') {
DialogMain.displayName = 'Dialog.Main';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import cx from 'classnames';
import {
WithCSSTransition,
SvgChevronRight,
Box,
useControlledState,
} from '../../utils/index.js';
import { SvgChevronRight, Box, useControlledState } from '../../utils/index.js';
import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
import { IconButton } from '../Buttons/IconButton.js';

Expand Down Expand Up @@ -45,12 +40,12 @@ type SideNavigationProps = {
*/
onExpanderClick?: () => void;
/**
* Submenu to show supplemental info assicated to the main item.
* Submenu to show supplemental info associated to the main item.
*
* Should be used with the `isSubmenuOpen` props from both `SideNavigation` and `SidenavButton`.
* @example
* <SideNavigation
* // ...
* //
* submenu={(
* <SidenavSubmenu>
* <SidenavSubmenuHeader>Documents</SidenavSubmenuHeader>
Expand Down Expand Up @@ -178,16 +173,7 @@ export const SideNavigation = React.forwardRef((props, forwardedRef) => {
{expanderPlacement === 'bottom' && ExpandButton}
</Box>

{submenu && (
<WithCSSTransition
in={isSubmenuOpen}
dimension='width'
timeout={200}
classNames='iui'
>
{submenu}
</WithCSSTransition>
)}
{submenu && isSubmenuOpen ? submenu : null}
</Box>
</SidenavExpandedContext.Provider>
);
Expand Down
9 changes: 9 additions & 0 deletions packages/itwinui-react/src/core/Toast/Toast.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ import {
import { userEvent } from '@testing-library/user-event';
import { ToastProvider } from './Toaster.js';

// Set reduced motion to not trigger animations since JSDom doesn't mock `animate()`.
const originalMatchMedia = window.matchMedia;
beforeAll(() => {
window.matchMedia = vi.fn().mockReturnValue({ matches: false });
});
afterAll(() => {
window.matchMedia = originalMatchMedia;
});

it('renders the category classes & icons correctly', () => {
const categories: Array<ToastCategory> = [
'negative',
Expand Down
Loading
Loading