feat: improve dark mode styling and simplify navbar

This commit is contained in:
Shine1i 2026-02-25 00:31:20 +01:00
commit 164560c6c9
7 changed files with 37 additions and 49 deletions

View file

@ -45,7 +45,6 @@ function getTourId(pathname: string): "studio" | "chat" | "export" | null {
export function Navbar() {
const pathname = useRouterState({ select: (s) => s.location.pathname });
const isTrainingRunning = useTrainingRuntimeStore((s) => s.isTrainingRunning);
const [logoHovered, setLogoHovered] = useState(false);
const [mobileOpen, setMobileOpen] = useState(false);
const tourId = getTourId(pathname);
@ -61,35 +60,18 @@ export function Navbar() {
<header className="relative top-0 z-40 h-16 w-full">
<div className="mx-auto flex h-full max-w-7xl items-center justify-between px-4 sm:px-6">
{/* Left: logo */}
<div
className="relative flex items-center gap-2.5 cursor-pointer select-none"
onMouseEnter={() => setLogoHovered(true)}
onMouseLeave={() => setLogoHovered(false)}
>
<motion.img
src="https://unsloth.ai/cgi/image/unsloth_sticker_no_shadow_ldN4V4iydw00qSIIWDCUv.png?width=96&quality=80&format=auto"
alt="unsloth"
className="size-10"
animate={{ rotate: logoHovered ? 360 : 0 }}
transition={{ duration: 0.5, ease: [0.165, 0.84, 0.44, 1] }}
<Link to="/studio" className="flex items-center select-none">
<img
src="/blacklogo.png"
alt="Unsloth"
className="h-9 w-auto dark:hidden"
/>
<span className="text-xl font-bold tracking-wide font-heading sm:text-2xl">
unsloth
</span>
<AnimatePresence>
{logoHovered && (
<motion.img
src="/Sloth emojis/large sloth wave.png"
alt="hi!"
className="absolute -bottom-10 left-1 size-10 pointer-events-none"
initial={{ y: 10, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 10, opacity: 0 }}
transition={{ duration: 0.25, ease: [0.215, 0.61, 0.355, 1] }}
/>
)}
</AnimatePresence>
</div>
<img
src="/whitelogo.png"
alt="Unsloth"
className="hidden h-9 w-auto dark:block"
/>
</Link>
{/* Center: pill nav */}
<nav

View file

@ -216,11 +216,11 @@ function InlineSidebar({
<aside
data-sidebar="sidebar"
className={cn(
"bg-sidebar text-sidebar-foreground h-full overflow-hidden rounded-2xl corner-squircle transition-[width] duration-200 ease-linear",
"bg-muted/70 text-sidebar-foreground h-full overflow-hidden rounded-2xl corner-squircle transition-[width] duration-200 ease-linear",
!collapsed &&
(side === "left"
? "border-r border-0 border-sidebar-border"
: "border-l border-0 border-sidebar-border"),
? "border-r border-sidebar-border/70"
: "border-l border-sidebar-border/70"),
collapsed ? "w-0" : "w-(--sidebar-width)",
)}
>

View file

@ -195,7 +195,7 @@ export function ChatSettingsPanel({
return (
<aside
className={`shrink-0 h-full overflow-hidden bg-sidebar rounded-2xl corner-squircle transition-[width] duration-200 ease-linear ${open ? "w-[17rem] border-sidebar-border" : "w-0"}`}
className={`shrink-0 h-full overflow-hidden bg-muted/70 rounded-2xl corner-squircle transition-[width] duration-200 ease-linear ${open ? "w-[17rem] border-l border-sidebar-border/70" : "w-0"}`}
>
<div className="flex h-full w-[17rem] flex-col">
<div className="flex items-center gap-2 px-4 py-3">

View file

@ -132,7 +132,7 @@ export function DatasetSection() {
title="Dataset"
description="Select or upload training data"
accent="indigo"
className="md:min-h-[450px]"
className="md:min-h-[450px] dark:shadow-border"
>
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">

View file

@ -64,9 +64,11 @@ const METHOD_DOTS: Record<string, string> = {
};
const DARK_TRIGGER =
"w-full bg-foreground text-background hover:bg-foreground/85 dark:bg-foreground dark:text-background [&_svg]:text-background/50";
"w-full bg-foreground text-background hover:bg-foreground/90 dark:bg-foreground dark:text-background dark:hover:bg-foreground [&_svg]:text-background/50";
const DARK_CONTENT =
"bg-foreground text-background shadow-xl border-background/10 [--accent:rgba(255,255,255,0.1)] [--accent-foreground:white] [&_[data-slot=select-item]]:text-white/70 [&_[data-slot=select-scroll-up-button]]:bg-foreground [&_[data-slot=select-scroll-down-button]]:bg-foreground";
"bg-foreground text-background shadow-xl border-background/10 [--accent:rgba(255,255,255,0.1)] [--accent-foreground:white] dark:[--accent:rgba(2,6,23,0.08)] dark:[--accent-foreground:rgb(2,6,23)] [&_[data-slot=select-item]]:text-white/80 dark:[&_[data-slot=select-item]]:text-slate-900 [&_[data-slot=select-scroll-up-button]]:bg-foreground [&_[data-slot=select-scroll-down-button]]:bg-foreground";
const DARK_COMBOBOX_CONTENT =
"bg-foreground text-background shadow-xl border-background/10 dark:[--accent:rgba(2,6,23,0.08)] dark:[--accent-foreground:rgb(2,6,23)] dark:[&_[data-slot=combobox-item]]:text-slate-900 dark:[&_.text-muted-foreground]:text-slate-500";
export function ModelSection() {
const gpu = useGpuInfo();
@ -296,7 +298,10 @@ export function ModelSection() {
<HugeiconsIcon icon={FolderSearchIcon} className="size-4" />
</InputGroupAddon>
</ComboboxInput>
<ComboboxContent anchor={localComboboxAnchorRef}>
<ComboboxContent
anchor={localComboboxAnchorRef}
className={DARK_COMBOBOX_CONTENT}
>
{isLoadingLocalModels ? (
<div className="flex items-center justify-center gap-2 py-4 text-xs text-muted-foreground">
<Spinner className="size-4" /> Scanning...

View file

@ -282,7 +282,7 @@ export function GuidedTour({
transition={{ duration: 0.22, ease: [0.165, 0.84, 0.44, 1] }}
className={cn(
"relative overflow-hidden rounded-[28px] corner-squircle",
"bg-white/95 text-foreground ring-1 ring-black/10",
"bg-white/95 text-foreground ring-1 ring-black/10 dark:bg-zinc-900/96 dark:text-zinc-100 dark:ring-white/12",
"shadow-[0_30px_120px_rgba(0,0,0,0.35)]",
)}
style={{
@ -291,7 +291,7 @@ export function GuidedTour({
>
<div
className={cn(
"absolute z-10 size-3 rotate-45 rounded-[3px] bg-white/95 ring-1 ring-black/10",
"absolute z-10 size-3 rotate-45 rounded-[3px] bg-white/95 ring-1 ring-black/10 dark:bg-zinc-900/96 dark:ring-white/12",
placement === "right" &&
"-left-1 top-1/2 -translate-y-1/2",
placement === "left" &&
@ -303,14 +303,14 @@ export function GuidedTour({
)}
aria-hidden={true}
/>
<div className="absolute inset-x-0 top-0 h-20 bg-gradient-to-b from-emerald-400/18 via-cyan-300/6 to-transparent" />
<div className="absolute -left-14 -top-16 size-44 rounded-full bg-emerald-400/20 blur-2xl" />
<div className="absolute -right-14 -bottom-16 size-44 rounded-full bg-cyan-300/18 blur-2xl" />
<div className="absolute inset-x-0 top-0 h-20 bg-gradient-to-b from-emerald-400/18 via-cyan-300/6 to-transparent dark:from-emerald-400/24 dark:via-cyan-300/12" />
<div className="absolute -left-14 -top-16 size-44 rounded-full bg-emerald-400/20 blur-2xl dark:bg-emerald-400/26" />
<div className="absolute -right-14 -bottom-16 size-44 rounded-full bg-cyan-300/18 blur-2xl dark:bg-cyan-300/24" />
<div className="relative p-5">
<div className="flex items-start justify-between gap-3">
<div className="min-w-0">
<div className="inline-flex items-center gap-2 rounded-full bg-black/[0.04] px-2.5 py-1 text-[10px] font-mono text-foreground/60 ring-1 ring-black/10">
<div className="inline-flex items-center gap-2 rounded-full bg-black/[0.04] px-2.5 py-1 text-[10px] font-mono text-foreground/60 ring-1 ring-black/10 dark:bg-white/[0.04] dark:text-zinc-200/75 dark:ring-white/14">
{idx + 1}/{total}
<span className="size-1 rounded-full bg-emerald-500/70" />
guided tour
@ -321,7 +321,7 @@ export function GuidedTour({
>
{step?.title ?? "Quick tour"}
</DialogPrimitive.Title>
<DialogPrimitive.Description className="mt-1.5 text-sm leading-relaxed text-foreground/70">
<DialogPrimitive.Description className="mt-1.5 text-sm leading-relaxed text-foreground/70 dark:text-zinc-200/75">
{step?.body ?? "Lets get you oriented."}
</DialogPrimitive.Description>
</div>
@ -329,7 +329,7 @@ export function GuidedTour({
<Button
variant="ghost"
size="icon-sm"
className="text-foreground/60 hover:text-foreground hover:bg-black/[0.05]"
className="text-foreground/60 hover:text-foreground hover:bg-black/[0.05] dark:text-zinc-300/70 dark:hover:text-zinc-100 dark:hover:bg-white/[0.08]"
onClick={() => requestClose("skip")}
aria-label="Skip tour"
>
@ -340,7 +340,7 @@ export function GuidedTour({
<div className="mt-5 flex items-center justify-between gap-3">
<Button
variant="ghost"
className="text-foreground/60 hover:text-foreground hover:bg-black/[0.05]"
className="text-foreground/60 hover:text-foreground hover:bg-black/[0.05] dark:text-zinc-300/70 dark:hover:text-zinc-100 dark:hover:bg-white/[0.08]"
onClick={() => requestClose("skip")}
>
Skip
@ -349,7 +349,7 @@ export function GuidedTour({
<div className="flex items-center gap-2">
<Button
variant="outline"
className="border-black/10 bg-white/70 text-foreground hover:bg-white hover:text-foreground"
className="border-black/10 bg-white/70 text-foreground hover:bg-white hover:text-foreground dark:border-white/15 dark:bg-white/[0.07] dark:text-zinc-100 dark:hover:bg-white/[0.12]"
disabled={idx === 0}
onClick={() => setIdx((i) => Math.max(0, i - 1))}
>
@ -379,8 +379,8 @@ export function GuidedTour({
</div>
</div>
<div className="h-px bg-gradient-to-r from-transparent via-black/10 to-transparent" />
<div className="px-5 py-3 text-[11px] text-foreground/55">
<div className="h-px bg-gradient-to-r from-transparent via-black/10 to-transparent dark:via-white/14" />
<div className="px-5 py-3 text-[11px] text-foreground/55 dark:text-zinc-300/65">
Tip: `Esc` skips. Tour blocks clicks so you can read.
</div>
</motion.div>

View file

@ -152,6 +152,7 @@
--shadow-2xl: 0px 0px 0px 0px hsl(0 0% 0% / 0);
}
@theme inline {
--font-sans: "Inter Variable", ui-sans-serif, sans-serif, system-ui;
--font-heading: "Hellix", "Space Grotesk Variable", ui-sans-serif, sans-serif;