Files
siftlode/frontend/src/components/SelectedViewChip.tsx
T
peter b4a6569d0d fix(design): the saved-view chip on one line, one Escape per layer, the /watch action row (E28 S3d)
- 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.
2026-09-25 01:40:45 +02:00

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>}
/>
);
}