unsloth/studio/frontend/src/features/export/components/method-picker.tsx
2026-02-04 13:28:39 +01:00

129 lines
4.5 KiB
TypeScript

import { Badge } from "@/components/ui/badge";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
import {
CheckmarkCircle01Icon,
InformationCircleIcon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { EXPORT_METHODS, type ExportMethod } from "../constants";
interface MethodPickerProps {
value: ExportMethod | null;
onChange: (v: ExportMethod) => void;
}
export function MethodPicker({ value, onChange }: MethodPickerProps) {
return (
<div className="flex flex-col gap-3">
<span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
Export Method
<Tooltip>
<TooltipTrigger asChild={true}>
<button
type="button"
className="text-foreground/70 hover:text-foreground"
>
<HugeiconsIcon icon={InformationCircleIcon} className="size-3" />
</button>
</TooltipTrigger>
<TooltipContent>
How your model is packaged for deployment.{" "}
<a
href="https://unsloth.ai/docs/basics/inference-and-deployment"
target="_blank"
rel="noopener noreferrer"
className="text-primary underline"
>
Read more
</a>
</TooltipContent>
</Tooltip>
</span>
<div className="grid grid-cols-3 gap-3">
{EXPORT_METHODS.map((m) => {
const selected = value === m.value;
return (
<button
key={m.value}
type="button"
onClick={() => onChange(m.value)}
className={cn(
"flex items-start gap-3 rounded-xl p-4 text-left ring-1 transition-all",
selected
? "ring-2 ring-primary bg-primary/5"
: "ring-border hover:-translate-y-0.5 hover:shadow-sm",
)}
>
<div
className={cn(
"mt-0.5 flex size-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
selected
? "border-primary bg-primary"
: "border-muted-foreground/30",
)}
>
{selected && (
<HugeiconsIcon
icon={CheckmarkCircle01Icon}
className="size-3 text-primary-foreground"
/>
)}
</div>
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2">
<span className="text-sm font-medium">{m.title}</span>
<Tooltip>
<TooltipTrigger asChild={true}>
<button
type="button"
className="shrink-0 text-foreground/50 hover:text-foreground cursor-help"
onClick={(e) => e.stopPropagation()}
aria-label={`${m.title} info`}
>
<HugeiconsIcon
icon={InformationCircleIcon}
className="size-3"
/>
</button>
</TooltipTrigger>
<TooltipContent className="max-w-xs">
{m.tooltip}{" "}
<a
href={
m.value === "gguf"
? "https://unsloth.ai/docs/basics/inference-and-deployment/saving-to-gguf"
: "https://unsloth.ai/docs/basics/inference-and-deployment"
}
target="_blank"
rel="noopener noreferrer"
className="text-primary underline"
>
Read more
</a>
</TooltipContent>
</Tooltip>
{m.badge && (
<Badge
variant="secondary"
className="text-[10px] px-1.5 py-0"
>
{m.badge}
</Badge>
)}
</div>
<span className="text-xs text-muted-foreground">
{m.description}
</span>
</div>
</button>
);
})}
</div>
</div>
);
}