Enhance Menubar with additional items and improved layout for better user experience
This commit is contained in:
@@ -50,6 +50,7 @@ import {
|
|||||||
MenubarMenu,
|
MenubarMenu,
|
||||||
MenubarSeparator,
|
MenubarSeparator,
|
||||||
MenubarShortcut,
|
MenubarShortcut,
|
||||||
|
MenubarCheckboxItem,
|
||||||
MenubarTrigger,
|
MenubarTrigger,
|
||||||
} from "@/components/ui/menubar";
|
} from "@/components/ui/menubar";
|
||||||
|
|
||||||
@@ -69,6 +70,10 @@ import {
|
|||||||
WholeWordIcon,
|
WholeWordIcon,
|
||||||
EllipsisIcon,
|
EllipsisIcon,
|
||||||
CogIcon,
|
CogIcon,
|
||||||
|
Menu,
|
||||||
|
ReceiptIcon,
|
||||||
|
WalletIcon,
|
||||||
|
RulerIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { ModeToggle } from "@/components/mode-toggle";
|
import { ModeToggle } from "@/components/mode-toggle";
|
||||||
@@ -313,10 +318,10 @@ export function App() {
|
|||||||
<div className="flex items-center gap-2 px-3">
|
<div className="flex items-center gap-2 px-3">
|
||||||
<SidebarTrigger />
|
<SidebarTrigger />
|
||||||
<Separator orientation="vertical" className="mr-2 h-4" />
|
<Separator orientation="vertical" className="mr-2 h-4" />
|
||||||
|
<h1 className="text-lg font-bold">{chatStore.model}</h1>
|
||||||
<div className="flex justify-between items-center gap-2">
|
<div className="flex justify-between items-center gap-2">
|
||||||
<div>
|
<div>
|
||||||
<div className="dropdown lg:hidden flex items-center gap-2">
|
<div className="dropdown lg:hidden flex items-center gap-2">
|
||||||
<h1 className="text-lg font-bold">{chatStore.model}</h1>{" "}
|
|
||||||
<Badge variant="outline">
|
<Badge variant="outline">
|
||||||
{chatStore.totalTokens.toString()}
|
{chatStore.totalTokens.toString()}
|
||||||
</Badge>
|
</Badge>
|
||||||
@@ -341,57 +346,61 @@ export function App() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="hidden lg:inline-grid">
|
<div className="hidden lg:inline-grid">
|
||||||
<Menubar>
|
<Menubar>
|
||||||
<MenubarMenu>
|
|
||||||
<MenubarTrigger>
|
|
||||||
<BoxesIcon className="w-4 h-4 mr-2" />
|
|
||||||
{chatStore.model}
|
|
||||||
</MenubarTrigger>
|
|
||||||
<MenubarContent>
|
|
||||||
<MenubarItem>
|
|
||||||
{models[chatStore.model]?.price?.prompt * 1000 * 1000}
|
|
||||||
$ / 1M input tokens
|
|
||||||
</MenubarItem>
|
|
||||||
</MenubarContent>
|
|
||||||
</MenubarMenu>
|
|
||||||
<MenubarMenu>
|
|
||||||
<MenubarTrigger>
|
|
||||||
<ArrowUpDownIcon className="w-4 h-4 mr-2" />
|
|
||||||
{chatStore.streamMode ? Tr("STREAM") : Tr("FETCH")}
|
|
||||||
</MenubarTrigger>
|
|
||||||
<MenubarContent>
|
|
||||||
<MenubarItem>STREAM/FETCH</MenubarItem>
|
|
||||||
</MenubarContent>
|
|
||||||
</MenubarMenu>
|
|
||||||
<MenubarMenu>
|
<MenubarMenu>
|
||||||
<MenubarTrigger>
|
<MenubarTrigger>
|
||||||
<WholeWordIcon className="w-4 h-4 mr-2" />{" "}
|
<WholeWordIcon className="w-4 h-4 mr-2" />{" "}
|
||||||
{chatStore.totalTokens}
|
{chatStore.totalTokens}
|
||||||
</MenubarTrigger>
|
<CircleDollarSignIcon className="w-4 h-4 mx-2" />
|
||||||
<MenubarContent>
|
|
||||||
<MenubarItem>Max: {chatStore.maxTokens}</MenubarItem>
|
|
||||||
</MenubarContent>
|
|
||||||
</MenubarMenu>
|
|
||||||
<MenubarMenu>
|
|
||||||
<MenubarTrigger>
|
|
||||||
<ScissorsIcon className="w-4 h-4 mr-2" />
|
|
||||||
{chatStore.postBeginIndex}
|
|
||||||
</MenubarTrigger>
|
|
||||||
<MenubarContent>
|
|
||||||
<MenubarItem>
|
|
||||||
Max:{" "}
|
|
||||||
{chatStore.history.filter(({ hide }) => !hide).length}
|
|
||||||
</MenubarItem>
|
|
||||||
</MenubarContent>
|
|
||||||
</MenubarMenu>
|
|
||||||
<MenubarMenu>
|
|
||||||
<MenubarTrigger>
|
|
||||||
<CircleDollarSignIcon className="w-4 h-4 mr-2" />
|
|
||||||
{chatStore.cost.toFixed(4)}
|
{chatStore.cost.toFixed(4)}
|
||||||
</MenubarTrigger>
|
</MenubarTrigger>
|
||||||
<MenubarContent>
|
<MenubarContent>
|
||||||
<MenubarItem>
|
<MenubarItem>
|
||||||
Accumulated: ${getTotalCost().toFixed(2)}
|
<RulerIcon className="w-4 h-4 mr-2" />
|
||||||
|
Max Length: {chatStore.maxTokens}
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
|
<MenubarItem>
|
||||||
|
<ReceiptIcon className="w-4 h-4 mr-2" />
|
||||||
|
Price:{" "}
|
||||||
|
{models[chatStore.model]?.price?.prompt * 1000 * 1000}
|
||||||
|
$ / 1M input tokens
|
||||||
|
</MenubarItem>
|
||||||
|
<MenubarItem>
|
||||||
|
<WalletIcon className="w-4 h-4 mr-2" />
|
||||||
|
Total: {getTotalCost().toFixed(2)}$
|
||||||
|
</MenubarItem>
|
||||||
|
<MenubarItem>
|
||||||
|
<ArrowUpDownIcon className="w-4 h-4 mr-2" />
|
||||||
|
{chatStore.streamMode ? (
|
||||||
|
<>
|
||||||
|
<span>{Tr("STREAM")}</span>·
|
||||||
|
<span style={{ color: "gray" }}>
|
||||||
|
{Tr("FETCH")}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<span style={{ color: "gray" }}>
|
||||||
|
{Tr("STREAM")}
|
||||||
|
</span>
|
||||||
|
·<span>{Tr("FETCH")}</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</MenubarItem>
|
||||||
|
<MenubarItem>
|
||||||
|
<ScissorsIcon className="w-4 h-4 mr-2" />
|
||||||
|
{chatStore.postBeginIndex} /{" "}
|
||||||
|
{chatStore.history.length}
|
||||||
|
</MenubarItem>
|
||||||
|
<MenubarSeparator />
|
||||||
|
<MenubarItem disabled>
|
||||||
|
Switch to Model (TODO):
|
||||||
|
</MenubarItem>
|
||||||
|
<MenubarCheckboxItem checked>
|
||||||
|
gpt-4o
|
||||||
|
</MenubarCheckboxItem>
|
||||||
|
<MenubarCheckboxItem>gpt-o1</MenubarCheckboxItem>
|
||||||
|
<MenubarCheckboxItem>gpt-o1-mini</MenubarCheckboxItem>
|
||||||
|
<MenubarCheckboxItem>gpt-o3</MenubarCheckboxItem>
|
||||||
</MenubarContent>
|
</MenubarContent>
|
||||||
</MenubarMenu>
|
</MenubarMenu>
|
||||||
</Menubar>
|
</Menubar>
|
||||||
|
|||||||
Reference in New Issue
Block a user