diff --git a/compiler/apps/playground/components/Editor/EditorImpl.tsx b/compiler/apps/playground/components/Editor/EditorImpl.tsx
index 9f000f85564a2..e7068534cd0cb 100644
--- a/compiler/apps/playground/components/Editor/EditorImpl.tsx
+++ b/compiler/apps/playground/components/Editor/EditorImpl.tsx
@@ -24,7 +24,11 @@ import BabelPluginReactCompiler, {
printFunctionWithOutlined,
type LoggerEvent,
} from 'babel-plugin-react-compiler';
-import {useDeferredValue, useMemo} from 'react';
+import {
+ useDeferredValue,
+ useMemo,
+ unstable_ViewTransition as ViewTransition,
+} from 'react';
import {useStore} from '../StoreContext';
import ConfigEditor from './ConfigEditor';
import Input from './Input';
diff --git a/compiler/apps/playground/components/TabbedWindow.tsx b/compiler/apps/playground/components/TabbedWindow.tsx
index 1fd5f188c7de1..c324e3ce4505a 100644
--- a/compiler/apps/playground/components/TabbedWindow.tsx
+++ b/compiler/apps/playground/components/TabbedWindow.tsx
@@ -4,8 +4,14 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
-import React from 'react';
+import React, {
+ startTransition,
+ useId,
+ unstable_ViewTransition as ViewTransition,
+ unstable_addTransitionType as addTransitionType,
+} from 'react';
import clsx from 'clsx';
+import {TOGGLE_TAB_TRANSITION} from '../lib/transitionTypes';
export default function TabbedWindow({
tabs,
@@ -16,6 +22,16 @@ export default function TabbedWindow({
activeTab: string;
onTabChange: (tab: string) => void;
}): React.ReactElement {
+ const id = useId();
+ const transitionName = `tab-highlight-${id}`;
+
+ const handleTabChange = (tab: string): void => {
+ startTransition(() => {
+ addTransitionType(TOGGLE_TAB_TRANSITION);
+ onTabChange(tab);
+ });
+ };
+
return (
@@ -25,13 +41,29 @@ export default function TabbedWindow({
return (
);
})}
diff --git a/compiler/apps/playground/lib/transitionTypes.ts b/compiler/apps/playground/lib/transitionTypes.ts
index 0c39e586fed54..0233a7a4923ab 100644
--- a/compiler/apps/playground/lib/transitionTypes.ts
+++ b/compiler/apps/playground/lib/transitionTypes.ts
@@ -6,3 +6,4 @@
*/
export const CONFIG_PANEL_TRANSITION = 'config-panel';
+export const TOGGLE_TAB_TRANSITION = 'toggle-tab';
diff --git a/compiler/apps/playground/styles/globals.css b/compiler/apps/playground/styles/globals.css
index e8b92e6c7be48..c85951ea15276 100644
--- a/compiler/apps/playground/styles/globals.css
+++ b/compiler/apps/playground/styles/globals.css
@@ -108,3 +108,11 @@
object-fit: none;
object-position: left;
}
+
+::view-transition-old(.tab-highlight),
+::view-transition-new(.tab-highlight) {
+ height: 100%;
+}
+::view-transition-group(.tab-text) {
+ z-index: 1;
+}
diff --git a/packages/shared/ReactIODescription.js b/packages/shared/ReactIODescription.js
index 7fa6bb243936f..e1a0fce2c4d0a 100644
--- a/packages/shared/ReactIODescription.js
+++ b/packages/shared/ReactIODescription.js
@@ -7,7 +7,7 @@
* @flow
*/
-export function getIODescription(value: any): string {
+export function getIODescription(value: mixed): string {
if (!__DEV__) {
return '';
}
@@ -34,11 +34,13 @@ export function getIODescription(value: any): string {
return value.command;
} else if (
typeof value.request === 'object' &&
+ value.request !== null &&
typeof value.request.url === 'string'
) {
return value.request.url;
} else if (
typeof value.response === 'object' &&
+ value.response !== null &&
typeof value.response.url === 'string'
) {
return value.response.url;
@@ -53,7 +55,11 @@ export function getIODescription(value: any): string {
return value.name;
} else {
const str = value.toString();
- if (str.startWith('[object ') || str.length < 5 || str.length > 500) {
+ if (
+ str.startsWith('[object ') ||
+ str.length < 5 ||
+ str.length > 500
+ ) {
// This is probably not a useful description.
return '';
}