Studio: clearer check mark and even plus-menu hover padding (#6253)

* Studio: use a clearer check mark for the app-wide tick

Route every check mark through a shared tick-icon module with a plain
tick geometry, sized slightly larger than the stock icon so it reads
clearly in menus. No Pro icon assets are vendored.

* Studio: even out plus-menu hover padding on all sides

Trim the plus-menu side gutter to 9px so it matches the 0.5rem top/bottom
padding, and drop the container radius to 21px to keep corners concentric.

* Studio: bake the tick fallback stroke at 1.5 to match the icon set

---------

Co-authored-by: shimmyshimmer <info@unsloth.ai>
This commit is contained in:
Michael Han 2026-06-12 06:44:08 -07:00 committed by GitHub
commit 587e59ca83
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 60 additions and 28 deletions

View file

@ -8,7 +8,8 @@ import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { preprocessLaTeX } from "@/lib/latex";
import { openLink } from "@/lib/open-link";
import { INTERNAL, useAuiState, useMessagePartText } from "@assistant-ui/react";
import { Copy01Icon, Download01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { Tick02Icon } from "@/lib/tick-icon";
import { Copy01Icon, Download01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { createMathPlugin } from "@streamdown/math";
import { mermaid } from "@streamdown/mermaid";

View file

@ -86,6 +86,7 @@ import { applyQwenThinkingParams } from "@/features/chat/utils/qwen-params";
import { isTauri } from "@/lib/api-base";
import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { toast } from "@/lib/toast";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import {
ActionBarMorePrimitive,
@ -115,7 +116,6 @@ import {
Image03Icon,
McpServerIcon,
PencilRulerIcon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { useNavigate } from "@tanstack/react-router";

View file

@ -4,8 +4,8 @@
import { Checkbox as CheckboxPrimitive } from "radix-ui";
import type * as React from "react";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { Tick02Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
function Checkbox({

View file

@ -17,11 +17,11 @@ import {
InputGroupButton,
InputGroupInput,
} from "@/components/ui/input-group";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import {
ArrowDown01Icon,
Cancel01Icon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";

View file

@ -14,8 +14,9 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { InputGroup, InputGroupAddon } from "@/components/ui/input-group";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { Search01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { Search01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
function Command({

View file

@ -6,8 +6,9 @@
import { ContextMenu as ContextMenuPrimitive } from "radix-ui";
import type * as React from "react";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { ArrowRight01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { ArrowRight01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
function ContextMenu({

View file

@ -9,8 +9,9 @@ import {
PopoverTrigger,
} from "@/components/ui/popover";
import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { Copy01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { Copy01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { useEffect, useRef, useState } from "react";

View file

@ -4,8 +4,9 @@
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
import type * as React from "react";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { ArrowRight01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { ArrowRight01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
function DropdownMenu({

View file

@ -6,8 +6,9 @@
import { Menubar as MenubarPrimitive } from "radix-ui";
import type * as React from "react";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { ArrowRight01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { ArrowRight01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
function Menubar({

View file

@ -7,12 +7,12 @@ import { Select as SelectPrimitive } from "radix-ui";
import type * as React from "react";
import { createContext, useContext, useState } from "react";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { useDialogPortalContainer } from "@/components/ui/dialog";
import {
ArrowDown01Icon,
ArrowUp01Icon,
Tick02Icon,
UnfoldMoreIcon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";

View file

@ -11,8 +11,8 @@ import {
import {
ArrowDown01Icon,
Folder01Icon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import { Tick02Icon } from "@/lib/tick-icon";
import { HugeiconsIcon } from "@hugeicons/react";
import type { ReactElement } from "react";
import type { ProjectRecord } from "../types";

View file

@ -1,7 +1,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
import { McpServerIcon, Tick02Icon } from "@hugeicons/core-free-icons";
import { Tick02Icon } from "@/lib/tick-icon";
import { McpServerIcon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { XIcon } from "lucide-react";
import { type FC, useCallback, useEffect, useState } from "react";

View file

@ -7,6 +7,7 @@ import {
thinkToggleAriaLabel,
} from "@/components/assistant-ui/think-aria-label";
import { Button } from "@/components/ui/button";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import {
DropdownMenu,
@ -46,7 +47,6 @@ import {
Image03Icon,
McpServerIcon,
PencilRulerIcon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import { useNavigate } from "@tanstack/react-router";
import { HugeiconsIcon } from "@hugeicons/react";

View file

@ -6,8 +6,9 @@ import {
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { ArrowDown01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { ArrowDown01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import {
type KeyboardEvent,

View file

@ -13,6 +13,7 @@ import {
} from "@/features/hub/hooks/use-hub-model-search";
import { useOnlineStatus } from "@/features/hub/hooks/use-online-status";
import { formatBytes, formatRelativeShort } from "@/features/hub/lib/format";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn, formatCompact } from "@/lib/utils";
import { confirmExternalLink } from "../stores/external-link-confirm";
import { useHfTokenStore } from "@/features/hub/stores/hf-token-store";
@ -30,7 +31,6 @@ import {
PackageIcon,
RamMemoryIcon,
Share05Icon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import type { IconSvgElement } from "@hugeicons/react";
import { HugeiconsIcon } from "@hugeicons/react";

View file

@ -13,11 +13,11 @@ import {
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import {
Copy01Icon,
FolderSearchIcon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import type { MouseEvent } from "react";

View file

@ -2,8 +2,9 @@
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
import { XIcon } from "lucide-react";
import { Tick02Icon } from "@/lib/tick-icon";
import { HugeiconsIcon } from "@hugeicons/react";
import { FileDatabaseIcon, Tick02Icon } from "@hugeicons/core-free-icons";
import { FileDatabaseIcon } from "@hugeicons/core-free-icons";
import { type FC, useCallback, useEffect, useState } from "react";
import {

View file

@ -21,9 +21,9 @@ import {
DocumentAttachmentIcon,
PlusSignIcon,
Search01Icon,
Tick02Icon,
Upload01Icon,
} from "@hugeicons/core-free-icons";
import { Tick02Icon } from "@/lib/tick-icon";
import { HugeiconsIcon } from "@hugeicons/react";
import {
useCallback,

View file

@ -4,8 +4,9 @@
import { Button } from "@/components/ui/button";
import { useT } from "@/i18n";
import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { Copy01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { Copy01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { useState } from "react";

View file

@ -3,11 +3,11 @@
import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { useT } from "@/i18n";
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import {
ArrowUpRight01Icon,
Copy01Icon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { AnimatePresence, motion, useReducedMotion } from "motion/react";

View file

@ -1,13 +1,13 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
import { Tick02Icon } from "@/lib/tick-icon";
import { cn } from "@/lib/utils";
import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { useT } from "@/i18n";
import {
ArrowUpRight01Icon,
Copy01Icon,
Tick02Icon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { useMemo, useState } from "react";

View file

@ -1313,16 +1313,16 @@
/* Soft elevation; [data-slot] outranks the component ring-1, dropping the border. */
.unsloth-plus-menu[data-slot] {
/* Concentric with the item hover boxes, like Gemini: container radius =
item radius (12px) + side gutter (10px), so the curves run parallel.
/* Concentric with the item hover boxes: container radius =
item radius (12px) + side gutter (9px), so the curves run parallel.
!important beats the global 14px dropdown radius. */
border-radius: 22px !important;
border-radius: 21px !important;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
/* Side gutter so item hover boxes sit inset from the menu edge, like
Gemini's menus (more breathing room than a hairline gutter). */
padding-left: 10px;
padding-right: 10px;
/* Side gutter ~matches the 0.5rem top/bottom padding so the hover box
sits evenly inset on all four sides. */
padding-left: 9px;
padding-right: 9px;
box-shadow: 0 2px 8px -2px rgba(0, 0, 0, 0.16);
}

View file

@ -0,0 +1,22 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
import type { IconSvgElement } from "@hugeicons/react";
// App-wide check mark. Plain tick geometry, sized a touch larger
// than the stock icon so it reads clearly in menus.
export const Tick02Icon: IconSvgElement = [
[
"path",
{
d: "M4.477 13.299L9.008 17.829L19.123 7.714",
stroke: "currentColor",
strokeLinecap: "round",
strokeLinejoin: "round",
// Fallback weight, matching the icon set; call sites with a
// strokeWidth prop override this.
strokeWidth: "1.5",
key: "0",
},
],
];