fix(issues): keep header controls horizontally scrollable

This commit is contained in:
Naiyuan Qing
2026-06-01 16:19:05 +08:00
parent c3021adb4d
commit d2c2fc1781
2 changed files with 126 additions and 122 deletions

View File

@@ -538,68 +538,70 @@ export function IssuesHeader({
const scopeLabel = t(($) => $.scope[SCOPE_LABEL_KEY[scope]]);
return (
<div className="flex h-12 shrink-0 items-center justify-between gap-2 px-4">
{/* Left: scope buttons */}
<div className="hidden items-center gap-1 md:flex">
{SCOPE_VALUES.map((s) => (
<Tooltip key={s}>
<TooltipTrigger
render={
<Button
variant="outline"
size="sm"
className={
scope === s
? "bg-accent text-accent-foreground hover:bg-accent/80"
: "text-muted-foreground"
}
onClick={() => setScope(s)}
>
<div className="h-12 shrink-0 overflow-x-auto px-4 [-webkit-overflow-scrolling:touch]">
<div className="flex h-full w-max min-w-full items-center justify-between gap-2">
{/* Left: scope buttons */}
<div className="hidden shrink-0 items-center gap-1 md:flex">
{SCOPE_VALUES.map((s) => (
<Tooltip key={s}>
<TooltipTrigger
render={
<Button
variant="outline"
size="sm"
className={
scope === s
? "bg-accent text-accent-foreground hover:bg-accent/80"
: "text-muted-foreground"
}
onClick={() => setScope(s)}
>
{t(($) => $.scope[SCOPE_LABEL_KEY[s]])}
</Button>
}
/>
<TooltipContent side="bottom">{t(($) => $.scope[SCOPE_DESC_KEY[s]])}</TooltipContent>
</Tooltip>
))}
</div>
<DropdownMenu>
<DropdownMenuTrigger
render={
<Button
variant="outline"
size="sm"
className="shrink-0 gap-1 text-muted-foreground md:hidden"
>
<span className="truncate">{scopeLabel}</span>
<ChevronDown className="size-3 text-muted-foreground" />
</Button>
}
/>
<DropdownMenuContent align="start" className="w-auto">
<DropdownMenuRadioGroup value={scope} onValueChange={(value) => setScope(value as IssuesScope)}>
{SCOPE_VALUES.map((s) => (
<DropdownMenuRadioItem key={s} value={s}>
{t(($) => $.scope[SCOPE_LABEL_KEY[s]])}
</Button>
}
/>
<TooltipContent side="bottom">{t(($) => $.scope[SCOPE_DESC_KEY[s]])}</TooltipContent>
</Tooltip>
))}
</div>
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger
render={
<Button
variant="outline"
size="sm"
className="min-w-0 gap-1 text-muted-foreground md:hidden"
>
<span className="truncate">{scopeLabel}</span>
<ChevronDown className="size-3 text-muted-foreground" />
</Button>
}
/>
<DropdownMenuContent align="start" className="w-auto">
<DropdownMenuRadioGroup value={scope} onValueChange={(value) => setScope(value as IssuesScope)}>
{SCOPE_VALUES.map((s) => (
<DropdownMenuRadioItem key={s} value={s}>
{t(($) => $.scope[SCOPE_LABEL_KEY[s]])}
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<div className="flex min-w-0 items-center gap-1">
{agentRunningFilter && (
<span className="mr-1 hidden text-xs text-muted-foreground md:inline">
{t(($) => $.agent_activity.filter_active_label)}
</span>
)}
<WorkspaceAgentWorkingChip
value={agentRunningFilter}
onToggle={toggleAgentRunningFilter}
scopedIssueIds={scopedIssueIds}
/>
<IssueDisplayControls scopedIssues={scopedIssues} allowGantt={allowGantt} />
<div className="flex shrink-0 items-center gap-1">
{agentRunningFilter && (
<span className="mr-1 hidden text-xs text-muted-foreground md:inline">
{t(($) => $.agent_activity.filter_active_label)}
</span>
)}
<WorkspaceAgentWorkingChip
value={agentRunningFilter}
onToggle={toggleAgentRunningFilter}
scopedIssueIds={scopedIssueIds}
/>
<IssueDisplayControls scopedIssues={scopedIssues} allowGantt={allowGantt} />
</div>
</div>
</div>
);
@@ -681,7 +683,7 @@ export function IssueDisplayControls({
const controlButtonClass = "h-8 w-8 gap-1 px-0 text-muted-foreground md:h-7 md:w-auto md:px-2.5";
return (
<div className="flex items-center gap-1">
<div className="flex shrink-0 items-center gap-1">
{/* Filter */}
<DropdownMenu>
<Tooltip>

View File

@@ -37,70 +37,72 @@ export function MyIssuesHeader({ allIssues }: { allIssues: Issue[] }) {
const scopeLabel = SCOPES.find((s) => s.value === scope)?.label ?? SCOPES[0]?.label;
return (
<div className="flex h-12 shrink-0 items-center justify-between gap-2 px-4">
<div className="hidden items-center gap-1 md:flex">
{SCOPES.map((s) => (
<Tooltip key={s.value}>
<TooltipTrigger
render={
<Button
variant="outline"
size="sm"
className={
scope === s.value
? "bg-accent text-accent-foreground hover:bg-accent/80"
: "text-muted-foreground"
}
onClick={() => act.setScope(s.value)}
>
{s.label}
</Button>
}
/>
<TooltipContent side="bottom">{s.description}</TooltipContent>
</Tooltip>
))}
</div>
<div className="h-12 shrink-0 overflow-x-auto px-4 [-webkit-overflow-scrolling:touch]">
<div className="flex h-full w-max min-w-full items-center justify-between gap-2">
<div className="hidden shrink-0 items-center gap-1 md:flex">
{SCOPES.map((s) => (
<Tooltip key={s.value}>
<TooltipTrigger
render={
<Button
variant="outline"
size="sm"
className={
scope === s.value
? "bg-accent text-accent-foreground hover:bg-accent/80"
: "text-muted-foreground"
}
onClick={() => act.setScope(s.value)}
>
{s.label}
</Button>
}
/>
<TooltipContent side="bottom">{s.description}</TooltipContent>
</Tooltip>
))}
</div>
<DropdownMenu>
<DropdownMenuTrigger
render={
<Button
variant="outline"
size="sm"
className="min-w-0 gap-1 text-muted-foreground md:hidden"
<DropdownMenu>
<DropdownMenuTrigger
render={
<Button
variant="outline"
size="sm"
className="shrink-0 gap-1 text-muted-foreground md:hidden"
>
<span className="truncate">{scopeLabel}</span>
<ChevronDown className="size-3 text-muted-foreground" />
</Button>
}
/>
<DropdownMenuContent align="start" className="w-auto">
<DropdownMenuRadioGroup
value={scope}
onValueChange={(value) => act.setScope(value as MyIssuesScope)}
>
<span className="truncate">{scopeLabel}</span>
<ChevronDown className="size-3 text-muted-foreground" />
</Button>
}
/>
<DropdownMenuContent align="start" className="w-auto">
<DropdownMenuRadioGroup
value={scope}
onValueChange={(value) => act.setScope(value as MyIssuesScope)}
>
{SCOPES.map((s) => (
<DropdownMenuRadioItem key={s.value} value={s.value}>
{s.label}
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
{SCOPES.map((s) => (
<DropdownMenuRadioItem key={s.value} value={s.value}>
{s.label}
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<div className="flex min-w-0 items-center gap-1">
{agentRunningFilter && (
<span className="mr-1 hidden text-xs text-muted-foreground md:inline">
{tIssues(($) => $.agent_activity.filter_active_label)}
</span>
)}
<WorkspaceAgentWorkingChip
value={agentRunningFilter}
onToggle={act.toggleAgentRunningFilter}
scopedIssueIds={scopedIssueIds}
/>
<IssueDisplayControls scopedIssues={allIssues} />
<div className="flex shrink-0 items-center gap-1">
{agentRunningFilter && (
<span className="mr-1 hidden text-xs text-muted-foreground md:inline">
{tIssues(($) => $.agent_activity.filter_active_label)}
</span>
)}
<WorkspaceAgentWorkingChip
value={agentRunningFilter}
onToggle={act.toggleAgentRunningFilter}
scopedIssueIds={scopedIssueIds}
/>
<IssueDisplayControls scopedIssues={allIssues} />
</div>
</div>
</div>
);