Skip to content

Commit 4745786

Browse files
committed
[NEB-54] Nebula: Improved Transaction action UI (#5931)
1 parent 3cb1ab9 commit 4745786

File tree

9 files changed

+417
-130
lines changed

9 files changed

+417
-130
lines changed

apps/dashboard/src/@/styles/globals.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ input:-webkit-autofill:active {
157157
transition: background-color 5000s ease-in-out 0s;
158158
}
159159

160+
.shiki,
161+
.shiki span {
162+
background-color: var(--background) !important;
163+
}
164+
160165
.dark .shiki,
161166
.dark .shiki span {
162167
color: var(--shiki-dark) !important;

apps/dashboard/src/app/nebula-app/(app)/components/ChatPageContent.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export function ChatPageContent(props: {
4343
try {
4444
const content = JSON.parse(message.content) as {
4545
session_id: string;
46-
request_id: string;
4746
data: string;
4847
type: "sign_transaction" | (string & {});
4948
};

apps/dashboard/src/app/nebula-app/(app)/components/ChatSidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export function ChatSidebar(props: {
7979
</ScrollShadow>
8080
)}
8181

82-
<div className="mb-2">
82+
<div className="mb-3 border-b border-dashed pt-2 pb-3">
8383
<SidebarIconLink
8484
href="https://portal.thirdweb.com/changelog"
8585
icon={TextIcon}

apps/dashboard/src/app/nebula-app/(app)/components/Chats.stories.tsx

Lines changed: 99 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { getThirdwebClient } from "@/constants/thirdweb.server";
22
import type { Meta, StoryObj } from "@storybook/react";
33
import { Toaster } from "sonner";
4+
import { ConnectButton, ThirdwebProvider } from "thirdweb/react";
45
import { accountStub, randomLorem } from "../../../../stories/stubs";
56
import { BadgeContainer, mobileViewport } from "../../../../stories/utils";
6-
import { Chats } from "./Chats";
7+
import { type ChatMessage, Chats } from "./Chats";
78

89
const meta = {
910
title: "Nebula/Chats",
@@ -139,13 +140,14 @@ ${markdownExample}
139140

140141
function Story() {
141142
return (
142-
<div className="container flex max-w-[800px] flex-col gap-14 py-10">
143-
<BadgeContainer label="User + Presence">
144-
<Chats
145-
authToken="xxxxx"
146-
isChatStreaming={false}
147-
sessionId="xxxxx"
148-
twAccount={accountStub()}
143+
<ThirdwebProvider>
144+
<div className="container flex max-w-[800px] flex-col gap-14 py-10">
145+
<div>
146+
<ConnectButton client={getThirdwebClient()} />
147+
</div>
148+
149+
<Variant
150+
label="user + presence + error"
149151
messages={[
150152
{
151153
text: randomLorem(10),
@@ -155,90 +157,117 @@ function Story() {
155157
text: randomLorem(20),
156158
type: "presence",
157159
},
158-
]}
159-
client={getThirdwebClient()}
160-
enableAutoScroll={true}
161-
setEnableAutoScroll={() => {}}
162-
/>
163-
</BadgeContainer>
164-
165-
<BadgeContainer label="User + Error">
166-
<Chats
167-
client={getThirdwebClient()}
168-
authToken="xxxxx"
169-
isChatStreaming={false}
170-
sessionId="xxxxx"
171-
twAccount={accountStub()}
172-
enableAutoScroll={true}
173-
setEnableAutoScroll={() => {}}
174-
messages={[
175-
{
176-
text: randomLorem(10),
177-
type: "user",
178-
},
179160
{
180161
text: randomLorem(20),
181162
type: "error",
182163
},
183164
]}
184165
/>
185-
</BadgeContainer>
186-
187-
<BadgeContainer label="User + Assistant responses">
188-
<Chats
189-
enableAutoScroll={true}
190-
setEnableAutoScroll={() => {}}
191-
client={getThirdwebClient()}
192-
authToken="xxxxx"
193-
isChatStreaming={false}
194-
sessionId="xxxxx"
195-
twAccount={accountStub()}
166+
167+
<Variant
168+
label="send-transaction"
196169
messages={[
197-
{
198-
text: randomLorem(10),
199-
type: "user",
200-
},
201170
{
202171
text: randomLorem(40),
203172
type: "assistant",
204-
request_id: "xxxxx",
205-
},
206-
{
207-
text: randomLorem(50),
208-
type: "assistant",
209173
request_id: undefined,
210174
},
211175
{
212-
text: responseWithCodeMarkdown,
213-
type: "assistant",
214-
request_id: undefined,
176+
type: "send_transaction",
177+
data: {
178+
chainId: 1,
179+
to: "0x1F846F6DAE38E1C88D71EAA191760B15f38B7A37",
180+
data: "0x",
181+
value: "0x16345785d8a0000",
182+
},
215183
},
216184
]}
217185
/>
218-
</BadgeContainer>
219-
220-
<BadgeContainer label="User Markdown">
221-
<Chats
222-
enableAutoScroll={true}
223-
setEnableAutoScroll={() => {}}
224-
client={getThirdwebClient()}
225-
authToken="xxxxx"
226-
isChatStreaming={false}
227-
sessionId="xxxxx"
228-
twAccount={accountStub()}
186+
187+
<Variant
188+
label="invalid send-transaction"
229189
messages={[
230190
{
231-
text: responseWithCodeMarkdown,
232-
type: "user",
191+
text: randomLorem(40),
192+
type: "assistant",
193+
request_id: undefined,
233194
},
234195
{
235-
text: randomLorem(20),
236-
type: "presence",
196+
type: "send_transaction",
197+
data: null,
237198
},
238199
]}
239200
/>
240-
</BadgeContainer>
241-
<Toaster richColors />
242-
</div>
201+
202+
<BadgeContainer label="Assistant response With request_id, Without request_id">
203+
<Chats
204+
enableAutoScroll={false}
205+
setEnableAutoScroll={() => {}}
206+
client={getThirdwebClient()}
207+
authToken="xxxxx"
208+
isChatStreaming={false}
209+
sessionId="xxxxx"
210+
twAccount={accountStub()}
211+
messages={[
212+
{
213+
text: randomLorem(40),
214+
type: "assistant",
215+
request_id: "xxxxx",
216+
},
217+
{
218+
text: randomLorem(50),
219+
type: "assistant",
220+
request_id: undefined,
221+
},
222+
]}
223+
/>
224+
</BadgeContainer>
225+
226+
<BadgeContainer label="Assistant markdown">
227+
<Chats
228+
enableAutoScroll={false}
229+
setEnableAutoScroll={() => {}}
230+
client={getThirdwebClient()}
231+
authToken="xxxxx"
232+
isChatStreaming={false}
233+
sessionId="xxxxx"
234+
twAccount={accountStub()}
235+
messages={[
236+
{
237+
text: responseWithCodeMarkdown,
238+
type: "assistant",
239+
request_id: undefined,
240+
},
241+
{
242+
text: responseWithCodeMarkdown,
243+
type: "user",
244+
},
245+
]}
246+
/>
247+
</BadgeContainer>
248+
249+
<Toaster richColors />
250+
</div>
251+
</ThirdwebProvider>
252+
);
253+
}
254+
255+
function Variant(props: {
256+
label: string;
257+
messages: ChatMessage[];
258+
}) {
259+
return (
260+
<BadgeContainer label={props.label}>
261+
<Chats
262+
enableAutoScroll={false}
263+
setEnableAutoScroll={() => {}}
264+
client={getThirdwebClient()}
265+
authToken="xxxxx"
266+
isChatStreaming={false}
267+
sessionId="xxxxx"
268+
twAccount={accountStub()}
269+
messages={props.messages}
270+
/>
271+
</BadgeContainer>
243272
);
244273
}

apps/dashboard/src/app/nebula-app/(app)/components/Chats.tsx

Lines changed: 9 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,13 @@ import {
1212
ThumbsDownIcon,
1313
ThumbsUpIcon,
1414
} from "lucide-react";
15-
import { useTheme } from "next-themes";
1615
import { useEffect, useRef, useState } from "react";
1716
import { toast } from "sonner";
18-
import { type ThirdwebClient, prepareTransaction } from "thirdweb";
19-
import { useSendTransaction } from "thirdweb/react";
20-
import { TransactionButton } from "../../../../components/buttons/TransactionButton";
17+
import type { ThirdwebClient } from "thirdweb";
2118
import { MarkdownRenderer } from "../../../../components/contract-components/published-contract/markdown-renderer";
22-
import { useV5DashboardChain } from "../../../../lib/v5-adapter";
23-
import { getSDKTheme } from "../../../components/sdk-component-theme";
2419
import { submitFeedback } from "../api/feedback";
2520
import { NebulaIcon } from "../icons/NebulaIcon";
21+
import { ExecuteTransactionCard } from "./ExecuteTransactionCard";
2622

2723
export type NebulaTxData = {
2824
chainId: number;
@@ -119,7 +115,7 @@ export function Chats(props: {
119115
key={index}
120116
>
121117
{message.type === "user" ? (
122-
<div className="flex justify-end gap-3">
118+
<div className="mt-6 flex justify-end">
123119
<div className="max-w-[80%] overflow-auto rounded-xl border bg-muted/50 px-4 py-2">
124120
<MarkdownRenderer
125121
skipHtml
@@ -180,11 +176,11 @@ export function Chats(props: {
180176
li={{ className: "text-foreground" }}
181177
/>
182178
) : message.type === "error" ? (
183-
<span className="text-destructive-text leading-loose">
179+
<div className="rounded-xl border bg-muted/50 px-4 py-2 text-destructive-text leading-normal">
184180
{message.text}
185-
</span>
181+
</div>
186182
) : message.type === "send_transaction" ? (
187-
<ExecuteTransaction
183+
<ExecuteTransactionCardWithFallback
188184
txData={message.data}
189185
twAccount={props.twAccount}
190186
client={props.client}
@@ -197,7 +193,7 @@ export function Chats(props: {
197193
</ScrollShadow>
198194

199195
{message.type === "assistant" &&
200-
!props.isChatStreaming &&
196+
!isMessagePending &&
201197
props.sessionId &&
202198
message.request_id && (
203199
<MessageActions
@@ -222,7 +218,7 @@ export function Chats(props: {
222218
);
223219
}
224220

225-
function ExecuteTransaction(props: {
221+
function ExecuteTransactionCardWithFallback(props: {
226222
txData: NebulaTxData | null;
227223
twAccount: TWAccount;
228224
client: ThirdwebClient;
@@ -237,7 +233,7 @@ function ExecuteTransaction(props: {
237233
}
238234

239235
return (
240-
<SendTransactionButton
236+
<ExecuteTransactionCard
241237
txData={props.txData}
242238
twAccount={props.twAccount}
243239
client={props.client}
@@ -337,46 +333,3 @@ function MessageActions(props: {
337333
</div>
338334
);
339335
}
340-
341-
function SendTransactionButton(props: {
342-
txData: NebulaTxData;
343-
twAccount: TWAccount;
344-
client: ThirdwebClient;
345-
}) {
346-
const { theme } = useTheme();
347-
const { txData } = props;
348-
const sendTransaction = useSendTransaction({
349-
payModal: {
350-
theme: getSDKTheme(theme === "light" ? "light" : "dark"),
351-
},
352-
});
353-
const chain = useV5DashboardChain(txData.chainId);
354-
355-
return (
356-
<TransactionButton
357-
isPending={sendTransaction.isPending}
358-
transactionCount={1}
359-
txChainID={txData.chainId}
360-
onClick={() => {
361-
const tx = prepareTransaction({
362-
chain: chain,
363-
client: props.client,
364-
data: txData.data,
365-
to: txData.to,
366-
value: BigInt(txData.value),
367-
});
368-
369-
const promise = sendTransaction.mutateAsync(tx);
370-
371-
toast.promise(promise, {
372-
success: "Transaction sent successfully",
373-
error: "Failed to send transaction",
374-
});
375-
}}
376-
className="gap-2"
377-
twAccount={props.twAccount}
378-
>
379-
Execute Transaction
380-
</TransactionButton>
381-
);
382-
}

apps/dashboard/src/app/nebula-app/(app)/components/EmptyStateChatPageContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function EmptyStateChatPageContent(props: {
2020
</div>
2121
</div>
2222
<div className="h-5" />
23-
<h1 className="text-center font-semibold text-4xl tracking-tight">
23+
<h1 className="px-4 text-center font-semibold text-3xl tracking-tight md:text-4xl">
2424
How can I help you <br className="max-sm:hidden" />
2525
with the blockchain today?
2626
</h1>

0 commit comments

Comments
 (0)