Skip to content

Commit 277cf6c

Browse files
committed
Add tab switching animation in default view
1 parent 32f2b67 commit 277cf6c

File tree

2 files changed

+56
-23
lines changed

2 files changed

+56
-23
lines changed

compiler/apps/playground/components/TabbedWindow.tsx

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*/
7-
import React from 'react';
7+
import React, {
8+
startTransition,
9+
useId,
10+
unstable_ViewTransition as ViewTransition,
11+
unstable_addTransitionType as addTransitionType,
12+
} from 'react';
813
import clsx from 'clsx';
914

1015
export default function TabbedWindow({
@@ -16,30 +21,50 @@ export default function TabbedWindow({
1621
activeTab: string;
1722
onTabChange: (tab: string) => void;
1823
}): React.ReactElement {
24+
const id = useId();
25+
const transitionName = `tab-highlight-${id}`;
26+
27+
const handleTabChange = (tab: string): void => {
28+
startTransition(() => {
29+
addTransitionType('tab');
30+
onTabChange(tab);
31+
});
32+
};
33+
1934
return (
20-
<div className="flex-1 min-w-[550px] sm:min-w-0">
21-
<div className="flex flex-col h-full max-w-full">
22-
<div className="flex p-2 flex-shrink-0">
23-
{Array.from(tabs.keys()).map(tab => {
24-
const isActive = activeTab === tab;
25-
return (
26-
<button
27-
key={tab}
28-
onClick={() => onTabChange(tab)}
29-
className={clsx(
30-
'active:scale-95 transition-transform py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full text-sm',
31-
!isActive && 'hover:bg-primary/5',
32-
isActive && 'bg-highlight text-link',
33-
)}>
34-
{tab}
35-
</button>
36-
);
37-
})}
38-
</div>
39-
<div className="flex-1 overflow-hidden w-full h-full">
40-
{tabs.get(activeTab)}
41-
</div>
35+
<div className="flex-1 min-w-[550px] sm:min-w-0">
36+
37+
<div className="flex flex-col h-full max-w-full">
38+
<div className="flex p-2 flex-shrink-0">
39+
{Array.from(tabs.keys()).map(tab => {
40+
const isActive = activeTab === tab;
41+
return (
42+
<button
43+
key={tab}
44+
onClick={() => handleTabChange(tab)}
45+
className={clsx(
46+
'transition-transform py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full text-sm relative',
47+
isActive ? 'text-link' : 'hover:bg-primary/5',
48+
)}>
49+
{isActive && (
50+
<ViewTransition
51+
name={transitionName}
52+
share={{tab: 'tab-highlight'}}
53+
update={{default: 'none'}}>
54+
<div className="absolute inset-0 bg-highlight rounded-full" />
55+
</ViewTransition>
56+
)}
57+
<ViewTransition update={{tab: 'tab-text', default: 'none'}}>
58+
<span className="relative z-1">{tab}</span>
59+
</ViewTransition>
60+
</button>
61+
);
62+
})}
4263
</div>
64+
<div className="flex-1 overflow-hidden w-full h-full">
65+
{tabs.get(activeTab)}
66+
</div>
67+
</div>
4368
</div>
4469
);
4570
}

compiler/apps/playground/styles/globals.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,11 @@
108108
object-fit: none;
109109
object-position: left;
110110
}
111+
112+
::view-transition-old(.tab-highlight),
113+
::view-transition-new(.tab-highlight) {
114+
height: 100%;
115+
}
116+
::view-transition-group(.tab-text) {
117+
z-index: 1;
118+
}

0 commit comments

Comments
 (0)