1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 01:47:00 +01:00

Multichain Activity Screen (#19557)

* layout wip

* Icon changes, add badgewrapped icons to smart tx

* grouping by date wip

* typo fix

* group txs by date, button styling

* removing queue/history division, adding datestamp for pending tx, minor styling changes

* adding tests, updating snap

* font size fix

* e2e fixes

* Remove unnecessary tabIndex and keypress handler

* Fix typo for fontWeight

* Fix nesting warning by removing unnecessary Text

* Fix tests

* Fix import and exports

* Remove unused verbiage

* Update E2E selectors

* More E2E

* More E2Es

* More test fixes

* awaiting find instead of click

* adding regularDelayMs to flaky test

* removing delay

* increasing delay outside of wait

* adding back first-child to selector

* test fixes

* using datatestid for primary currency

* sorting date txgroups

* wip alignment for big numbers

* alignment issues fix

* lintfix

* adding tabindex, cursor pointer, updating snap

* unit test fix

* storybook additions

* snaphot update

* update snap

---------

Co-authored-by: David Walsh <davidwalsh83@gmail.com>
This commit is contained in:
vthomas13 2023-07-17 13:48:15 -04:00 committed by GitHub
parent ea589a6e5c
commit 4dcde1e216
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
85 changed files with 813 additions and 414 deletions

View File

@ -545,9 +545,6 @@
"privateNetwork": {
"message": "የግል አውታረ መረብ"
},
"queue": {
"message": "ወረፋ"
},
"readdToken": {
"message": "በመለያ አማራጮችዎ ምናሌ ውስጥ ወደ “ተለዋጭ ስም አክል” በመግባት ለወደፊቱ ይህን ተለዋጭ ስም መልሰው ማከል ይችላሉ።"
},

View File

@ -557,9 +557,6 @@
"privateNetwork": {
"message": "شبكة خاصة"
},
"queue": {
"message": "اللائحة"
},
"readdToken": {
"message": "يمكنك إضافة هذه العملة الرمزية مرة أخرى في المستقبل من خلال الانتقال إلى \"إضافة عملة رمزية\" في قائمة خيارات الحسابات الخاصة بك."
},

View File

@ -556,9 +556,6 @@
"privateNetwork": {
"message": "Частна мрежа"
},
"queue": {
"message": "Опашка"
},
"readdToken": {
"message": "Можете да добавите този жетон в бъдеще, като отидете на „Добавяне на жетон“ в менюто с опции на акаунти."
},

View File

@ -554,9 +554,6 @@
"privateNetwork": {
"message": "ব্যক্তিগত নেটওয়ার্ক"
},
"queue": {
"message": "অপেক্ষমাণ"
},
"readdToken": {
"message": "আপনি আপনার অ্যাকাউন্টস বিকল্পের মেনুতে \"টোকেনগুলি যোগ করুন\" এ গিয়ে ভবিষ্যতে আবার এই টোকেনটি যোগ করতে পারবেন। "
},

View File

@ -541,9 +541,6 @@
"privateNetwork": {
"message": "Xarxa privada"
},
"queue": {
"message": "Cua"
},
"readdToken": {
"message": "Pots tornar a afegir aquesta fitxa en el futur anant a \"Afegir fitxa\" al menu d'opcions dels teus comptes."
},

View File

@ -541,9 +541,6 @@
"privateNetwork": {
"message": "Privat netværk"
},
"queue": {
"message": "Kø"
},
"readdToken": {
"message": "Du kan tilføje denne token i fremtiden, ved at gå til \"Tilføj token\" under dine valgmenuen for dine konti."
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Öffentliche Adresse"
},
"queue": {
"message": "Warteschlange"
},
"queued": {
"message": "In Warteschlange"
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Δημόσια Διεύθυνση"
},
"queue": {
"message": "Ουρά"
},
"queued": {
"message": "Σε Αναμονή"
},

View File

@ -3341,9 +3341,6 @@
"publicAddress": {
"message": "Public address"
},
"queue": {
"message": "Queue"
},
"queued": {
"message": "Queued"
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Dirección pública"
},
"queue": {
"message": "Cola"
},
"queued": {
"message": "En cola"
},

View File

@ -1767,9 +1767,6 @@
"publicAddress": {
"message": "Dirección pública"
},
"queue": {
"message": "Cola"
},
"queued": {
"message": "En cola"
},

View File

@ -550,9 +550,6 @@
"privateNetwork": {
"message": "Privaatvõrk"
},
"queue": {
"message": "Järjekord"
},
"readdToken": {
"message": "Saate selle loa tulevikus tagasi lisada, kui lähete oma kontovalikute menüüs vahelehele „Lisa luba“."
},

View File

@ -560,9 +560,6 @@
"privateNetwork": {
"message": "شبکه شخصی"
},
"queue": {
"message": "صف"
},
"readdToken": {
"message": "شما میتوانید این رمزیاب را دوباره برای آینده با رفتن به گزینه \"Add token\" در مینوی تنظیمات حساب ها، اضافه نمایید."
},

View File

@ -557,9 +557,6 @@
"privateNetwork": {
"message": "Yksityinen verkko"
},
"queue": {
"message": "Jono"
},
"readdToken": {
"message": "Voit lisätä tämän tietueen myöhemmin takaisin siirtymällä tilisi vaihtoehtovalikon kohtaan ”Lisää tietue”."
},

View File

@ -484,9 +484,6 @@
"privateNetwork": {
"message": "Pribadong Network"
},
"queue": {
"message": "I-queue"
},
"readdToken": {
"message": "Puwede mong idagdag ulit ang token na ito sa hinaharap sa pamamagitan ng pagpunta sa “Magdagdag ng token” sa menu ng mga opsyon ng iyong mga accounts."
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Adresse publique"
},
"queue": {
"message": "File dattente"
},
"queued": {
"message": "En attente"
},

View File

@ -103,9 +103,6 @@
"password": {
"message": "પાસવર્ડ"
},
"queue": {
"message": "કતારમાં"
},
"reject": {
"message": "નકારો"
},

View File

@ -557,9 +557,6 @@
"privateNetwork": {
"message": "רשת פרטית"
},
"queue": {
"message": "תור"
},
"readdToken": {
"message": "באפשרותך להוסיף טוקן זה בחזרה בעתיד על ידי מעבר אל \"הוסף טוקן\" בתפריט אפשרויות החשבונות שלך."
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "सार्वजनिक पता"
},
"queue": {
"message": "कतार"
},
"queued": {
"message": "कतारबद्ध"
},

View File

@ -553,9 +553,6 @@
"privateNetwork": {
"message": "Privatna mreža"
},
"queue": {
"message": "Red čekanja"
},
"readdToken": {
"message": "Ovaj token možete dodati kasnije odlaskom pod stavku „Dodaj token” u izborniku mogućnosti računa. "
},

View File

@ -553,9 +553,6 @@
"privateNetwork": {
"message": "Magánhálózat"
},
"queue": {
"message": "Nyomtatólista"
},
"readdToken": {
"message": "Ezt a tokent a jövőben is hozzáadhatja, ha a fiókbeállítások menü „Token hozzáadása” elemére lép."
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Alamat publik"
},
"queue": {
"message": "Antrean"
},
"queued": {
"message": "Antrean"
},

View File

@ -1301,9 +1301,6 @@
"provide": {
"message": "Fornisci"
},
"queue": {
"message": "Coda"
},
"queued": {
"message": "In coda"
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "パブリックアドレス"
},
"queue": {
"message": "キュー"
},
"queued": {
"message": "キュー待ち"
},

View File

@ -560,9 +560,6 @@
"privateNetwork": {
"message": "ಖಾಸಗಿ ನೆಟ್‌ವರ್ಕ್"
},
"queue": {
"message": "ಸರತಿ"
},
"readdToken": {
"message": "ನಿಮ್ಮ ಖಾತೆಗಳ ಆಯ್ಕೆಗಳ ಮೆನುವಿನಲ್ಲಿ \"ಟೋಕನ್ ಸೇರಿಸು\" ಗೆ ಹೋಗುವ ಮೂಲಕ ನೀವು ಈ ಟೋಕನ್ ಅನ್ನು ಭವಿಷ್ಯದಲ್ಲಿ ಮರಳಿ ಸೇರಿಸಬಹುದು."
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "공개 주소"
},
"queue": {
"message": "대기열"
},
"queued": {
"message": "대기열에 지정됨"
},

View File

@ -560,9 +560,6 @@
"privateNetwork": {
"message": "Privatus tinklas"
},
"queue": {
"message": "Eilė"
},
"readdToken": {
"message": "Šį žetoną galite bet kada galite įtraukti ir vėl, tiesiog savo paskyros parinkčių meniu nueikite į „Įtraukti žetoną“."
},

View File

@ -556,9 +556,6 @@
"privateNetwork": {
"message": "Privātais tīkls"
},
"queue": {
"message": "Rinda"
},
"readdToken": {
"message": "Jūs varat šo marķieri iestatīt atpakaļ nākotnē, konta opciju izvēlnē atverot \"Pievienot marķieri\"."
},

View File

@ -103,9 +103,6 @@
"password": {
"message": "പാസ്‌വേഡ്"
},
"queue": {
"message": "ക്യൂവിൽ"
},
"reject": {
"message": "നിരസിക്കുക"
},

View File

@ -103,9 +103,6 @@
"password": {
"message": "पासवर्ड"
},
"queue": {
"message": "रांग"
},
"reject": {
"message": "नाकारा"
},

View File

@ -540,9 +540,6 @@
"privateNetwork": {
"message": "Rangkaian Persendirian"
},
"queue": {
"message": "Baris Gilir"
},
"readdToken": {
"message": "Anda boleh tambah token ini kembali pada masa depan dengan pergi ke \"Tambah token\" di dalam menu pilihan akaun anda."
},

View File

@ -544,9 +544,6 @@
"privateNetwork": {
"message": "Privat nettverk "
},
"queue": {
"message": "Kø"
},
"readdToken": {
"message": "Du kan legge til dette tokenet igjen i fremtiden ved å gå til \"Legg til token\" i menyen for kontoalternativer."
},

View File

@ -1105,9 +1105,6 @@
"publicAddress": {
"message": "Pampublikong Address"
},
"queue": {
"message": "Queue"
},
"queued": {
"message": "Naka-queue"
},

View File

@ -554,9 +554,6 @@
"privateNetwork": {
"message": "Sieć prywatna"
},
"queue": {
"message": "Kolejka"
},
"readdToken": {
"message": "Możesz później ponownie dodać ten token poprzez \"Dodaj token\" w opcjach menu swojego konta."
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Endereço público"
},
"queue": {
"message": "Fila"
},
"queued": {
"message": "Na fila"
},

View File

@ -1767,9 +1767,6 @@
"publicAddress": {
"message": "Endereço público"
},
"queue": {
"message": "Fila"
},
"queued": {
"message": "Na fila"
},

View File

@ -113,9 +113,6 @@
"privacyMsg": {
"message": "Política de Privacidade"
},
"queue": {
"message": "Fila"
},
"reject": {
"message": "Rejeitar"
},

View File

@ -547,9 +547,6 @@
"privateNetwork": {
"message": "Rețea privată"
},
"queue": {
"message": "Coadă"
},
"readdToken": {
"message": "Puteți adăuga din nou acest indicativ în viitor accesând „Adăugați indicativ” din meniul de opțiuni al contului dvs."
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Открытый адрес"
},
"queue": {
"message": "Очередь"
},
"queued": {
"message": "В очереди"
},

View File

@ -532,9 +532,6 @@
"privateNetwork": {
"message": "Soukromá síť"
},
"queue": {
"message": "Poradie"
},
"readdToken": {
"message": "Tento token můžete v budoucnu přidat zpět s „Přidat token“ v nastavení účtu."
},

View File

@ -548,9 +548,6 @@
"privateNetwork": {
"message": "Zasebno omrežje"
},
"queue": {
"message": "Čakalna vrsta"
},
"readdToken": {
"message": "Ta žeton lahko dodate tudi kasneje z uporabo gumba “Dodaj žeton” v možnostih vašega računa."
},

View File

@ -551,9 +551,6 @@
"privateNetwork": {
"message": "Privatna mreža"
},
"queue": {
"message": "Ред"
},
"readdToken": {
"message": "U budućnosti možete vratiti ovaj token tako što ćete otvoriti „Dodaj token“ u meniju opcija vašeg naloga."
},

View File

@ -544,9 +544,6 @@
"privateNetwork": {
"message": "Privat nätverk"
},
"queue": {
"message": "Utskriftskö"
},
"readdToken": {
"message": "Du kan lägga till denna token i framtiden genom att välja \"Lägg till token\" i kontots alternativmeny."
},

View File

@ -538,9 +538,6 @@
"privateNetwork": {
"message": "Mtandao Binafsi"
},
"queue": {
"message": "Foleni"
},
"readdToken": {
"message": "Unaweza kuongeza tena kianzio hiki hapo baadaye kwa kwenda kwenye \"Ongeza kianzio\" kwenye machaguo yako ya menyu ya akaunti."
},

View File

@ -322,9 +322,6 @@
"privateNetwork": {
"message": "தனியார் நெட்வொர்க்"
},
"queue": {
"message": "வரிசை"
},
"readdToken": {
"message": "உங்கள் கணக்கு விருப்பங்கள் மெனுவில் \"டோக்கனைச் சேர்\" என்பதன் மூலம் நீங்கள் எதிர்காலத்தில் இந்த டோக்கனை மீண்டும் சேர்க்கலாம்."
},

View File

@ -103,9 +103,6 @@
"password": {
"message": "పాస్‌వర్డ్"
},
"queue": {
"message": "క్రమ వరుస"
},
"reject": {
"message": "తిరస్కరించు"
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Pampublikong Address"
},
"queue": {
"message": "Pila"
},
"queued": {
"message": "Naka-queue"
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Genel adres"
},
"queue": {
"message": "Kuyruğa al"
},
"queued": {
"message": "Kuyruğa alındı"
},

View File

@ -560,9 +560,6 @@
"privateNetwork": {
"message": "Приватна мережа"
},
"queue": {
"message": "Черга"
},
"readdToken": {
"message": "Ви можете знову додати цей токен у меню облікового запису у розділі “Додати токен”. "
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "Địa chỉ công khai"
},
"queue": {
"message": "Hàng đợi"
},
"queued": {
"message": "Đã đưa vào hàng đợi"
},

View File

@ -2753,9 +2753,6 @@
"publicAddress": {
"message": "公共地址"
},
"queue": {
"message": "队列"
},
"queued": {
"message": "队列中"
},

View File

@ -1051,9 +1051,6 @@
"publicAddress": {
"message": "公開位址"
},
"queue": {
"message": "佇列"
},
"queued": {
"message": "已排入佇列"
},

View File

@ -339,12 +339,12 @@ describe('MetaMask', function () {
it('finds the transaction in the transactions list', async function () {
await driver.waitForSelector({
css: '.transaction-list__completed-transactions .transaction-list-item__primary-currency',
css: '.transaction-list__completed-transactions [data-testid="transaction-list-item-primary-currency"]',
text: '-1 TST',
});
await driver.waitForSelector({
css: '.list-item__heading',
css: '[data-testid="activity-list-item-action"]',
text: 'Send TST',
});
});
@ -370,10 +370,12 @@ describe('MetaMask', function () {
await driver.findElements('.transaction-list__pending-transactions');
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-1.5 TST',
});
await driver.clickElement('.transaction-list-item__primary-currency');
await driver.clickElement(
'[data-testid="transaction-list-item-primary-currency"]',
);
await driver.delay(regularDelayMs);
const transactionAmounts = await driver.findElements(
@ -415,12 +417,12 @@ describe('MetaMask', function () {
it('finds the transaction in the transactions list', async function () {
await driver.waitForSelector({
css: '.transaction-list__completed-transactions .transaction-list-item__primary-currency',
css: '.transaction-list__completed-transactions [data-testid="transaction-list-item-primary-currency"]',
text: '-1.5 TST',
});
await driver.waitForSelector({
css: '.list-item__heading',
css: '[data-testid="activity-list-item-action"]',
text: 'Send TST',
});
});
@ -462,20 +464,20 @@ describe('MetaMask', function () {
});
await driver.switchToWindow(extension);
await driver.delay(regularDelayMs);
await driver.delay(veryLargeDelayMs);
await driver.wait(async () => {
const pendingTxes = await driver.findElements(
'.transaction-list__pending-transactions .transaction-list-item',
'.transaction-list__pending-transactions .activity-list-item',
);
return pendingTxes.length === 1;
}, 10000);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-1.5 TST',
});
await driver.clickElement('.transaction-list-item');
await driver.clickElement('.activity-list-item');
await driver.delay(regularDelayMs);
});
@ -489,12 +491,12 @@ describe('MetaMask', function () {
await driver.waitForSelector({
// Select the heading of the first transaction list item in the
// completed transaction list with text matching Send TST
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading',
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="activity-list-item-action"]',
text: 'Send TST',
});
await driver.waitForSelector({
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .transaction-list-item__primary-currency',
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="transaction-list-item-primary-currency"]',
text: '-1.5 TST',
});
});

View File

@ -132,7 +132,7 @@ describe('MV3 - Restart service worker multiple times', function () {
await driver.clickElement('[data-testid="page-container-footer-next"]');
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.findElement('.transaction-list-item');
await driver.findElement('.activity-list-item');
// reset view to assets tab
await driver.clickElement('[data-testid="home__asset-tab"]');

View File

@ -66,7 +66,7 @@ describe('ERC1155 NFTs testdapp interaction', function () {
await driver.switchToWindow(extension);
await driver.clickElement('[data-testid="home__activity-tab"]');
const transactionItem = await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Deposit',
});
assert.equal(
@ -120,7 +120,7 @@ describe('ERC1155 NFTs testdapp interaction', function () {
await driver.switchToWindow(extension);
await driver.clickElement('[data-testid="home__activity-tab"]');
const transactionItem = await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Deposit',
});
assert.equal(

View File

@ -58,7 +58,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
await driver.switchToWindow(extension);
await driver.clickElement('[data-testid="home__activity-tab"]');
const transactionItem = await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Deposit',
});
assert.equal(await transactionItem.isDisplayed(), true);
@ -169,7 +169,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
await driver.switchToWindow(extension);
await driver.clickElement('[data-testid="home__activity-tab"]');
const transactionItem = await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Deposit',
});
assert.equal(await transactionItem.isDisplayed(), true);
@ -266,7 +266,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
await driver.switchToWindow(extension);
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
// Verify transaction
@ -339,7 +339,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
// Verify transaction
const completedTx = await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Approve TDN spending cap',
});
assert.equal(await completedTx.isDisplayed(), true);
@ -405,12 +405,12 @@ describe('ERC721 NFTs testdapp interaction', function () {
await driver.switchToWindow(extension);
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
// Verify transaction
const completedTx = await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Approve TDN with no spend limit',
});
assert.equal(await completedTx.isDisplayed(), true);
@ -484,7 +484,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
// Verify transaction
const completedTx = await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Approve TDN with no spend limit',
});
assert.equal(await completedTx.isDisplayed(), true);

View File

@ -64,13 +64,13 @@ describe('Send NFT', function () {
// When transaction complete, check the send NFT is displayed in activity tab
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const sendNftItem = await driver.findElement({
css: 'h2',
css: '[data-testid="activity-list-item-action"]',
text: 'Send Test Dapp NFTs',
});
assert.equal(await sendNftItem.isDisplayed(), true);

View File

@ -122,10 +122,10 @@ const waitForTransactionToComplete = async (driver, options) => {
const checkActivityTransaction = async (driver, options) => {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector('[data-testid="list-item-title"]');
await driver.waitForSelector('.activity-list-item');
const transactionList = await driver.findElements(
'[data-testid="list-item-title"]',
'[data-testid="activity-list-item-action"]',
);
const transactionText = await transactionList[options.index].getText();
assert.equal(
@ -135,7 +135,7 @@ const checkActivityTransaction = async (driver, options) => {
);
await driver.findElement({
css: '[data-testid="list-item-right-content"]',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: `-${options.amount} ${options.swapFrom}`,
});
@ -143,8 +143,8 @@ const checkActivityTransaction = async (driver, options) => {
await driver.delay(regularDelayMs);
await driver.findElement({
css: '[data-testid="transaction-list-item-details-tx-status"]',
text: `Confirmed`,
css: '.transaction-status-label',
text: 'Confirmed',
});
await driver.findElement({

View File

@ -62,13 +62,13 @@ describe('Address Book', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-2 ETH',
});
},

View File

@ -35,11 +35,11 @@ describe('Clear account activity', function () {
// Check send transaction and receive transaction history are all displayed
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Send',
});
await driver.waitForSelector({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Receive',
});
@ -58,11 +58,11 @@ describe('Clear account activity', function () {
// Check send transaction history is cleared and receive transaction history is kept
const sendTransaction = await driver.isElementPresent({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Send',
});
const receiveTransaction = await driver.isElementPresent({
css: '.list-item__title',
css: '[data-testid="activity-list-item-action"]',
text: 'Receive',
});
assert.equal(sendTransaction, false);

View File

@ -65,10 +65,10 @@ describe('Deploy contract and call contract methods', function () {
);
await driver.clickElement({ text: 'Activity', tag: 'button' });
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-4 ETH',
});
@ -84,10 +84,10 @@ describe('Deploy contract and call contract methods', function () {
WINDOW_TITLES.ExtensionInFullScreenView,
);
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(2)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(2)',
);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-0 ETH',
});

View File

@ -178,15 +178,13 @@ describe('Create token, approve token and approve token without gas', function (
// check list of pending transactions in extension
await driver.wait(async () => {
const pendingTxes = await driver.findElements(
'.transaction-list-item',
);
const pendingTxes = await driver.findElements('.activity-list-item');
return pendingTxes.length === 1;
}, 10000);
const approveTokenTask = await driver.waitForSelector({
// Selects only the very first transaction list item immediately following the 'Pending' header
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading',
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="activity-list-item-action"]',
text: 'Approve TST spending cap',
});
assert.equal(
@ -323,14 +321,12 @@ describe('Create token, approve token and approve token without gas', function (
await driver.clickElement({ tag: 'button', text: 'Activity' });
await driver.wait(async () => {
const pendingTxes = await driver.findElements(
'.transaction-list-item',
);
const pendingTxes = await driver.findElements('.activity-list-item');
return pendingTxes.length === 1;
}, 10000);
const approveTokenTask = await driver.waitForSelector({
// Select only the heading of the first entry in the transaction list.
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading',
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="activity-list-item-action"]',
text: 'Approve TST spending cap',
});
assert.equal(
@ -374,7 +370,7 @@ describe('Create token, approve token and approve token without gas', function (
await driver.clickElement({ tag: 'button', text: 'Activity' });
const pendingTxes = await driver.findElements(
'.transaction-list__pending-transactions .transaction-list-item',
'.transaction-list__pending-transactions .activity-list-item',
);
pendingTxes[0].click();
@ -414,7 +410,7 @@ describe('Create token, approve token and approve token without gas', function (
const approveTokenTask = await driver.waitForSelector({
// Select only the heading of the first entry in the transaction list.
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading',
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="activity-list-item-action"]',
text: 'Approve TST spending cap',
});
assert.equal(
@ -459,7 +455,7 @@ describe('Create token, approve token and approve token without gas', function (
await driver.switchToWindow(extension);
await driver.clickElement({ tag: 'button', text: 'Activity' });
const pendingTxes = await driver.findElements('.transaction-list-item');
const pendingTxes = await driver.findElements('.activity-list-item');
pendingTxes[0].click();
// set custom spending cap
@ -483,7 +479,7 @@ describe('Create token, approve token and approve token without gas', function (
// check transaction in Activity tab
const approveTokenTask = await driver.waitForSelector({
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading',
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="activity-list-item-action"]',
text: 'Approve TST spending cap',
});
assert.equal(

View File

@ -80,13 +80,13 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const txValues = await driver.findElements(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
assert.equal(txValues.length, 1);
assert.ok(/-1\s*ETH/u.test(await txValues[0].getText()));
@ -165,13 +165,13 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const txValues = await driver.findElements(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
assert.equal(txValues.length, 1);
assert.ok(/-1\s*ETH/u.test(await txValues[0].getText()));
@ -254,13 +254,13 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const txValues = await driver.findElements(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
assert.equal(txValues.length, 1);
assert.ok(/-0\s*ETH/u.test(await txValues[0].getText()));

View File

@ -68,12 +68,12 @@ describe('Failing contract interaction ', function () {
await driver.switchToWindow(extension);
await driver.clickElement({ text: 'Activity', tag: 'button' });
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
// display the transaction status
const transactionStatus = await driver.findElement(
'.transaction-list-item:nth-of-type(1) .transaction-status-label',
'.activity-list-item:nth-of-type(1) .transaction-status-label',
);
assert.equal(await transactionStatus.getText(), 'Failed');
},
@ -151,12 +151,12 @@ describe('Failing contract interaction on non-EIP1559 network', function () {
await driver.switchToWindow(extension);
await driver.clickElement({ text: 'Activity', tag: 'button' });
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
// display the transaction status
const transactionStatus = await driver.findElement(
'.transaction-list-item:nth-of-type(1) .transaction-status-label',
'.activity-list-item:nth-of-type(1) .transaction-status-label',
);
assert.equal(await transactionStatus.getText(), 'Failed');
},

View File

@ -124,13 +124,13 @@ describe('Import flow', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const txValues = await driver.findElements(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
assert.equal(txValues.length, 1);
assert.ok(/-1\s*ETH/u.test(await txValues[0].getText()));

View File

@ -159,13 +159,13 @@ describe('MetaMask Responsive UI', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-1 ETH',
});
},

View File

@ -72,7 +72,7 @@ describe('Multiple transactions', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
assert.equal(confirmedTxes.length, 2);
@ -137,7 +137,7 @@ describe('Multiple transactions', function () {
// should not be present
await driver.assertElementNotPresent(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
},
);

View File

@ -68,13 +68,13 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const txValues = await driver.findElements(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
assert.equal(txValues.length, 1);
assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText()));
@ -159,13 +159,13 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const txValues = await driver.findElements(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
assert.equal(txValues.length, 1);
assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText()));

View File

@ -79,13 +79,13 @@ describe('Send ETH from inside MetaMask using default gas', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-1 ETH',
});
},
@ -199,13 +199,13 @@ describe('Send ETH from inside MetaMask using advanced gas modal', function () {
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-1 ETH',
});
},
@ -279,16 +279,16 @@ describe('Send ETH from dapp using advanced gas controls', function () {
// finds the transaction in the transactions list
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-0 ETH',
});
// the transaction has the expected gas price
const txValue = await driver.findClickableElement(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
await txValue.click();
const gasPrice = await driver.waitForSelector({
@ -363,16 +363,16 @@ describe('Send ETH from dapp using advanced gas controls', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
await driver.waitForSelector({
css: '.transaction-list-item__primary-currency',
css: '[data-testid="transaction-list-item-primary-currency"]',
text: '-0 ETH',
});
// the transaction has the expected gas value
const txValue = await driver.findClickableElement(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
await txValue.click();
const baseFeeValue = await driver.waitForSelector(
@ -432,7 +432,7 @@ describe('Send ETH from inside MetaMask to a Multisig Address', function () {
await assertAccountBalanceForDOM(driver, ganacheServer);
await driver.clickElement('[data-testid="home__activity-tab"]');
const txn = await driver.isElementPresent(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
assert.equal(txn, true);

View File

@ -50,7 +50,7 @@ describe('Send ETH to a 40 character hexadecimal address', function () {
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.clickElement('[data-testid="home__activity-tab"]');
const sendTransactionListItem = await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
await sendTransactionListItem.click();
await driver.clickElement({ text: 'Activity log', tag: 'summary' });
@ -95,7 +95,7 @@ describe('Send ETH to a 40 character hexadecimal address', function () {
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.clickElement('[data-testid="home__activity-tab"]');
const sendTransactionListItem = await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
await sendTransactionListItem.click();
await driver.clickElement({ text: 'Activity log', tag: 'summary' });
@ -166,10 +166,10 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () {
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
const sendTransactionListItem = await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
await sendTransactionListItem.click();
await driver.clickElement({ text: 'Activity log', tag: 'summary' });
@ -227,10 +227,10 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () {
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
const sendTransactionListItem = await driver.waitForSelector(
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
);
await sendTransactionListItem.click();
await driver.clickElement({ text: 'Activity log', tag: 'summary' });

View File

@ -31,13 +31,13 @@ describe('Editing Confirm Transaction', function () {
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
'.transaction-list__completed-transactions .activity-list-item',
);
return confirmedTxes.length === 1;
}, 10000);
const txValues = await driver.findElements(
'.transaction-list-item__primary-currency',
'[data-testid="transaction-list-item-primary-currency"]',
);
assert.equal(txValues.length, 1);
assert.ok(/-1\s*ETH/u.test(await txValues[0].getText()));

View File

@ -1,47 +1,56 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import Approve from '../../ui/icon/approve-icon.component';
import Interaction from '../../ui/icon/interaction-icon.component';
import Receive from '../../ui/icon/receive-icon.component';
import Send from '../../ui/icon/send-icon.component';
import Sign from '../../ui/icon/sign-icon.component';
import Swap from '../../ui/icon/swap-icon-for-list.component';
import {
TransactionGroupCategory,
TransactionGroupStatus,
TransactionStatus,
} from '../../../../shared/constants/transaction';
import { captureSingleException } from '../../../store/actions';
import { AvatarIcon, IconName } from '../../component-library';
import {
BackgroundColor,
IconColor,
Size,
} from '../../../helpers/constants/design-system';
const ICON_MAP = {
[TransactionGroupCategory.approval]: Approve,
[TransactionGroupCategory.interaction]: Interaction,
[TransactionGroupCategory.receive]: Receive,
[TransactionGroupCategory.send]: Send,
[TransactionGroupCategory.signatureRequest]: Sign,
[TransactionGroupCategory.swap]: Swap,
[TransactionGroupCategory.approval]: IconName.Check,
[TransactionGroupCategory.interaction]: IconName.ProgrammingArrows,
[TransactionGroupCategory.receive]: IconName.Received,
[TransactionGroupCategory.send]: IconName.Arrow2UpRight,
[TransactionGroupCategory.signatureRequest]: IconName.SecurityTick,
[TransactionGroupCategory.swap]: IconName.SwapHorizontal,
};
const FAIL_COLOR = 'var(--color-error-default)';
const PENDING_COLOR = 'var(--color-icon-default)';
const OK_COLOR = 'var(--color-primary-default)';
const COLOR_MAP = {
[TransactionGroupStatus.pending]: PENDING_COLOR,
[TransactionGroupStatus.cancelled]: FAIL_COLOR,
[TransactionStatus.approved]: PENDING_COLOR,
[TransactionStatus.dropped]: FAIL_COLOR,
[TransactionStatus.failed]: FAIL_COLOR,
[TransactionStatus.rejected]: FAIL_COLOR,
[TransactionStatus.submitted]: PENDING_COLOR,
[TransactionStatus.unapproved]: PENDING_COLOR,
[TransactionGroupStatus.pending]: IconColor.primaryDefault,
[TransactionGroupStatus.cancelled]: IconColor.errorDefault,
[TransactionStatus.approved]: IconColor.primaryDefault,
[TransactionStatus.dropped]: IconColor.errorDefault,
[TransactionStatus.failed]: IconColor.errorDefault,
[TransactionStatus.rejected]: IconColor.errorDefault,
[TransactionStatus.submitted]: IconColor.primaryDefault,
[TransactionStatus.unapproved]: IconColor.primaryDefault,
};
const BACKGROUND_COLOR_MAP = {
[TransactionGroupStatus.pending]: BackgroundColor.primaryMuted,
[TransactionGroupStatus.cancelled]: BackgroundColor.errorMuted,
[TransactionStatus.approved]: BackgroundColor.primaryMuted,
[TransactionStatus.dropped]: BackgroundColor.errorMuted,
[TransactionStatus.failed]: BackgroundColor.errorMuted,
[TransactionStatus.rejected]: BackgroundColor.errorMuted,
[TransactionStatus.submitted]: BackgroundColor.primaryMuted,
[TransactionStatus.unapproved]: BackgroundColor.primaryMuted,
};
export default function TransactionIcon({ status, category }) {
const dispatch = useDispatch();
const color = COLOR_MAP[status] || OK_COLOR;
const color = COLOR_MAP[status] || IconColor.primaryDefault;
const backgroundColor =
BACKGROUND_COLOR_MAP[status] || BackgroundColor.primaryMuted;
const Icon = ICON_MAP[category];
if (!Icon) {
@ -50,10 +59,22 @@ export default function TransactionIcon({ status, category }) {
`The category prop passed to TransactionIcon is not supported. The prop is: ${category}`,
),
);
return <div className="transaction-icon__grey-circle" />;
return (
<AvatarIcon
backgroundColor={BackgroundColor.backgroundAlternative}
size={Size.MD}
/>
);
}
return <Icon color={color} size={28} />;
return (
<AvatarIcon
backgroundColor={backgroundColor}
iconName={Icon}
size={Size.MD}
color={color}
/>
);
}
TransactionIcon.propTypes = {

View File

@ -23,14 +23,12 @@
}
&__pending-actions {
padding-top: 12px;
display: flex;
.button {
@include H8;
@include H6;
padding: 8px;
width: 75px;
width: 90px;
white-space: nowrap;
}
@ -57,11 +55,6 @@
text-overflow: initial;
}
.transaction-status-label::after {
content: "·";
margin: 0 4px;
}
&__address {
overflow: hidden;
text-overflow: ellipsis;

View File

@ -1,7 +1,6 @@
import React, { useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import ListItem from '../../ui/list-item';
import { useDispatch, useSelector } from 'react-redux';
import TransactionStatusLabel from '../transaction-status-label/transaction-status-label';
import TransactionIcon from '../transaction-icon';
import { useI18nContext } from '../../../hooks/useI18nContext';
@ -15,8 +14,20 @@ import {
import CancelButton from '../cancel-button';
import { cancelSwapsSmartTransaction } from '../../../ducks/swaps/swaps';
import SiteOrigin from '../../ui/site-origin';
import TransactionListItemDetails from '../transaction-list-item-details';
import { ActivityListItem } from '../../multichain';
import {
AvatarNetwork,
BadgeWrapper,
BadgeWrapperAnchorElementShape,
Box,
} from '../../component-library';
import {
BackgroundColor,
Display,
Size,
} from '../../../helpers/constants/design-system';
import { getCurrentNetwork } from '../../../selectors';
export default function SmartTransactionListItem({
smartTransaction,
@ -29,6 +40,8 @@ export default function SmartTransactionListItem({
const [showDetails, setShowDetails] = useState(false);
const { primaryCurrency, recipientAddress, isPending, senderAddress } =
useTransactionDisplayData(transactionGroup);
const currentChain = useSelector(getCurrentNetwork);
const { sourceTokenSymbol, destinationTokenSymbol, time, status } =
smartTransaction;
const category = TransactionGroupCategory.swap;
@ -36,8 +49,7 @@ export default function SmartTransactionListItem({
sourceTokenSymbol,
destinationTokenSymbol,
]);
const subtitle = 'metamask';
const date = formatDateWithYearContext(time);
const date = formatDateWithYearContext(time, 'MMM d, y', 'MMM d');
let displayedStatusKey;
if (status === SmartTransactionStatus.pending) {
displayedStatusKey = TransactionGroupStatus.pending;
@ -52,32 +64,45 @@ export default function SmartTransactionListItem({
}, []);
return (
<>
<ListItem
<ActivityListItem
className={className}
title={title}
onClick={toggleShowDetails}
icon={
<BadgeWrapper
anchorElementShape={BadgeWrapperAnchorElementShape.circular}
positionObj={{ top: -4, right: -4 }}
display={Display.Block}
badge={
<AvatarNetwork
className="activity-tx__network-badge"
data-testid="activity-tx-network-badge"
size={Size.XS}
name={currentChain?.nickname}
src={currentChain?.rpcPrefs?.imageUrl}
borderWidth={1}
borderColor={BackgroundColor.backgroundDefault}
/>
}
>
<TransactionIcon category={category} status={displayedStatusKey} />
</BadgeWrapper>
}
subtitle={
<h3>
<TransactionStatusLabel
isPending
isEarliestNonce={isEarliestNonce}
date={date}
status={displayedStatusKey}
/>
<SiteOrigin
className="transaction-list-item__origin"
siteOrigin={subtitle}
title={subtitle}
/>
</h3>
}
>
{displayedStatusKey === TransactionGroupStatus.pending &&
showCancelSwapLink && (
<div className="transaction-list-item__pending-actions">
<Box
paddingTop={4}
className="transaction-list-item__pending-actions"
>
<CancelButton
transaction={smartTransaction.uuid}
cancelTransaction={(e) => {
@ -86,9 +111,9 @@ export default function SmartTransactionListItem({
setCancelSwapLinkClicked(true);
}}
/>
</div>
</Box>
)}
</ListItem>
</ActivityListItem>
{showDetails && (
<TransactionListItemDetails
title={title}

View File

@ -1,10 +1,10 @@
/* eslint-disable import/no-duplicates */
import React, { useMemo, useState, useCallback, useContext } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';
import ListItem from '../../ui/list-item';
import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData';
import { useI18nContext } from '../../../hooks/useI18nContext';
@ -13,6 +13,23 @@ import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes';
import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp';
import TransactionStatusLabel from '../transaction-status-label/transaction-status-label';
import TransactionIcon from '../transaction-icon';
import {
BackgroundColor,
Color,
Display,
FontWeight,
Size,
TextAlign,
TextVariant,
} from '../../../helpers/constants/design-system';
import {
AvatarNetwork,
BadgeWrapper,
BadgeWrapperAnchorElementShape,
Box,
Text,
} from '../../component-library';
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
import { IconColor } from '../../../helpers/constants/design-system';
import { Icon, IconName, IconSize } from '../../component-library';
@ -31,8 +48,12 @@ import {
TransactionModalContextProvider,
useTransactionModalContext,
} from '../../../contexts/transaction-modal';
import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
import {
checkNetworkAndAccountSupports1559,
getCurrentNetwork,
} from '../../../selectors';
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util';
import { formatDateWithYearContext } from '../../../helpers/utils/util';
import Button from '../../ui/button';
import AdvancedGasFeePopover from '../advanced-gas-fee-popover';
import CancelButton from '../cancel-button';
@ -40,7 +61,7 @@ import CancelSpeedupPopover from '../cancel-speedup-popover';
import EditGasFeePopover from '../edit-gas-fee-popover';
import EditGasPopover from '../edit-gas-popover';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import SiteOrigin from '../../ui/site-origin';
import { ActivityListItem } from '../../multichain';
function TransactionListItemInner({
transactionGroup,
@ -113,9 +134,6 @@ function TransactionListItemInner({
const {
title,
subtitle,
subtitleContainsOrigin,
date,
category,
primaryCurrency,
recipientAddress,
@ -124,7 +142,11 @@ function TransactionListItemInner({
isPending,
senderAddress,
} = useTransactionDisplayData(transactionGroup);
const date = formatDateWithYearContext(
transactionGroup.primaryTransaction.time,
'MMM d, y',
'MMM d',
);
const isSignatureReq = category === TransactionGroupCategory.signatureRequest;
const isApproval = category === TransactionGroupCategory.approval;
const isUnapproved = status === TransactionStatus.unapproved;
@ -195,7 +217,7 @@ function TransactionListItemInner({
isCustodian,
///: END:ONLY_INCLUDE_IN
]);
const currentChain = useSelector(getCurrentNetwork);
let showCancelButton = !hasCancelled && isPending && !isUnapproved;
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
@ -219,14 +241,15 @@ function TransactionListItemInner({
return (
<>
<ListItem
<ActivityListItem
data-testid="activity-list-item"
onClick={toggleShowDetails}
className={className}
title={title}
icon={
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
isCustodian ? (
<div style={{ position: 'relative' }} data-testid="custody-icon">
<Box style={{ position: 'relative' }} data-testid="custody-icon">
<TransactionIcon
category={category}
status={displayedStatusKey}
@ -237,17 +260,37 @@ function TransactionListItemInner({
color={getTransactionColor(status)}
size={IconSize.Xs}
/>
</div>
</Box>
) : (
///: END:ONLY_INCLUDE_IN
<TransactionIcon category={category} status={displayedStatusKey} />
<BadgeWrapper
anchorElementShape={BadgeWrapperAnchorElementShape.circular}
positionObj={{ top: -4, right: -4 }}
display={Display.Block}
badge={
<AvatarNetwork
className="activity-tx__network-badge"
data-testid="activity-tx-network-badge"
size={Size.XS}
name={currentChain?.nickname}
src={currentChain?.rpcPrefs?.imageUrl}
borderWidth={1}
borderColor={BackgroundColor.backgroundDefault}
/>
}
>
<TransactionIcon
category={category}
status={displayedStatusKey}
/>
</BadgeWrapper>
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
)
///: END:ONLY_INCLUDE_IN
}
subtitle={
<h3>
<TransactionStatusLabel
statusOnly
isPending={isPending}
isEarliestNonce={isEarliestNonce}
error={err}
@ -260,47 +303,50 @@ function TransactionListItemInner({
}
///: END:ONLY_INCLUDE_IN
/>
{subtitleContainsOrigin ? (
<SiteOrigin siteOrigin={subtitle} />
) : (
<span className="transaction-list-item__address" title={subtitle}>
{subtitle}
</span>
)}
</h3>
}
rightContent={
!isSignatureReq &&
!isApproval && (
<>
<h2
<Text
variant={TextVariant.bodyLgMedium}
fontWeight={FontWeight.Medium}
color={Color.textDefault}
title={primaryCurrency}
className="transaction-list-item__primary-currency"
textAlign={TextAlign.Right}
data-testid="transaction-list-item-primary-currency"
className="activity-list-item__primary-currency"
ellipsis
>
{primaryCurrency}
</h2>
<h3 className="transaction-list-item__secondary-currency">
</Text>
<Text
variant={TextVariant.bodyMd}
color={Color.textAlternative}
textAlign={TextAlign.Right}
data-testid="transaction-list-item-secondary-currency"
>
{secondaryCurrency}
</h3>
</Text>
</>
)
}
>
<div className="transaction-list-item__pending-actions">
{speedUpButton}
<Box paddingTop={4} className="transaction-list-item__pending-actions">
{showCancelButton && (
<CancelButton
transaction={transactionGroup.primaryTransaction}
cancelTransaction={cancelTransaction}
/>
)}
</div>
{speedUpButton}
</Box>
{
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
<a {...debugTransactionMeta} className="test-transaction-meta" />
///: END:ONLY_INCLUDE_IN
}
</ListItem>
</ActivityListItem>
{showDetails && (
<TransactionListItemDetails
title={title}

View File

@ -10,6 +10,7 @@ import {
getTokenExchangeRates,
getPreferences,
getShouldShowFiat,
getCurrentNetwork,
} from '../../../selectors';
import {
renderWithProvider,
@ -53,7 +54,7 @@ jest.mock('react-redux', () => {
return {
...actual,
useSelector: jest.fn(),
useDispatch: () => jest.fn(),
useDispatch: jest.fn(),
};
});
@ -97,6 +98,8 @@ const generateUseSelectorRouter = (opts) => (selector) => {
};
} else if (selector === getTokenExchangeRates) {
return opts.tokenExchangeRates ?? {};
} else if (selector === getCurrentNetwork) {
return { nickname: 'Ethereum Mainnet' };
} else if (selector === getPreferences) {
return (
opts.preferences ?? {

View File

@ -14,6 +14,12 @@ import { TOKEN_CATEGORY_HASH } from '../../../helpers/constants/transactions';
import { SWAPS_CHAINID_CONTRACT_ADDRESS_MAP } from '../../../../shared/constants/swaps';
import { TransactionType } from '../../../../shared/constants/transaction';
import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils';
import { Box, Text } from '../../component-library';
import {
TextColor,
TextVariant,
} from '../../../helpers/constants/design-system';
import { formatDateWithYearContext } from '../../../helpers/utils/util';
const PAGE_INCREMENT = 10;
@ -64,6 +70,35 @@ const getFilteredTransactionGroups = (
return transactionGroups;
};
const groupTransactionsByDate = (transactionGroups) => {
const groupedTransactions = [];
transactionGroups.forEach((transactionGroup) => {
const date = formatDateWithYearContext(
transactionGroup.primaryTransaction.time,
'MMM d, y',
'MMM d',
);
const existingGroup = groupedTransactions.find(
(group) => group.date === date,
);
if (existingGroup) {
existingGroup.transactionGroups.push(transactionGroup);
} else {
groupedTransactions.push({
date,
dateMillis: transactionGroup.primaryTransaction.time,
transactionGroups: [transactionGroup],
});
}
groupedTransactions.sort((a, b) => b.dateMillis - a.dateMillis);
});
return groupedTransactions;
};
export default function TransactionList({
hideTokenTransactions,
tokenAddress,
@ -78,15 +113,30 @@ export default function TransactionList({
nonceSortedCompletedTransactionsSelector,
);
const chainId = useSelector(getCurrentChainId);
const renderDateStamp = (index, dateGroup) => {
return index === 0 ? (
<Text
paddingTop={4}
paddingInline={4}
variant={TextVariant.bodyMd}
color={TextColor.textDefault}
key={dateGroup.dateMillis}
>
{dateGroup.date}
</Text>
) : null;
};
const pendingTransactions = useMemo(
() =>
groupTransactionsByDate(
getFilteredTransactionGroups(
unfilteredPendingTransactions,
hideTokenTransactions,
tokenAddress,
chainId,
),
),
[
hideTokenTransactions,
tokenAddress,
@ -94,14 +144,17 @@ export default function TransactionList({
chainId,
],
);
const completedTransactions = useMemo(
() =>
groupTransactionsByDate(
getFilteredTransactionGroups(
unfilteredCompletedTransactions,
hideTokenTransactions,
tokenAddress,
chainId,
),
),
[
hideTokenTransactions,
tokenAddress,
@ -116,49 +169,55 @@ export default function TransactionList({
);
return (
<div className="transaction-list">
<div className="transaction-list__transactions">
<Box className="transaction-list" paddingTop={4}>
<Box className="transaction-list__transactions">
{pendingTransactions.length > 0 && (
<div className="transaction-list__pending-transactions">
<div className="transaction-list__header">
{`${t('queue')} (${pendingTransactions.length})`}
</div>
<Box className="transaction-list__pending-transactions">
{pendingTransactions
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
.sort(
(a, b) => b.primaryTransaction.time - a.primaryTransaction.time,
)
///: END:ONLY_INCLUDE_IN
.map((transactionGroup, index) => {
.map((dateGroup) => {
return dateGroup.transactionGroups.map(
(transactionGroup, index) => {
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
if (
transactionGroup.initialTransaction.transactionType ===
TransactionType.smart
) {
return (
<>
{renderDateStamp(index, dateGroup)}
<SmartTransactionListItem
isEarliestNonce={index === 0}
smartTransaction={transactionGroup.initialTransaction}
smartTransaction={
transactionGroup.initialTransaction
}
transactionGroup={transactionGroup}
key={`${transactionGroup.nonce}:${index}`}
/>
</>
);
}
///: END:ONLY_INCLUDE_IN
return (
<>
{renderDateStamp(index, dateGroup)}
<TransactionListItem
isEarliestNonce={index === 0}
transactionGroup={transactionGroup}
key={`${transactionGroup.nonce}:${index}`}
/>
</>
);
},
);
})}
</div>
</Box>
)}
<div className="transaction-list__completed-transactions">
{pendingTransactions.length > 0 ? (
<div className="transaction-list__header">{t('history')}</div>
) : null}
<Box className="transaction-list__completed-transactions">
{completedTransactions.length > 0 ? (
completedTransactions
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
@ -167,27 +226,40 @@ export default function TransactionList({
)
///: END:ONLY_INCLUDE_IN
.slice(0, limit)
.map((transactionGroup, index) =>
transactionGroup.initialTransaction?.transactionType ===
'smart' ? (
.map((dateGroup) => {
return dateGroup.transactionGroups.map(
(transactionGroup, index) => {
return (
<>
{renderDateStamp(index, dateGroup)}
{transactionGroup.initialTransaction
?.transactionType === 'smart' ? (
<SmartTransactionListItem
transactionGroup={transactionGroup}
smartTransaction={transactionGroup.initialTransaction}
smartTransaction={
transactionGroup.initialTransaction
}
key={`${transactionGroup.nonce}:${index}`}
/>
) : (
<TransactionListItem
transactionGroup={transactionGroup}
key={`${transactionGroup.nonce}:${limit + index - 10}`}
key={`${transactionGroup.nonce}:${
limit + index - 10
}`}
/>
),
)
)}
</>
);
},
);
})
) : (
<div className="transaction-list__empty">
<div className="transaction-list__empty-text">
<Box className="transaction-list__empty">
<Box className="transaction-list__empty-text">
{t('noTransactions')}
</div>
</div>
</Box>
</Box>
)}
{completedTransactions.length > limit && (
<Button
@ -198,9 +270,9 @@ export default function TransactionList({
{t('viewMore')}
</Button>
)}
</div>
</div>
</div>
</Box>
</Box>
</Box>
);
}

View File

@ -0,0 +1,99 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ActivityListItem should match snapshot with no props 1`] = `
<div>
<div
class="mm-box activity-list-item activity-list-item--single-content-row mm-box--padding-4 mm-box--display-flex mm-box--gap-4 mm-box--flex-wrap-wrap mm-box--width-full mm-box--background-color-background-default"
tabindex="0"
>
<div
class="mm-box mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--width-full"
>
<div
class="mm-box mm-box--display-inline-flex mm-box--width-full"
>
<div
class="mm-box activity-list-item__detail-container mm-box--display-inline-flex mm-box--flex-direction-column mm-box--width-1/3 mm-box--sm:width-7/12"
>
<p
class="mm-box mm-text mm-text--body-lg-medium mm-text--font-weight-medium mm-text--ellipsis mm-text--text-align-left mm-box--color-text-default"
data-testid="activity-list-item-action"
/>
</div>
</div>
</div>
</div>
</div>
`;
exports[`ActivityListItem should match snapshot with props 1`] = `
<div>
<div
class="mm-box activity-list-item list-item-test mm-box--padding-4 mm-box--display-flex mm-box--gap-4 mm-box--flex-wrap-wrap mm-box--width-full mm-box--background-color-background-default"
data-testid="test-id"
tabindex="0"
>
<p
class="mm-box mm-text mm-text--body-md mm-box--display-flex mm-box--width-full mm-box--color-text-default"
>
<p>
Content rendered at the top
</p>
</p>
<div
class="mm-box mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--width-full"
>
<div
class="mm-box mm-box--display-inline-flex"
>
<span
class="box mm-icon mm-icon--size-xs box--display-inline-block box--flex-direction-row box--color-inherit"
style="mask-image: url('./images/icons/custody.svg');"
/>
</div>
<div
class="mm-box mm-box--display-inline-flex mm-box--width-full"
>
<div
class="mm-box activity-list-item__detail-container mm-box--display-inline-flex mm-box--flex-direction-column mm-box--width-1/3 mm-box--sm:width-7/12"
>
<p
class="mm-box mm-text mm-text--body-lg-medium mm-text--font-weight-medium mm-text--ellipsis mm-text--text-align-left mm-box--color-text-default"
data-testid="activity-list-item-action"
>
Hello World
</p>
<div
class="mm-box mm-text mm-text--body-md mm-text--font-weight-normal mm-text--ellipsis mm-text--text-align-left mm-box--color-text-default"
>
<p>
I am a list item
</p>
</div>
<div
class="mm-box activity-list-item__children"
>
<button>
I am a button
</button>
</div>
</div>
<div
class="mm-box activity-list-item__mid-content mm-box--display-inline-flex"
>
<p>
Content rendered in the middle
</p>
</div>
<div
class="mm-box activity-list-item__right-content mm-box--display-inline-flex mm-box--flex-direction-column mm-box--align-items-flex-end mm-box--width-full"
>
<p>
Content rendered to the right
</p>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,137 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import {
AlignItems,
BackgroundColor,
BlockSize,
Display,
FlexDirection,
FlexWrap,
FontWeight,
TextAlign,
TextColor,
TextVariant,
} from '../../../helpers/constants/design-system';
import { Box, Text } from '../../component-library';
export const ActivityListItem = ({
topContent,
icon,
title,
subtitle,
midContent,
children,
rightContent,
onClick,
className,
'data-testid': dataTestId,
}) => {
const primaryClassName = classnames('activity-list-item', className, {
'activity-list-item--single-content-row': !(subtitle || children),
});
return (
<Box
tabIndex={0}
backgroundColor={BackgroundColor.backgroundDefault}
className={primaryClassName}
onClick={onClick}
onKeyPress={(event) => {
if (event.key === 'Enter') {
onClick();
}
}}
data-testid={dataTestId}
padding={4}
display={Display.Flex}
width={BlockSize.Full}
flexWrap={FlexWrap.Wrap}
gap={4}
>
{topContent && (
<Text
variant={TextVariant.bodyMd}
color={TextColor.textDefault}
display={Display.Flex}
width={BlockSize.Full}
>
{topContent}
</Text>
)}
<Box
display={Display.Flex}
width={BlockSize.Full}
flexDirection={FlexDirection.Row}
gap={4}
>
{icon && <Box display={Display.InlineFlex}>{icon}</Box>}
<Box display={Display.InlineFlex} width={BlockSize.Full}>
<Box
display={Display.InlineFlex}
width={[BlockSize.OneThird, BlockSize.SevenTwelfths]}
flexDirection={FlexDirection.Column}
className="activity-list-item__detail-container"
>
<Text
ellipsis
textAlign={TextAlign.Left}
variant={TextVariant.bodyLgMedium}
fontWeight={FontWeight.Medium}
data-testid="activity-list-item-action"
>
{title}
</Text>
{subtitle && (
<Text
as="div"
ellipsis
textAlign={TextAlign.Left}
variant={TextVariant.bodyMd}
fontWeight={FontWeight.Normal}
>
{subtitle}
</Text>
)}
{children && (
<Box className="activity-list-item__children">{children}</Box>
)}
</Box>
{midContent && (
<Box
display={Display.InlineFlex}
className="activity-list-item__mid-content"
>
{midContent}
</Box>
)}
{rightContent && (
<Box
display={Display.InlineFlex}
width={BlockSize.Full}
flexDirection={FlexDirection.Column}
alignItems={AlignItems.flexEnd}
className="activity-list-item__right-content"
>
{rightContent}
</Box>
)}
</Box>
</Box>
</Box>
);
};
ActivityListItem.propTypes = {
topContent: PropTypes.node,
icon: PropTypes.node,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
subtitle: PropTypes.node,
midContent: PropTypes.node,
children: PropTypes.node,
rightContent: PropTypes.node,
onClick: PropTypes.func,
className: PropTypes.string,
'data-testid': PropTypes.string,
};

View File

@ -0,0 +1,102 @@
import React from 'react';
import TransactionStatusLabel from '../../app/transaction-status-label';
import TransactionIcon from '../../app/transaction-icon';
import CancelButton from '../../app/cancel-button';
import {
BackgroundColor,
Color,
Display,
FontWeight,
Size,
TextAlign,
TextVariant,
} from '../../../helpers/constants/design-system';
import {
AvatarNetwork,
BadgeWrapper,
BadgeWrapperAnchorElementShape,
Box,
Text,
} from '../../component-library';
import { ActivityListItem } from './activity-list-item';
export default {
title: 'Components/Multichain/ActivityListItem',
component: ActivityListItem,
};
const Template = (args) => <ActivityListItem {...args} />;
export const DefaultStory = Template.bind({});
DefaultStory.args = {
'data-testid': 'activity-list-item',
onClick: () => {
console.log('clicked list item');
},
className: 'custom-class',
title: 'Activity Title',
icon: (
<BadgeWrapper
anchorElementShape={BadgeWrapperAnchorElementShape.circular}
positionObj={{ top: -4, right: -4 }}
display={Display.Block}
badge={
<AvatarNetwork
className="activity-tx__network-badge"
data-testid="activity-tx-network-badge"
size={Size.XS}
name="Network Name"
src="./images/eth_logo.png"
borderWidth={1}
borderColor={BackgroundColor.backgroundDefault}
/>
}
>
<TransactionIcon category="interaction" status="failed" />
</BadgeWrapper>
),
subtitle: (
<TransactionStatusLabel
statusOnly
isPending
isEarliestNonce
error={{}}
date={new Date().toDateString()}
status="pending"
/>
),
rightContent: (
<>
<Text
variant={TextVariant.bodyLgMedium}
fontWeight={FontWeight.Medium}
color={Color.textDefault}
title="Primary Currency"
textAlign={TextAlign.Right}
data-testid="transaction-list-item-primary-currency"
className="activity-list-item__primary-currency"
ellipsis
>
Primary Currency
</Text>
<Text
variant={TextVariant.bodyMd}
color={Color.textAlternative}
textAlign={TextAlign.Right}
data-testid="transaction-list-item-secondary-currency"
>
Secondary Currency
</Text>
</>
),
children: (
<Box paddingTop={4} className="transaction-list-item__pending-actions">
<CancelButton
transaction={{}}
cancelTransaction={() => {
console.log('canceled');
}}
/>
</Box>
),
};

View File

@ -0,0 +1,45 @@
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { Icon, IconName, IconSize } from '../../component-library';
import { ActivityListItem } from './activity-list-item';
const TITLE = 'Hello World';
const SUBTITLE = <p>I am a list item</p>;
const CLASSNAME = 'list-item-test';
const RIGHT_CONTENT = <p>Content rendered to the right</p>;
const CHILDREN = <button>I am a button</button>;
const MID_CONTENT = <p>Content rendered in the middle</p>;
const TOP_CONTENT = <p>Content rendered at the top</p>;
describe('ActivityListItem', () => {
const defaultProps = {
className: CLASSNAME,
title: TITLE,
'data-testid': 'test-id',
subtitle: SUBTITLE,
rightContent: RIGHT_CONTENT,
midContent: MID_CONTENT,
topContent: TOP_CONTENT,
icon: <Icon name={IconName.Custody} size={IconSize.Xs} />,
onClick: jest.fn(),
};
it('should match snapshot with no props', () => {
const { container } = render(<ActivityListItem />);
expect(container).toMatchSnapshot();
});
it('should match snapshot with props', () => {
const { container } = render(
<ActivityListItem {...defaultProps}>{CHILDREN}</ActivityListItem>,
);
expect(container).toMatchSnapshot();
});
it('calls onClick when clicked', () => {
const { getByTestId } = render(<ActivityListItem {...defaultProps} />);
fireEvent.click(getByTestId('test-id'));
expect(defaultProps.onClick).toHaveBeenCalled();
});
});

View File

@ -0,0 +1 @@
export { ActivityListItem } from './activity-list-item';

View File

@ -0,0 +1,11 @@
.activity-list-item {
cursor: pointer;
&__primary-currency {
max-width: 130px;
@include screen-sm-min {
max-width: max-content;
}
}
}

View File

@ -2,6 +2,7 @@ export { AccountListItem } from './account-list-item';
export { AccountListItemMenu } from './account-list-item-menu';
export { AccountListMenu } from './account-list-menu';
export { AccountPicker } from './account-picker';
export { ActivityListItem } from './activity-list-item';
export { AppHeader } from './app-header';
export { DetectedTokensBanner } from './detected-token-banner';
export { GlobalMenu } from './global-menu';

View File

@ -10,6 +10,7 @@
@import 'account-list-item-menu/index';
@import 'account-list-menu/index';
@import 'account-picker/index';
@import 'activity-list-item/index';
@import 'app-header/app-header';
@import 'connected-site-menu/index';
@import 'account-list-menu/';