feat: improve dark mode styling and simplify navbar
This commit is contained in:
parent
2548720c01
commit
164560c6c9
7 changed files with 37 additions and 49 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)",
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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 ?? "Let’s 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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue