fix(studio): equal padding in the dataset source segmented control (#7230)

* fix(studio): equal padding in dataset source segmented control

* fix(studio): scope dataset source pill layoutId per component instance
This commit is contained in:
Michael Han 2026-07-18 21:08:55 -07:00 committed by GitHub
commit 9073f07705
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -70,11 +70,13 @@ import {
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { useNavigate } from "@tanstack/react-router";
import { motion, useReducedMotion } from "motion/react";
import {
type ChangeEvent,
type DragEvent,
useCallback,
useEffect,
useId,
useMemo,
useRef,
useState,
@ -153,6 +155,9 @@ function normalizeSliceInput(value: string): string | null {
export function DatasetSection() {
const t = useT();
const navigate = useNavigate();
const reducedMotion = useReducedMotion();
// Scopes the pill layoutId so multiple instances never share one.
const sourcePillLayoutId = useId();
const {
dataset,
datasetSource,
@ -686,6 +691,9 @@ export function DatasetSection() {
{(() => {
// Hub-style sliding-pill segmented control, matching the Hub tabs
// via the shared .hub-tab-toggle / .hub-tab-toggle-pill classes.
// flex-auto buttons share leftover space equally so padding stays
// equal for all labels; the pill sits inside the active button so
// it always matches its bounds.
const sourceTabs: {
value: "huggingface" | "upload" | "s3";
label: string;
@ -696,24 +704,12 @@ export function DatasetSection() {
? []
: [{ value: "s3" as const, label: "Amazon S3" }]),
];
const activeIndex = Math.max(
0,
sourceTabs.findIndex((item) => item.value === datasetSource),
);
return (
<div
role="radiogroup"
aria-label="Dataset source"
className="hub-tab-toggle relative inline-flex h-9 w-full items-center rounded-full"
className="hub-tab-toggle relative flex h-9 w-full items-center rounded-full"
>
<span
aria-hidden="true"
className="hub-tab-toggle-pill pointer-events-none absolute inset-y-0 left-0 rounded-full transition-transform duration-200 ease-out"
style={{
width: `${100 / sourceTabs.length}%`,
transform: `translateX(${activeIndex * 100}%)`,
}}
/>
{sourceTabs.map((item) => (
<button
key={item.value}
@ -732,13 +728,30 @@ export function DatasetSection() {
}
}}
className={cn(
"relative z-10 inline-flex h-9 flex-1 cursor-pointer items-center justify-center rounded-full px-3 text-[12.5px] font-medium transition-colors",
"relative inline-flex h-9 flex-auto cursor-pointer items-center justify-center rounded-full px-3 text-[12.5px] font-medium transition-colors",
datasetSource === item.value
? "text-foreground"
: "text-muted-foreground hover:text-foreground",
)}
>
{item.label}
{datasetSource === item.value && (
<motion.span
aria-hidden="true"
layoutId={sourcePillLayoutId}
className="hub-tab-toggle-pill absolute inset-0 rounded-full"
transition={
reducedMotion
? { duration: 0 }
: {
type: "spring",
stiffness: 500,
damping: 35,
mass: 0.5,
}
}
/>
)}
<span className="relative z-10">{item.label}</span>
</button>
))}
</div>