"use client";
import { IconX, IconDeviceFloppy, IconBookmark } from "@tabler/icons-react";
import type { Icon } from "@tabler/icons-react";
import { cn } from "@/lib/utils";
import { MR_PRESETS, ISSUE_PRESETS, type PresetOption, type PresetGroup } from "./presets";
import type { SavedPreset } from "./use-saved-presets";
import { useTranslation } from "react-i18next";
import { useResponsiveBreakpoint } from "@/hooks/use-responsive-breakpoint";
import { SavedTaskViewDeleteConfirmation } from "@/components/confirmation/saved-task-view-delete-confirmation";
import { useSavedTaskViewDeleteConfirmation } from "@/components/confirmation/use-saved-task-view-delete-confirmation";
export type SidebarSelection = {
kind: "mr" | "issue";
source: "preset" | "saved";
id: string;
};
type PresetsSidebarProps = {
selected: SidebarSelection;
onSelect: (s: SidebarSelection) => void;
savedPresets: SavedPreset[];
onDeleteSaved: (id: string) => void;
canSaveCurrent: boolean;
onSaveCurrent: () => void;
mrPresets?: PresetOption[];
issuePresets?: PresetOption[];
};
function KindToggle({
kind,
onChange,
}: {
kind: "mr" | "issue";
onChange: (k: "mr" | "issue") => void;
}) {
const { t } = useTranslation();
return (
{(["mr", "issue"] as const).map((value) => (
))}
);
}
/**
* `id` is a stable section identifier and `title` is the visible label. They
* were one value: the testid was built as `gitlab-section-${title.toLowerCase()}`,
* so translating the title moved the selector with it — under pseudo the inbox
* section became `gitlab-section-ĩńƀōx`. apps/web/AGENTS.md is explicit that a
* `data-testid` is never translated; deriving one from copy translates it by
* the back door.
*/
function SectionHeader({ id, title }: { id: string; title: string }) {
return (
{title}
);
}
function PresetItem({
label,
Icon: ItemIcon,
active,
onClick,
trailing,
}: {
label: string;
Icon: Icon;
active: boolean;
onClick: () => void;
trailing?: React.ReactNode;
}) {
const onKeyDown = (e: React.KeyboardEvent) => {
// Ignore keys originating from descendants (e.g. the nested delete button),
// otherwise Enter/Space on delete would also fire row selection.
if (e.currentTarget !== e.target) return;
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
onClick();
}
};
return (