mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-02-01 20:10:35 +01:00
add favorites to sidebar
This commit is contained in:
parent
2960a23a63
commit
89b2cb7d30
@ -275,8 +275,7 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.tool-panel__fullscreen-item:hover .tool-panel__fullscreen-star,
|
||||
.tool-panel__fullscreen-star:focus {
|
||||
.tool-panel__fullscreen-item:hover .tool-panel__fullscreen-star {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@ -293,8 +292,7 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.tool-panel__fullscreen-list-item:hover .tool-panel__fullscreen-star-compact,
|
||||
.tool-panel__fullscreen-star-compact:focus {
|
||||
.tool-panel__fullscreen-list-item:hover .tool-panel__fullscreen-star-compact {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,10 @@ import { useToolSections } from "../../hooks/useToolSections";
|
||||
import NoToolsFound from "./shared/NoToolsFound";
|
||||
import { renderToolButtons } from "./shared/renderToolButtons";
|
||||
import Badge from "../shared/Badge";
|
||||
import SubcategoryHeader from "./shared/SubcategoryHeader";
|
||||
import ToolButton from "./toolPicker/ToolButton";
|
||||
import { useToolWorkflow } from "../../contexts/ToolWorkflowContext";
|
||||
import { ToolId } from "../../types/toolId";
|
||||
|
||||
interface ToolPickerProps {
|
||||
selectedToolKey: string | null;
|
||||
@ -62,6 +66,18 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
||||
}, []);
|
||||
|
||||
const { sections: visibleSections } = useToolSections(filteredTools);
|
||||
const { favoriteTools, toolRegistry } = useToolWorkflow();
|
||||
|
||||
const favoriteToolItems = useMemo(() => {
|
||||
return favoriteTools
|
||||
.map((toolId) => {
|
||||
const tool = (toolRegistry as any)[toolId as ToolId] as ToolRegistryEntry | undefined;
|
||||
return tool ? { id: toolId as string, tool } : null;
|
||||
})
|
||||
.filter(Boolean)
|
||||
// Only include ready tools (component or link) and navigational exceptions
|
||||
.filter((item: any) => item && (item.tool.component || item.tool.link || item.id === 'read' || item.id === 'multiTool')) as Array<{ id: string; tool: ToolRegistryEntry }>;
|
||||
}, [favoriteTools, toolRegistry]);
|
||||
|
||||
const quickSection = useMemo(
|
||||
() => visibleSections.find(s => s.key === 'quick'),
|
||||
@ -142,7 +158,7 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
||||
}}
|
||||
onClick={() => scrollTo(quickAccessRef)}
|
||||
>
|
||||
<span style={{ fontSize: "1rem" }}>{t("toolPicker.quickAccess", "QUICK ACCESS")}</span>
|
||||
<span style={{ fontSize: "1rem" }}>{t("toolPicker.recommended", "RECOMMENDED")}</span>
|
||||
<Badge>
|
||||
{quickSection?.subcategories.reduce((acc, sc) => acc + sc.tools.length, 0)}
|
||||
</Badge>
|
||||
@ -150,9 +166,26 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
||||
|
||||
<Box ref={quickAccessRef} w="100%" my="sm">
|
||||
<Stack p="sm" gap="xs">
|
||||
{quickSection?.subcategories.map(sc =>
|
||||
renderToolButtons(t, sc, selectedToolKey, onSelect, false, false)
|
||||
)}
|
||||
{favoriteToolItems.length > 0 && (
|
||||
<Box w="100%">
|
||||
<SubcategoryHeader label={t('toolPanel.fullscreen.favorites', 'Favourites')} mt={0} />
|
||||
<div>
|
||||
{favoriteToolItems.map(({ id, tool }) => (
|
||||
<ToolButton
|
||||
key={`fav-${id}`}
|
||||
id={id}
|
||||
tool={tool}
|
||||
isSelected={selectedToolKey === id}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Box>
|
||||
)}
|
||||
<SubcategoryHeader label={t('toolPanel.recommendedTools', 'Recommended Tools')} />
|
||||
{quickSection?.subcategories.map(sc =>
|
||||
renderToolButtons(t, sc, selectedToolKey, onSelect, false, false)
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
</>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Button } from "@mantine/core";
|
||||
import { ActionIcon, Button } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Tooltip } from "../../shared/Tooltip";
|
||||
import { ToolIcon } from "../../shared/ToolIcon";
|
||||
@ -9,6 +9,10 @@ import { handleUnlessSpecialClick } from "../../../utils/clickHandlers";
|
||||
import FitText from "../../shared/FitText";
|
||||
import { useHotkeys } from "../../../contexts/HotkeyContext";
|
||||
import HotkeyDisplay from "../../hotkeys/HotkeyDisplay";
|
||||
import StarRoundedIcon from '@mui/icons-material/StarRounded';
|
||||
import StarBorderRoundedIcon from '@mui/icons-material/StarBorderRounded';
|
||||
import { useToolWorkflow } from "../../../contexts/ToolWorkflowContext";
|
||||
import { ToolId } from "../../../types/toolId";
|
||||
|
||||
interface ToolButtonProps {
|
||||
id: string;
|
||||
@ -27,6 +31,8 @@ const ToolButton: React.FC<ToolButtonProps> = ({ id, tool, isSelected, onSelect,
|
||||
const { hotkeys } = useHotkeys();
|
||||
const binding = hotkeys[id];
|
||||
const { getToolNavigation } = useToolNavigation();
|
||||
const { isFavorite, toggleFavorite } = useToolWorkflow();
|
||||
const fav = isFavorite(id as ToolId);
|
||||
|
||||
const handleClick = (id: string) => {
|
||||
if (isUnavailable) return;
|
||||
@ -163,10 +169,33 @@ const ToolButton: React.FC<ToolButtonProps> = ({ id, tool, isSelected, onSelect,
|
||||
</Button>
|
||||
);
|
||||
|
||||
const star = !isUnavailable ? (
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
radius="xl"
|
||||
size="xs"
|
||||
onClick={(e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
toggleFavorite(id as ToolId);
|
||||
}}
|
||||
className="tool-button-star"
|
||||
aria-label={fav ? t('toolPanel.fullscreen.unfavorite', 'Remove from favourites') : t('toolPanel.fullscreen.favorite', 'Add to favourites')}
|
||||
>
|
||||
{fav ? (
|
||||
<StarRoundedIcon fontSize="inherit" style={{ color: '#FFC107', fontSize: '1rem' }} />
|
||||
) : (
|
||||
<StarBorderRoundedIcon fontSize="inherit" style={{ fontSize: '1rem' }} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<Tooltip content={tooltipContent} position="right" arrow={true} delay={500}>
|
||||
{buttonElement}
|
||||
</Tooltip>
|
||||
<div className="tool-button-container">
|
||||
{star}
|
||||
<Tooltip content={tooltipContent} position="right" arrow={true} delay={500}>
|
||||
{buttonElement}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -71,6 +71,24 @@
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* Container to enable hover-only favourite star overlay */
|
||||
.tool-button-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tool-button-star {
|
||||
position: absolute;
|
||||
top: 0.35rem;
|
||||
right: 0.35rem;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
z-index: 1; /* lower than sticky section headers */
|
||||
}
|
||||
|
||||
.tool-button-container:hover .tool-button-star {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.search-input-container {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user