From 4e7773017e1c05e191fac09e34529b656bf99311 Mon Sep 17 00:00:00 2001
From: plam-ml <127577476+plam-ml@users.noreply.github.com>
Date: Wed, 26 Jul 2023 13:48:03 -0700
Subject: [PATCH] [Explorer]: update TXN page header (#13105)
## Description
https://mysten.atlassian.net/browse/APPS-1484
![txn-ok](https://github.com/MystenLabs/sui/assets/127577476/2f5743dd-9c7c-4552-9dbb-048eb64c19e4)
![txn-error](https://github.com/MystenLabs/sui/assets/127577476/273f7246-c799-4c4e-852a-a5070c80fac8)
## Test Plan
How did you test the new or updated feature?
---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.
### Type of Change (Check all that apply)
- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration
### Release notes
---
apps/core/tailwind.config.ts | 12 ++-
.../src/components/Layout/PageLayout.tsx | 65 +++++++++----
apps/explorer/src/pages/home/Home.tsx | 51 +++++-----
.../transaction-result/TransactionResult.tsx | 36 +++++++
.../transaction-result/TransactionView.tsx | 65 +++++--------
apps/explorer/src/ui/Banner.tsx | 2 +-
apps/explorer/src/ui/Card.tsx | 2 +-
apps/explorer/src/ui/CopyToClipboard.tsx | 6 +-
apps/explorer/src/ui/PageHeader.tsx | 93 +++++++++----------
apps/explorer/src/ui/StatusIcon.tsx | 21 +++++
apps/icons/src/Copy24.tsx | 29 ++++++
apps/icons/src/ThumbDownFill12.tsx | 26 ++++++
apps/icons/src/ThumbUpFill12.tsx | 26 ++++++
apps/icons/src/index.ts | 3 +
apps/icons/svgs/copy_24.svg | 4 +
apps/icons/svgs/thumb_down_fill_12.svg | 10 ++
apps/icons/svgs/thumb_up_fill_12.svg | 10 ++
apps/ui/src/Heading.tsx | 4 +-
18 files changed, 322 insertions(+), 143 deletions(-)
create mode 100644 apps/explorer/src/ui/StatusIcon.tsx
create mode 100644 apps/icons/src/Copy24.tsx
create mode 100644 apps/icons/src/ThumbDownFill12.tsx
create mode 100644 apps/icons/src/ThumbUpFill12.tsx
create mode 100644 apps/icons/svgs/copy_24.svg
create mode 100644 apps/icons/svgs/thumb_down_fill_12.svg
create mode 100644 apps/icons/svgs/thumb_up_fill_12.svg
diff --git a/apps/core/tailwind.config.ts b/apps/core/tailwind.config.ts
index 7b09a7b26dfc8..afbd7aa83c174 100644
--- a/apps/core/tailwind.config.ts
+++ b/apps/core/tailwind.config.ts
@@ -85,7 +85,8 @@ export default {
colors: {
'gradient-blue-start': '#589AEA',
'gradient-blue-end': '#4C75A6',
- 'gradient-graph-bg-01-start': '#D2EBFA',
+ 'gradients-graph-cards-start': '#D2EBFA',
+ 'gradients-failure-start': '#FBF0FF',
},
// Line-heights that are found in the design:
lineHeight: {
@@ -105,6 +106,7 @@ export default {
drop: '0px 0px 10px rgba(111, 188, 240, 0.2)',
mistyEdge:
'0px 0px 0px 1px rgba(160, 182, 195, 0.08), 0px 5px 30px 0px rgba(86, 104, 115, 0.20)',
+ cardSoft: '1px 2px 8px 2px rgba(21, 82, 123, 0.05)',
},
fontSize: {
// Text sizes:
@@ -152,6 +154,9 @@ export default {
3.75: '0.9375rem',
4.5: '1.125rem',
7.5: '1.875rem',
+ 17: '4.25rem',
+ 18: '4.5rem',
+ 19: '4.75rem',
50: '12.5rem',
verticalListShort: '13.0625rem',
verticalListLong: '35.6875rem',
@@ -166,6 +171,8 @@ export default {
walletLogo: '4.813rem',
},
minWidth: {
+ 10: '2.5rem',
+ 18: '4.5rem',
transactionColumn: '31.875rem',
},
transitionTimingFunction: {
@@ -179,7 +186,8 @@ export default {
placeholderGradient01: 'linear-gradient(165.96deg, #e6f5ff 10%, #ebecff 95%)',
placeholderShimmer:
'linear-gradient(90deg, #ecf1f4 -24.18%, rgba(237 242 245 / 40%) 73.61%, #f3f7f9 114.81%, #ecf1f4 114.82%)',
- main: 'linear-gradient(176deg, #D2EBFA 51.68%, #D5F7EE 100%)',
+ 'gradients-graph-cards': 'linear-gradient(176deg, #D2EBFA 51.68%, #D5F7EE 100%)',
+ 'gradients-failure': 'linear-gradient(166deg, #FBF0FF 0%, #FFF0F0 100%)',
},
rotate: {
135: '135deg',
diff --git a/apps/explorer/src/components/Layout/PageLayout.tsx b/apps/explorer/src/components/Layout/PageLayout.tsx
index 5033a9475e08a..0f9c450101058 100644
--- a/apps/explorer/src/components/Layout/PageLayout.tsx
+++ b/apps/explorer/src/components/Layout/PageLayout.tsx
@@ -13,11 +13,16 @@ import { Banner } from '~/ui/Banner';
import { Network } from '~/utils/api/DefaultRpcClient';
export type PageLayoutProps = {
- gradientContent?: ReactNode;
+ gradient?: {
+ content: ReactNode;
+ size: 'lg' | 'md';
+ type?: 'success' | 'error';
+ };
content: ReactNode;
+ error?: string;
};
-export function PageLayout({ gradientContent, content }: PageLayoutProps) {
+export function PageLayout({ gradient, content }: PageLayoutProps) {
const [network] = useNetworkContext();
const { request } = useAppsBackend();
const { data } = useQuery({
@@ -31,33 +36,53 @@ export function PageLayout({ gradientContent, content }: PageLayoutProps) {
retry: false,
enabled: network === Network.MAINNET,
});
- const isGradientVisible = !!gradientContent;
+ const isGradientVisible = !!gradient;
+ const isError = gradient?.type === 'error';
+
return (
-
+
- {network === Network.MAINNET && data?.degraded && (
-
-
-
- We’re sorry that the explorer is running slower than usual. We’re
- working to fix the issue and appreciate your patience.
-
-
-
- )}
{isGradientVisible ? (
-
-
- {gradientContent}
+
+ {network === Network.MAINNET && data?.degraded && (
+
+
+
+ We’re sorry that the explorer is running slower than usual. We’re
+ working to fix the issue and appreciate your patience.
+
+
+
+ )}
+
+ {gradient.content}
) : null}
-
+
);
}
+
+//mx-auto max-w-[1440px] px-5 py-8 md:p-10
diff --git a/apps/explorer/src/pages/home/Home.tsx b/apps/explorer/src/pages/home/Home.tsx
index 73ccb26ae010d..5491a7a00bdcb 100644
--- a/apps/explorer/src/pages/home/Home.tsx
+++ b/apps/explorer/src/pages/home/Home.tsx
@@ -4,15 +4,15 @@
import clsx from 'clsx';
import { lazy, Suspense } from 'react';
-import { ErrorBoundary } from '../../components/error-boundary/ErrorBoundary';
-import { TopValidatorsCard } from '../../components/top-validators-card/TopValidatorsCard';
import { AccountsCardGraph } from '~/components/AccountCardGraph';
import { Activity } from '~/components/Activity';
import { CurrentEpoch, OnTheNetwork } from '~/components/HomeMetrics';
import { PageLayout } from '~/components/Layout/PageLayout';
import { SuiTokenCard } from '~/components/SuiTokenCard';
import { TransactionsCardGraph } from '~/components/TransactionsCardGraph';
+import { ErrorBoundary } from '~/components/error-boundary/ErrorBoundary';
import { TopPackagesCard } from '~/components/top-packages/TopPackagesCard';
+import { TopValidatorsCard } from '~/components/top-validators-card/TopValidatorsCard';
import { useNetwork } from '~/context';
import { Card } from '~/ui/Card';
import { TabHeader } from '~/ui/Tabs';
@@ -27,30 +27,33 @@ function Home() {
const isSuiTokenCardEnabled = network === Network.MAINNET;
return (
-
-
-
-
-
-
- {isSuiTokenCardEnabled ? (
-
-
+ gradient={{
+ content: (
+
+
+
+
+
+
+
+ {isSuiTokenCardEnabled ? (
+
+
+
+ ) : null}
+
+
+
+
- ) : null}
-
-
-
-
-
- }
+ ),
+ size: 'lg',
+ }}
content={
diff --git a/apps/explorer/src/pages/transaction-result/TransactionResult.tsx b/apps/explorer/src/pages/transaction-result/TransactionResult.tsx
index dc09a8683f79c..56703c4b5d7bc 100644
--- a/apps/explorer/src/pages/transaction-result/TransactionResult.tsx
+++ b/apps/explorer/src/pages/transaction-result/TransactionResult.tsx
@@ -1,6 +1,7 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
+import { getExecutionStatusError, type SuiTransactionBlockResponse } from '@mysten/sui.js';
import { LoadingIndicator } from '@mysten/ui';
import { useParams } from 'react-router-dom';
@@ -8,12 +9,47 @@ import { TransactionView } from './TransactionView';
import { PageLayout } from '~/components/Layout/PageLayout';
import { useGetTransaction } from '~/hooks/useGetTransaction';
import { Banner } from '~/ui/Banner';
+import { PageHeader } from '~/ui/PageHeader';
+import { StatusIcon } from '~/ui/StatusIcon';
+
+function TransactionResultPageHeader({
+ transaction,
+ error,
+}: {
+ transaction: SuiTransactionBlockResponse;
+ error?: string;
+}) {
+ const txnKindName = transaction.transaction?.data.transaction?.kind;
+ const txnDigest = transaction.digest;
+ const txnStatus = transaction.effects?.status.status;
+
+ const isProgrammableTransaction = txnKindName === 'ProgrammableTransaction';
+
+ return (
+
}
+ />
+ );
+}
export default function TransactionResult() {
const { id } = useParams();
const { isLoading, isError, data } = useGetTransaction(id as string);
+ const txError = data ? getExecutionStatusError(data) : undefined;
+
return (
,
+ size: 'md',
+ type: txError ? 'error' : 'success',
+ }
+ }
content={
isLoading ? (
diff --git a/apps/explorer/src/pages/transaction-result/TransactionView.tsx b/apps/explorer/src/pages/transaction-result/TransactionView.tsx
index ecbeaa6d09242..942009d057ebf 100644
--- a/apps/explorer/src/pages/transaction-result/TransactionView.tsx
+++ b/apps/explorer/src/pages/transaction-result/TransactionView.tsx
@@ -1,15 +1,9 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
-import {
- getExecutionStatusError,
- getExecutionStatusType,
- getTransactionDigest,
- getTransactionKind,
- getTransactionKindName,
- type SuiTransactionBlockResponse,
-} from '@mysten/sui.js';
+import { type SuiTransactionBlockResponse } from '@mysten/sui.js';
import clsx from 'clsx';
+import { type ReactNode } from 'react';
import { Signatures } from './Signatures';
import { ErrorBoundary } from '~/components/error-boundary/ErrorBoundary';
@@ -17,21 +11,25 @@ import { useBreakpoint } from '~/hooks/useBreakpoint';
import { Events } from '~/pages/transaction-result/Events';
import { TransactionData } from '~/pages/transaction-result/TransactionData';
import { TransactionSummary } from '~/pages/transaction-result/transaction-summary';
-import { Banner } from '~/ui/Banner';
-import { PageHeader } from '~/ui/PageHeader';
import { SplitPanes } from '~/ui/SplitPanes';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '~/ui/Tabs';
import styles from './TransactionResult.module.css';
+function TabsContentContainer({ value, children }: { value: string; children: ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
export function TransactionView({ transaction }: { transaction: SuiTransactionBlockResponse }) {
const isMediumOrAbove = useBreakpoint('md');
const hasEvents = !!transaction.events?.length;
- const txError = getExecutionStatusError(transaction);
-
- const transactionKindName = getTransactionKindName(getTransactionKind(transaction)!);
+ const transactionKindName = transaction.transaction?.data.transaction?.kind;
const isProgrammableTransaction = transactionKindName === 'ProgrammableTransaction';
@@ -44,25 +42,19 @@ export function TransactionView({ transaction }: { transaction: SuiTransactionBl
{hasEvents &&
Events}
{isProgrammableTransaction &&
Signatures}
-
-
-
-
-
+
+
+
{hasEvents && (
-
-
-
-
-
+
+
+
)}
-
-
-
-
-
-
-
+
+
+
+
+
),
@@ -84,19 +76,6 @@ export function TransactionView({ transaction }: { transaction: SuiTransactionBl
return (
-
-
- {txError && (
-
- {txError}
-
- )}
-
> = {
Transaction: 'Transaction Block',
};
-const TYPE_TO_ICON: Record = {
- Transaction: CallIcon,
+const TYPE_TO_ICON: Record = {
+ Transaction: null,
Checkpoint: Flag16,
Object: Nft16,
Package: CallIcon,
- Address: () => (
-
- ),
+ Address: null,
};
-const STATUS_TO_TEXT = {
- success: 'Success',
- failure: 'Failure',
-};
-
-export function PageHeader({ title, subtitle, type, status }: PageHeaderProps) {
+export function PageHeader({ title, subtitle, type, before, error }: PageHeaderProps) {
const Icon = TYPE_TO_ICON[type];
return (
-
-
- {Icon && }
-
- {type in TYPE_TO_COPY ? TYPE_TO_COPY[type] : type}
-
-
-
-
-
-
- {title}
-
+
+
+ {before &&
{before}
}
+
+
+
+
+ {Icon && }
+
+ {type in TYPE_TO_COPY ? TYPE_TO_COPY[type] : type}
+
+
+
+
+ {title}
+
+
+ {subtitle && (
+
+
+ {subtitle}
+
+
+ )}
+
+
+
+
-
+ {error && (
+
+ }>
+
+ {error}
+
+
+
+ )}
-
- {status && (
-
- {STATUS_TO_TEXT[status]}
-
- )}
- {subtitle && (
-
-
- {subtitle}
-
-
- )}
);
}
diff --git a/apps/explorer/src/ui/StatusIcon.tsx b/apps/explorer/src/ui/StatusIcon.tsx
new file mode 100644
index 0000000000000..8474186a67e78
--- /dev/null
+++ b/apps/explorer/src/ui/StatusIcon.tsx
@@ -0,0 +1,21 @@
+// Copyright (c) Mysten Labs, Inc.
+// SPDX-License-Identifier: Apache-2.0
+import { ThumbUpFill24, ThumbDownFill24 } from '@mysten/icons';
+import clsx from 'clsx';
+
+export function StatusIcon({ success }: { success: boolean }) {
+ const Icon = success ? ThumbUpFill24 : ThumbDownFill24;
+
+ return (
+
+ );
+}
diff --git a/apps/icons/src/Copy24.tsx b/apps/icons/src/Copy24.tsx
new file mode 100644
index 0000000000000..fd30ed86a0a2b
--- /dev/null
+++ b/apps/icons/src/Copy24.tsx
@@ -0,0 +1,29 @@
+// Copyright (c) Mysten Labs, Inc.
+// SPDX-License-Identifier: Apache-2.0
+import { SVGProps } from 'react';
+const SvgCopy24 = (props: SVGProps
) => (
+
+);
+export default SvgCopy24;
diff --git a/apps/icons/src/ThumbDownFill12.tsx b/apps/icons/src/ThumbDownFill12.tsx
new file mode 100644
index 0000000000000..de748a865c4b4
--- /dev/null
+++ b/apps/icons/src/ThumbDownFill12.tsx
@@ -0,0 +1,26 @@
+// Copyright (c) Mysten Labs, Inc.
+// SPDX-License-Identifier: Apache-2.0
+import { SVGProps } from 'react';
+const SvgThumbDownFill12 = (props: SVGProps) => (
+
+);
+export default SvgThumbDownFill12;
diff --git a/apps/icons/src/ThumbUpFill12.tsx b/apps/icons/src/ThumbUpFill12.tsx
new file mode 100644
index 0000000000000..e9fa6b761877b
--- /dev/null
+++ b/apps/icons/src/ThumbUpFill12.tsx
@@ -0,0 +1,26 @@
+// Copyright (c) Mysten Labs, Inc.
+// SPDX-License-Identifier: Apache-2.0
+import { SVGProps } from 'react';
+const SvgThumbUpFill12 = (props: SVGProps) => (
+
+);
+export default SvgThumbUpFill12;
diff --git a/apps/icons/src/index.ts b/apps/icons/src/index.ts
index ce731f06de312..477c2a3f974c8 100644
--- a/apps/icons/src/index.ts
+++ b/apps/icons/src/index.ts
@@ -57,6 +57,7 @@ export { default as Coins24 } from './Coins24';
export { default as Copy12 } from './Copy12';
export { default as Copy16 } from './Copy16';
export { default as Copy18 } from './Copy18';
+export { default as Copy24 } from './Copy24';
export { default as CopyArchiveDoNotUse16 } from './CopyArchiveDoNotUse16';
export { default as CopyArchiveDoNotUse24 } from './CopyArchiveDoNotUse24';
export { default as CopyNew24 } from './CopyNew24';
@@ -139,10 +140,12 @@ export { default as SuiTestnet } from './SuiTestnet';
export { default as Support24 } from './Support24';
export { default as Swap16 } from './Swap16';
export { default as Tag16 } from './Tag16';
+export { default as ThumbDownFill12 } from './ThumbDownFill12';
export { default as ThumbDownFill24 } from './ThumbDownFill24';
export { default as ThumbDownFill32 } from './ThumbDownFill32';
export { default as ThumbDownStroke24 } from './ThumbDownStroke24';
export { default as ThumbDownStroke32 } from './ThumbDownStroke32';
+export { default as ThumbUpFill12 } from './ThumbUpFill12';
export { default as ThumbUpFill24 } from './ThumbUpFill24';
export { default as ThumbUpFill32 } from './ThumbUpFill32';
export { default as ThumbUpStroke24 } from './ThumbUpStroke24';
diff --git a/apps/icons/svgs/copy_24.svg b/apps/icons/svgs/copy_24.svg
new file mode 100644
index 0000000000000..3f39e4e178026
--- /dev/null
+++ b/apps/icons/svgs/copy_24.svg
@@ -0,0 +1,4 @@
+
diff --git a/apps/icons/svgs/thumb_down_fill_12.svg b/apps/icons/svgs/thumb_down_fill_12.svg
new file mode 100644
index 0000000000000..212cdf422bff9
--- /dev/null
+++ b/apps/icons/svgs/thumb_down_fill_12.svg
@@ -0,0 +1,10 @@
+
diff --git a/apps/icons/svgs/thumb_up_fill_12.svg b/apps/icons/svgs/thumb_up_fill_12.svg
new file mode 100644
index 0000000000000..26fc9a1c66991
--- /dev/null
+++ b/apps/icons/svgs/thumb_up_fill_12.svg
@@ -0,0 +1,10 @@
+
diff --git a/apps/ui/src/Heading.tsx b/apps/ui/src/Heading.tsx
index 673aa2c077c86..790f209d51e0a 100644
--- a/apps/ui/src/Heading.tsx
+++ b/apps/ui/src/Heading.tsx
@@ -16,10 +16,10 @@ const headingStyles = cva([], {
size: {
heading1: 'text-heading1',
heading2: 'md:text-heading2 text-heading4',
- heading3: 'text-heading3',
+ heading3: 'md:text-heading3 text-heading6',
heading4: 'md:text-heading4 text-heading6',
heading5: 'text-heading5',
- heading6: 'text-heading6',
+ heading6: 'md:text-heading6 text-body',
},
color: {
issue: 'text-issue',