show tools with component = null as greyed out tools with coming soon tooltip on hover. Other snmall styling snags

This commit is contained in:
EthanHealy01 2025-08-26 11:51:10 +01:00
parent 87959ae9c4
commit 0306a79cbd
5 changed files with 69 additions and 42 deletions

View File

@ -6,6 +6,7 @@ import VisibilityIcon from "@mui/icons-material/Visibility";
import EditNoteIcon from "@mui/icons-material/EditNote"; import EditNoteIcon from "@mui/icons-material/EditNote";
import FolderIcon from "@mui/icons-material/Folder"; import FolderIcon from "@mui/icons-material/Folder";
import { ModeType, isValidMode } from '../../contexts/NavigationContext'; import { ModeType, isValidMode } from '../../contexts/NavigationContext';
import { Tooltip } from "./Tooltip";
const viewOptionStyle = { const viewOptionStyle = {
display: 'inline-flex', display: 'inline-flex',
@ -17,44 +18,56 @@ const viewOptionStyle = {
} }
// Create view options with icons and loading states // Build view options showing text only for current view; others icon-only with tooltip
const createViewOptions = (switchingTo: ModeType | null) => [ const createViewOptions = (currentView: ModeType, switchingTo: ModeType | null) => [
{ {
label: ( label: (
<Tooltip content="Viewer" position="bottom" arrow={true}>
<div style={viewOptionStyle as React.CSSProperties}> <div style={viewOptionStyle as React.CSSProperties}>
{switchingTo === "viewer" ? ( {currentView === "viewer" ? (
<Loader size="xs" /> <>
{switchingTo === "viewer" ? <Loader size="xs" /> : <VisibilityIcon fontSize="small" />}
<span>Viewer</span>
</>
) : ( ) : (
<VisibilityIcon fontSize="small" /> switchingTo === "viewer" ? <Loader size="xs" /> : <VisibilityIcon fontSize="small" />
)} )}
<span>Read</span>
</div> </div>
</Tooltip>
), ),
value: "viewer", value: "viewer",
}, },
{ {
label: ( label: (
<Tooltip content="Page Editor" position="bottom" arrow={true}>
<div style={viewOptionStyle as React.CSSProperties}> <div style={viewOptionStyle as React.CSSProperties}>
{switchingTo === "pageEditor" ? ( {currentView === "pageEditor" ? (
<Loader size="xs" /> <>
) : ( {switchingTo === "pageEditor" ? <Loader size="xs" /> : <EditNoteIcon fontSize="small" />}
<EditNoteIcon fontSize="small" />
)}
<span>Page Editor</span> <span>Page Editor</span>
</>
) : (
switchingTo === "pageEditor" ? <Loader size="xs" /> : <EditNoteIcon fontSize="small" />
)}
</div> </div>
</Tooltip>
), ),
value: "pageEditor", value: "pageEditor",
}, },
{ {
label: ( label: (
<Tooltip content="Active Files" position="bottom" arrow={true}>
<div style={viewOptionStyle as React.CSSProperties}> <div style={viewOptionStyle as React.CSSProperties}>
{switchingTo === "fileEditor" ? ( {currentView === "fileEditor" ? (
<Loader size="xs" /> <>
{switchingTo === "fileEditor" ? <Loader size="xs" /> : <FolderIcon fontSize="small" />}
<span>Active Files</span>
</>
) : ( ) : (
<FolderIcon fontSize="small" /> switchingTo === "fileEditor" ? <Loader size="xs" /> : <FolderIcon fontSize="small" />
)} )}
<span>File Manager</span>
</div> </div>
</Tooltip>
), ),
value: "fileEditor", value: "fileEditor",
}, },
@ -103,11 +116,10 @@ const TopControls = ({
{!isToolSelected && ( {!isToolSelected && (
<div className="flex justify-center mt-[0.5rem]"> <div className="flex justify-center mt-[0.5rem]">
<SegmentedControl <SegmentedControl
data={createViewOptions(switchingTo)} data={createViewOptions(currentView, switchingTo)}
value={currentView} value={currentView}
onChange={handleViewChange} onChange={handleViewChange}
color="blue" color="blue"
radius="xl"
fullWidth fullWidth
className={isRainbowMode ? rainbowStyles.rainbowSegmentedControl : ''} className={isRainbowMode ? rainbowStyles.rainbowSegmentedControl : ''}
style={{ style={{
@ -118,13 +130,18 @@ const TopControls = ({
styles={{ styles={{
root: { root: {
borderRadius: 9999, borderRadius: 9999,
maxHeight: '2.6rem',
}, },
control: { control: {
borderRadius: 9999, borderRadius: 9999,
}, },
indicator: { indicator: {
borderRadius: 9999, borderRadius: 9999,
maxHeight: '2rem',
}, },
label: {
paddingTop: '0rem',
}
}} }}
/> />
</div> </div>

View File

@ -12,7 +12,9 @@ interface ToolButtonProps {
} }
const ToolButton: React.FC<ToolButtonProps> = ({ id, tool, isSelected, onSelect }) => { const ToolButton: React.FC<ToolButtonProps> = ({ id, tool, isSelected, onSelect }) => {
const isUnavailable = !tool.component && !tool.link;
const handleClick = (id: string) => { const handleClick = (id: string) => {
if (isUnavailable) return;
if (tool.link) { if (tool.link) {
// Open external link in new tab // Open external link in new tab
window.open(tool.link, '_blank', 'noopener,noreferrer'); window.open(tool.link, '_blank', 'noopener,noreferrer');
@ -22,8 +24,12 @@ const ToolButton: React.FC<ToolButtonProps> = ({ id, tool, isSelected, onSelect
onSelect(id); onSelect(id);
}; };
const tooltipContent = isUnavailable
? (<span><strong>Coming soon:</strong> {tool.description}</span>)
: tool.description;
return ( return (
<Tooltip content={tool.description} position="right" arrow={true} delay={500}> <Tooltip content={tooltipContent} position="right" arrow={true} delay={500}>
<Button <Button
variant={isSelected ? "filled" : "subtle"} variant={isSelected ? "filled" : "subtle"}
onClick={()=> handleClick(id)} onClick={()=> handleClick(id)}
@ -32,15 +38,16 @@ const ToolButton: React.FC<ToolButtonProps> = ({ id, tool, isSelected, onSelect
fullWidth fullWidth
justify="flex-start" justify="flex-start"
className="tool-button" className="tool-button"
styles={{ root: { borderRadius: 0, color: "var(--tools-text-and-icon-color)" } }} aria-disabled={isUnavailable}
styles={{ root: { borderRadius: 0, color: "var(--tools-text-and-icon-color)", cursor: isUnavailable ? 'not-allowed' : undefined } }}
> >
<div className="tool-button-icon" style={{ color: "var(--tools-text-and-icon-color)", marginRight: "0.5rem", transform: "scale(0.8)", transformOrigin: "center" }}>{tool.icon}</div> <div className="tool-button-icon" style={{ color: "var(--tools-text-and-icon-color)", marginRight: "0.5rem", transform: "scale(0.8)", transformOrigin: "center", opacity: isUnavailable ? 0.25 : 1 }}>{tool.icon}</div>
<FitText <FitText
text={tool.name} text={tool.name}
lines={1} lines={1}
minimumFontScale={0.8} minimumFontScale={0.8}
as="span" as="span"
style={{ display: 'inline-block', maxWidth: '100%' }} style={{ display: 'inline-block', maxWidth: '100%', opacity: isUnavailable ? 0.25 : 1 }}
/> />
</Button> </Button>
</Tooltip> </Tooltip>

View File

@ -550,12 +550,14 @@ const Viewer = ({
justifyContent: "center", justifyContent: "center",
pointerEvents: "none", pointerEvents: "none",
background: "transparent", background: "transparent",
}} }}
> >
<Paper <Paper
radius="xl xl 0 0" radius="xl xl 0 0"
shadow="sm" shadow="sm"
p={12} p={12}
pb={24}
style={{ style={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",

View File

@ -40,7 +40,7 @@ import OCRSettings from '../components/tools/ocr/OCRSettings';
import ConvertSettings from '../components/tools/convert/ConvertSettings'; import ConvertSettings from '../components/tools/convert/ConvertSettings';
import ChangePermissionsSettings from '../components/tools/changePermissions/ChangePermissionsSettings'; import ChangePermissionsSettings from '../components/tools/changePermissions/ChangePermissionsSettings';
const showPlaceholderTools = false; // For development purposes. Allows seeing the full list of tools, even if they're unimplemented const showPlaceholderTools = true; // Show all tools; grey out unavailable ones in UI
// Hook to get the translated tool registry // Hook to get the translated tool registry
export function useFlatToolRegistry(): ToolRegistry { export function useFlatToolRegistry(): ToolRegistry {
@ -671,7 +671,7 @@ export function useFlatToolRegistry(): ToolRegistry {
if (showPlaceholderTools) { if (showPlaceholderTools) {
return allTools; return allTools;
} else { }
const filteredTools = Object.keys(allTools) const filteredTools = Object.keys(allTools)
.filter(key => allTools[key].component !== null || allTools[key].link) .filter(key => allTools[key].component !== null || allTools[key].link)
.reduce((obj, key) => { .reduce((obj, key) => {
@ -679,6 +679,5 @@ export function useFlatToolRegistry(): ToolRegistry {
return obj; return obj;
}, {} as ToolRegistry); }, {} as ToolRegistry);
return filteredTools; return filteredTools;
}
}, [t]); // Only re-compute when translations change }, [t]); // Only re-compute when translations change
} }

View File

@ -64,7 +64,9 @@ export function useToolSections(filteredTools: [string /* FIX ME: Should be Tool
Object.entries(subs).forEach(([s, tools]) => { Object.entries(subs).forEach(([s, tools]) => {
const subcategoryId = s as SubcategoryId; const subcategoryId = s as SubcategoryId;
if (!quick[subcategoryId]) quick[subcategoryId] = []; if (!quick[subcategoryId]) quick[subcategoryId] = [];
quick[subcategoryId].push(...tools); // Only include ready tools (have a component or external link) in Quick Access
const readyTools = tools.filter(({ tool }) => tool.component !== null || !!tool.link);
quick[subcategoryId].push(...readyTools);
}); });
} }
}); });