address reviews and add external link support

This commit is contained in:
Anthony Stirling 2025-09-03 12:29:14 +01:00
parent b6d8f5cece
commit 66ea1c96b2
5 changed files with 115 additions and 84 deletions

View File

@ -47,30 +47,28 @@ const AllToolsNavButton: React.FC<AllToolsNavButtonProps> = ({ activeButton, set
return ( return (
<Tooltip content={t("quickAccess.allTools", "All Tools")} position="right" arrow containerStyle={{ marginTop: "-1rem" }} maxWidth={200}> <Tooltip content={t("quickAccess.allTools", "All Tools")} position="right" arrow containerStyle={{ marginTop: "-1rem" }} maxWidth={200}>
<Anchor <div className="flex flex-col items-center gap-1 mt-4 mb-2">
href={navProps.href} <ActionIcon
onClick={handleNavClick} component="a"
style={{ textDecoration: 'none', color: 'inherit' }} href={navProps.href}
> onClick={handleNavClick}
<div className="flex flex-col items-center gap-1 mt-4 mb-2"> size={'lg'}
<ActionIcon variant="subtle"
size={'lg'} style={{
variant="subtle" backgroundColor: isActive ? 'var(--icon-tools-bg)' : 'var(--icon-inactive-bg)',
style={{ color: isActive ? 'var(--icon-tools-color)' : 'var(--icon-inactive-color)',
backgroundColor: isActive ? 'var(--icon-tools-bg)' : 'var(--icon-inactive-bg)', border: 'none',
color: isActive ? 'var(--icon-tools-color)' : 'var(--icon-inactive-color)', borderRadius: '8px',
border: 'none', textDecoration: 'none'
borderRadius: '8px', }}
}} className={isActive ? 'activeIconScale' : ''}
className={isActive ? 'activeIconScale' : ''} >
> {iconNode}
{iconNode} </ActionIcon>
</ActionIcon> <span className={`all-tools-text ${isActive ? 'active' : 'inactive'}`}>
<span className={`all-tools-text ${isActive ? 'active' : 'inactive'}`}> {t("quickAccess.allTools", "All Tools")}
{t("quickAccess.allTools", "All Tools")} </span>
</span> </div>
</div>
</Anchor>
</Tooltip> </Tooltip>
); );
}; };

View File

@ -60,8 +60,33 @@ const QuickAccessBar = forwardRef<HTMLDivElement>(({
config.onClick(); config.onClick();
}; };
const buttonElement = ( // Render with URL navigation if available, otherwise regular div
<div className="flex flex-col items-center gap-1" style={{ marginTop: index === 0 ? '0.5rem' : "0rem" }}> if (navProps) {
return (
<div key={config.id} className="flex flex-col items-center gap-1" style={{ marginTop: index === 0 ? '0.5rem' : "0rem" }}>
<ActionIcon
component="a"
href={navProps.href}
onClick={(e: React.MouseEvent) => handleClick(e)}
size={isActive ? (config.size || 'lg') : 'lg'}
variant="subtle"
style={getNavButtonStyle(config, activeButton, isFilesModalOpen, configModalOpen, selectedToolKey, leftPanelView)}
className={isActive ? 'activeIconScale' : ''}
data-testid={`${config.id}-button`}
>
<span className="iconContainer">
{config.icon}
</span>
</ActionIcon>
<span className={`button-text ${isActive ? 'active' : 'inactive'}`}>
{config.name}
</span>
</div>
);
}
return (
<div key={config.id} className="flex flex-col items-center gap-1" style={{ marginTop: index === 0 ? '0.5rem' : "0rem" }}>
<ActionIcon <ActionIcon
size={isActive ? (config.size || 'lg') : 'lg'} size={isActive ? (config.size || 'lg') : 'lg'}
variant="subtle" variant="subtle"
@ -79,22 +104,6 @@ const QuickAccessBar = forwardRef<HTMLDivElement>(({
</span> </span>
</div> </div>
); );
// Wrap with Anchor if it has URL navigation
if (navProps) {
return (
<Anchor
key={config.id}
href={navProps.href}
onClick={handleClick}
style={{ textDecoration: 'none', color: 'inherit' }}
>
{buttonElement}
</Anchor>
);
}
return <div key={config.id}>{buttonElement}</div>;
}; };

View File

@ -143,7 +143,8 @@ const ActiveToolButton: React.FC<ActiveToolButtonProps> = ({ activeButton, setAc
<div className="current-tool-content"> <div className="current-tool-content">
<div className="flex flex-col items-center gap-1"> <div className="flex flex-col items-center gap-1">
<Tooltip content={isBackHover ? 'Back to all tools' : indicatorTool.name} position="right" arrow maxWidth={140}> <Tooltip content={isBackHover ? 'Back to all tools' : indicatorTool.name} position="right" arrow maxWidth={140}>
<Anchor <ActionIcon
component="a"
href={getHomeNavigation().href} href={getHomeNavigation().href}
onClick={(e: React.MouseEvent) => { onClick={(e: React.MouseEvent) => {
// Check if it's a special click (middle click, ctrl+click, etc.) // Check if it's a special click (middle click, ctrl+click, etc.)
@ -156,31 +157,28 @@ const ActiveToolButton: React.FC<ActiveToolButtonProps> = ({ activeButton, setAc
setActiveButton('tools'); setActiveButton('tools');
handleBackToTools(); handleBackToTools();
}} }}
style={{ textDecoration: 'none', color: 'inherit' }} size={'xl'}
variant="subtle"
onMouseEnter={() => setIsBackHover(true)}
onMouseLeave={() => setIsBackHover(false)}
aria-label={isBackHover ? 'Back to all tools' : indicatorTool.name}
style={{
backgroundColor: isBackHover ? 'var(--color-gray-300)' : 'var(--icon-tools-bg)',
color: isBackHover ? '#fff' : 'var(--icon-tools-color)',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
textDecoration: 'none'
}}
> >
<ActionIcon <span className="iconContainer">
size={'xl'} {isBackHover ? (
variant="subtle" <ArrowBackRoundedIcon sx={{ fontSize: '1.5rem' }} />
onMouseEnter={() => setIsBackHover(true)} ) : (
onMouseLeave={() => setIsBackHover(false)} indicatorTool.icon
aria-label={isBackHover ? 'Back to all tools' : indicatorTool.name} )}
style={{ </span>
backgroundColor: isBackHover ? 'var(--color-gray-300)' : 'var(--icon-tools-bg)', </ActionIcon>
color: isBackHover ? '#fff' : 'var(--icon-tools-color)',
border: 'none',
borderRadius: '8px',
cursor: 'pointer'
}}
>
<span className="iconContainer">
{isBackHover ? (
<ArrowBackRoundedIcon sx={{ fontSize: '1.5rem' }} />
) : (
indicatorTool.icon
)}
</span>
</ActionIcon>
</Anchor>
</Tooltip> </Tooltip>
<FitText <FitText
as="span" as="span"

View File

@ -48,27 +48,53 @@ const ToolButton: React.FC<ToolButtonProps> = ({ id, tool, isSelected, onSelect
</> </>
); );
const handleExternalClick = (e: React.MouseEvent) => {
// Check if it's a special click (middle click, ctrl+click, etc.)
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) {
return; // Let browser handle it via href
}
// For regular clicks, prevent default and use window.open
e.preventDefault();
handleClick(id);
};
const buttonElement = navProps ? ( const buttonElement = navProps ? (
// For tools with URLs, wrap in anchor for proper link behavior // For internal tools with URLs, render Button as an anchor for proper link behavior
<Anchor <Button
component="a"
href={navProps.href} href={navProps.href}
onClick={navProps.onClick} onClick={navProps.onClick}
style={{ textDecoration: 'none', color: 'inherit' }} variant={isSelected ? "filled" : "subtle"}
size="sm"
radius="md"
fullWidth
justify="flex-start"
className="tool-button"
styles={{ root: { borderRadius: 0, color: "var(--tools-text-and-icon-color)" } }}
> >
<Button {buttonContent}
variant={isSelected ? "filled" : "subtle"} </Button>
size="sm" ) : tool.link && !isUnavailable ? (
radius="md" // For external links, render Button as an anchor with proper href
fullWidth <Button
justify="flex-start" component="a"
className="tool-button" href={tool.link}
styles={{ root: { borderRadius: 0, color: "var(--tools-text-and-icon-color)" } }} target="_blank"
> rel="noopener noreferrer"
{buttonContent} onClick={handleExternalClick}
</Button> variant={isSelected ? "filled" : "subtle"}
</Anchor> size="sm"
radius="md"
fullWidth
justify="flex-start"
className="tool-button"
styles={{ root: { borderRadius: 0, color: "var(--tools-text-and-icon-color)" } }}
>
{buttonContent}
</Button>
) : ( ) : (
// For external links and unavailable tools, use regular button // For unavailable tools, use regular button
<Button <Button
variant={isSelected ? "filled" : "subtle"} variant={isSelected ? "filled" : "subtle"}
onClick={() => handleClick(id)} onClick={() => handleClick(id)}

View File

@ -46,7 +46,7 @@ export function useToolNavigation(): {
}; };
return { href, onClick }; return { href, onClick };
}, [actions, handleToolSelect]); }, [handleToolSelect]);
return { getToolNavigation }; return { getToolNavigation };
} }