Skip to content

Commit aecfb11

Browse files
committed
Add ViewTransition on config editor open/close
1 parent 81f0b8e commit aecfb11

File tree

5 files changed

+161
-88
lines changed

5 files changed

+161
-88
lines changed

compiler/apps/playground/__tests__/e2e/page.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ function formatPrint(data: Array<string>): Promise<string> {
2323

2424
async function expandConfigs(page: Page): Promise<void> {
2525
const expandButton = page.locator('[title="Expand config editor"]');
26-
expandButton.click();
26+
await expandButton.click();
27+
await page.waitForSelector('.monaco-editor-config', {state: 'visible'});
2728
}
2829

2930
const TEST_SOURCE = `export default function TestComponent({ x }) {

compiler/apps/playground/components/Editor/ConfigEditor.tsx

Lines changed: 99 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ import MonacoEditor, {loader, type Monaco} from '@monaco-editor/react';
99
import {PluginOptions} from 'babel-plugin-react-compiler';
1010
import type {editor} from 'monaco-editor';
1111
import * as monaco from 'monaco-editor';
12-
import React, {useState, useRef} from 'react';
12+
import React, {
13+
useState,
14+
useRef,
15+
unstable_ViewTransition as ViewTransition,
16+
unstable_addTransitionType as addTransitionType,
17+
startTransition,
18+
} from 'react';
1319
import {Resizable} from 're-resizable';
1420
import {useStore, useStoreDispatch} from '../StoreContext';
1521
import {monacoOptions} from './monacoOptions';
@@ -36,15 +42,27 @@ export default function ConfigEditor({
3642
display: isExpanded ? 'block' : 'none',
3743
}}>
3844
<ExpandedEditor
39-
onToggle={setIsExpanded}
45+
onToggle={() => {
46+
startTransition(() => {
47+
addTransitionType('config-panel');
48+
setIsExpanded(false);
49+
});
50+
}}
4051
appliedOptions={appliedOptions}
4152
/>
4253
</div>
4354
<div
4455
style={{
4556
display: !isExpanded ? 'block' : 'none',
4657
}}>
47-
<CollapsedEditor onToggle={setIsExpanded} />
58+
<CollapsedEditor
59+
onToggle={() => {
60+
startTransition(() => {
61+
addTransitionType('config-panel');
62+
setIsExpanded(true);
63+
});
64+
}}
65+
/>{' '}
4866
</div>
4967
</>
5068
);
@@ -54,7 +72,7 @@ function ExpandedEditor({
5472
onToggle,
5573
appliedOptions,
5674
}: {
57-
onToggle: (expanded: boolean) => void;
75+
onToggle: () => void;
5876
appliedOptions: PluginOptions | null;
5977
}): React.ReactElement {
6078
const store = useStore();
@@ -111,90 +129,92 @@ function ExpandedEditor({
111129
: 'Invalid configs';
112130

113131
return (
114-
<Resizable
115-
minWidth={300}
116-
maxWidth={600}
117-
defaultSize={{width: 350}}
118-
enable={{right: true, bottom: false}}>
119-
<div className="bg-blue-10 relative h-full flex flex-col !h-[calc(100vh_-_3.5rem)] border border-gray-300">
120-
<div
121-
className="absolute w-8 h-16 bg-blue-10 rounded-r-full flex items-center justify-center z-[2] cursor-pointer border border-l-0 border-gray-300"
122-
title="Minimize config editor"
123-
onClick={() => onToggle(false)}
124-
style={{
125-
top: '50%',
126-
marginTop: '-32px',
127-
right: '-32px',
128-
borderTopLeftRadius: 0,
129-
borderBottomLeftRadius: 0,
130-
}}>
131-
<IconChevron displayDirection="left" className="text-blue-50" />
132-
</div>
133-
134-
<div className="flex-1 flex flex-col m-2 mb-2">
135-
<div className="pb-2">
136-
<h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">
137-
Config Overrides
138-
</h2>
139-
</div>
140-
<div className="flex-1 rounded-lg overflow-hidden border border-gray-300">
141-
<MonacoEditor
142-
path={'config.ts'}
143-
language={'typescript'}
144-
value={store.config}
145-
onMount={handleMount}
146-
onChange={handleChange}
147-
loading={''}
148-
className="monaco-editor-config"
149-
options={{
150-
...monacoOptions,
151-
lineNumbers: 'off',
152-
renderLineHighlight: 'none',
153-
overviewRulerBorder: false,
154-
overviewRulerLanes: 0,
155-
fontSize: 12,
156-
scrollBeyondLastLine: false,
157-
glyphMargin: false,
158-
}}
159-
/>
132+
<ViewTransition update={{'config-panel': 'slide-in', default: 'none'}}>
133+
<Resizable
134+
minWidth={300}
135+
maxWidth={600}
136+
defaultSize={{width: 350}}
137+
enable={{right: true, bottom: false}}>
138+
<div className="bg-blue-10 relative h-full flex flex-col !h-[calc(100vh_-_3.5rem)] border border-gray-300">
139+
<div
140+
className="absolute w-8 h-16 bg-blue-10 rounded-r-full flex items-center justify-center z-[2] cursor-pointer border border-l-0 border-gray-300"
141+
title="Minimize config editor"
142+
onClick={onToggle}
143+
style={{
144+
top: '50%',
145+
marginTop: '-32px',
146+
right: '-32px',
147+
borderTopLeftRadius: 0,
148+
borderBottomLeftRadius: 0,
149+
}}>
150+
<IconChevron displayDirection="left" className="text-blue-50" />
160151
</div>
161-
</div>
162-
<div className="flex-1 flex flex-col m-2">
163-
<div className="pb-2">
164-
<h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">
165-
Applied Configs
166-
</h2>
152+
153+
<div className="flex-1 flex flex-col m-2 mb-2">
154+
<div className="pb-2">
155+
<h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">
156+
Config Overrides
157+
</h2>
158+
</div>
159+
<div className="flex-1 rounded-lg overflow-hidden border border-gray-300">
160+
<MonacoEditor
161+
path={'config.ts'}
162+
language={'typescript'}
163+
value={store.config}
164+
onMount={handleMount}
165+
onChange={handleChange}
166+
loading={''}
167+
className="monaco-editor-config"
168+
options={{
169+
...monacoOptions,
170+
lineNumbers: 'off',
171+
renderLineHighlight: 'none',
172+
overviewRulerBorder: false,
173+
overviewRulerLanes: 0,
174+
fontSize: 12,
175+
scrollBeyondLastLine: false,
176+
glyphMargin: false,
177+
}}
178+
/>
179+
</div>
167180
</div>
168-
<div className="flex-1 rounded-lg overflow-hidden border border-gray-300">
169-
<MonacoEditor
170-
path={'applied-config.js'}
171-
language={'javascript'}
172-
value={formattedAppliedOptions}
173-
loading={''}
174-
className="monaco-editor-applied-config"
175-
options={{
176-
...monacoOptions,
177-
lineNumbers: 'off',
178-
renderLineHighlight: 'none',
179-
overviewRulerBorder: false,
180-
overviewRulerLanes: 0,
181-
fontSize: 12,
182-
scrollBeyondLastLine: false,
183-
readOnly: true,
184-
glyphMargin: false,
185-
}}
186-
/>
181+
<div className="flex-1 flex flex-col m-2">
182+
<div className="pb-2">
183+
<h2 className="inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm">
184+
Applied Configs
185+
</h2>
186+
</div>
187+
<div className="flex-1 rounded-lg overflow-hidden border border-gray-300">
188+
<MonacoEditor
189+
path={'applied-config.js'}
190+
language={'javascript'}
191+
value={formattedAppliedOptions}
192+
loading={''}
193+
className="monaco-editor-applied-config"
194+
options={{
195+
...monacoOptions,
196+
lineNumbers: 'off',
197+
renderLineHighlight: 'none',
198+
overviewRulerBorder: false,
199+
overviewRulerLanes: 0,
200+
fontSize: 12,
201+
scrollBeyondLastLine: false,
202+
readOnly: true,
203+
glyphMargin: false,
204+
}}
205+
/>
206+
</div>
187207
</div>
188208
</div>
189-
</div>
190-
</Resizable>
209+
</Resizable>
210+
</ViewTransition>
191211
);
192212
}
193213

194214
function CollapsedEditor({
195215
onToggle,
196216
}: {
197-
onToggle: (expanded: boolean) => void;
217+
onToggle: () => void;
198218
}): React.ReactElement {
199219
return (
200220
<div
@@ -203,7 +223,7 @@ function CollapsedEditor({
203223
<div
204224
className="absolute w-10 h-16 bg-blue-10 hover:translate-x-2 transition-transform rounded-r-full flex items-center justify-center z-[2] cursor-pointer border border-gray-300"
205225
title="Expand config editor"
206-
onClick={() => onToggle(true)}
226+
onClick={onToggle}
207227
style={{
208228
top: '50%',
209229
marginTop: '-32px',

compiler/apps/playground/components/Editor/EditorImpl.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ import BabelPluginReactCompiler, {
2424
printFunctionWithOutlined,
2525
type LoggerEvent,
2626
} from 'babel-plugin-react-compiler';
27-
import {useDeferredValue, useMemo} from 'react';
27+
import {
28+
useDeferredValue,
29+
useMemo,
30+
unstable_ViewTransition as ViewTransition,
31+
} from 'react';
2832
import {useStore} from '../StoreContext';
2933
import ConfigEditor from './ConfigEditor';
3034
import Input from './Input';
@@ -342,14 +346,21 @@ export default function Editor(): JSX.Element {
342346
<div className="flex-shrink-0">
343347
<ConfigEditor appliedOptions={appliedOptions} />
344348
</div>
345-
<div className="flex flex-1 min-w-0">
346-
<div className="flex-1 min-w-[550px] sm:min-w-0">
347-
<Input language={language} errors={errors} />
348-
</div>
349-
<div className="flex-1 min-w-[550px] sm:min-w-0">
350-
<Output store={deferredStore} compilerOutput={mergedOutput} />
349+
350+
<ViewTransition
351+
update={{
352+
'config-panel': 'container',
353+
default: 'none',
354+
}}>
355+
<div className="flex flex-1 min-w-0">
356+
<div className="flex-1 min-w-[550px] sm:min-w-0">
357+
<Input language={language} errors={errors} />
358+
</div>
359+
<div className="flex-1 min-w-[550px] sm:min-w-0">
360+
<Output store={deferredStore} compilerOutput={mergedOutput} />
361+
</div>
351362
</div>
352-
</div>
363+
</ViewTransition>
353364
</div>
354365
</>
355366
);

compiler/apps/playground/next.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const path = require('path');
1111
const nextConfig = {
1212
experimental: {
1313
reactCompiler: true,
14+
viewTransition: true,
1415
},
1516
reactStrictMode: true,
1617
webpack: (config, options) => {

compiler/apps/playground/styles/globals.css

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,43 @@
6969
scrollbar-width: none; /* Firefox */
7070
}
7171
}
72+
73+
::view-transition-old(.slide-in) {
74+
animation-name: slideOutLeft;
75+
}
76+
::view-transition-new(.slide-in) {
77+
animation-name: slideInLeft;
78+
}
79+
::view-transition-group(.slide-in) {
80+
z-index: 1;
81+
}
82+
83+
@keyframes slideOutLeft {
84+
from {
85+
transform: translateX(0);
86+
}
87+
to {
88+
transform: translateX(-100%);
89+
}
90+
}
91+
@keyframes slideInLeft {
92+
from {
93+
transform: translateX(-100%);
94+
}
95+
to {
96+
transform: translateX(0);
97+
}
98+
}
99+
@keyframes slideInRight {
100+
from {
101+
transform: translateX(100%);
102+
}
103+
to {
104+
transform: translateX(0);
105+
}
106+
}
107+
108+
::view-transition-old(.container),
109+
::view-transition-new(.container) {
110+
height: 100%;
111+
}

0 commit comments

Comments
 (0)