Commit 7465a0e9 authored by Mike Grabowski's avatar Mike Grabowski Committed by GitHub

feat: various improvements to banner (#5317)

* initial commit

* chore: responsive improvements

* feat: responsive carousel

* chore: fix carousel

* chore: less magic, components

* chore: bump friction a bit to compensate for carousel changes

* fix: position of loading bubbles

* chore: fix max-width on fullscreen breakpoints not taking 100 space

* fix full screen max-width

* chore: remove first card offset
parent 6aac9787
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.64864 2L1 7.65256L10.5 17.1487L20 7.65256L14.3514 2H6.64864ZM6.13513 5.59458C8.5352 3.18398 12.4648 3.18396 14.8649 5.59456L16.9189 7.64866L14.8649 9.70272C12.4648 12.1133 8.5352 12.1133 6.13513 9.70274L4.08109 7.64866L6.13513 5.59458ZM7.54702 7.64848C7.54702 9.27987 8.86966 10.6012 10.4997 10.6012C12.1298 10.6012 13.4524 9.27987 13.4524 7.64848C13.4524 6.01708 12.1298 4.69576 10.4997 4.69576C8.86966 4.69576 7.54702 6.01708 7.54702 7.64848ZM10.4997 8.93225C9.791 8.93225 9.21593 8.35778 9.21593 7.64848C9.21593 6.93917 9.791 6.3647 10.4997 6.3647C11.2084 6.3647 11.7835 6.93917 11.7835 7.64848C11.7835 8.35778 11.2084 8.93225 10.4997 8.93225Z" fill="#5D6785"/>
</svg>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 1C5.0302 1 1 5.0302 1 10C1 14.9698 5.0302 19 10 19C14.9698 19 19 14.9698 19 10C19 5.0302 14.9716 1 10 1ZM5.4406 10.3024L5.4784 10.2412L7.8202 6.5782C7.8544 6.526 7.9354 6.5314 7.9606 6.589C8.3512 7.4656 8.6896 8.5564 8.5312 9.235C8.4646 9.514 8.2792 9.892 8.0704 10.2412C8.0434 10.2916 8.0146 10.342 7.9822 10.3906C7.9678 10.4122 7.9426 10.4248 7.9156 10.4248H5.509C5.4442 10.4248 5.4064 10.3546 5.4406 10.3024ZM15.8752 11.5624C15.8752 11.5966 15.8554 11.6254 15.8266 11.638C15.6448 11.7154 15.0238 12.0016 14.7664 12.3598C14.1076 13.276 13.6054 14.5864 12.4804 14.5864H7.7896C6.1264 14.5864 4.78 13.2346 4.78 11.566V11.512C4.78 11.4688 4.816 11.4328 4.861 11.4328H7.4746C7.5268 11.4328 7.5646 11.4796 7.561 11.5318C7.5412 11.701 7.5736 11.8756 7.6546 12.034C7.8094 12.349 8.1316 12.5452 8.479 12.5452H9.7732V11.5354H8.4934C8.4286 11.5354 8.389 11.4598 8.4268 11.4058C8.4412 11.3842 8.4556 11.3626 8.4736 11.3374C8.5942 11.1646 8.767 10.8982 8.9398 10.594C9.0568 10.3888 9.1702 10.1692 9.262 9.9496C9.28 9.91 9.2944 9.8686 9.3106 9.829C9.3358 9.7588 9.361 9.6922 9.379 9.6274C9.397 9.5716 9.4132 9.514 9.4276 9.46C9.4708 9.2728 9.4888 9.0748 9.4888 8.8696C9.4888 8.7886 9.4852 8.704 9.478 8.6248C9.4744 8.5366 9.4636 8.4484 9.4528 8.3602C9.4456 8.2828 9.4312 8.2054 9.4168 8.1262C9.397 8.0092 9.3718 7.8922 9.343 7.7752L9.3322 7.7302C9.3106 7.6492 9.2908 7.5736 9.2656 7.4926C9.1918 7.2406 9.109 6.994 9.019 6.7636C8.9866 6.6718 8.9506 6.5836 8.9128 6.4972C8.8588 6.364 8.803 6.2434 8.7526 6.13C8.7256 6.0778 8.704 6.031 8.6824 5.9824C8.6572 5.9284 8.632 5.8744 8.605 5.8222C8.587 5.7826 8.5654 5.7448 8.551 5.7088L8.3926 5.4172C8.371 5.3776 8.407 5.329 8.4502 5.3416L9.4402 5.6098H9.4438C9.4456 5.6098 9.4456 5.6098 9.4474 5.6098L9.577 5.6476L9.721 5.6872L9.7732 5.7016V5.1148C9.7732 4.8304 10 4.6 10.2826 4.6C10.423 4.6 10.5508 4.6576 10.6408 4.7512C10.7326 4.8448 10.7902 4.9726 10.7902 5.1148V5.9878L10.8964 6.0166C10.9036 6.0202 10.9126 6.0238 10.9198 6.0292C10.945 6.0472 10.9828 6.076 11.0296 6.112C11.0674 6.1408 11.107 6.1768 11.1538 6.2146C11.2492 6.292 11.3644 6.391 11.4886 6.5044C11.521 6.5332 11.5534 6.562 11.584 6.5926C11.7442 6.742 11.9242 6.9166 12.097 7.111C12.1456 7.1668 12.1924 7.2208 12.241 7.2802C12.2878 7.3396 12.34 7.3972 12.3832 7.4548C12.4426 7.5322 12.5038 7.6132 12.5596 7.6978C12.5848 7.7374 12.6154 7.7788 12.6388 7.8184C12.7108 7.9246 12.772 8.0344 12.8314 8.1442C12.8566 8.1946 12.8818 8.2504 12.9034 8.3044C12.97 8.452 13.0222 8.6014 13.0546 8.7526C13.0654 8.785 13.0726 8.8192 13.0762 8.8516V8.8588C13.087 8.902 13.0906 8.9488 13.0942 8.9974C13.1086 9.1504 13.1014 9.3052 13.069 9.46C13.0546 9.5248 13.0366 9.586 13.015 9.6526C12.9916 9.7156 12.97 9.7804 12.9412 9.8434C12.8854 9.9712 12.8206 10.1008 12.7432 10.2196C12.718 10.2646 12.6874 10.3114 12.6586 10.3564C12.6262 10.4032 12.592 10.4482 12.5632 10.4914C12.5218 10.5472 12.4786 10.6048 12.4336 10.657C12.394 10.711 12.3544 10.765 12.3094 10.8136C12.2482 10.8874 12.1888 10.9558 12.1258 11.0224C12.0898 11.0656 12.0502 11.1106 12.0088 11.1502C11.9692 11.1952 11.9278 11.2348 11.8918 11.2708C11.8288 11.3338 11.7784 11.3806 11.7352 11.422L11.6326 11.5138C11.6182 11.5282 11.5984 11.5354 11.5786 11.5354H10.7902V12.5452H11.782C12.0034 12.5452 12.214 12.4678 12.385 12.322C12.4426 12.2716 12.6964 12.052 12.997 11.7208C13.0078 11.7082 13.0204 11.701 13.0348 11.6974L15.7726 10.9054C15.8248 10.891 15.8752 10.9288 15.8752 10.9828V11.5624Z" fill="#5D6785"/>
</svg>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.26028 7.69661C8.2265 7.827 8.16752 7.94944 8.0867 8.05696C7.93627 8.25309 7.73717 8.40605 7.50935 8.50052C7.30443 8.58922 7.08744 8.64655 6.8656 8.67061C6.81999 8.67641 6.77273 8.68001 6.72695 8.68349L6.72692 8.68349L6.71944 8.68406C6.57894 8.68943 6.44384 8.73983 6.33392 8.82791C6.224 8.91598 6.14503 9.03709 6.10858 9.17351C6.09189 9.24138 6.07949 9.31024 6.07143 9.37969C6.05867 9.4844 6.0521 9.59161 6.04499 9.70758L6.04499 9.7076C6.03989 9.79082 6.03451 9.87856 6.02636 9.97313C5.97864 10.3583 5.86772 10.7329 5.6981 11.0817C5.66343 11.155 5.62809 11.2261 5.59338 11.2959C5.40739 11.6701 5.23937 12.008 5.28761 12.4607C5.32537 12.8095 5.50321 13.0432 5.73951 13.2842C5.85174 13.3995 6.00056 13.4981 6.15504 13.6003C6.58739 13.8866 7.06406 14.2022 6.90702 14.9973C6.77851 15.6415 5.71515 16.3175 4.2206 16.5537C4.36557 16.5316 4.04625 15.9843 4.01077 15.9235L4.00866 15.9199C3.96746 15.855 3.92525 15.7912 3.88311 15.7274L3.88309 15.7274L3.88309 15.7274C3.76142 15.5433 3.64034 15.3601 3.5458 15.157C3.29609 14.6265 3.18038 14.0129 3.2827 13.4317C3.37538 12.9056 3.72157 12.4854 4.05489 12.0808C4.10923 12.0149 4.16323 11.9493 4.21573 11.8838C4.66153 11.3277 5.12927 10.599 5.2328 9.87708C5.24153 9.81436 5.24933 9.74598 5.25753 9.67402C5.2722 9.54524 5.28819 9.40501 5.31319 9.26528C5.35036 9.02398 5.4256 8.79019 5.53609 8.57271C5.61152 8.43009 5.71082 8.30157 5.82965 8.19278C5.8916 8.13503 5.93248 8.05806 5.94573 7.9742C5.95898 7.89035 5.94384 7.80445 5.90273 7.73026L3.52022 3.4256L6.94234 7.66786C6.98131 7.71701 7.03057 7.75695 7.08663 7.78484C7.14269 7.81273 7.20417 7.82788 7.26671 7.82922C7.32925 7.83056 7.39132 7.81807 7.44852 7.79261C7.50571 7.76716 7.55663 7.72937 7.59765 7.68193C7.641 7.63115 7.66558 7.56689 7.66725 7.50002C7.66891 7.43314 7.64756 7.36774 7.60679 7.31484C7.44767 7.11058 7.28207 6.90352 7.11724 6.69742L7.11693 6.69703C7.05033 6.61376 6.98385 6.53063 6.91798 6.44792L6.05682 5.37726L4.32839 3.23962L2.40918 0.957275L4.55008 3.04812L6.38995 5.09155L7.30776 6.11571C7.39208 6.21109 7.4764 6.30562 7.56072 6.40016C7.78091 6.64702 8.0011 6.89388 8.2213 7.15578L8.27124 7.21696L8.2822 7.31179C8.29704 7.44037 8.28963 7.57057 8.26028 7.69661ZM17.0557 9.13522L17.0593 9.14073L17.0593 9.14022C17.0585 8.68377 16.7771 7.93092 16.2079 7.20681L16.1945 7.18907C16.0191 6.97129 15.828 6.7668 15.6226 6.57727L15.6058 6.56111L15.625 6.57774C15.6005 6.55502 15.5756 6.53252 15.5507 6.51012L15.5032 6.467L15.5386 6.49973L15.5008 6.46653C15.2378 6.23604 14.9502 6.03537 14.6433 5.86818L14.6214 5.85717C13.6573 5.32979 12.4027 5.05815 10.8558 5.36406C10.648 5.11068 10.4242 4.87097 10.1859 4.64641C9.82077 4.29694 9.39101 4.02277 8.9209 3.83944C8.45502 3.66813 7.9561 3.607 7.46289 3.66079C7.93832 3.70379 8.40139 3.83664 8.82772 4.05235C9.23946 4.27394 9.61026 4.56489 9.92397 4.91254C10.2419 5.26742 10.5408 5.63911 10.8192 6.02603L10.8891 6.11741C11.1616 6.47389 11.439 6.83678 11.7846 7.1597C11.9748 7.33953 12.187 7.49433 12.4161 7.62039C12.477 7.65159 12.5385 7.68096 12.5988 7.70666C12.6591 7.73235 12.7158 7.75621 12.7767 7.77824C12.8942 7.82412 13.016 7.86205 13.1378 7.89693C13.625 8.03642 14.1238 8.08659 14.611 8.11351C14.6789 8.11709 14.7466 8.12044 14.814 8.12378C14.988 8.13239 15.1604 8.14093 15.3303 8.15327C15.5631 8.16717 15.794 8.20363 16.0197 8.26217C16.3589 8.35099 16.6575 8.55399 16.8657 8.83727C16.9364 8.93161 17 9.03121 17.0557 9.13522ZM15.0299 11.0846C13.4631 10.446 11.8242 9.77791 12.0682 7.90283C12.5913 8.46392 13.4125 8.58159 14.3056 8.70957C15.1158 8.82566 15.9851 8.95023 16.745 9.42194C18.5379 10.5342 18.2761 12.6951 17.667 13.4904C17.7219 12.182 16.4037 11.6446 15.0299 11.0846ZM8.70682 10.1459C9.12035 10.1061 10.0016 9.89012 9.60757 9.19327C9.52279 9.05151 9.39993 8.93664 9.25309 8.86186C9.10626 8.78708 8.94141 8.75542 8.77747 8.77052C8.6111 8.78845 8.45424 8.85736 8.32819 8.9679C8.20214 9.07844 8.11298 9.22526 8.07283 9.38844C7.95041 9.84423 8.08013 10.207 8.70682 10.1459ZM8.59812 4.63104C8.33868 4.33003 7.93611 4.17219 7.54146 4.11468C7.5267 4.21341 7.51734 4.31287 7.51345 4.41263C7.49579 5.23428 7.78629 6.1367 8.34842 6.7638C8.52823 6.96652 8.74511 7.13267 8.98729 7.25324C9.12737 7.32176 9.49887 7.49185 9.63651 7.3389C9.64699 7.32488 9.65359 7.30832 9.65562 7.29091C9.65765 7.2735 9.65505 7.25585 9.64808 7.23978C9.62528 7.17428 9.58121 7.11485 9.53747 7.05585L9.53747 7.05585C9.50644 7.01401 9.47558 6.97239 9.45259 6.92899C9.42932 6.88521 9.40443 6.84254 9.37956 6.7999L9.37956 6.79989L9.37955 6.79988L9.37955 6.79988L9.37955 6.79987L9.37954 6.79986L9.37954 6.79985C9.33282 6.71975 9.28616 6.63975 9.25039 6.55272C9.15602 6.3249 9.10688 6.08265 9.05789 5.84116C9.04807 5.79277 9.03826 5.74441 9.0281 5.6962C8.95319 5.32361 8.85757 4.93205 8.59812 4.63104ZM14.1416 11.1862C13.7391 12.3144 14.3883 13.2674 15.0336 14.2147C15.7554 15.2744 16.4724 16.3271 15.7074 17.6101C17.1941 16.9934 17.8999 15.1305 17.283 13.6524C16.8942 12.7175 15.9573 12.2106 15.0876 11.7402C14.7501 11.5577 14.4228 11.3806 14.1416 11.1862ZM9.78299 13.8799C9.51358 13.9903 9.25954 14.1353 9.02718 14.3112C9.5555 14.1187 10.1101 14.0088 10.6716 13.9851C10.7734 13.9791 10.8758 13.9743 10.9792 13.9695L10.9793 13.9695C11.1579 13.9613 11.3391 13.9529 11.5242 13.9374C11.8277 13.9167 12.127 13.855 12.414 13.7538C12.7148 13.6481 12.9885 13.4768 13.2155 13.2522C13.4448 13.0203 13.6056 12.7291 13.6802 12.4109C13.7457 12.1104 13.7365 11.7982 13.6533 11.5021C13.5702 11.2059 13.4156 10.935 13.2033 10.7132C13.3057 10.9741 13.3687 11.249 13.3903 11.5287C13.4088 11.7891 13.3736 12.0505 13.2867 12.2965C13.2019 12.5297 13.0634 12.7394 12.8823 12.9083C12.6953 13.0789 12.4788 13.2137 12.2435 13.306C11.9164 13.4384 11.5466 13.4925 11.1613 13.5489C10.9856 13.5746 10.8066 13.6009 10.6271 13.6352C10.3383 13.6883 10.0555 13.7703 9.78299 13.8799ZM14.4825 18.5143L14.4282 18.558L14.4282 18.5581C14.3601 18.6131 14.2909 18.6691 14.2164 18.7193C14.1214 18.7822 14.0218 18.8378 13.9186 18.8857C13.7036 18.9911 13.4671 19.0449 13.2279 19.0429C12.5799 19.0307 12.1219 18.5462 11.854 17.9986C11.7837 17.8551 11.7218 17.7071 11.6599 17.5591C11.5609 17.3223 11.4618 17.0855 11.3284 16.8667C11.0184 16.3583 10.4879 15.949 9.86671 16.0249C9.61335 16.0567 9.37583 16.1711 9.23515 16.392C8.86486 16.9689 9.39654 17.7771 10.0744 17.6627C10.132 17.6539 10.1885 17.6383 10.2425 17.6162C10.2963 17.5932 10.3466 17.5625 10.3917 17.525C10.4864 17.4458 10.5578 17.3422 10.5981 17.2253C10.6427 17.1033 10.6526 16.9714 10.6268 16.8441C10.599 16.7111 10.5208 16.5942 10.4087 16.518C10.539 16.5793 10.6405 16.689 10.6919 16.8239C10.7453 16.9628 10.759 17.1139 10.7315 17.2601C10.7049 17.4125 10.638 17.555 10.5379 17.6725C10.4846 17.7329 10.4231 17.7855 10.3551 17.8285C10.2878 17.871 10.2156 17.9053 10.1402 17.9307C9.98719 17.9832 9.82434 18.0001 9.6639 17.9802C9.43863 17.948 9.22616 17.8554 9.04878 17.7123C9.01043 17.6818 8.97388 17.6496 8.93858 17.6162C8.82611 17.5169 8.72353 17.4067 8.63236 17.2871C8.58742 17.2373 8.54176 17.1881 8.49396 17.1408C8.27683 16.912 8.02065 16.724 7.73755 16.5859C7.54232 16.4998 7.33801 16.4362 7.12852 16.3963C7.02316 16.3742 6.91658 16.3583 6.81 16.3449C6.79841 16.3437 6.77607 16.3398 6.7483 16.335C6.65931 16.3194 6.51457 16.2942 6.48904 16.318C6.81846 16.0133 7.17757 15.7428 7.56093 15.5104C7.95455 15.2757 8.37719 15.0941 8.81796 14.9702C9.27496 14.8409 9.75294 14.8041 10.2242 14.8619C10.4668 14.8911 10.7044 14.9529 10.9307 15.0454C11.1678 15.1405 11.3866 15.2763 11.5775 15.4467C11.7663 15.6255 11.919 15.8393 12.0269 16.0763C12.1244 16.2982 12.1971 16.5303 12.2437 16.7682C12.2687 16.8963 12.2876 17.037 12.3071 17.1827C12.3959 17.8464 12.4984 18.6121 13.259 18.7456C13.3073 18.755 13.3561 18.762 13.4052 18.7664L13.5568 18.7701C13.6611 18.7626 13.7647 18.7477 13.8668 18.7254C14.0784 18.6754 14.2846 18.6047 14.4825 18.5143Z" fill="#FC72FF"/>
</svg>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.146 4.52803C15.767 3.18049 13.8805 2.35 11.8 2.35C7.57502 2.35 4.15 5.77502 4.15 10C4.15 14.225 7.57502 17.65 11.8 17.65C13.8805 17.65 15.767 16.8195 17.146 15.472C15.501 17.617 12.912 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1C12.912 1 15.501 2.38301 17.146 4.52803Z" fill="#5D6785"/>
<path d="M6.08317 14.3776C7.18644 15.4556 8.69563 16.12 10.36 16.12C13.74 16.12 16.48 13.38 16.48 10C16.48 6.62002 13.74 3.88 10.36 3.88C8.69563 3.88 7.18644 4.54439 6.08317 5.62243C7.39916 3.90641 9.47037 2.8 11.8 2.8C15.7765 2.8 19 6.02355 19 10C19 13.9764 15.7764 17.2 11.8 17.2C9.47037 17.2 7.39916 16.0936 6.08317 14.3776Z" fill="#5D6785"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.4 10C15.4 12.9823 12.9823 15.4 10 15.4C7.01766 15.4 4.6 12.9823 4.6 10C4.6 7.01766 7.01766 4.6 10 4.6C12.9823 4.6 15.4 7.01766 15.4 10ZM13.6 10C13.6 11.9882 11.9882 13.6 10 13.6C8.01177 13.6 6.4 11.9882 6.4 10C6.4 8.01178 8.01177 6.4 10 6.4C11.9882 6.4 13.6 8.01178 13.6 10Z" fill="#5D6785"/>
</svg>
...@@ -6,7 +6,7 @@ import { calculateCardIndex } from 'nft/utils' ...@@ -6,7 +6,7 @@ import { calculateCardIndex } from 'nft/utils'
import { Suspense, useCallback, useMemo, useState } from 'react' import { Suspense, useCallback, useMemo, useState } from 'react'
import { useQuery } from 'react-query' import { useQuery } from 'react-query'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import styled, { css } from 'styled-components/macro' import styled from 'styled-components/macro'
import { opacify } from 'theme/utils' import { opacify } from 'theme/utils'
import { Carousel, LoadingCarousel } from './Carousel' import { Carousel, LoadingCarousel } from './Carousel'
...@@ -16,14 +16,12 @@ const BannerContainer = styled.div` ...@@ -16,14 +16,12 @@ const BannerContainer = styled.div`
display: flex; display: flex;
justify-content: center; justify-content: center;
width: 100%; width: 100%;
padding: 32px 16px 0 16px; padding-top: 32px;
position: relative; position: relative;
`
// Safari has issues with blur / overflow @media only screen and (min-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) {
// https://stackoverflow.com/a/71353198 padding: 32px 16px 0 16px;
const fixBlurOnSafari = css` }
transform: translate3d(0, 0, 0);
` `
const AbsoluteFill = styled.div` const AbsoluteFill = styled.div`
...@@ -34,13 +32,15 @@ const AbsoluteFill = styled.div` ...@@ -34,13 +32,15 @@ const AbsoluteFill = styled.div`
bottom: 0; bottom: 0;
` `
// Safari has issues with blur / overflow, forcing GPU rendering with `translate3d` fixes it
// https://stackoverflow.com/a/71353198
const BannerBackground = styled(AbsoluteFill)<{ backgroundImage: string }>` const BannerBackground = styled(AbsoluteFill)<{ backgroundImage: string }>`
${fixBlurOnSafari} transform: translate3d(0, 0, 0) scaleY(1.1);
background-image: ${(props) => `url(${props.backgroundImage})`}; background-image: ${(props) => `url(${props.backgroundImage})`};
filter: blur(62px); filter: blur(62px);
opacity: ${({ theme }) => (theme.darkMode ? 0.3 : 0.2)}; opacity: ${({ theme }) => (theme.darkMode ? 0.3 : 0.2)};
transform: scaleY(1.1);
` `
const PlainBackground = styled(AbsoluteFill)` const PlainBackground = styled(AbsoluteFill)`
......
import { useWindowSize } from 'hooks/useWindowSize'
import { ChevronLeftIcon, ChevronRightIcon } from 'nft/components/icons' import { ChevronLeftIcon, ChevronRightIcon } from 'nft/components/icons'
import { calculateCardIndex, calculateFirstCardIndex, calculateRank } from 'nft/utils' import { calculateCardIndex, calculateFirstCardIndex, calculateRank } from 'nft/utils'
import { ReactNode, useCallback, useEffect, useRef, useState } from 'react' import { ReactNode, useCallback, useEffect, useRef } from 'react'
import { a, useSprings } from 'react-spring' import { a, useSprings } from 'react-spring'
import styled, { css } from 'styled-components/macro' import styled from 'styled-components/macro'
const MAX_CARD_WIDTH = 530
const carouselHeightStyle = css`
height: 296px;
@media only screen and (min-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
height: 316px;
}
`
const CarouselContainer = styled.div` const CarouselContainer = styled.div`
display: flex; display: flex;
...@@ -22,38 +11,44 @@ const CarouselContainer = styled.div` ...@@ -22,38 +11,44 @@ const CarouselContainer = styled.div`
` `
const CarouselCardContainer = styled.div` const CarouselCardContainer = styled.div`
${carouselHeightStyle}
position: relative; position: relative;
width: 100%; width: 100%;
max-width: ${MAX_CARD_WIDTH}px;
overflow-x: hidden; overflow-x: hidden;
max-width: 100%;
height: 390px;
@media only screen and (min-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
max-width: 600px;
}
` `
const CarouselItemCard = styled(a.div)` const CarouselItemCard = styled(a.div)`
${carouselHeightStyle}
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 4px 12px 32px; padding: 4px 12px 32px;
position: absolute; position: absolute;
will-change: transform; will-change: transform;
width: calc(100%);
height: calc(100%);
@media screen and (min-width: ${({ theme }) => theme.breakpoint.lg}px) { @media screen and (min-width: ${({ theme }) => theme.breakpoint.md}px) {
padding: 4px 32px 32px; padding: 4px 32px 32px;
} }
` `
const CarouselItemIcon = styled.div` const CarouselItemIcon = styled.div`
${carouselHeightStyle}
align-items: center; align-items: center;
color: ${({ theme }) => theme.textPrimary}; color: ${({ theme }) => theme.accentAction};
cursor: pointer; cursor: pointer;
display: none; display: none;
user-select: none; user-select: none;
height: calc(100%);
padding: 4px 0 32px;
@media only screen and (min-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) { @media only screen and (min-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) {
display: flex; display: flex;
} }
:hover { :hover {
opacity: ${({ theme }) => theme.opacity.hover}; opacity: ${({ theme }) => theme.opacity.hover};
} }
...@@ -65,53 +60,43 @@ interface CarouselProps { ...@@ -65,53 +60,43 @@ interface CarouselProps {
toggleNextSlide: (idx: number) => void toggleNextSlide: (idx: number) => void
} }
const FIRST_CARD_OFFSET = 0 const MAX_CARD_WIDTH = 800
export const Carousel = ({ children, activeIndex, toggleNextSlide }: CarouselProps) => { export const Carousel = ({ children, activeIndex, toggleNextSlide }: CarouselProps) => {
const { width } = useWindowSize()
const carouselCardContainerRef = useRef<HTMLDivElement>(null)
const [cardWidth, setCardWidth] = useState(MAX_CARD_WIDTH)
useEffect(() => {
if (carouselCardContainerRef.current) {
setCardWidth(Math.min(carouselCardContainerRef.current.offsetWidth, MAX_CARD_WIDTH))
}
}, [width])
const idx = useCallback((x: number, l = children.length) => calculateCardIndex(x, l), [children]) const idx = useCallback((x: number, l = children.length) => calculateCardIndex(x, l), [children])
const getPos = useCallback( const getPos = useCallback(
(i: number, firstVis: number, firstVisIdx: number) => calculateFirstCardIndex(i, firstVis, firstVisIdx, idx), (i: number, firstVis: number, firstVisIdx: number) => calculateFirstCardIndex(i, firstVis, firstVisIdx, idx),
[idx] [idx]
) )
const [springs, set] = useSprings(children.length, (i) => ({ const [springs, set] = useSprings(children.length, (i) => ({
x: (i < children.length - 1 ? i : -1) * cardWidth + FIRST_CARD_OFFSET, x: (i < children.length - 1 ? i : -1) * MAX_CARD_WIDTH,
})) }))
const prev = useRef([0, 1]) const prev = useRef([0, 1])
const runSprings = useCallback( const runSprings = useCallback(
(y: number, vy: number) => { (y: number, vy: number) => {
const firstVis = idx(Math.floor(y / cardWidth) % children.length) const firstVis = idx(Math.floor(y / MAX_CARD_WIDTH) % children.length)
const firstVisIdx = vy < 0 ? children.length - 2 : 1 const firstVisIdx = vy < 0 ? children.length - 2 : 1
set((i) => { set((i) => {
const position = getPos(i, firstVis, firstVisIdx) const position = getPos(i, firstVis, firstVisIdx)
const prevPosition = getPos(i, prev.current[0], prev.current[1]) const prevPosition = getPos(i, prev.current[0], prev.current[1])
const rank = calculateRank(firstVis, firstVisIdx, position, children.length, y) const rank = calculateRank(firstVis, firstVisIdx, position, children.length, y)
return { return {
x: (-y % (cardWidth * children.length)) + cardWidth * rank + FIRST_CARD_OFFSET, x: (-y % (MAX_CARD_WIDTH * children.length)) + MAX_CARD_WIDTH * rank,
immediate: vy < 0 ? prevPosition > position : prevPosition < position, immediate: vy < 0 ? prevPosition > position : prevPosition < position,
config: { tension: 250, friction: 30 }, config: { tension: 250, friction: 35 },
} }
}) })
prev.current = [firstVis, firstVisIdx] prev.current = [firstVis, firstVisIdx]
}, },
[idx, getPos, set, cardWidth, children.length] [idx, getPos, set, children.length]
) )
const direction = useRef(0) const direction = useRef(0)
useEffect(() => { useEffect(() => {
runSprings(activeIndex * cardWidth, direction.current) runSprings(activeIndex * MAX_CARD_WIDTH, direction.current)
}, [activeIndex, cardWidth, runSprings]) }, [activeIndex, runSprings])
const toggleSlide = useCallback( const toggleSlide = useCallback(
(next: -1 | 1) => { (next: -1 | 1) => {
...@@ -135,15 +120,9 @@ export const Carousel = ({ children, activeIndex, toggleNextSlide }: CarouselPro ...@@ -135,15 +120,9 @@ export const Carousel = ({ children, activeIndex, toggleNextSlide }: CarouselPro
<CarouselItemIcon onClick={() => toggleSlide(-1)}> <CarouselItemIcon onClick={() => toggleSlide(-1)}>
<ChevronLeftIcon width="16px" height="16px" /> <ChevronLeftIcon width="16px" height="16px" />
</CarouselItemIcon> </CarouselItemIcon>
<CarouselCardContainer ref={carouselCardContainerRef}> <CarouselCardContainer>
{springs.map(({ x }, i) => ( {springs.map(({ x }, i) => (
<CarouselItemCard <CarouselItemCard key={i} style={{ x }}>
key={i}
style={{
width: cardWidth,
x,
}}
>
{children[i]} {children[i]}
</CarouselItemCard> </CarouselItemCard>
))} ))}
......
...@@ -6,7 +6,7 @@ import { VerifiedIcon } from 'nft/components/icons' ...@@ -6,7 +6,7 @@ import { VerifiedIcon } from 'nft/components/icons'
import { Markets, TrendingCollection } from 'nft/types' import { Markets, TrendingCollection } from 'nft/types'
import { formatWeiToDecimal } from 'nft/utils' import { formatWeiToDecimal } from 'nft/utils'
import styled, { useTheme } from 'styled-components/macro' import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme/components/text'
const CarouselCardContainer = styled.div` const CarouselCardContainer = styled.div`
display: flex; display: flex;
...@@ -14,13 +14,10 @@ const CarouselCardContainer = styled.div` ...@@ -14,13 +14,10 @@ const CarouselCardContainer = styled.div`
background-color: ${({ theme }) => theme.backgroundSurface}; background-color: ${({ theme }) => theme.backgroundSurface};
border: 1px solid ${({ theme }) => theme.backgroundOutline}; border: 1px solid ${({ theme }) => theme.backgroundOutline};
border-radius: 20px; border-radius: 20px;
gap: 8px;
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
@media screen and (min-width: ${({ theme }) => theme.breakpoint.lg}px) {
gap: 20px;
}
` `
const CarouselCardBorder = styled.div` const CarouselCardBorder = styled.div`
width: 100%; width: 100%;
position: relative; position: relative;
...@@ -58,12 +55,6 @@ const CarouselCardBorder = styled.div` ...@@ -58,12 +55,6 @@ const CarouselCardBorder = styled.div`
const CardHeaderContainer = styled.div<{ src: string }>` const CardHeaderContainer = styled.div<{ src: string }>`
position: relative; position: relative;
width: 100%;
height: 108px;
padding-top: 32px;
padding-bottom: 16px;
padding-left: 28px;
padding-right: 28px;
background-image: ${({ src }) => `url(${src})`}; background-image: ${({ src }) => `url(${src})`};
background-size: cover; background-size: cover;
background-position: center; background-position: center;
...@@ -71,12 +62,6 @@ const CardHeaderContainer = styled.div<{ src: string }>` ...@@ -71,12 +62,6 @@ const CardHeaderContainer = styled.div<{ src: string }>`
const LoadingCardHeaderContainer = styled.div` const LoadingCardHeaderContainer = styled.div`
position: relative; position: relative;
width: 100%;
height: 108px;
padding-top: 32px;
padding-bottom: 16px;
padding-left: 28px;
padding-right: 28px;
animation: ${loadingAnimation} 1.5s infinite; animation: ${loadingAnimation} 1.5s infinite;
animation-fill-mode: both; animation-fill-mode: both;
background: linear-gradient( background: linear-gradient(
...@@ -89,15 +74,15 @@ const LoadingCardHeaderContainer = styled.div` ...@@ -89,15 +74,15 @@ const LoadingCardHeaderContainer = styled.div`
background-size: 400%; background-size: 400%;
` `
const CardHeaderRow = styled.div` const CardHeaderColumn = styled.div`
position: relative; position: relative;
z-index: 1;
display: flex; display: flex;
gap: 8px; flex: 1;
align-items: center; align-items: center;
@media screen and (min-width: ${({ theme }) => theme.breakpoint.lg}px) { flex-direction: column;
gap: 12px; gap: 8px;
} padding: 40px;
z-index: 1;
` `
const CardNameRow = styled.div` const CardNameRow = styled.div`
...@@ -126,7 +111,7 @@ const LoadingCollectionNameContainer = styled(LoadingBubble)` ...@@ -126,7 +111,7 @@ const LoadingCollectionNameContainer = styled(LoadingBubble)`
const HeaderOverlay = styled.div` const HeaderOverlay = styled.div`
position: absolute; position: absolute;
height: 108px; bottom: 0px;
top: 0px; top: 0px;
right: 0px; right: 0px;
left: 0px; left: 0px;
...@@ -135,16 +120,16 @@ const HeaderOverlay = styled.div` ...@@ -135,16 +120,16 @@ const HeaderOverlay = styled.div`
` `
const CollectionImage = styled.img` const CollectionImage = styled.img`
width: 60px; width: 86px;
height: 60px; height: 86px;
background: ${({ theme }) => theme.accentTextLightPrimary}; background: ${({ theme }) => theme.accentTextLightPrimary};
border: 2px solid ${({ theme }) => theme.accentTextLightPrimary}; border: 2px solid ${({ theme }) => theme.accentTextLightPrimary};
border-radius: 100px; border-radius: 100px;
` `
const LoadingCollectionImage = styled.div` const LoadingCollectionImage = styled.div`
width: 60px; width: 86px;
height: 60px; height: 86px;
border-radius: 100px; border-radius: 100px;
animation: ${loadingAnimation} 1.5s infinite; animation: ${loadingAnimation} 1.5s infinite;
animation-fill-mode: both; animation-fill-mode: both;
...@@ -158,44 +143,42 @@ const LoadingCollectionImage = styled.div` ...@@ -158,44 +143,42 @@ const LoadingCollectionImage = styled.div`
background-size: 400%; background-size: 400%;
` `
const CardBottomContainer = styled.div` const LoadingTableElement = styled(LoadingBubble)`
display: grid; width: 50px;
grid-template-columns: auto auto auto; `
row-gap: 8px;
column-gap: 20px; const TableElement = styled.div`
padding-right: 28px; display: flex;
padding-left: 28px; align-items: center;
padding-bottom: 20px; gap: 6px;
justify-content: space-between; `
@media only screen and (min-width: ${({ theme }) => `${theme.breakpoint.lg}px`}) { const FirstColumnTextWrapper = styled.div`
row-gap: 16px; @media (min-width: ${({ theme }) => theme.breakpoint.sm}px) and (max-width: ${({ theme }) => theme.breakpoint.lg}px) {
display: none;
} }
}
` `
const HeaderRow = styled.div` const CardBottomContainer = styled.div`
color: ${({ theme }) => theme.userThemeColor}; display: grid;
font-size: 14px; flex: 1;
font-weight: 500; gap: 8px;
line-height: 20px; grid-template-columns: auto auto auto;
row-gap: 8px; padding: 16px 16px 20px;
@media only screen and (min-width: ${({ theme }) => `${theme.breakpoint.lg}px`}) { ${TableElement}:nth-child(3n-1), ${LoadingTableElement}:nth-child(3n-1) {
font-size: 16px; justify-self: center;
line-height: 24px;
row-gap: 12px;
} }
`
const LoadingTableElement = styled(LoadingBubble)` ${TableElement}:nth-child(3n), ${LoadingTableElement}:nth-child(3n) {
width: 50px; justify-self: right;
}
` `
const TableElement = styled.div` const MarketplaceIcon = styled.img`
color: ${({ theme }) => theme.textSecondary}; width: 20px;
font-size: 14px; height: 20px;
font-weight: 400;
line-height: 20px;
` `
interface MarketplaceRowProps { interface MarketplaceRowProps {
...@@ -207,12 +190,23 @@ interface MarketplaceRowProps { ...@@ -207,12 +190,23 @@ interface MarketplaceRowProps {
export const MarketplaceRow = ({ marketplace, floorInEth, listings }: MarketplaceRowProps) => { export const MarketplaceRow = ({ marketplace, floorInEth, listings }: MarketplaceRowProps) => {
return ( return (
<> <>
<TableElement>{marketplace}</TableElement>
<TableElement> <TableElement>
{floorInEth !== undefined ? formatNumberOrString(floorInEth, NumberType.NFTTokenFloorPriceTrailingZeros) : '-'}{' '} <MarketplaceIcon src={`/nft/svgs/marketplaces/${marketplace}-grey.svg`} alt={`${marketplace} icon`} />
<FirstColumnTextWrapper>
<ThemedText.BodySmall color="textSecondary">{marketplace}</ThemedText.BodySmall>
</FirstColumnTextWrapper>
</TableElement>
<TableElement>
<ThemedText.BodySmall color="textSecondary">
{floorInEth !== undefined
? formatNumberOrString(floorInEth, NumberType.NFTTokenFloorPriceTrailingZeros)
: '-'}{' '}
ETH ETH
</ThemedText.BodySmall>
</TableElement>
<TableElement>
<ThemedText.BodySmall color="textSecondary">{listings ?? '-'}</ThemedText.BodySmall>
</TableElement> </TableElement>
<TableElement>{listings ?? '-'}</TableElement>
</> </>
) )
} }
...@@ -238,9 +232,22 @@ export const CarouselCard = ({ collection, onClick }: CarouselCardProps) => { ...@@ -238,9 +232,22 @@ export const CarouselCard = ({ collection, onClick }: CarouselCardProps) => {
<CarouselCardHeader collection={collection} /> <CarouselCardHeader collection={collection} />
<CardBottomContainer> <CardBottomContainer>
<> <>
<HeaderRow>Uniswap</HeaderRow> <TableElement>
<HeaderRow>{formatWeiToDecimal(collection.floor.toString())} ETH Floor</HeaderRow> <MarketplaceIcon src="/nft/svgs/marketplaces/uniswap-magenta.svg" alt="Uniswap icon" />
<HeaderRow>{gqlCollection.marketplaceCount?.reduce((acc, cur) => acc + cur.count, 0)} Listings</HeaderRow> <FirstColumnTextWrapper>
<ThemedText.SubHeaderSmall color="userThemeColor">Uniswap</ThemedText.SubHeaderSmall>
</FirstColumnTextWrapper>
</TableElement>
<TableElement>
<ThemedText.SubHeaderSmall color="userThemeColor">
{formatWeiToDecimal(collection.floor.toString())} ETH Floor
</ThemedText.SubHeaderSmall>
</TableElement>
<TableElement>
<ThemedText.SubHeaderSmall color="userThemeColor">
{gqlCollection.marketplaceCount?.reduce((acc, cur) => acc + cur.count, 0)} Listings
</ThemedText.SubHeaderSmall>
</TableElement>
{MARKETS_TO_CHECK.map((market) => { {MARKETS_TO_CHECK.map((market) => {
const marketplace = gqlCollection.marketplaceCount?.find( const marketplace = gqlCollection.marketplaceCount?.find(
(marketplace) => marketplace.marketplace === market (marketplace) => marketplace.marketplace === market
...@@ -280,7 +287,7 @@ const CarouselCardHeader = ({ collection }: { collection: TrendingCollection }) ...@@ -280,7 +287,7 @@ const CarouselCardHeader = ({ collection }: { collection: TrendingCollection })
const theme = useTheme() const theme = useTheme()
return ( return (
<CardHeaderContainer src={collection.bannerImageUrl}> <CardHeaderContainer src={collection.bannerImageUrl}>
<CardHeaderRow> <CardHeaderColumn>
<CollectionImage src={collection.imageUrl} /> <CollectionImage src={collection.imageUrl} />
<CardNameRow> <CardNameRow>
<CollectionNameContainer> <CollectionNameContainer>
...@@ -294,7 +301,7 @@ const CarouselCardHeader = ({ collection }: { collection: TrendingCollection }) ...@@ -294,7 +301,7 @@ const CarouselCardHeader = ({ collection }: { collection: TrendingCollection })
</IconContainer> </IconContainer>
)} )}
</CardNameRow> </CardNameRow>
</CardHeaderRow> </CardHeaderColumn>
<HeaderOverlay /> <HeaderOverlay />
</CardHeaderContainer> </CardHeaderContainer>
) )
...@@ -308,10 +315,10 @@ export const LoadingCarouselCard = ({ collection }: { collection?: TrendingColle ...@@ -308,10 +315,10 @@ export const LoadingCarouselCard = ({ collection }: { collection?: TrendingColle
<CarouselCardHeader collection={collection} /> <CarouselCardHeader collection={collection} />
) : ( ) : (
<LoadingCardHeaderContainer> <LoadingCardHeaderContainer>
<CardHeaderRow> <CardHeaderColumn>
<LoadingCollectionImage /> <LoadingCollectionImage />
<LoadingCollectionNameContainer /> <LoadingCollectionNameContainer />
</CardHeaderRow> </CardHeaderColumn>
<HeaderOverlay /> <HeaderOverlay />
</LoadingCardHeaderContainer> </LoadingCardHeaderContainer>
)} )}
......
...@@ -12,7 +12,6 @@ const TextWrapper = styled(Text)<{ color: keyof string }>` ...@@ -12,7 +12,6 @@ const TextWrapper = styled(Text)<{ color: keyof string }>`
type TextProps = Omit<TextPropsOriginal, 'css'> type TextProps = Omit<TextPropsOriginal, 'css'>
// todo: export each component individually // todo: export each component individually
export const ThemedText = { export const ThemedText = {
// todo: there should be just one `Body` with default color, no need to make all variations // todo: there should be just one `Body` with default color, no need to make all variations
BodyPrimary(props: TextProps) { BodyPrimary(props: TextProps) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment