Skip to content

Commit a917c6e

Browse files
authored
Merge pull request #3492 from motiondivision/motion-animate-layout-codex
Refactor LayoutAnimationBuilder
2 parents ebf4af2 + 7ea87bd commit a917c6e

25 files changed

+1837
-499
lines changed

dev/html/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "html-env",
33
"private": true,
4-
"version": "12.29.0",
4+
"version": "12.28.1-alpha.1",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",
@@ -10,9 +10,9 @@
1010
"preview": "vite preview"
1111
},
1212
"dependencies": {
13-
"framer-motion": "^12.29.0",
14-
"motion": "^12.29.0",
15-
"motion-dom": "^12.29.0",
13+
"framer-motion": "^12.28.1-alpha.1",
14+
"motion": "^12.28.1-alpha.1",
15+
"motion-dom": "^12.28.1-alpha.1",
1616
"react": "^18.3.1",
1717
"react-dom": "^18.3.1"
1818
},
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
<html>
2+
<head>
3+
<style>
4+
* {
5+
box-sizing: border-box;
6+
margin: 0;
7+
padding: 0;
8+
}
9+
10+
body {
11+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
12+
sans-serif;
13+
background: #1a1a1a;
14+
color: #fff;
15+
min-height: 100vh;
16+
padding: 40px;
17+
}
18+
19+
.card-list {
20+
display: flex;
21+
flex-wrap: wrap;
22+
gap: 20px;
23+
list-style: none;
24+
max-width: 800px;
25+
}
26+
27+
.card {
28+
width: 240px;
29+
height: 320px;
30+
cursor: pointer;
31+
position: relative;
32+
}
33+
34+
.card-content {
35+
width: 100%;
36+
height: 100%;
37+
border-radius: 16px;
38+
overflow: hidden;
39+
background: #2a2a2a;
40+
position: relative;
41+
}
42+
43+
.card-image-container {
44+
overflow: hidden;
45+
height: 200px;
46+
display: flex;
47+
justify-content: stretch;
48+
flex-direction: column;
49+
position: relative;
50+
}
51+
52+
.card-image {
53+
width: 100%;
54+
height: 240px;
55+
background: #3b3b3b;
56+
position: absolute;
57+
top: -40px;
58+
}
59+
60+
.title-container {
61+
position: absolute;
62+
top: 12px;
63+
left: 12px;
64+
max-width: 200px;
65+
}
66+
67+
.title-container h2 {
68+
color: #fff;
69+
margin: 6px 0;
70+
font-size: 16px;
71+
}
72+
73+
.title-container span {
74+
color: #fff;
75+
font-size: 11px;
76+
text-transform: uppercase;
77+
}
78+
79+
.content-container {
80+
padding: 20px;
81+
}
82+
83+
.hidden {
84+
display: none;
85+
}
86+
87+
.card-content-container.open {
88+
top: 200px;
89+
left: 200px;
90+
position: fixed;
91+
z-index: 100;
92+
padding: 40px 0;
93+
justify-content: center;
94+
}
95+
96+
.open .card-content {
97+
width: unset;
98+
height: unset;
99+
max-width: 560px;
100+
pointer-events: none;
101+
}
102+
103+
.open .title-container {
104+
top: 22px;
105+
left: 22px;
106+
}
107+
108+
[data-layout-correct="false"] {
109+
background: #dd1144 !important;
110+
opacity: 0.5;
111+
}
112+
</style>
113+
</head>
114+
<body>
115+
<ul class="card-list">
116+
<li class="card" data-id="b">
117+
<div class="card-content" data-layout-id="card-container-b">
118+
<div
119+
class="card-image-container"
120+
data-layout-id="card-image-container-b"
121+
>
122+
<div
123+
class="card-image"
124+
data-layout-id="card-image-b"
125+
data-layout="preserve-aspect"
126+
></div>
127+
</div>
128+
<div
129+
class="title-container"
130+
data-layout-id="title-container-b"
131+
data-layout="position"
132+
>
133+
<span>Hats</span>
134+
<h2>Take Control of Your Hat Life</h2>
135+
</div>
136+
<div class="content-container hidden" data-layout="position">
137+
<p>
138+
Stay up to date with the latest hat trends, get
139+
personalized hat care reminders, and use predictive
140+
analytics to discover the last place you left your
141+
hat.
142+
</p>
143+
</div>
144+
</div>
145+
</li>
146+
</ul>
147+
148+
<script type="module" src="/src/imports/animate-layout.js"></script>
149+
<script type="module" src="/src/imports/script-assert.js"></script>
150+
<script type="module">
151+
const { animateLayout, frame } = window.AnimateLayout
152+
const { matchViewportBox, matchOpacity } = window.Assert
153+
const { showError } = window
154+
155+
let currentOpenId = null
156+
157+
function openCard(id) {
158+
if (currentOpenId) {
159+
closeCard()
160+
}
161+
162+
currentOpenId = id
163+
164+
const sourceCard = document.querySelector(
165+
`.card[data-id="${id}"]`
166+
)
167+
const clonedContent = sourceCard
168+
.querySelector(".card-content")
169+
.cloneNode(true)
170+
171+
clonedContent.id = "modal"
172+
173+
const expandedCardContainer = document.createElement("div")
174+
expandedCardContainer.className = "card-content-container open"
175+
expandedCardContainer.appendChild(clonedContent)
176+
177+
const contentContainer =
178+
expandedCardContainer.querySelector(".content-container")
179+
contentContainer.classList.remove("hidden")
180+
181+
document.body.appendChild(expandedCardContainer)
182+
183+
return expandedCardContainer
184+
}
185+
186+
function closeCard() {
187+
if (!currentOpenId) return
188+
189+
const expandedCardContainer = document.querySelector(
190+
".card-content-container.open"
191+
)
192+
193+
if (expandedCardContainer) expandedCardContainer.remove()
194+
195+
currentOpenId = null
196+
}
197+
198+
async function runTest() {
199+
const openControls = await animateLayout(
200+
() => openCard("b"),
201+
{ duration: 1, ease: "linear" }
202+
)
203+
204+
openControls.pause()
205+
openControls.time = 0.5
206+
207+
await new Promise((resolve) => frame.postRender(resolve))
208+
209+
const closeControls = await animateLayout(
210+
() => closeCard(),
211+
{ duration: 1, ease: "linear" }
212+
)
213+
214+
if (!closeControls.animations.length) {
215+
showError(document.querySelector("li .card-content"), "No animations")
216+
}
217+
218+
if (document.querySelector(".card-content-container .card-content") !== null) {
219+
showError( "Card should not exist in DOM")
220+
}
221+
222+
closeControls.pause()
223+
224+
closeControls.time = 0.1
225+
226+
await new Promise((resolve) => frame.postRender(resolve))
227+
228+
matchOpacity(document.querySelector("li .card-content"), 1)
229+
230+
closeControls.time = 0.5
231+
232+
await new Promise((resolve) => frame.postRender(resolve))
233+
234+
matchViewportBox(
235+
document.querySelector("li .card-content"),
236+
{ top: 90, left: 80, right: 400, bottom: 404 },5
237+
)
238+
239+
matchViewportBox(
240+
document.querySelector("li .title-container"),
241+
{ top: 104, left: 95, right: 294, bottom: 167 },5
242+
)
243+
}
244+
245+
runTest().catch(console.error)
246+
</script>
247+
</body>
248+
</html>

0 commit comments

Comments
 (0)