",{"_key":850,"_type":53,"marks":851,"text":852},"46f7b2860fd74",[]," with a JSX expression which maps over ",{"_key":854,"_type":53,"marks":855,"text":674},"46f7b2860fd75",[228],{"_key":857,"_type":53,"marks":858,"text":720},"46f7b2860fd76",[],[],{"_key":861,"_type":49,"children":862,"markDefs":912,"style":80},"6b4b91865cd7",[863,867,871,875,878,882,886,890,893,897,900,904,908],{"_key":864,"_type":53,"marks":865,"text":866},"6b4b91865cd70",[],"We can de-structure ",{"_key":868,"_type":53,"marks":869,"text":870},"6b4b91865cd71",[228],"item",{"_key":872,"_type":53,"marks":873,"text":874},"6b4b91865cd72",[],", ",{"_key":876,"_type":53,"marks":877,"text":740},"6b4b91865cd73",[228],{"_key":879,"_type":53,"marks":880,"text":881},"6b4b91865cd74",[],", and ",{"_key":883,"_type":53,"marks":884,"text":885},"6b4b91865cd75",[228],"props",{"_key":887,"_type":53,"marks":888,"text":889},"6b4b91865cd76",[]," out of ",{"_key":891,"_type":53,"marks":892,"text":674},"6b4b91865cd77",[228],{"_key":894,"_type":53,"marks":895,"text":896},"6b4b91865cd78",[],". ",{"_key":898,"_type":53,"marks":899,"text":885},"6b4b91865cd79",[228],{"_key":901,"_type":53,"marks":902,"text":903},"6b4b91865cd710",[]," is a bit confusing as it's actually the animation we're going to be passing to our modal component, so let's rename it ",{"_key":905,"_type":53,"marks":906,"text":907},"6b4b91865cd711",[228],"style",{"_key":909,"_type":53,"marks":910,"text":911},"6b4b91865cd712",[]," to make it more clear.",[],{"_key":914,"_type":49,"children":915,"markDefs":933,"style":80},"de05e25e2382",[916,920,923,927,930],{"_key":917,"_type":53,"marks":918,"text":919},"de05e25e23820",[],"We will pass ",{"_key":921,"_type":53,"marks":922,"text":907},"de05e25e23821",[228],{"_key":924,"_type":53,"marks":925,"text":926},"de05e25e23822",[]," as an argument to our modal component, as well as ",{"_key":928,"_type":53,"marks":929,"text":740},"de05e25e23823",[228],{"_key":931,"_type":53,"marks":932,"text":720},"de05e25e23824",[],[],{"_key":935,"_type":49,"children":936,"markDefs":948,"style":80},"27c26d1f4d62",[937,941,944],{"_key":938,"_type":53,"marks":939,"text":940},"27c26d1f4d620",[],"We also need to pass a function which will close the modal by updating the ",{"_key":942,"_type":53,"marks":943,"text":610},"27c26d1f4d621",[228],{"_key":945,"_type":53,"marks":946,"text":947},"27c26d1f4d622",[]," state when the Close modal button is clicked.\n",[],{"_key":950,"_type":49,"children":951,"markDefs":959,"style":80},"8637e19cabca",[952,956],{"_key":953,"_type":53,"marks":954,"text":549},"8637e19cabca0",[955],"842d60d487fa",{"_key":957,"_type":53,"marks":958,"text":347},"8637e19cabca1",[],[960],{"_key":955,"_type":76,"href":961},"https://gist.github.com/emmabostian/3261e849e074d0b232eda7c9cbd00b00",{"_key":963,"_type":49,"children":964,"markDefs":969,"style":80},"b39ee17f8084",[965],{"_key":966,"_type":53,"marks":967,"text":968},"b39ee17f80840",[],"Now let's add a button to show the modal. Before the transition mapping, add the following.\n",[],{"_key":971,"_type":49,"children":972,"markDefs":980,"style":80},"7ed356b4abf2",[973,977],{"_key":974,"_type":53,"marks":975,"text":549},"7ed356b4abf20",[976],"8cb9e719d6a1",{"_key":978,"_type":53,"marks":979,"text":347},"7ed356b4abf21",[],[981],{"_key":976,"_type":76,"href":982},"https://gist.github.com/emmabostian/fe0d26ae593fa873ed4ae146fa8b5b38",{"_key":984,"_type":49,"children":985,"markDefs":996,"style":80},"c9fae116866c",[986,990,993],{"_key":987,"_type":53,"marks":988,"text":989},"c9fae116866c0",[],"Here is our finalized ",{"_key":991,"_type":53,"marks":992,"text":343},"c9fae116866c1",[228],{"_key":994,"_type":53,"marks":995,"text":334},"c9fae116866c2",[],[],{"_key":998,"_type":49,"children":999,"markDefs":1007,"style":80},"9a8bf8813e23",[1000,1004],{"_key":1001,"_type":53,"marks":1002,"text":549},"9a8bf8813e230",[1003],"6e02d0b5a5a6",{"_key":1005,"_type":53,"marks":1006,"text":347},"9a8bf8813e231",[],[1008],{"_key":1003,"_type":76,"href":1009},"https://gist.github.com/emmabostian/7af066576ae9a2d1c852e19eba044121",{"_key":1011,"_type":49,"children":1012,"markDefs":1017,"style":80},"b3592e97f34a",[1013],{"_key":1014,"_type":53,"marks":1015,"text":1016},"b3592e97f34a0",[],"When the UI is rendered we see a button:",[],{"_key":1019,"_type":171,"alt":12,"caption":172},"76bc3b1a622c",{"_key":1021,"_type":171,"alt":12,"caption":172},"b13654e6b5f0",{"_key":1023,"_type":49,"children":1024,"markDefs":1029,"style":80},"e7c04213be1f",[1025],{"_key":1026,"_type":53,"marks":1027,"text":1028},"e7c04213be1f0",[],"And when we click it, we see the word “Modal”, but there is currently no animation.",[],{"_key":1031,"_type":49,"children":1032,"markDefs":1037,"style":80},"d5e101690fbf",[1033],{"_key":1034,"_type":53,"marks":1035,"text":1036},"d5e101690fbf0",[],"Now let's build our modal. This will take two arguments:\n",[],{"_key":1039,"_type":49,"children":1040,"level":230,"listItem":231,"markDefs":1048,"style":80},"769d93b9364c",[1041,1044],{"_key":1042,"_type":53,"marks":1043,"text":907},"769d93b9364c0",[228],{"_key":1045,"_type":53,"marks":1046,"text":1047},"769d93b9364c1",[],": The animation",[],{"_key":1050,"_type":49,"children":1051,"level":230,"listItem":231,"markDefs":1060,"style":80},"ed43b3fdfc9e",[1052,1056],{"_key":1053,"_type":53,"marks":1054,"text":1055},"ed43b3fdfc9e0",[228],"closeModal",{"_key":1057,"_type":53,"marks":1058,"text":1059},"ed43b3fdfc9e1",[],": The event handler for closing the modal",[],{"_key":1062,"_type":49,"children":1063,"markDefs":1071,"style":80},"3881723af1fa",[1064,1068],{"_key":1065,"_type":53,"marks":1066,"text":318},"3881723af1fa0",[1067],"253a04b665bb",{"_key":1069,"_type":53,"marks":1070,"text":347},"3881723af1fa1",[],[1072],{"_key":1067,"_type":76,"href":1073},"https://gist.github.com/emmabostian/26fe36d686958d56284942599f279a50",{"_key":1075,"_type":49,"children":1076,"markDefs":1081,"style":80},"5cec8b37b0cb",[1077],{"_key":1078,"_type":53,"marks":1079,"text":1080},"5cec8b37b0cb0",[],"The modal will contain a title, some content, and a close button, so let's add those, as well as some class names for styling.\n",[],{"_key":1083,"_type":49,"children":1084,"markDefs":1092,"style":80},"4fe26a0bd6e0",[1085,1089],{"_key":1086,"_type":53,"marks":1087,"text":318},"4fe26a0bd6e00",[1088],"9767f88bee44",{"_key":1090,"_type":53,"marks":1091,"text":100},"4fe26a0bd6e01",[],[1093],{"_key":1088,"_type":76,"href":1094},"https://gist.github.com/emmabostian/0245634245cf881b437cafd61921d63c",{"_key":1096,"_type":49,"children":1097,"markDefs":1109,"style":80},"f44ffbc80c19",[1098,1102,1105],{"_key":1099,"_type":53,"marks":1100,"text":1101},"f44ffbc80c190",[],"Let's pass our ",{"_key":1103,"_type":53,"marks":1104,"text":1055},"f44ffbc80c191",[228],{"_key":1106,"_type":53,"marks":1107,"text":1108},"f44ffbc80c192",[]," function to the close button as an on click handler so the user can dismiss the modal.\n",[],{"_key":1111,"_type":49,"children":1112,"markDefs":1120,"style":80},"2037a8c74cb3",[1113,1117],{"_key":1114,"_type":53,"marks":1115,"text":318},"2037a8c74cb30",[1116],"e54898b832a7",{"_key":1118,"_type":53,"marks":1119,"text":347},"2037a8c74cb31",[],[1121],{"_key":1116,"_type":76,"href":1122},"https://gist.github.com/emmabostian/0629fe02e5238e284d73b991d933488c",{"_key":1124,"_type":49,"children":1125,"markDefs":1130,"style":80},"1e9318434b8d",[1126],{"_key":1127,"_type":53,"marks":1128,"text":1129},"1e9318434b8d0",[],"If we head back to the browser, we can see our modal appears and closes, but isn't being animated.\n",[],{"_key":1132,"_type":49,"children":1133,"markDefs":1161,"style":80},"3324ad8bac01",[1134,1138,1142,1146,1150,1154,1157],{"_key":1135,"_type":53,"marks":1136,"text":1137},"3324ad8bac010",[],"This is because we have to use a special animated HTML element to get our modal to animate. Any element we want to be animated must be prefaced by ",{"_key":1139,"_type":53,"marks":1140,"text":1141},"3324ad8bac011",[228],"animated",{"_key":1143,"_type":53,"marks":1144,"text":1145},"3324ad8bac012",[],"., for example ",{"_key":1147,"_type":53,"marks":1148,"text":1149},"3324ad8bac013",[228],"\u003Canimated.div>",{"_key":1151,"_type":53,"marks":1152,"text":1153},"3324ad8bac014",[],". So let's change our ",{"_key":1155,"_type":53,"marks":1156,"text":470},"3324ad8bac015",[228],{"_key":1158,"_type":53,"marks":1159,"text":1160},"3324ad8bac016",[]," elements into animated divs.\n",[],{"_key":1163,"_type":49,"children":1164,"markDefs":1172,"style":80},"a2e31d8af978",[1165,1169],{"_key":1166,"_type":53,"marks":1167,"text":318},"a2e31d8af9780",[1168],"e8ec7de08899",{"_key":1170,"_type":53,"marks":1171,"text":347},"a2e31d8af9781",[],[1173],{"_key":1168,"_type":76,"href":1174},"https://gist.github.com/emmabostian/dff42c16b72caea286e252afe5fb98db",{"_key":1176,"_type":49,"children":1177,"markDefs":1196,"style":80},"de8157d2a737",[1178,1182,1185,1189,1192],{"_key":1179,"_type":53,"marks":1180,"text":1181},"de8157d2a7370",[],"Lastly, we have to pass ",{"_key":1183,"_type":53,"marks":1184,"text":907},"de8157d2a7371",[228],{"_key":1186,"_type":53,"marks":1187,"text":1188},"de8157d2a7372",[]," to ",{"_key":1190,"_type":53,"marks":1191,"text":1149},"de8157d2a7373",[228],{"_key":1193,"_type":53,"marks":1194,"text":1195},"de8157d2a7374",[]," as a prop to see our animation.\n",[],{"_key":1198,"_type":49,"children":1199,"markDefs":1207,"style":80},"496ee4ddad79",[1200,1204],{"_key":1201,"_type":53,"marks":1202,"text":318},"496ee4ddad790",[1203],"b3ac051f55a6",{"_key":1205,"_type":53,"marks":1206,"text":347},"496ee4ddad791",[],[1208],{"_key":1203,"_type":76,"href":1209},"https://gist.github.com/emmabostian/d5ec869cdd3468a27d845d239dd2e6e8",{"_key":1211,"_type":49,"children":1212,"markDefs":1217,"style":80},"70158d2b4877",[1213],{"_key":1214,"_type":53,"marks":1215,"text":1216},"70158d2b48770",[],"And that's it! You now have a fully-animated modal which mounts and unmounts when it's shown and hidden.\n",[],{"_key":1219,"_type":49,"children":1220,"markDefs":1229,"style":80},"e0ad13368d8e",[1221,1226],{"_key":1222,"_type":53,"marks":1223,"text":1225},"e0ad13368d8e0",[1224],"4fc3d7d46b09","View the final code here",{"_key":1227,"_type":53,"marks":1228,"text":347},"e0ad13368d8e1",[],[1230],{"_key":1224,"_type":76,"href":1231},"https://codesandbox.io/s/github/emmawedekind/react-spring-animated-modal/tree/master/?fontsize=14&hidenavigation=1&theme=dark",{"_key":1233,"_type":106,"url":1234},"d6c03e15c920","https://codesandbox.io/embed/github/emmawedekind/react-spring-animated-modal/tree/master/?fontsize=14&hidenavigation=1&theme=dark",{"_key":1236,"_type":49,"children":1237,"markDefs":1242,"style":133},"2aefccee389a",[1238],{"_key":1239,"_type":53,"marks":1240,"text":1241},"2aefccee389a0",[],"Building an image gallery",[],{"_key":1244,"_type":49,"children":1245,"markDefs":1250,"style":80},"239366270396",[1246],{"_key":1247,"_type":53,"marks":1248,"text":1249},"2393662703960",[],"Making an image gallery with plain JavaScript, and animating it, can be tedious. But not with react-spring! Let's make an image gallery that switches between three photos.",[],{"_key":1252,"_type":49,"children":1253,"markDefs":1258,"style":142},"115793b1b10b",[1254],{"_key":1255,"_type":53,"marks":1256,"text":1257},"115793b1b10b0",[],"What We’ll Build",[],{"_key":1260,"_type":171,"alt":12,"caption":172},"8fc2a9eadfd7",{"_key":1262,"_type":49,"children":1263,"markDefs":1272,"style":80},"d2042e49b4b0",[1264,1269],{"_key":1265,"_type":53,"marks":1266,"text":1268},"d2042e49b4b00",[1267],"e2db5ce24295","The end code:",{"_key":1270,"_type":53,"marks":1271,"text":334},"d2042e49b4b01",[],[1273],{"_key":1267,"_type":76,"href":121},{"_key":1275,"_type":106,"url":124},"8da08e804aeb",{"_key":1277,"_type":49,"children":1278,"markDefs":1283,"style":142},"466776089a94",[1279],{"_key":1280,"_type":53,"marks":1281,"text":1282},"466776089a940",[],"Defining The micro-interaction",[],{"_key":1285,"_type":49,"children":1286,"markDefs":1290,"style":197},"bcd74a4c2033",[1287],{"_key":1288,"_type":53,"marks":1289,"text":195},"bcd74a4c20330",[],[],{"_key":1292,"_type":49,"children":1293,"markDefs":1298,"style":80},"197d6b99e564",[1294],{"_key":1295,"_type":53,"marks":1296,"text":1297},"197d6b99e5640",[],"The gallery will transition to the next image when the user clicks anywhere in the viewport.",[],{"_key":1300,"_type":49,"children":1301,"markDefs":1305,"style":197},"4ad89f109fa1",[1302],{"_key":1303,"_type":53,"marks":1304,"text":212},"4ad89f109fa10",[],[],{"_key":1307,"_type":49,"children":1308,"markDefs":1313,"style":80},"cffd078d017f",[1309],{"_key":1310,"_type":53,"marks":1311,"text":1312},"cffd078d017f0",[],"We will have three images in our gallery so its state will be one of the following states, each number representing the image currently being shown.\n",[],{"_key":1315,"_type":49,"children":1316,"level":230,"listItem":231,"markDefs":1321,"style":80},"3f52062b8c90",[1317],{"_key":1318,"_type":53,"marks":1319,"text":1320},"3f52062b8c900",[228],"0",[],{"_key":1323,"_type":49,"children":1324,"level":230,"listItem":231,"markDefs":1329,"style":80},"5d0788191768",[1325],{"_key":1326,"_type":53,"marks":1327,"text":1328},"5d07881917680",[228],"1",[],{"_key":1331,"_type":49,"children":1332,"level":230,"listItem":231,"markDefs":1337,"style":80},"40ce7ad19d95",[1333],{"_key":1334,"_type":53,"marks":1335,"text":1336},"40ce7ad19d950",[228],"2",[],{"_key":1339,"_type":49,"children":1340,"markDefs":1345,"style":197},"91e016ad84ea",[1341],{"_key":1342,"_type":53,"marks":1343,"text":1344},"91e016ad84ea0",[],"Animation definition",[],{"_key":1347,"_type":49,"children":1348,"markDefs":1353,"style":80},"1fe6835ff6d6",[1349],{"_key":1350,"_type":53,"marks":1351,"text":1352},"1fe6835ff6d60",[],"The leaving image will fade out and slide to the left while the entering image will fade in and slide in from the right.",[],{"_key":1355,"_type":49,"children":1356,"markDefs":1361,"style":142},"a8b89963906b",[1357],{"_key":1358,"_type":53,"marks":1359,"text":1360},"a8b89963906b0",[],"Let’s build an image gallery",[],{"_key":1363,"_type":49,"children":1364,"markDefs":1369,"style":80},"d10d81dce2e0",[1365],{"_key":1366,"_type":53,"marks":1367,"text":1368},"d10d81dce2e00",[],"Let's make an image gallery that switches between three photos.\n",[],{"_key":1371,"_type":49,"children":1372,"markDefs":1390,"style":80},"633381f7e701",[1373,1377,1381,1384,1387],{"_key":1374,"_type":53,"marks":1375,"text":1376},"633381f7e7010",[],"Create a ",{"_key":1378,"_type":53,"marks":1379,"text":284},"633381f7e7011",[1380],"9fe79a9020ab",{"_key":1382,"_type":53,"marks":1383,"text":288},"633381f7e7012",[],{"_key":1385,"_type":53,"marks":1386,"text":292},"633381f7e7013",[228],{"_key":1388,"_type":53,"marks":1389,"text":296},"633381f7e7014",[],[1391],{"_key":1380,"_type":76,"href":299},{"_key":1393,"_type":49,"children":1394,"markDefs":1401,"style":80},"3a9d39fea732",[1395,1398],{"_key":1396,"_type":53,"marks":1397,"text":330},"3a9d39fea7320",[157],{"_key":1399,"_type":53,"marks":1400,"text":334},"3a9d39fea7321",[],[],{"_key":1403,"_type":49,"children":1404,"markDefs":1412,"style":80},"96ca79b0a871",[1405,1409],{"_key":1406,"_type":53,"marks":1407,"text":343},"96ca79b0a8710",[1408],"6a1d0b7c4d95",{"_key":1410,"_type":53,"marks":1411,"text":347},"96ca79b0a8711",[],[1413],{"_key":1408,"_type":76,"href":350},{"_key":1415,"_type":49,"children":1416,"markDefs":1443,"style":80},"ea2cebdc0bfe",[1417,1421,1425,1428,1432,1436,1439],{"_key":1418,"_type":53,"marks":1419,"text":1420},"ea2cebdc0bfe0",[],"Create two new files: ",{"_key":1422,"_type":53,"marks":1423,"text":1424},"ea2cebdc0bfe1",[228],"Gallery.js",{"_key":1426,"_type":53,"marks":1427,"text":438},"ea2cebdc0bfe2",[],{"_key":1429,"_type":53,"marks":1430,"text":1431},"ea2cebdc0bfe3",[228],"gallery.css",{"_key":1433,"_type":53,"marks":1434,"text":1435},"ea2cebdc0bfe4",[]," and add the following code to ",{"_key":1437,"_type":53,"marks":1438,"text":1431},"ea2cebdc0bfe5",[228],{"_key":1440,"_type":53,"marks":1441,"text":1442},"ea2cebdc0bfe6",[],". We won’t be covering CSS today so we’ve provided the styling for you!\n",[],{"_key":1445,"_type":49,"children":1446,"markDefs":1455,"style":80},"42d7be28496c",[1447,1452],{"_key":1448,"_type":53,"marks":1449,"text":1451},"42d7be28496c0",[1450],"4abbd680f78c","Gallery.css",{"_key":1453,"_type":53,"marks":1454,"text":347},"42d7be28496c1",[],[1456],{"_key":1450,"_type":76,"href":1457},"https://gist.github.com/emmabostian/aaf58ed1303af19dcdf3b0f6f98b37e5",{"_key":1459,"_type":49,"children":1460,"markDefs":1473,"style":80},"9e106a2bfc94",[1461,1465,1469],{"_key":1462,"_type":53,"marks":1463,"text":1464},"9e106a2bfc940",[],"Create an ",{"_key":1466,"_type":53,"marks":1467,"text":1468},"9e106a2bfc941",[228],"images",{"_key":1470,"_type":53,"marks":1471,"text":1472},"9e106a2bfc942",[]," folder in the root and add three photos.\n",[],{"_key":1475,"_type":49,"children":1476,"markDefs":1511,"style":80},"fa28e8a8a6a2",[1477,1481,1486,1490,1494,1497,1501,1504,1508],{"_key":1478,"_type":53,"marks":1479,"text":1480},"fa28e8a8a6a20",[],"You can find some on ",{"_key":1482,"_type":53,"marks":1483,"text":1485},"fa28e8a8a6a21",[1484],"0991242dad12","Unsplash",{"_key":1487,"_type":53,"marks":1488,"text":1489},"fa28e8a8a6a22",[],". I added ",{"_key":1491,"_type":53,"marks":1492,"text":1493},"fa28e8a8a6a23",[228],"mountains.jpg",{"_key":1495,"_type":53,"marks":1496,"text":874},"fa28e8a8a6a24",[],{"_key":1498,"_type":53,"marks":1499,"text":1500},"fa28e8a8a6a25",[228],"beach.jpg",{"_key":1502,"_type":53,"marks":1503,"text":881},"fa28e8a8a6a26",[],{"_key":1505,"_type":53,"marks":1506,"text":1507},"fa28e8a8a6a27",[228],"desert.jpg",{"_key":1509,"_type":53,"marks":1510,"text":445},"fa28e8a8a6a28",[],[1512],{"_key":1484,"_type":76,"href":1513},"http://unsplash.com/",{"_key":1515,"_type":49,"children":1516,"markDefs":1528,"style":80},"6909a5095614",[1517,1521,1524],{"_key":1518,"_type":53,"marks":1519,"text":1520},"6909a50956140",[],"Inside of ",{"_key":1522,"_type":53,"marks":1523,"text":1424},"6909a50956141",[228],{"_key":1525,"_type":53,"marks":1526,"text":1527},"6909a50956142",[],", import the following packages, as well as the three images you just uploaded, and the CSS file.\n",[],{"_key":1530,"_type":49,"children":1531,"markDefs":1539,"style":80},"60a4a98e7cbd",[1532,1536],{"_key":1533,"_type":53,"marks":1534,"text":1424},"60a4a98e7cbd0",[1535],"0f9d43ed0570",{"_key":1537,"_type":53,"marks":1538,"text":347},"60a4a98e7cbd1",[],[1540],{"_key":1535,"_type":76,"href":1541},"https://gist.github.com/emmabostian/e263a6374020e37904b3532a70f42c8e",{"_key":1543,"_type":49,"children":1544,"markDefs":1564,"style":80},"341bcaae836a",[1545,1549,1553,1557,1560],{"_key":1546,"_type":53,"marks":1547,"text":1548},"341bcaae836a0",[],"Now let's define three images we want to iterate between. Each will take in a style and render an ",{"_key":1550,"_type":53,"marks":1551,"text":1552},"341bcaae836a1",[228],"animated.img",{"_key":1554,"_type":53,"marks":1555,"text":1556},"341bcaae836a2",[]," tag (as react-spring requires any animatable element to be prefaced with ",{"_key":1558,"_type":53,"marks":1559,"text":1141},"341bcaae836a3",[228],{"_key":1561,"_type":53,"marks":1562,"text":1563},"341bcaae836a4",[],". ) with its respective image source, alt tag, and style.\n",[],{"_key":1566,"_type":49,"children":1567,"markDefs":1575,"style":80},"67f42a299050",[1568,1572],{"_key":1569,"_type":53,"marks":1570,"text":1424},"67f42a2990500",[1571],"6aaab3378bdc",{"_key":1573,"_type":53,"marks":1574,"text":347},"67f42a2990501",[],[1576],{"_key":1571,"_type":76,"href":1577},"https://gist.github.com/emmabostian/edbe8e98577642f35b07cecef408a8a7",{"_key":1579,"_type":49,"children":1580,"markDefs":1585,"style":80},"e7c5a3cc1f48",[1581],{"_key":1582,"_type":53,"marks":1583,"text":1584},"e7c5a3cc1f480",[],"Next, let's set up our component.\n",[],{"_key":1587,"_type":49,"children":1588,"markDefs":1596,"style":80},"f0a4007e389b",[1589,1593],{"_key":1590,"_type":53,"marks":1591,"text":1424},"f0a4007e389b0",[1592],"43dc854d9c22",{"_key":1594,"_type":53,"marks":1595,"text":347},"f0a4007e389b1",[],[1597],{"_key":1592,"_type":76,"href":1598},"https://gist.github.com/emmabostian/78ddd761c7b6ec9f64f9cd322e3046db",{"_key":1600,"_type":49,"children":1601,"markDefs":1629,"style":80},"3a9dbdaf3e03",[1602,1606,1610,1614,1618,1622,1625],{"_key":1603,"_type":53,"marks":1604,"text":1605},"3a9dbdaf3e030",[],"First we need to establish our state for which photo we're currently viewing. Above the return statement, we'll call this state ",{"_key":1607,"_type":53,"marks":1608,"text":1609},"3a9dbdaf3e031",[228],"index",{"_key":1611,"_type":53,"marks":1612,"text":1613},"3a9dbdaf3e032",[]," and it's setter function ",{"_key":1615,"_type":53,"marks":1616,"text":1617},"3a9dbdaf3e033",[228],"setIndex",{"_key":1619,"_type":53,"marks":1620,"text":1621},"3a9dbdaf3e034",[],", and initialize the value to ",{"_key":1623,"_type":53,"marks":1624,"text":1320},"3a9dbdaf3e035",[228],{"_key":1626,"_type":53,"marks":1627,"text":1628},"3a9dbdaf3e036",[]," for the first image.\n",[],{"_key":1631,"_type":49,"children":1632,"markDefs":1640,"style":80},"dae0a463aeac",[1633,1637],{"_key":1634,"_type":53,"marks":1635,"text":1424},"dae0a463aeac0",[1636],"f39fd823b2e9",{"_key":1638,"_type":53,"marks":1639,"text":347},"dae0a463aeac1",[],[1641],{"_key":1636,"_type":76,"href":1642},"https://gist.github.com/emmabostian/2c34fdfbbf5a35116137618db5d98858",{"_key":1644,"_type":49,"children":1645,"markDefs":1658,"style":80},"b9a0e2da22d9",[1646,1650,1654],{"_key":1647,"_type":53,"marks":1648,"text":1649},"b9a0e2da22d90",[],"When the user clicks anywhere in the viewport, we want to switch to the next image. We can use ",{"_key":1651,"_type":53,"marks":1652,"text":1653},"b9a0e2da22d91",[228],"useCallback",{"_key":1655,"_type":53,"marks":1656,"text":1657},"b9a0e2da22d92",[]," to do this.\n",[],{"_key":1660,"_type":49,"children":1661,"markDefs":1666,"style":80},"9d5fb5179f32",[1662],{"_key":1663,"_type":53,"marks":1664,"text":1665},"9d5fb5179f320",[],"Since we have three images, we want to ensure the state value remains either 0, 1, or 2, so we can use modulus to grab the remainder of the next state value divided by three.\n",[],{"_key":1668,"_type":49,"children":1669,"markDefs":1674,"style":80},"4866bd9a0da1",[1670],{"_key":1671,"_type":53,"marks":1672,"text":1673},"4866bd9a0da10",[],"For example if the state is currently 2 and we want the next photo, we add 1, which totals 3. Since 3 is outside the bounds of the number of photos we have (indexing from 0, we have 0, 1 and 2 for available photo indices), let's mod it by 3 to get the remainder.\n",[],{"_key":1676,"_type":49,"children":1677,"markDefs":1682,"style":80},"597356116fba",[1678],{"_key":1679,"_type":53,"marks":1680,"text":1681},"597356116fba0",[],"(2 + 1) % 3 = 0 because 3 mod 3 yields a remainder of 0.\n",[],{"_key":1684,"_type":49,"children":1685,"markDefs":1697,"style":80},"d23c5356ccf7",[1686,1690,1694],{"_key":1687,"_type":53,"marks":1688,"text":1689},"d23c5356ccf70",[],"You can read more about mods ",{"_key":1691,"_type":53,"marks":1692,"text":795},"d23c5356ccf71",[1693],"d44a6c65f6da",{"_key":1695,"_type":53,"marks":1696,"text":445},"d23c5356ccf72",[],[1698],{"_key":1693,"_type":76,"href":1699},"https://riptutorial.com/javascript/example/760/remainder---modulus----",{"_key":1701,"_type":49,"children":1702,"markDefs":1710,"style":80},"b254b71337bc",[1703,1707],{"_key":1704,"_type":53,"marks":1705,"text":1424},"b254b71337bc0",[1706],"b4f3d46de95e",{"_key":1708,"_type":53,"marks":1709,"text":347},"b254b71337bc1",[],[1711],{"_key":1706,"_type":76,"href":1712},"https://gist.github.com/emmabostian/65dfc78cc997c838981652248591cddc",{"_key":1714,"_type":49,"children":1715,"markDefs":1735,"style":80},"f4ac410ddfaa",[1716,1720,1724,1728,1731],{"_key":1717,"_type":53,"marks":1718,"text":1719},"f4ac410ddfaa0",[],"Let's add our ",{"_key":1721,"_type":53,"marks":1722,"text":1723},"f4ac410ddfaa1",[228],"onClick",{"_key":1725,"_type":53,"marks":1726,"text":1727},"f4ac410ddfaa2",[]," handler as an argument on the wrapping ",{"_key":1729,"_type":53,"marks":1730,"text":470},"f4ac410ddfaa3",[228],{"_key":1732,"_type":53,"marks":1733,"text":1734},"f4ac410ddfaa4",[]," so the user can switch to the next photo by clicking in the viewport.\n",[],{"_key":1737,"_type":49,"children":1738,"markDefs":1746,"style":80},"e41834c3e925",[1739,1743],{"_key":1740,"_type":53,"marks":1741,"text":1424},"e41834c3e9250",[1742],"bfcaaf01124b",{"_key":1744,"_type":53,"marks":1745,"text":347},"e41834c3e9251",[],[1747],{"_key":1742,"_type":76,"href":1748},"https://gist.github.com/emmabostian/ce5dc60071c77e6391025f0a76d9ac3d",{"_key":1750,"_type":49,"children":1751,"markDefs":1763,"style":80},"442a8250489c",[1752,1756,1759],{"_key":1753,"_type":53,"marks":1754,"text":1755},"442a8250489c0",[],"Next, let's set up our animation. We'll use ",{"_key":1757,"_type":53,"marks":1758,"text":521},"442a8250489c1",[228],{"_key":1760,"_type":53,"marks":1761,"text":1762},"442a8250489c2",[]," to mount and unmount the photos from the DOM so we're only rendering one at a time.\n",[],{"_key":1765,"_type":49,"children":1766,"markDefs":1774,"style":80},"1b48502e024b",[1767,1770],{"_key":1768,"_type":53,"marks":1769,"text":521},"1b48502e024b0",[228],{"_key":1771,"_type":53,"marks":1772,"text":1773},"1b48502e024b1",[]," takes in three arguments:\n",[],{"_key":1776,"_type":49,"children":1777,"level":230,"listItem":231,"markDefs":1785,"style":80},"42edc2096e79",[1778,1781],{"_key":1779,"_type":53,"marks":1780,"text":870},"42edc2096e790",[228],{"_key":1782,"_type":53,"marks":1783,"text":1784},"42edc2096e791",[],": The index for our photo",[],{"_key":1787,"_type":49,"children":1788,"level":230,"listItem":231,"markDefs":1796,"style":80},"8c53d6651ff0",[1789,1792],{"_key":1790,"_type":53,"marks":1791,"text":740},"8c53d6651ff00",[228],{"_key":1793,"_type":53,"marks":1794,"text":1795},"8c53d6651ff01",[],": The key for our mapped over item",[],{"_key":1798,"_type":49,"children":1799,"level":230,"listItem":231,"markDefs":1808,"style":80},"f3dd0a32dacf",[1800,1804],{"_key":1801,"_type":53,"marks":1802,"text":1803},"f3dd0a32dacf0",[228],"lifecycle",{"_key":1805,"_type":53,"marks":1806,"text":1807},"f3dd0a32dacf1",[],": An object describing the animation",[],{"_key":1810,"_type":49,"children":1811,"markDefs":1831,"style":80},"112b03672146",[1812,1816,1820,1823,1827],{"_key":1813,"_type":53,"marks":1814,"text":1815},"112b036721460",[],"We want our images to fade in and out while sliding them into and out of view so we'll define ",{"_key":1817,"_type":53,"marks":1818,"text":1819},"112b036721461",[228],"opacity",{"_key":1821,"_type":53,"marks":1822,"text":438},"112b036721462",[],{"_key":1824,"_type":53,"marks":1825,"text":1826},"112b036721463",[228],"transform",{"_key":1828,"_type":53,"marks":1829,"text":1830},"112b036721464",[]," at each of the lifecycle steps.\n",[],{"_key":1833,"_type":49,"children":1834,"markDefs":1854,"style":80},"8968c3ea7edf",[1835,1839,1843,1847,1851],{"_key":1836,"_type":53,"marks":1837,"text":1838},"8968c3ea7edf0",[],"We will also add a ",{"_key":1840,"_type":53,"marks":1841,"text":1842},"8968c3ea7edf1",[228],"config",{"_key":1844,"_type":53,"marks":1845,"text":1846},"8968c3ea7edf2",[]," option to change the speed at which this animation occurs. You can check the full options for config ",{"_key":1848,"_type":53,"marks":1849,"text":795},"8968c3ea7edf3",[1850],"fd59d2ced355",{"_key":1852,"_type":53,"marks":1853,"text":445},"8968c3ea7edf4",[],[1855],{"_key":1850,"_type":76,"href":1856},"https://www.react-spring.io/docs/hooks/api",{"_key":1858,"_type":49,"children":1859,"markDefs":1867,"style":80},"afe2c77944ea",[1860,1864],{"_key":1861,"_type":53,"marks":1862,"text":1424},"afe2c77944ea0",[1863],"8587a2e60bbe",{"_key":1865,"_type":53,"marks":1866,"text":347},"afe2c77944ea1",[],[1868],{"_key":1863,"_type":76,"href":1869},"https://gist.github.com/emmabostian/c88791dab8806b5f1e9a8fbb42cc0b66",{"_key":1871,"_type":49,"children":1872,"markDefs":1877,"style":80},"6330f32f1ec7",[1873],{"_key":1874,"_type":53,"marks":1875,"text":1876},"6330f32f1ec70",[],"Now we're ready to add some JSX. Let's first render a paragraph that tells the user they can click anywhere to change to the next image.\n",[],{"_key":1879,"_type":49,"children":1880,"markDefs":1888,"style":80},"ee69adfb54ed",[1881,1885],{"_key":1882,"_type":53,"marks":1883,"text":1424},"ee69adfb54ed0",[1884],"17c8dbf409ce",{"_key":1886,"_type":53,"marks":1887,"text":347},"ee69adfb54ed1",[],[1889],{"_key":1884,"_type":76,"href":1890},"https://gist.github.com/emmabostian/abd39c7a4bef618c085a71f93dbfd7f0",{"_key":1892,"_type":49,"children":1893,"markDefs":1930,"style":80},"09b33a57d7b2",[1894,1898,1901,1905,1908,1911,1914,1917,1920,1923,1927],{"_key":1895,"_type":53,"marks":1896,"text":1897},"09b33a57d7b20",[],"Since ",{"_key":1899,"_type":53,"marks":1900,"text":521},"09b33a57d7b21",[228],{"_key":1902,"_type":53,"marks":1903,"text":1904},"09b33a57d7b22",[]," requires we map over its return value, let's map over our transitions and render each image. We'll de-structure ",{"_key":1906,"_type":53,"marks":1907,"text":870},"09b33a57d7b23",[228],{"_key":1909,"_type":53,"marks":1910,"text":874},"09b33a57d7b24",[],{"_key":1912,"_type":53,"marks":1913,"text":885},"09b33a57d7b25",[228],{"_key":1915,"_type":53,"marks":1916,"text":881},"09b33a57d7b26",[],{"_key":1918,"_type":53,"marks":1919,"text":740},"09b33a57d7b27",[228],{"_key":1921,"_type":53,"marks":1922,"text":525},"09b33a57d7b28",[],{"_key":1924,"_type":53,"marks":1925,"text":1926},"09b33a57d7b29",[228],"transitions",{"_key":1928,"_type":53,"marks":1929,"text":445},"09b33a57d7b210",[],[],{"_key":1932,"_type":49,"children":1933,"markDefs":1965,"style":80},"64ad005a48ef",[1934,1938,1941,1945,1948,1952,1955,1959,1962],{"_key":1935,"_type":53,"marks":1936,"text":1937},"64ad005a48ef0",[],"Then we'll grab the image component from our ",{"_key":1939,"_type":53,"marks":1940,"text":1468},"64ad005a48ef1",[228],{"_key":1942,"_type":53,"marks":1943,"text":1944},"64ad005a48ef2",[]," array by using the ",{"_key":1946,"_type":53,"marks":1947,"text":870},"64ad005a48ef3",[228],{"_key":1949,"_type":53,"marks":1950,"text":1951},"64ad005a48ef4",[],", or ",{"_key":1953,"_type":53,"marks":1954,"text":1609},"64ad005a48ef5",[228],{"_key":1956,"_type":53,"marks":1957,"text":1958},"64ad005a48ef6",[]," defined in ",{"_key":1960,"_type":53,"marks":1961,"text":521},"64ad005a48ef7",[228],{"_key":1963,"_type":53,"marks":1964,"text":445},"64ad005a48ef8",[],[],{"_key":1967,"_type":49,"children":1968,"markDefs":1986,"style":80},"287f4b7b5149",[1969,1973,1976,1979,1982],{"_key":1970,"_type":53,"marks":1971,"text":1972},"287f4b7b51490",[],"Finally we'll return the Image component and pass it the ",{"_key":1974,"_type":53,"marks":1975,"text":740},"287f4b7b51491",[228],{"_key":1977,"_type":53,"marks":1978,"text":438},"287f4b7b51492",[],{"_key":1980,"_type":53,"marks":1981,"text":885},"287f4b7b51493",[228],{"_key":1983,"_type":53,"marks":1984,"text":1985},"287f4b7b51494",[]," (as the style attribute).\n",[],{"_key":1988,"_type":49,"children":1989,"markDefs":1997,"style":80},"cc30a16ae0e9",[1990,1994],{"_key":1991,"_type":53,"marks":1992,"text":1424},"cc30a16ae0e90",[1993],"f746b589765a",{"_key":1995,"_type":53,"marks":1996,"text":347},"cc30a16ae0e91",[],[1998],{"_key":1993,"_type":76,"href":1999},"https://gist.github.com/emmabostian/8c700da6b273b9bb33220d3e5f4a8fbf",{"_key":2001,"_type":49,"children":2002,"markDefs":2014,"style":80},"9f658baa041b",[2003,2007,2011],{"_key":2004,"_type":53,"marks":2005,"text":2006},"9f658baa041b0",[],"Here is our completed ",{"_key":2008,"_type":53,"marks":2009,"text":1424},"9f658baa041b1",[228,2010],"f3a1fbb66073",{"_key":2012,"_type":53,"marks":2013,"text":347},"9f658baa041b2",[],[2015],{"_key":2010,"_type":76,"href":2016},"https://gist.github.com/emmabostian/0b619af6ae176b01c0ee55747171226a",{"_key":2018,"_type":49,"children":2019,"markDefs":2031,"style":80},"a0930cf570ca",[2020,2024,2027],{"_key":2021,"_type":53,"marks":2022,"text":2023},"a0930cf570ca0",[],"Finally let's head back to ",{"_key":2025,"_type":53,"marks":2026,"text":343},"a0930cf570ca1",[228],{"_key":2028,"_type":53,"marks":2029,"text":2030},"a0930cf570ca2",[]," to import our Gallery component and render it.\n",[],{"_key":2033,"_type":49,"children":2034,"markDefs":2042,"style":80},"7e56b2f80850",[2035,2039],{"_key":2036,"_type":53,"marks":2037,"text":343},"7e56b2f808500",[2038],"04c7f0c53c5a",{"_key":2040,"_type":53,"marks":2041,"text":347},"7e56b2f808501",[],[2043],{"_key":2038,"_type":76,"href":2044},"https://gist.github.com/emmabostian/64301d33d9f6b47ca982f14cd5ba98be",{"_key":2046,"_type":49,"children":2047,"markDefs":2052,"style":80},"eef310ae6497",[2048],{"_key":2049,"_type":53,"marks":2050,"text":2051},"eef310ae64970",[],"And that's it! You now have a fully-functional image gallery.\n",[],{"_key":2054,"_type":49,"children":2055,"markDefs":2067,"style":80},"efaaa08904dd",[2056,2060,2064],{"_key":2057,"_type":53,"marks":2058,"text":2059},"efaaa08904dd0",[],"You can view the final code ",{"_key":2061,"_type":53,"marks":2062,"text":795},"efaaa08904dd1",[2063],"d9a6e8f122de",{"_key":2065,"_type":53,"marks":2066,"text":347},"efaaa08904dd2",[],[2068],{"_key":2063,"_type":76,"href":2069},"https://codesandbox.io/s/amazing-wiles-5vs9d?fontsize=14&hidenavigation=1&theme=dark",{"_key":2071,"_type":106,"url":124},"a1687ce4f00f",{"_key":2073,"_type":49,"children":2074,"markDefs":2079,"style":133},"6afa95e4c1e6",[2075],{"_key":2076,"_type":53,"marks":2077,"text":2078},"6afa95e4c1e60",[],"Conclusion",[],{"_key":2081,"_type":49,"children":2082,"markDefs":2087,"style":80},"299415fc41f6",[2083],{"_key":2084,"_type":53,"marks":2085,"text":2086},"299415fc41f60",[],"I hope this series of blog posts on creating micro-interactions with react-spring has empowered you to create fun interactions within your website.\n",[],{"_key":2089,"_type":49,"children":2090,"markDefs":2095,"style":80},"54dcbeba214b",[2091],{"_key":2092,"_type":53,"marks":2093,"text":2094},"54dcbeba214b0",[],"You can create complex animations and interactions with just a few lines of code.\n",[],{"_key":2097,"_type":49,"children":2098,"markDefs":2103,"style":80},"8f9fa5182fbc",[2099],{"_key":2100,"_type":53,"marks":2101,"text":2102},"8f9fa5182fbc0",[],"For more articles on micro-animations and micro-interactions check out the resources below.\n",[],{"_key":2105,"_type":49,"children":2106,"level":230,"listItem":231,"markDefs":2112,"style":80},"68c0a41b0f7d",[2107],{"_key":2108,"_type":53,"marks":2109,"text":2111},"68c0a41b0f7d0",[2110],"19696b117899","Why Use Micro-Animations In Your Design?",[2113],{"_key":2110,"_type":76,"href":2114},"https://hike.one/update/why-use-micro-animations-in-your-design",{"_key":2116,"_type":49,"children":2117,"level":230,"listItem":231,"markDefs":2123,"style":80},"866f8bd01fb4",[2118],{"_key":2119,"_type":53,"marks":2120,"text":2122},"866f8bd01fb40",[2121],"b118153bfef1","Micro-Interactions",[2124],{"_key":2121,"_type":76,"href":2125},"https://uxdesign.cc/micro-interactions-why-when-and-how-to-use-them-to-boost-the-ux-17094b3baaa0",{"_key":2127,"_type":49,"children":2128,"level":230,"listItem":231,"markDefs":2134,"style":80},"9ee033c684a4",[2129],{"_key":2130,"_type":53,"marks":2131,"text":2133},"9ee033c684a40",[2132],"190ce721d83a","Should You Advocate For Micro-Animations?",[2135],{"_key":2132,"_type":76,"href":2136},"https://medium.com/@MentorMate/should-you-advocate-for-micro-animations-cdf625635261",{"_key":2138,"_type":49,"children":2139,"level":230,"listItem":231,"markDefs":2145,"style":80},"820f34dc50a1",[2140],{"_key":2141,"_type":53,"marks":2142,"text":2144},"820f34dc50a10",[2143],"e152721d73eb","Micro-Interactions & Micro-Animations",[2146],{"_key":2143,"_type":76,"href":2147},"https://blog.geekyants.com/micro-interactions-and-micro-animations-4eb2ed5cc7f3",true,"2020/01/30",{"_type":171,"asset":2151},{"_ref":2152,"_type":2153},"image-b7239df79d9659f7172a412ba24cf22e78a9dde3-2547x1177-jpg","reference",{"code":2155,"language":2156},"\u003C!-- wp:paragraph -->\n\u003Cp>In the \u003Ca href=\"https://stackoverflow.blog/2020/01/16/how-to-create-micro-interactions-with-react-spring-part-1/\">first post\u003C/a> in this series, we examined the basics of micro-interactions: what are they, why should you use them, how you build them. In the \u003Ca href=\"https://stackoverflow.blog/2020/01/23/micro-interactions-with-react-spring-part-2/\">second post\u003C/a>, we built two animated menus.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>In this tutorial, we’ll build two fun animations: a modal and an image gallery.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://codesandbox.io/s/react-spring-animated-modal-sl19p\">Modal\u003C/a>:\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Ciframe src=\"https://codesandbox.io/embed/react-spring-animated-modal-sl19p?fontsize=14&hidenavigation=1&theme=dark\" style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;\" title=\"React Spring Animated Modal\" allow=\"geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb\" sandbox=\"allow-modals allow-forms allow-popups allow-scripts allow-same-origin\">\u003C/iframe>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://codesandbox.io/s/react-spring-animated-image-gallery-5vs9d\">Image Gallery\u003C/a>:\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Ciframe src=\"https://codesandbox.io/embed/react-spring-animated-image-gallery-5vs9d?fontsize=14&hidenavigation=1&theme=dark\" style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;\" title=\"React Spring Animated Image Gallery\" allow=\"geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb\" sandbox=\"allow-modals allow-forms allow-popups allow-scripts allow-same-origin\">\u003C/iframe>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:heading {\"level\":1} -->\n\u003Ch1>Building an animated modal\u003C/h1>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>What we’ll build\u003C/h2>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We’ll use react-spring’s useTransition to illustrate how you can mount and unmount a component, in our case a modal, from the DOM and mount photos to and from a photo gallery.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cem>\u003Ca href=\"https://codesandbox.io/s/react-spring-animated-menu-qe6kn\">Embed Code Sandbox\u003C/a>\u003C/em>:\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Ciframe src=\"https://codesandbox.io/embed/react-spring-animated-menu-qe6kn?fontsize=14&hidenavigation=1&theme=dark\" style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;\" title=\"React Spring Animated Menu\" allow=\"geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb\" sandbox=\"allow-modals allow-forms allow-popups allow-scripts allow-same-origin\">\u003C/iframe>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https://lh6.googleusercontent.com/Xt4x9GI2xjh-UoPP35QlzlwwpOrX0PTyk5MrVmjaxTiVEHnmBV4M6JS6wnZlgYJxHGOKVu6vaSz5jDTU7gpUKlIzqGm-o6PVn4oFN31gmHHop18AJjvOEDQuJ5Mv54aoLqoql0Rs\" alt=\"\"/>\u003C/figure>\n\u003C!-- /wp:image -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Defining the micro-interaction\u003C/h2>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>In the previous blog, we looked at the pieces of a micro-interaction. Let’s define the interaction trigger, state definition, and animation definition for our modal component.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3>Interaction trigger\u003C/h3>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Our modal will be triggered by a button in the main UI and will be dismissed when the Close button inside of the modal is clicked.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3>State definition\u003C/h3>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Our modal will be in one of two states:\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>\u003Ccode>visible\u003C/code>\u003C/li>\u003Cli>\u003Ccode>hidden\u003C/code>\u003C/li>\u003C/ul>\n\u003C!-- /wp:list -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3>Animation Definition\u003C/h3>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When the modal trigger button is clicked, the modal will fade in and translate its Y position from the top of the viewport.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When the modal close button is clicked, the modal will fade out and translate its Y position towards the top of the viewport.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Let’s build a modal\u003C/h2>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Create a new \u003Ca href=\"http://codesandbox.io/\">React Code Sandbox\u003C/a> and add \u003Ccode>react-spring\u003C/code> as a dependency.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Next, create a new file in the \u003Ccode>src\u003C/code> directory called \u003Ccode>Modal.js\u003C/code>. The modal will fade in and slide in from the top of the viewport on enter, and fade out and slide out towards the top of the viewport on exit.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cem>If you have an App.js file, you can delete it—we’ll be working in index.js. You’ll also have to remove the import to App.js and the instantiation of the component inside index.js. Replace index.js with the following code:\u003C/em>\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/298ba649936bf82dfbbadf6d146e366d\">index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/298ba649936bf82dfbbadf6d146e366d.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Create a new file called \u003Ccode>modal.css\u003C/code> in the \u003Ccode>src\u003C/code> directory and add the following code. We won’t cover styling in this tutorial, so we’ve provided everything you need to focus on the animation.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/576396e3c31eb9f41b2642dcf4b66a5a\">Modal.css\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/576396e3c31eb9f41b2642dcf4b66a5a.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Let's also add a style to \u003Ccode>styles.css\u003C/code>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/ff79873a1b3e68ed58c567c33c05d46d\">Styles.css\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/ff79873a1b3e68ed58c567c33c05d46d.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Inside \u003Ccode>Modal.js\u003C/code> import React, \u003Ccode>{ animated } from \"react-spring\"\u003C/code> and \u003Ccode>modal.css\u003C/code>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/67875d4669607a8d91744c3b8fae6b50\">Modal.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/67875d4669607a8d91744c3b8fae6b50.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>For now, let's simply return a \u003Ccode><div>\u003C/code> with \"Modal\" written inside to ensure everything is rendering as expected.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/fca8ef470b9b452304b47afe83d3ebab\">Modal.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/fca8ef470b9b452304b47afe83d3ebab.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The majority of the animation work will be done in \u003Ccode>index.js\u003C/code> because this is where our state will live.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>In \u003Ccode>index.js\u003C/code> import our Modal component, \u003Ccode>useTransition\u003C/code> from \u003Ccode>react-spring\u003C/code>, and add \u003Ccode>useState\u003C/code> to the React import.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/61efab80f836de4f5cae0c1ff4957b73\">Index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/61efab80f836de4f5cae0c1ff4957b73.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If you have them, remove the Code Sandbox \u003Ccode>h1\u003C/code> and \u003Ccode>h2\u003C/code> elements and instantiate our Modal component.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/757f77a93a5d11a48a64d56f7650bda1\">Index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/757f77a93a5d11a48a64d56f7650bda1.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You should see \"Modal\" rendering in the UI.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https://lh3.googleusercontent.com/q-6c0YxliidXU7THno_qHPMkBX-NQbJ-HkZc_RROpebv4tGKR2FPXJGYVPSNs6W3BkEwtIrKyaPLLplMxPF6BokyA0HjDK_Mq01PbzMhxn8FxxM6T8GcHsb7I3CTiROMYHT6U4W0\" alt=\"\"/>\u003C/figure>\n\u003C!-- /wp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Let's add some state to show and hide our modal. To show our modal, we'll have a \"Show modal\" button. Since our modal will not be visible by default, we'll initialize the \u003Ccode>modalVisible\u003C/code> state to false.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Before the return statement inside of \u003Ccode>App\u003C/code>, add the following:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/398fde78e9cdad3fe760675af2bfaeca\">Index.js\u003C/a>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/398fde78e9cdad3fe760675af2bfaeca.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Now let's build our animation using react-spring's \u003Ccode>useTransition\u003C/code> which mounts and unmounts a component from the DOM.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Underneath the \u003Ccode>useState\u003C/code> hook, let's declare a \u003Ccode>fadingAnimation\u003C/code> const and set it equal to the result of calling \u003Ccode>useTransition\u003C/code>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/326b3ba8a69fbc0de27bb22f6c81fed0\">Index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/326b3ba8a69fbc0de27bb22f6c81fed0.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>This hook takes three arguments:\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:list {\"ordered\":true} -->\n\u003Col>\u003Cli>The first argument is the state this animation is dependent on, in our case \u003Ccode>modalVisible\u003C/code>.\u003C/li>\u003Cli>The second argument is the keys for each item. React requires keys for elements which are being mapped over, and since the result of calling the \u003Ccode>useTransition\u003C/code>hook must be mapped over, we must pass a value for \u003Ccode>key\u003C/code>, which in our case is null (since we just have one item, the modal).\u003C/li>\u003Cli>The third argument is the lifecycle definition. The lifecycle definition object takes several required properties. We have to define these three properties to use \u003Ccode>useTransition\u003C/code>: \u003C/li>\u003C/ol>\n\u003C!-- /wp:list -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>from\u003C/li>\u003Cli>enter\u003C/li>\u003Cli>leave\u003C/li>\u003C/ul>\n\u003C!-- /wp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You can view the full list of optional properties \u003Ca href=\"https://www.react-spring.io/docs/hooks/use-transition)\">here\u003C/a>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Each of these three values expects an object with the CSS properties that change during the animation.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We want our modal to transition from an opacity of 0 and start outside of the viewport. When the modal enters, we want to fade it in by changing the opacity to 1 and slide in from the top by translating the Y-property. And on leave we want the modal to fade out and slide out towards the top.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/6003e4e46a60c2d9b485eebf8408e66b\">Index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/6003e4e46a60c2d9b485eebf8408e66b.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The \u003Ccode>useTransition\u003C/code> hook requires its results to be mapped over in the render function. So let's replace the simple \u003Ccode><Modal />\u003C/code> with a JSX expression which maps over \u003Ccode>fadingAnimation\u003C/code>.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We can de-structure \u003Ccode>item\u003C/code>, \u003Ccode>key\u003C/code>, and \u003Ccode>props\u003C/code> out of \u003Ccode>fadingAnimation\u003C/code>. \u003Ccode>props\u003C/code> is a bit confusing as it's actually the animation we're going to be passing to our modal component, so let's rename it \u003Ccode>style\u003C/code> to make it more clear.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We will pass \u003Ccode>style\u003C/code> as an argument to our modal component, as well as \u003Ccode>key\u003C/code>.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We also need to pass a function which will close the modal by updating the \u003Ccode>modalVisible\u003C/code> state when the Close modal button is clicked.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/3261e849e074d0b232eda7c9cbd00b00\">Index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/3261e849e074d0b232eda7c9cbd00b00.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Now let's add a button to show the modal. Before the transition mapping, add the following.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/fe0d26ae593fa873ed4ae146fa8b5b38\">Index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/fe0d26ae593fa873ed4ae146fa8b5b38.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Here is our finalized \u003Ccode>index.js\u003C/code>\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/7af066576ae9a2d1c852e19eba044121\">Index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/7af066576ae9a2d1c852e19eba044121.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When the UI is rendered we see a button:\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https://lh4.googleusercontent.com/mOftOAQy4yj2QjMh5dvtNoM1ETDIMzwrULHlB_jdQ_w93i3ObgdPIPv4Qse2KCLLaV7Bcs94Cq-Nh45xf26vMWQM-uhN39tFdhuN1S0TT3TeoIAnVmRO6QO8FOVNJ1Vo8gIAKO32\" alt=\"\"/>\u003C/figure>\n\u003C!-- /wp:image -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https://lh3.googleusercontent.com/SBc9ofa-t5OBxrkkRHOakqVQx7Fa_wFnu71QPfWMGr9EMOPCLeoK4H6ou95WWBuAkjSkMF3LIZNpBAxSQOprCWrsZ8DlajwP61QaAMB4J9BBdA-wvgSCj5fIoEn5RJNC9iWk8S1S\" alt=\"\"/>\u003C/figure>\n\u003C!-- /wp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>And when we click it, we see the word “Modal”, but there is currently no animation.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Now let's build our modal. This will take two arguments:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>\u003Ccode>style\u003C/code>: The animation\u003C/li>\u003Cli>\u003Ccode>closeModal\u003C/code>: The event handler for closing the modal\u003C/li>\u003C/ul>\n\u003C!-- /wp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/26fe36d686958d56284942599f279a50\">Modal.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/26fe36d686958d56284942599f279a50.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The modal will contain a title, some content, and a close button, so let's add those, as well as some class names for styling.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/0245634245cf881b437cafd61921d63c\">Modal.js\u003C/a>:\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/0245634245cf881b437cafd61921d63c.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Let's pass our \u003Ccode>closeModal\u003C/code> function to the close button as an on click handler so the user can dismiss the modal.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/0629fe02e5238e284d73b991d933488c\">Modal.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/0629fe02e5238e284d73b991d933488c.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If we head back to the browser, we can see our modal appears and closes, but isn't being animated.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>This is because we have to use a special animated HTML element to get our modal to animate. Any element we want to be animated must be prefaced by \u003Ccode>animated\u003C/code>., for example \u003Ccode><animated.div>\u003C/code>. So let's change our \u003Ccode><div>\u003C/code> elements into animated divs.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/dff42c16b72caea286e252afe5fb98db\">Modal.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/dff42c16b72caea286e252afe5fb98db.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Lastly, we have to pass \u003Ccode>style\u003C/code> to \u003Ccode><animated.div>\u003C/code> as a prop to see our animation.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/d5ec869cdd3468a27d845d239dd2e6e8\">Modal.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/d5ec869cdd3468a27d845d239dd2e6e8.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>And that's it! You now have a fully-animated modal which mounts and unmounts when it's shown and hidden.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://codesandbox.io/s/github/emmawedekind/react-spring-animated-modal/tree/master/?fontsize=14&hidenavigation=1&theme=dark\">View the final code here\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Ciframe\n src=\"https://codesandbox.io/embed/github/emmawedekind/react-spring-animated-modal/tree/master/?fontsize=14&hidenavigation=1&theme=dark\"\n style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;\"\n title=\"react-spring-animated-modal\"\n allow=\"geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb\"\n sandbox=\"allow-modals allow-forms allow-popups allow-scripts allow-same-origin\"\n >\u003C/iframe>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:heading {\"level\":1} -->\n\u003Ch1>Building an image gallery\u003C/h1>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Making an image gallery with plain JavaScript, and animating it, can be tedious. But not with react-spring! Let's make an image gallery that switches between three photos.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>What We’ll Build\u003C/h2>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https://lh6.googleusercontent.com/CYOk53zQbc2EdYzNvPqx_xUVSFsekATW3slZSUwe9YuUOcDPdhJp192SCW0nq5voJA967EM69ZgTu-E6easpP6pEUALdH3mQ2xezZws0qRsMWQiqxFCmLkSGmV875zpg04GHb8OK\" alt=\"\"/>\u003C/figure>\n\u003C!-- /wp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://codesandbox.io/s/react-spring-animated-image-gallery-5vs9d\">The end code:\u003C/a>\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Ciframe\n src=\"https://codesandbox.io/embed/react-spring-animated-image-gallery-5vs9d?fontsize=14&hidenavigation=1&theme=dark\"\n style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;\"\n title=\"React Spring Animated Image Gallery\"\n allow=\"geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb\"\n sandbox=\"allow-modals allow-forms allow-popups allow-scripts allow-same-origin\"\n >\u003C/iframe>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Defining The micro-interaction\u003C/h2>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3>Interaction trigger\u003C/h3>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The gallery will transition to the next image when the user clicks anywhere in the viewport.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3>State definition\u003C/h3>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We will have three images in our gallery so its state will be one of the following states, each number representing the image currently being shown.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>\u003Ccode>0\u003C/code>\u003C/li>\u003Cli>\u003Ccode>1\u003C/code>\u003C/li>\u003Cli>\u003Ccode>2\u003C/code>\u003C/li>\u003C/ul>\n\u003C!-- /wp:list -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3>Animation definition\u003C/h3>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The leaving image will fade out and slide to the left while the entering image will fade in and slide in from the right.\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Let’s build an image gallery\u003C/h2>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Let's make an image gallery that switches between three photos.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Create a \u003Ca href=\"http://codesandbox.io/\">React Code Sandbox\u003C/a> and add \u003Ccode>react-spring\u003C/code> as a dependency.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cem>If you have an App.js file, you can delete it—we’ll be working in index.js. You’ll also have to remove the import to App.js and the instantiation of the component inside index.js. Replace index.js with the following code:\u003C/em>\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/298ba649936bf82dfbbadf6d146e366d\">index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/298ba649936bf82dfbbadf6d146e366d.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Create two new files: \u003Ccode>Gallery.js\u003C/code> and \u003Ccode>gallery.css\u003C/code> and add the following code to \u003Ccode>gallery.css\u003C/code>. We won’t be covering CSS today so we’ve provided the styling for you!\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/aaf58ed1303af19dcdf3b0f6f98b37e5\">Gallery.css\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/aaf58ed1303af19dcdf3b0f6f98b37e5.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Create an \u003Ccode>images\u003C/code> folder in the root and add three photos.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You can find some on \u003Ca href=\"http://unsplash.com/\">Unsplash\u003C/a>. I added \u003Ccode>mountains.jpg\u003C/code>, \u003Ccode>beach.jpg\u003C/code>, and \u003Ccode>desert.jpg\u003C/code>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Inside of \u003Ccode>Gallery.js\u003C/code>, import the following packages, as well as the three images you just uploaded, and the CSS file.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/e263a6374020e37904b3532a70f42c8e\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/e263a6374020e37904b3532a70f42c8e.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Now let's define three images we want to iterate between. Each will take in a style and render an \u003Ccode>animated.img\u003C/code> tag (as react-spring requires any animatable element to be prefaced with \u003Ccode>animated\u003C/code>. ) with its respective image source, alt tag, and style.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/edbe8e98577642f35b07cecef408a8a7\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/edbe8e98577642f35b07cecef408a8a7.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Next, let's set up our component.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/78ddd761c7b6ec9f64f9cd322e3046db\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/78ddd761c7b6ec9f64f9cd322e3046db.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>First we need to establish our state for which photo we're currently viewing. Above the return statement, we'll call this state \u003Ccode>index\u003C/code> and it's setter function \u003Ccode>setIndex\u003C/code>, and initialize the value to \u003Ccode>0\u003C/code> for the first image.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/2c34fdfbbf5a35116137618db5d98858\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/2c34fdfbbf5a35116137618db5d98858.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When the user clicks anywhere in the viewport, we want to switch to the next image. We can use \u003Ccode>useCallback\u003C/code> to do this.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Since we have three images, we want to ensure the state value remains either 0, 1, or 2, so we can use modulus to grab the remainder of the next state value divided by three.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>For example if the state is currently 2 and we want the next photo, we add 1, which totals 3. Since 3 is outside the bounds of the number of photos we have (indexing from 0, we have 0, 1 and 2 for available photo indices), let's mod it by 3 to get the remainder.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>(2 + 1) % 3 = 0 because 3 mod 3 yields a remainder of 0.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You can read more about mods \u003Ca href=\"https://riptutorial.com/javascript/example/760/remainder---modulus----\">here\u003C/a>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/65dfc78cc997c838981652248591cddc\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/65dfc78cc997c838981652248591cddc.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Let's add our \u003Ccode>onClick\u003C/code> handler as an argument on the wrapping \u003Ccode><div>\u003C/code> so the user can switch to the next photo by clicking in the viewport.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/ce5dc60071c77e6391025f0a76d9ac3d\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/ce5dc60071c77e6391025f0a76d9ac3d.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Next, let's set up our animation. We'll use \u003Ccode>useTransition\u003C/code> to mount and unmount the photos from the DOM so we're only rendering one at a time.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ccode>useTransition\u003C/code> takes in three arguments:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>\u003Ccode>item\u003C/code>: The index for our photo\u003C/li>\u003Cli>\u003Ccode>key\u003C/code>: The key for our mapped over item\u003C/li>\u003Cli>\u003Ccode>lifecycle\u003C/code>: An object describing the animation\u003C/li>\u003C/ul>\n\u003C!-- /wp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We want our images to fade in and out while sliding them into and out of view so we'll define \u003Ccode>opacity\u003C/code> and \u003Ccode>transform\u003C/code> at each of the lifecycle steps.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We will also add a \u003Ccode>config\u003C/code> option to change the speed at which this animation occurs. You can check the full options for config \u003Ca href=\"https://www.react-spring.io/docs/hooks/api\">here\u003C/a>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/c88791dab8806b5f1e9a8fbb42cc0b66\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/c88791dab8806b5f1e9a8fbb42cc0b66.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Now we're ready to add some JSX. Let's first render a paragraph that tells the user they can click anywhere to change to the next image.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/abd39c7a4bef618c085a71f93dbfd7f0\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/abd39c7a4bef618c085a71f93dbfd7f0.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Since \u003Ccode>useTransition\u003C/code> requires we map over its return value, let's map over our transitions and render each image. We'll de-structure \u003Ccode>item\u003C/code>, \u003Ccode>props\u003C/code>, and \u003Ccode>key\u003C/code> from \u003Ccode>transitions\u003C/code>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Then we'll grab the image component from our \u003Ccode>images\u003C/code> array by using the \u003Ccode>item\u003C/code>, or \u003Ccode>index\u003C/code> defined in \u003Ccode>useTransition\u003C/code>.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Finally we'll return the Image component and pass it the \u003Ccode>key\u003C/code> and \u003Ccode>props\u003C/code> (as the style attribute).\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/8c700da6b273b9bb33220d3e5f4a8fbf\">Gallery.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/8c700da6b273b9bb33220d3e5f4a8fbf.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Here is our completed \u003Ccode>\u003Ca href=\"https://gist.github.com/emmabostian/0b619af6ae176b01c0ee55747171226a\">Gallery.js\u003C/a>\u003C/code>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/0b619af6ae176b01c0ee55747171226a.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Finally let's head back to \u003Ccode>index.js\u003C/code> to import our Gallery component and render it.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https://gist.github.com/emmabostian/64301d33d9f6b47ca982f14cd5ba98be\">index.js\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Cscript src=\"https://gist.github.com/emmabostian/64301d33d9f6b47ca982f14cd5ba98be.js\">\u003C/script>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>And that's it! You now have a fully-functional image gallery.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You can view the final code \u003Ca href=\"https://codesandbox.io/s/amazing-wiles-5vs9d?fontsize=14&hidenavigation=1&theme=dark\">here\u003C/a>:\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:html -->\n\u003Ciframe\n src=\"https://codesandbox.io/embed/react-spring-animated-image-gallery-5vs9d?fontsize=14&hidenavigation=1&theme=dark\"\n style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;\"\n title=\"React Spring Animated Image Gallery\"\n allow=\"geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb\"\n sandbox=\"allow-modals allow-forms allow-popups allow-scripts allow-same-origin\"\n >\u003C/iframe>\n\u003C!-- /wp:html -->\n\n\u003C!-- wp:heading {\"level\":1} -->\n\u003Ch1>Conclusion\u003C/h1>\n\u003C!-- /wp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>I hope this series of blog posts on creating micro-interactions with react-spring has empowered you to create fun interactions within your website.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You can create complex animations and interactions with just a few lines of code.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>For more articles on micro-animations and micro-interactions check out the resources below.\u003Cbr>\u003C/p>\n\u003C!-- /wp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>\u003Ca href=\"https://hike.one/update/why-use-micro-animations-in-your-design\">Why Use Micro-Animations In Your Design?\u003C/a>\u003C/li>\u003Cli>\u003Ca href=\"https://uxdesign.cc/micro-interactions-why-when-and-how-to-use-them-to-boost-the-ux-17094b3baaa0\">Micro-Interactions\u003C/a>\u003C/li>\u003Cli>\u003Ca href=\"https://medium.com/@MentorMate/should-you-advocate-for-micro-animations-cdf625635261\">Should You Advocate For Micro-Animations?\u003C/a>\u003C/li>\u003Cli>\u003Ca href=\"https://blog.geekyants.com/micro-interactions-and-micro-animations-4eb2ed5cc7f3\">Micro-Interactions & Micro-Animations\u003C/a>\u003C/li>\u003C/ul>\n\u003C!-- /wp:list -->","html","2020-01-30T15:08:24.000Z",{"current":2159},"micro-interactions-with-react-spring-part-3",[2161,2168,2173,2178,2181],{"_createdAt":2162,"_id":2163,"_rev":2164,"_type":2165,"_updatedAt":2162,"slug":2166,"title":2167},"2023-05-23T16:43:21Z","wp-tagcat-animation","9HpbCsT2tq0xwozQfkc4ih","blogTag",{"current":2167},"animation",{"_createdAt":2162,"_id":2169,"_rev":2164,"_type":2165,"_updatedAt":2162,"slug":2170,"title":2172},"wp-tagcat-bulletin",{"current":2171},"bulletin","Bulletin",{"_createdAt":2162,"_id":2174,"_rev":2164,"_type":2165,"_updatedAt":2162,"slug":2175,"title":2177},"wp-tagcat-code-for-a-living",{"current":2176},"code-for-a-living","Code for a Living",{"_createdAt":2162,"_id":2179,"_rev":2164,"_type":2165,"_updatedAt":2162,"slug":2180,"title":292},"wp-tagcat-react-spring",{"current":292},{"_createdAt":2162,"_id":2182,"_rev":2164,"_type":2165,"_updatedAt":2162,"slug":2183,"title":2185},"wp-tagcat-stackoverflow",{"current":2184},"stackoverflow","Stackoverflow","Micro-interactions with react-spring: Part 3",[2188,2194,2200,2206],{"_id":2189,"publishedAt":2190,"slug":2191,"sponsored":12,"title":2193},"370eca08-3da8-4a13-b71e-5ab04e7d1f8b","2025-08-28T16:00:00.000Z",{"_type":10,"current":2192},"moving-the-public-stack-overflow-sites-to-the-cloud-part-1","Moving the public Stack Overflow sites to the cloud: Part 1",{"_id":2195,"publishedAt":2196,"slug":2197,"sponsored":2148,"title":2199},"e10457b6-a9f6-4aa9-90f2-d9e04eb77b7c","2025-08-27T04:40:00.000Z",{"_type":10,"current":2198},"from-punch-cards-to-prompts-a-history-of-how-software-got-better","From punch cards to prompts: a history of how software got better",{"_id":2201,"publishedAt":2202,"slug":2203,"sponsored":12,"title":2205},"65472515-0b62-40d1-8b79-a62bdd2f508a","2025-08-25T16:00:00.000Z",{"_type":10,"current":2204},"making-continuous-learning-work-at-work","Making continuous learning work at work",{"_id":2207,"publishedAt":2208,"slug":2209,"sponsored":12,"title":2211},"1b0bdf8c-5558-4631-80ca-40cb8e54b571","2025-08-21T14:00:25.054Z",{"_type":10,"current":2210},"research-roadmap-update-august-2025","Research roadmap update, August 2025",{"count":2213,"lastTimestamp":2214},5,"2023-05-25T09:47:03Z",["Reactive",2216],{"$sarticleModal":2217},false,["Set"],["ShallowReactive",2220],{"sanity-5gVxFIj5gUL9zp24IxMign6rOrXzeFETUOMV7mn0mAw":-1,"sanity-comment-wp-post-14876-1756433811174":-1},"/2020/01/30/micro-interactions-with-react-spring-part-3/?cb=1"]