- SelectTrigger lays its toolbar value out as a row; the saved-view chip passes its glyph and modified dot through the icon/trailing slots (an <svg> is display:block and broke the chip in two). - One Escape in a dialog's open list closed the list AND the dialog: the list's close flushes synchronously and pops its layer before the dialog's window listener runs. takeEscape() is the one close-on-Escape test (topmost AND not yet taken); Modal, the Welcome lightbox and useLayer use it, and keymap.dispatch ignores a taken Escape. - /watch: the Download sits on the toolbar rung, level with the Repeat chip.
32 lines
1.2 KiB
TypeScript
32 lines
1.2 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
|
import { Bookmark } from "lucide-react";
|
|
import SavedViewsPopover from "./SavedViewsPopover";
|
|
import { useSavedViews } from "./savedViewsContext";
|
|
|
|
// The active personal view, shown as the leading pill before the active-filter chip row. Styled like
|
|
// the toolbar's FilterSelect pills; a warn-coloured dot appears when the live filters have diverged
|
|
// from the saved view. Clicking it opens the saved-views picker to switch views. Renders nothing when
|
|
// no view is active (nothing applied and the filters match no saved view).
|
|
export default function SelectedViewChip() {
|
|
const { t } = useTranslation();
|
|
const { displayView, isDirty } = useSavedViews();
|
|
if (!displayView) return null;
|
|
return (
|
|
<SavedViewsPopover
|
|
ariaLabel={t("views.saved")}
|
|
toolbar
|
|
icon={<Bookmark className="h-3.5 w-3.5 shrink-0 text-accent" aria-hidden="true" />}
|
|
trailing={
|
|
isDirty && (
|
|
<span
|
|
className="h-1.5 w-1.5 shrink-0 rounded-full bg-warn"
|
|
title={t("views.modified")}
|
|
aria-label={t("views.modified")}
|
|
/>
|
|
)
|
|
}
|
|
trigger={<span className="block max-w-40 truncate">{displayView.name}</span>}
|
|
/>
|
|
);
|
|
}
|