112 lines
3.7 KiB
TypeScript
112 lines
3.7 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { IconInfoCircle } from "@tabler/icons-react";
|
|
import {
|
|
Drawer,
|
|
DrawerContent,
|
|
DrawerDescription,
|
|
DrawerHeader,
|
|
DrawerTitle,
|
|
DrawerTrigger,
|
|
} from "@kandev/ui/drawer";
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@kandev/ui/select";
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip";
|
|
import { useTranslation } from "react-i18next";
|
|
import { TASK_PRIORITY_LABEL_KEYS, TASK_PRIORITY_TOKENS } from "@/lib/tasks/task-priority";
|
|
import { useTouchDrawer } from "@/hooks/use-compact-task-chrome";
|
|
import type { TaskPriority } from "@/lib/types/http";
|
|
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
|
|
|
function PriorityInfo({ label, description }: { label: string; description: string }) {
|
|
const usesTouchDrawer = useTouchDrawer();
|
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
const trigger = (
|
|
<button
|
|
type="button"
|
|
className={`${controlSizingClassName("icon")} cursor-pointer rounded-md border-0 bg-transparent p-0 text-muted-foreground/70 hover:bg-transparent hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`}
|
|
aria-label={label}
|
|
aria-expanded={usesTouchDrawer ? drawerOpen : undefined}
|
|
aria-haspopup={usesTouchDrawer ? "dialog" : undefined}
|
|
data-testid="task-create-priority-setting-info"
|
|
>
|
|
<IconInfoCircle className="h-3.5 w-3.5" aria-hidden="true" />
|
|
</button>
|
|
);
|
|
|
|
if (usesTouchDrawer) {
|
|
return (
|
|
<Drawer open={drawerOpen} onOpenChange={setDrawerOpen}>
|
|
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
|
<DrawerContent>
|
|
<DrawerHeader>
|
|
<DrawerTitle>{label}</DrawerTitle>
|
|
<DrawerDescription>{description}</DrawerDescription>
|
|
</DrawerHeader>
|
|
</DrawerContent>
|
|
</Drawer>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>{trigger}</TooltipTrigger>
|
|
<TooltipContent side="top" className="z-[60] max-w-xs">
|
|
{description}
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
export function TaskCreatePrioritySelect({
|
|
value,
|
|
onChange,
|
|
disabled,
|
|
}: {
|
|
value: TaskPriority;
|
|
onChange: (value: TaskPriority) => void;
|
|
disabled?: boolean;
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const priorityLabel = t("kanban:priority");
|
|
const priorityInfoLabel = t("task:priorityInfoLabel");
|
|
const priorityInfo = t("task:priorityInfo");
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
<div className="flex min-h-11 shrink-0 items-center gap-1 text-xs text-muted-foreground md:min-h-6">
|
|
<label htmlFor="task-create-priority-select">{priorityLabel}</label>
|
|
<PriorityInfo label={priorityInfoLabel} description={priorityInfo} />
|
|
</div>
|
|
<Select
|
|
value={value}
|
|
onValueChange={(next) => onChange(next as TaskPriority)}
|
|
disabled={disabled}
|
|
>
|
|
<SelectTrigger
|
|
id="task-create-priority-select"
|
|
data-testid="task-create-priority-select"
|
|
aria-label={priorityLabel}
|
|
className={controlSizingClassName(
|
|
"standard",
|
|
"w-32 border-border/60 bg-muted/30 hover:bg-muted/60",
|
|
)}
|
|
>
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{TASK_PRIORITY_TOKENS.map((token) => (
|
|
<SelectItem
|
|
key={token}
|
|
value={token}
|
|
data-testid={`task-create-priority-option-${token}`}
|
|
className="min-h-11 sm:min-h-7"
|
|
>
|
|
{t(TASK_PRIORITY_LABEL_KEYS[token])}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
);
|
|
}
|