From 820b5c2e201380ec4f359426d26a36533713c7b5 Mon Sep 17 00:00:00 2001 From: Lee Jackson <130007945+Imagineer99@users.noreply.github.com> Date: Mon, 4 May 2026 14:29:26 +0100 Subject: [PATCH] Studio: Always show API usage examples and docs links (#5270) * chore: always show API usage examples and docs links * chore: add colon to API setup docs label * settings: move help links, add API shortcut, and update API copy --- .../frontend/src/components/app-sidebar.tsx | 54 ++----- .../settings/components/usage-examples.tsx | 140 ++++++++++-------- .../src/features/settings/settings-dialog.tsx | 12 +- .../src/features/settings/tabs/about-tab.tsx | 17 ++- .../features/settings/tabs/api-keys-tab.tsx | 11 +- 5 files changed, 120 insertions(+), 114 deletions(-) diff --git a/studio/frontend/src/components/app-sidebar.tsx b/studio/frontend/src/components/app-sidebar.tsx index b1dc286df5..88a0b03a21 100644 --- a/studio/frontend/src/components/app-sidebar.tsx +++ b/studio/frontend/src/components/app-sidebar.tsx @@ -31,16 +31,14 @@ import { import { useAnimatedThemeToggle } from "@/components/ui/animated-theme-toggler"; import { cn } from "@/lib/utils"; import { - Book03Icon, ChefHatIcon, ColumnInsertIcon, CursorInfo02Icon, Delete02Icon, Download03Icon, GemIcon, - MessageSearch01Icon, + Key01Icon, Search01Icon, - NewReleasesIcon, PowerIcon, PencilEdit02Icon, LayoutAlignLeftIcon, @@ -547,6 +545,15 @@ export function AppSidebar() { Settings ⌘, + useSettingsDialogStore.getState().openDialog("api-keys")} + > + + API Keys + + New + + } onSelect={(e) => { e.preventDefault(); toggleTheme(); }} @@ -571,47 +578,6 @@ export function AppSidebar() { - - - - - Learn More - - - - - - What's New - - - - - - Feedback - - - - setShutdownOpen(true)}> Shutdown diff --git a/studio/frontend/src/features/settings/components/usage-examples.tsx b/studio/frontend/src/features/settings/components/usage-examples.tsx index a2dc2c3774..a8f8ce31a6 100644 --- a/studio/frontend/src/features/settings/components/usage-examples.tsx +++ b/studio/frontend/src/features/settings/components/usage-examples.tsx @@ -4,12 +4,11 @@ import { cn } from "@/lib/utils"; import { copyToClipboard } from "@/lib/copy-to-clipboard"; import { - ArrowDown01Icon, + ArrowUpRight01Icon, Copy01Icon, Tick02Icon, } from "@hugeicons/core-free-icons"; import { HugeiconsIcon } from "@hugeicons/react"; -import { AnimatePresence, motion } from "motion/react"; import { useMemo, useState } from "react"; type Lang = "curl" | "python" | "tools"; @@ -20,6 +19,29 @@ const TABS: { id: Lang; label: string }[] = [ { id: "tools", label: "Tools" }, ]; +const DOC_LINKS = [ + { + label: "Claude Code", + href: "https://unsloth.ai/docs/basics/claude-code", + }, + { + label: "Codex", + href: "https://unsloth.ai/docs/basics/codex", + }, + { + label: "OpenClaw", + href: "https://unsloth.ai/docs/integrations/openclaw", + }, + { + label: "OpenCode", + href: "https://unsloth.ai/docs/integrations/opencode", + }, + { + label: "Hermes Agent", + href: "https://unsloth.ai/docs/integrations/hermes-agent", + }, +]; + function buildSnippets(base: string) { return { curl: `curl ${base}/v1/chat/completions \\ @@ -56,7 +78,6 @@ for chunk in response: } export function UsageExamples() { - const [open, setOpen] = useState(false); const [lang, setLang] = useState("curl"); const [copied, setCopied] = useState(false); const snippets = useMemo( @@ -76,71 +97,62 @@ export function UsageExamples() { return (
- - - - {open && ( - -
-
-
- {TABS.map((t) => { - const active = lang === t.id; - return ( - - ); - })} -
+

Usage examples

+
+
+
+ {TABS.map((t) => { + const active = lang === t.id; + return ( -
-
-                {snippets[lang]}
-              
-
- - )} - + ); + })} +
+ +
+
+          {snippets[lang]}
+        
+
+ Setup docs: + {DOC_LINKS.map((link) => ( + + {link.label} + + + ))} +
+
); } diff --git a/studio/frontend/src/features/settings/settings-dialog.tsx b/studio/frontend/src/features/settings/settings-dialog.tsx index bb22fcb89c..423b5c74f0 100644 --- a/studio/frontend/src/features/settings/settings-dialog.tsx +++ b/studio/frontend/src/features/settings/settings-dialog.tsx @@ -31,6 +31,7 @@ interface TabDef { id: SettingsTab; label: string; icon: typeof Settings02Icon; + badge?: string; } const TABS: TabDef[] = [ @@ -38,8 +39,8 @@ const TABS: TabDef[] = [ { id: "profile", label: "Profile", icon: UserIcon }, { id: "appearance", label: "Appearance", icon: PaintBrush02Icon }, { id: "chat", label: "Chat", icon: Message01Icon }, - { id: "api-keys", label: "API Keys", icon: Key01Icon }, - { id: "about", label: "About", icon: SparklesIcon }, + { id: "api-keys", label: "API Keys", icon: Key01Icon, badge: "New" }, + { id: "about", label: "Help", icon: SparklesIcon }, ]; function renderTab(tab: SettingsTab) { @@ -121,7 +122,12 @@ export function SettingsDialog() { strokeWidth={1.5} className="relative z-10 size-[18px]" /> - {tab.label} + {tab.label} + {tab.badge ? ( + + {tab.badge} + + ) : null} ); })} diff --git a/studio/frontend/src/features/settings/tabs/about-tab.tsx b/studio/frontend/src/features/settings/tabs/about-tab.tsx index bb4454aa43..9629900237 100644 --- a/studio/frontend/src/features/settings/tabs/about-tab.tsx +++ b/studio/frontend/src/features/settings/tabs/about-tab.tsx @@ -12,6 +12,7 @@ import { Book03Icon, Cancel01Icon, MessageNotification01Icon, + NewReleasesIcon, } from "@hugeicons/core-free-icons"; import { HugeiconsIcon } from "@hugeicons/react"; import { useEffect, useState } from "react"; @@ -48,9 +49,9 @@ export function AboutTab() { return (
-

About

+

Help

- Unsloth Studio build info and support. + Documentation, release notes, feedback, and Studio build info.

@@ -79,6 +80,18 @@ export function AboutTab() { + + + + What's new + + +

API Keys

- Access Unsloth Studio programmatically via the OpenAI-compatible API. + Access Unsloth programmatically via the OpenAI-compatible API.{" "} + + Read the API docs + + .