Список транзакций с анимацией переходов между типами
See the Pen transaction list with view transitions by Danny Moerkerke (@dannymoerkerke) on CodePen.
HTML
<div class="container"><div class="list-header">Transactions</div><div class="transaction-list"><div class="transaction" style="view-transition-name: transaction-1"><div class="icon-container"><div class="icon" style="view-transition-name: icon-1"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 3h18v18H3z" stroke-width="2"/><path d="M9 12h6M12 9v6" stroke-width="2" stroke-linecap="round"/></svg></div><button class="close-btn" style="view-transition-name: close-btn-1"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"><path d="M12 4L4 12M4 4l8 8" stroke-width="2" stroke-linecap="round"/></svg></button></div><div class="details"><div class="title-container" style="view-transition-name: title-container-1"><div class="title">Netflix</div><div class="subtitle">Subscription</div></div><div class="amount" style="view-transition-name: amount-1">-$6.99</div></div><div class="transaction-details" style="view-transition-name: transaction-details-1"><div class="transaction-id">#67593</div><div class="transaction-date">September 26</div><div class="transaction-time">12:01 am</div></div><div class="payment-details" style="view-transition-name: payment-details-1"><div class="payment-method">Paid Via Credit Card</div><div class="payment-info">XXXX 9342 VISA</div></div></div><div class="transaction" style="view-transition-name: transaction-2"><div class="icon-container"><div class="icon" style="view-transition-name: icon-2"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M20 10c0 4.4-8 12-8 12s-8-7.6-8-12a8 8 0 1116 0z" stroke-width="2"/><circle cx="12" cy="10" r="3" stroke-width="2"/></svg></div><button class="close-btn" style="view-transition-name: close-btn-2"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"><path d="M12 4L4 12M4 4l8 8" stroke-width="2" stroke-linecap="round"/></svg></button></div><div class="details"><div class="title-container" style="view-transition-name: title-container-2"><div class="title">Verizon</div><div class="subtitle">Mobile Recharge</div></div><div class="amount" style="view-transition-name: amount-2">-$4.05</div></div><div class="transaction-details" style="view-transition-name: transaction-details-2"><div class="transaction-id">#67482</div><div class="transaction-date">September 24</div><div class="transaction-time">05:18 pm</div></div><div class="payment-details" style="view-transition-name: payment-details-2"><div class="payment-method">Paid Via Credit Card</div><div class="payment-info">XXXX 2316 Mastercard</div></div></div><div class="transaction" style="view-transition-name: transaction-3"><div class="icon-container"><div class="icon" style="view-transition-name: icon-3"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 3h18v18H3z" stroke-width="2"/><path d="M9 12h6M12 9v6" stroke-width="2" stroke-linecap="round"/></svg></div><button class="close-btn" style="view-transition-name: close-btn-3"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"><path d="M12 4L4 12M4 4l8 8" stroke-width="2" stroke-linecap="round"/></svg></button></div><div class="details"><div class="title-container" style="view-transition-name: title-container-3"><div class="title">Rive</div><div class="subtitle">Subscription</div></div><div class="amount" style="view-transition-name: amount-3">-$32.00</div></div><div class="transaction-details" style="view-transition-name: transaction-details-3"><div class="transaction-id">#54635</div><div class="transaction-date">September 16</div><div class="transaction-time">02:11 pm</div></div><div class="payment-details" style="view-transition-name: payment-details-3"><div class="payment-method">Paid Via Credit Card</div><div class="payment-info">XXXX 9342 VISA</div></div></div><div class="transaction" style="view-transition-name: transaction-4"><div class="icon-container"><div class="icon" style="view-transition-name: icon-4"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 3h18v18H3z" stroke-width="2"/><path d="M9 12h6M12 9v6" stroke-width="2" stroke-linecap="round"/></svg></div><button class="close-btn" style="view-transition-name: close-btn-4"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"><path d="M12 4L4 12M4 4l8 8" stroke-width="2" stroke-linecap="round"/></svg></button></div><div class="details"><div class="title-container" style="view-transition-name: title-container-4"><div class="title">Figma</div><div class="subtitle">Subscription</div></div><div class="amount" style="view-transition-name: amount-4">-$15.00</div></div><div class="transaction-details" style="view-transition-name: transaction-details-4"><div class="transaction-id">#52363</div><div class="transaction-date">September 15</div><div class="transaction-time">01:11 am</div></div><div class="payment-details" style="view-transition-name: payment-details-4"><div class="payment-method">Paid Via Credit Card</div><div class="payment-info">XXXX 9342 VISA</div></div></div><div class="transaction" style="view-transition-name: transaction-5"><div class="icon-container"><div class="icon" style="view-transition-name: icon-5"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 12h18M12 3v18" stroke-width="2" stroke-linecap="round"/></svg></div><button class="close-btn" style="view-transition-name: close-btn-5"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"><path d="M12 4L4 12M4 4l8 8" stroke-width="2" stroke-linecap="round"/></svg></button></div><div class="details"><div class="title-container" style="view-transition-name: title-container-5"><div class="title">Big Belly Burger</div><div class="subtitle">Restaurant</div></div><div class="amount" style="view-transition-name: amount-5">-$12.05</div></div><div class="transaction-details" style="view-transition-name: transaction-details-5"><div class="transaction-id">#52342</div><div class="transaction-date">September 12</div><div class="transaction-time">09:06 am</div></div><div class="payment-details" style="view-transition-name: payment-details-5"><div class="payment-method">Paid Via Credit Card</div><div class="payment-info">XXXX 2316 Mastercard</div></div></div></div><div class="all-transactions">All Transactions →</div></div>
CSS
body {font-family: system-ui, -apple-system, sans-serif;background: #fafafa;display: flex;justify-content: center;align-items: center;height: 100vh;}.container {background: white;border-radius: 24px;padding: 16px 12px;box-shadow: 0 2px 4px rgba(0,0,0,0.05);view-transition-name: container;width: 400px;height: fit-content;}.list-header {font-size: 20px;font-weight: 500;color: #18181b;margin-bottom: 24px;padding-left: 12px;view-transition-name: list-header;height: fit-content;overflow: hidden;}.close-button {display: none;justify-content: flex-end;view-transition-name: close-button;}.not-expanded {view-transition-class: not-expanded;* {view-transition-class: not-expanded;}}.container:has(.not-expanded) :is(.list-header, .all-transactions) {view-transition-class: not-expanded;}.container:has(.expanded) {.list-header {display: none;}.close-button {display: flex;}.all-transactions {display: none;}.transaction:not(.expanded) {display: none;}}.transaction-list {display: flex;flex-direction: column;gap: 16px;view-transition-name: transaction-list;}.transaction {display: flex;align-items: center;gap: 12px;padding: 0 12px;border-radius: 16px;cursor: pointer;&.expanded {flex-direction: column;align-items: flex-start;background: #ffffff;.transaction-details,.payment-details {display: flex;}.icon-container {width: 100%;.close-btn {display: flex;}}}}.title-container {display: flex;flex-direction: column;gap: 4px;}.icon-container {display: flex;justify-content: space-between;}.icon {width: 40px;height: 40px;background: #18181b;border-radius: 12px;display: grid;place-items: center;}.icon svg {width: 20px;height: 20px;color: white;}.details {display: flex;flex-direction: row;justify-content: space-between;flex: 1;width: 100%;}.title {font-weight: 500;color: #18181b;margin-bottom: 4px;}.subtitle {font-size: 14px;color: #71717a;}.amount {font-weight: 500;color: #71717a;}.transaction-details,.payment-details {display: flex;flex-direction: column;gap: 6px;color: #71717a;border-top: 1px dotted #71717a;padding-top: 6px;width: 100%;display: none;}.transaction-details {view-transition-class: transaction-details;}.payment-details {view-transition-class: payment-details;}.all-transactions {display: flex;align-items: center;justify-content: center;padding: 16px;color: #18181b;font-weight: 500;margin-top: 8px;cursor: pointer;view-transition-name: all-transactions;}.close-btn {width: 32px;height: 32px;border: none;background: #f4f4f5;border-radius: 50%;cursor: pointer;display: none;align-items: center;justify-content: center;}@keyframes slide-up {from {opacity: 0;margin-top: 30px;}to {opacity: 1;margin-top: 0;}}@keyframes fade-out {0% {opacity: 1;}50% {opacity: 0;}100% {opacity: 0;}}@keyframes squash {0% {transform: scaleY(1);}100% {transform: scaleY(0);}}::view-transition-group(*) {animation-duration: 0.4s;animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1);}::view-transition-old(*),::view-transition-new(*) {height: 100%;}html:active-view-transition-type(expand) {&::view-transition-group(.transaction-details),&::view-transition-group(.payment-details) {animation-name: slide-up;animation-duration: 0.5s;}}html:active-view-transition-type(collapse) {&::view-transition-group(.transaction-details),&::view-transition-group(.payment-details) {animation-name: fade-out;}}::view-transition-group(.not-expanded) {animation-name: fade-out;}
JS
const container = document.querySelector('.container');let currentTransaction = null;container.addEventListener('click', (e) => {const transaction = e.target.closest('.transaction');const closeBtn = e.target.closest('.close-btn');if (closeBtn) {const expandedTransaction = document.querySelector('.transaction.expanded');const otherTransactions = [...document.querySelectorAll('.transaction')].filter(t => t !== expandedTransaction);otherTransactions.forEach(t => t.classList.remove('not-expanded'));if(expandedTransaction) {document.startViewTransition({update: () => {expandedTransaction.classList.remove('expanded');},types: ['collapse']});}return;}else if(transaction) {if(!transaction.classList.contains('expanded')) {const otherTransactions = [...document.querySelectorAll('.transaction')].filter(t => t !== transaction);otherTransactions.forEach(t => t.classList.add('not-expanded'));document.startViewTransition({update: () => {transaction.classList.add('expanded');},types: ['expand']});}}});
transaction-list-with-view-transitions.zip
0
29.7 Kb
Нашли ошибку? Сообщите нам, мы исправим!
Комментариев нет
Чтобы оставить комментарий, необходимо на сайте.
Копирование запрещено!