Skip to content

[TOOL-3036] Nebula: Various UI improvements #5929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions apps/dashboard/src/@/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
--background: 0 0% 0%;
--card: 0 0% 0%;
--popover: 0 0% 0%;
--secondary: 0 0% 10%;
--muted: 0 0% 9%;
--accent: 0 0% 9%;
--inverted: 0 0% 98%;
--secondary: 0 0% 11%;
--muted: 0 0% 11%;
--accent: 0 0% 11%;
--inverted: 0 0% 100%;

/* bg - colorful */
--primary: 221 83% 54%;
Expand Down
38 changes: 20 additions & 18 deletions apps/dashboard/src/app/nebula-app/(app)/components/ChatBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,26 @@ export function ChatBar(props: {

return (
<div className="rounded-2xl border border-border bg-muted/50 p-2">
<AutoResizeTextarea
placeholder={"Ask Nebula"}
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={(e) => {
// ignore if shift key is pressed to allow entering new lines
if (e.shiftKey) {
return;
}
if (e.key === "Enter" && !props.isChatStreaming) {
e.preventDefault();
setMessage("");
props.sendMessage(message);
}
}}
className="min-h-[40px] resize-none border-none bg-transparent pt-2 leading-relaxed focus-visible:ring-0 focus-visible:ring-offset-0"
disabled={props.isChatStreaming}
/>
<div className="max-h-[70vh] overflow-y-auto">
<AutoResizeTextarea
placeholder={"Ask Nebula"}
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={(e) => {
// ignore if shift key is pressed to allow entering new lines
if (e.shiftKey) {
return;
}
if (e.key === "Enter" && !props.isChatStreaming) {
e.preventDefault();
setMessage("");
props.sendMessage(message);
}
}}
className="min-h-[40px] resize-none border-none bg-transparent pt-2 leading-relaxed focus-visible:ring-0 focus-visible:ring-offset-0"
disabled={props.isChatStreaming}
/>
</div>

<div className="-mt-3 flex justify-end gap-3 px-2 pb-2">
{/* Send / Stop */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ export function ChatPageContent(props: {
isChatStreaming={isChatStreaming}
authToken={props.authToken}
sessionId={sessionId}
className="min-w-0 pt-10 pb-32"
className="min-w-0 pt-6 pb-32"
twAccount={props.account}
client={client}
enableAutoScroll={enableAutoScroll}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { ScrollShadow } from "@/components/ui/ScrollShadow/ScrollShadow";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
import { MessagesSquareIcon, SquareDashedBottomCodeIcon } from "lucide-react";
import {
MessagesSquareIcon,
SquareDashedBottomCodeIcon,
TextIcon,
} from "lucide-react";
import Link from "next/link";
import type { TruncatedSessionInfo } from "../api/types";
import { useNewChatPageLink } from "../hooks/useNewChatPageLink";
Expand Down Expand Up @@ -42,26 +46,17 @@ export function ChatSidebar(props: {
</Button>
</div>

<div className="h-4" />

<div>
<SidebarIconLink
href="/chat/history"
icon={MessagesSquareIcon}
label="All Chats"
/>
<div className="h-3" />

<SidebarIconLink
href="https://portal.thirdweb.com/nebula"
icon={SquareDashedBottomCodeIcon}
label="Documentation"
target="_blank"
/>
</div>
<SidebarIconLink
href="/chat/history"
icon={MessagesSquareIcon}
label="All Chats"
/>

{sessionsToShow.length > 0 && (
<ScrollShadow
className="my-4 flex-1 border-t border-dashed pt-2"
className="my-3 flex-1 border-t border-dashed pt-2"
scrollableClassName="max-h-full"
shadowColor="transparent"
shadowClassName="z-10"
Expand All @@ -84,6 +79,22 @@ export function ChatSidebar(props: {
</ScrollShadow>
)}

<div className="mb-2">
<SidebarIconLink
href="https://portal.thirdweb.com/changelog"
icon={TextIcon}
label="Changelog"
target="_blank"
/>

<SidebarIconLink
href="https://portal.thirdweb.com/nebula"
icon={SquareDashedBottomCodeIcon}
label="Documentation"
target="_blank"
/>
</div>

<NebulaAccountButton
account={props.account}
className="mt-auto"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,28 @@ function Story() {
]}
/>
</BadgeContainer>

<BadgeContainer label="User Markdown">
<Chats
enableAutoScroll={true}
setEnableAutoScroll={() => {}}
client={getThirdwebClient()}
authToken="xxxxx"
isChatStreaming={false}
sessionId="xxxxx"
twAccount={accountStub()}
messages={[
{
text: responseWithCodeMarkdown,
type: "user",
},
{
text: randomLorem(20),
type: "presence",
},
]}
/>
</BadgeContainer>
<Toaster richColors />
</div>
);
Expand Down
139 changes: 80 additions & 59 deletions apps/dashboard/src/app/nebula-app/(app)/components/Chats.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { GradientAvatar } from "@/components/blocks/Avatars/GradientAvatar";
import { ScrollShadow } from "@/components/ui/ScrollShadow/ScrollShadow";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Alert, AlertTitle } from "@/components/ui/alert";
Expand All @@ -13,13 +12,15 @@ import {
ThumbsDownIcon,
ThumbsUpIcon,
} from "lucide-react";
import { useTheme } from "next-themes";
import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { type ThirdwebClient, prepareTransaction } from "thirdweb";
import { useSendTransaction } from "thirdweb/react";
import { TransactionButton } from "../../../../components/buttons/TransactionButton";
import { MarkdownRenderer } from "../../../../components/contract-components/published-contract/markdown-renderer";
import { useV5DashboardChain } from "../../../../lib/v5-adapter";
import { getSDKTheme } from "../../../components/sdk-component-theme";
import { submitFeedback } from "../api/feedback";
import { NebulaIcon } from "../icons/NebulaIcon";

Expand Down Expand Up @@ -97,7 +98,7 @@ export function Chats(props: {

return (
<div
className="flex max-h-full flex-1 flex-col overflow-hidden"
className="relative flex max-h-full flex-1 flex-col overflow-hidden"
ref={chatContainerRef}
>
<ScrollShadow
Expand All @@ -113,27 +114,34 @@ export function Chats(props: {
props.isChatStreaming && index === props.messages.length - 1;
return (
<div
className="fade-in-0 min-w-0 animate-in pt-1 text-sm duration-300 lg:text-base"
// biome-ignore lint/suspicious/noArrayIndexKey: index is the unique key
key={index}
>
<div
className={cn(
"fade-in-0 flex min-w-0 animate-in gap-3 duration-300",
)}
>
<div className="-translate-y-[2px] relative shrink-0 ">
{message.type === "user" ? (
<GradientAvatar
id={props.twAccount?.id || "default"}
// TODO- set account image when available in account object
src={""}
className="size-8 shrink-0 rounded-lg"
client={props.client}
{message.type === "user" ? (
<div className="flex justify-end gap-3">
<div className="max-w-[80%] overflow-auto rounded-xl border bg-muted/50 px-4 py-2">
<MarkdownRenderer
skipHtml
markdownText={message.text}
code={{
ignoreFormattingErrors: true,
className: "bg-transparent",
}}
className="text-foreground [&>*:last-child]:mb-0"
p={{ className: "text-foreground leading-normal" }}
li={{ className: "text-foreground" }}
inlineCode={{ className: "border-none" }}
/>
) : (
</div>
</div>
) : (
<div className="flex gap-3">
{/* Left Icon */}
<div className="-translate-y-[2px] relative shrink-0">
<div
className={cn(
"flex size-8 items-center justify-center rounded-lg",
"flex size-9 items-center justify-center rounded-full",
message.type === "assistant" &&
"border bg-muted/50",
message.type === "error" && "border",
Expand All @@ -152,49 +160,57 @@ export function Chats(props: {
<AlertCircleIcon className="size-5 text-destructive-text" />
)}
</div>
)}
</div>
<div className="min-w-0 grow">
{message.type === "assistant" ? (
<MarkdownRenderer
skipHtml
markdownText={message.text}
code={{
disableCodeHighlight: isMessagePending,
ignoreFormattingErrors: true,
}}
className="text-foreground"
p={{ className: "text-foreground" }}
li={{ className: "text-foreground" }}
/>
) : message.type === "error" ? (
<span className="text-destructive-text leading-loose">
{message.text}
</span>
) : message.type === "send_transaction" ? (
<ExecuteTransaction
txData={message.data}
twAccount={props.twAccount}
client={props.client}
/>
) : (
<span className="leading-loose">{message.text}</span>
)}
</div>

{message.type === "assistant" &&
!props.isChatStreaming &&
props.sessionId &&
message.request_id && (
<MessageActions
messageText={message.text}
authToken={props.authToken}
requestId={message.request_id}
sessionId={props.sessionId}
className="mt-4"
/>
)}
{/* Right Message */}
<div className="min-w-0 grow">
<ScrollShadow className="rounded-lg">
{message.type === "assistant" ? (
<MarkdownRenderer
skipHtml
markdownText={message.text}
code={{
disableCodeHighlight: isMessagePending,
ignoreFormattingErrors: true,
}}
className="text-foreground [&>*:last-child]:mb-0"
p={{
className: "text-foreground",
}}
li={{ className: "text-foreground" }}
/>
) : message.type === "error" ? (
<span className="text-destructive-text leading-loose">
{message.text}
</span>
) : message.type === "send_transaction" ? (
<ExecuteTransaction
txData={message.data}
twAccount={props.twAccount}
client={props.client}
/>
) : (
<span className="leading-loose">
{message.text}
</span>
)}
</ScrollShadow>

{message.type === "assistant" &&
!props.isChatStreaming &&
props.sessionId &&
message.request_id && (
<MessageActions
messageText={message.text}
authToken={props.authToken}
requestId={message.request_id}
sessionId={props.sessionId}
className="mt-4"
/>
)}
</div>
</div>
</div>
)}
</div>
);
})}
Expand Down Expand Up @@ -327,8 +343,13 @@ function SendTransactionButton(props: {
twAccount: TWAccount;
client: ThirdwebClient;
}) {
const { theme } = useTheme();
const { txData } = props;
const sendTransaction = useSendTransaction();
const sendTransaction = useSendTransaction({
payModal: {
theme: getSDKTheme(theme === "light" ? "light" : "dark"),
},
});
const chain = useV5DashboardChain(txData.chainId);

return (
Expand Down
Loading
Loading