mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-03-04 02:20:19 +01:00
options everywhere!
This commit is contained in:
@@ -1981,3 +1981,35 @@ toolPanel.legacy.favorites=Favourites
|
||||
toolPanel.legacy.recent=Recently used
|
||||
toolPanel.legacy.favorite=Add to favourites
|
||||
toolPanel.legacy.unfavorite=Remove from favourites
|
||||
toolPanel.legacy.settings.title=Customise appearance
|
||||
toolPanel.legacy.settings.iconBackground.label=Tool icon background
|
||||
toolPanel.legacy.settings.iconBackground.description=When to show coloured backgrounds behind tool icons
|
||||
toolPanel.legacy.settings.iconBackground.none=None
|
||||
toolPanel.legacy.settings.iconBackground.hover=On hover
|
||||
toolPanel.legacy.settings.iconBackground.always=Always
|
||||
toolPanel.legacy.settings.iconColor.label=Tool icon colour
|
||||
toolPanel.legacy.settings.iconColor.description=Colour scheme for tool icons
|
||||
toolPanel.legacy.settings.iconColor.colored=Coloured
|
||||
toolPanel.legacy.settings.iconColor.vibrant=Vibrant
|
||||
toolPanel.legacy.settings.iconColor.monochrome=Monochrome
|
||||
toolPanel.legacy.settings.sectionTitle.label=Section titles
|
||||
toolPanel.legacy.settings.sectionTitle.description=Colour for category section titles
|
||||
toolPanel.legacy.settings.sectionTitle.colored=Coloured
|
||||
toolPanel.legacy.settings.sectionTitle.neutral=Neutral
|
||||
toolPanel.legacy.settings.headerIcon.label=Section header icons
|
||||
toolPanel.legacy.settings.headerIcon.description=Colour for Favourites/Recent icons
|
||||
toolPanel.legacy.settings.headerIcon.colored=Coloured
|
||||
toolPanel.legacy.settings.headerIcon.monochrome=Monochrome
|
||||
toolPanel.legacy.settings.headerBadge.label=Section header badges
|
||||
toolPanel.legacy.settings.headerBadge.description=Colour for count badges in section headers
|
||||
toolPanel.legacy.settings.headerBadge.colored=Coloured
|
||||
toolPanel.legacy.settings.headerBadge.neutral=Neutral
|
||||
toolPanel.legacy.settings.border.label=Tool item borders
|
||||
toolPanel.legacy.settings.border.description=Show borders around tool items
|
||||
toolPanel.legacy.settings.border.visible=Visible
|
||||
toolPanel.legacy.settings.border.hidden=Hidden
|
||||
toolPanel.legacy.settings.hover.label=Hover effect intensity
|
||||
toolPanel.legacy.settings.hover.description=How prominent the hover effect should be
|
||||
toolPanel.legacy.settings.hover.subtle=Subtle
|
||||
toolPanel.legacy.settings.hover.moderate=Moderate
|
||||
toolPanel.legacy.settings.hover.prominent=Prominent
|
||||
|
||||
@@ -33,7 +33,7 @@ const LegacyToolList = ({
|
||||
}: LegacyToolListProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { hotkeys } = useHotkeys();
|
||||
const { toolRegistry, recentTools, favoriteTools, toggleFavorite, isFavorite } = useToolWorkflow();
|
||||
const { toolRegistry, recentTools, favoriteTools, toggleFavorite, isFavorite, legacyToolSettings } = useToolWorkflow();
|
||||
|
||||
const { sections, searchGroups } = useToolSections(filteredTools, searchQuery);
|
||||
|
||||
@@ -85,6 +85,38 @@ const LegacyToolList = ({
|
||||
? 'tool-panel__legacy-groups tool-panel__legacy-groups--detailed'
|
||||
: 'tool-panel__legacy-groups tool-panel__legacy-groups--compact';
|
||||
|
||||
const getItemClasses = (isDetailed: boolean) => {
|
||||
const base = isDetailed ? 'tool-panel__legacy-item--detailed' : '';
|
||||
const border = legacyToolSettings.toolItemBorder === 'hidden' ? 'tool-panel__legacy-item--no-border' : '';
|
||||
const hover = `tool-panel__legacy-item--hover-${legacyToolSettings.hoverIntensity}`;
|
||||
return [base, border, hover].filter(Boolean).join(' ');
|
||||
};
|
||||
|
||||
const getIconBackground = (categoryColor: string, isDetailed: boolean) => {
|
||||
if (legacyToolSettings.iconBackground === 'none' || legacyToolSettings.iconBackground === 'hover') {
|
||||
return 'transparent';
|
||||
}
|
||||
|
||||
const baseColor = isDetailed ? 'var(--legacy-bg-icon-detailed)' : 'var(--legacy-bg-icon-compact)';
|
||||
const blend1 = isDetailed ? '18%' : '15%';
|
||||
const blend2 = isDetailed ? '8%' : '6%';
|
||||
|
||||
return `linear-gradient(135deg,
|
||||
color-mix(in srgb, ${categoryColor} ${blend1}, ${baseColor}),
|
||||
color-mix(in srgb, ${categoryColor} ${blend2}, ${baseColor})
|
||||
)`;
|
||||
};
|
||||
|
||||
const getIconStyle = () => {
|
||||
if (legacyToolSettings.iconColorScheme === 'monochrome') {
|
||||
return { filter: 'grayscale(1) opacity(0.8)' };
|
||||
}
|
||||
if (legacyToolSettings.iconColorScheme === 'vibrant') {
|
||||
return { filter: 'saturate(1.5) brightness(1.1)' };
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
// Helper function to render a tool item
|
||||
const renderToolItem = (id: string, tool: ToolRegistryEntry) => {
|
||||
const matchedText = matchedTextMap.get(id);
|
||||
@@ -123,25 +155,37 @@ const LegacyToolList = ({
|
||||
|
||||
// Detailed view
|
||||
if (showDescriptions) {
|
||||
const iconBg = getIconBackground(categoryColor, true);
|
||||
const iconClasses = legacyToolSettings.iconBackground === 'hover'
|
||||
? 'tool-panel__legacy-icon tool-panel__legacy-icon--hover-bg'
|
||||
: 'tool-panel__legacy-icon';
|
||||
|
||||
const hoverBgDetailed = legacyToolSettings.iconBackground === 'hover'
|
||||
? `linear-gradient(135deg,
|
||||
color-mix(in srgb, ${categoryColor} 18%, var(--legacy-bg-icon-detailed)),
|
||||
color-mix(in srgb, ${categoryColor} 8%, var(--legacy-bg-icon-detailed))
|
||||
)`
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={id}
|
||||
type="button"
|
||||
className={`tool-panel__legacy-item tool-panel__legacy-item--detailed ${isSelected ? 'tool-panel__legacy-item--selected' : ''} tool-panel__legacy-item--with-star`}
|
||||
className={`tool-panel__legacy-item ${getItemClasses(true)} ${isSelected ? 'tool-panel__legacy-item--selected' : ''} tool-panel__legacy-item--with-star`}
|
||||
onClick={handleClick}
|
||||
aria-disabled={isDisabled}
|
||||
disabled={isDisabled}
|
||||
style={{
|
||||
['--legacy-icon-hover-bg' as any]: hoverBgDetailed,
|
||||
}}
|
||||
>
|
||||
{tool.icon ? (
|
||||
<span
|
||||
className="tool-panel__legacy-icon"
|
||||
className={iconClasses}
|
||||
aria-hidden
|
||||
style={{
|
||||
background: `linear-gradient(135deg,
|
||||
color-mix(in srgb, ${categoryColor} 18%, var(--legacy-bg-icon-detailed)),
|
||||
color-mix(in srgb, ${categoryColor} 8%, var(--legacy-bg-icon-detailed))
|
||||
)`,
|
||||
color: categoryColor
|
||||
background: iconBg,
|
||||
...getIconStyle(),
|
||||
}}
|
||||
>
|
||||
{iconNode}
|
||||
@@ -189,25 +233,37 @@ const LegacyToolList = ({
|
||||
}
|
||||
|
||||
// Compact view
|
||||
const iconBg = getIconBackground(categoryColor, false);
|
||||
const iconClasses = legacyToolSettings.iconBackground === 'hover'
|
||||
? 'tool-panel__legacy-list-icon tool-panel__legacy-list-icon--hover-bg'
|
||||
: 'tool-panel__legacy-list-icon';
|
||||
|
||||
const hoverBgCompact = legacyToolSettings.iconBackground === 'hover'
|
||||
? `linear-gradient(135deg,
|
||||
color-mix(in srgb, ${categoryColor} 15%, var(--legacy-bg-icon-compact)),
|
||||
color-mix(in srgb, ${categoryColor} 6%, var(--legacy-bg-icon-compact))
|
||||
)`
|
||||
: undefined;
|
||||
|
||||
const compactButton = (
|
||||
<button
|
||||
key={id}
|
||||
type="button"
|
||||
className={`tool-panel__legacy-list-item ${isSelected ? 'tool-panel__legacy-list-item--selected' : ''} ${!isDisabled ? 'tool-panel__legacy-list-item--with-star' : ''}`}
|
||||
className={`tool-panel__legacy-list-item ${getItemClasses(false)} ${isSelected ? 'tool-panel__legacy-list-item--selected' : ''} ${!isDisabled ? 'tool-panel__legacy-list-item--with-star' : ''}`}
|
||||
onClick={handleClick}
|
||||
aria-disabled={isDisabled}
|
||||
disabled={isDisabled}
|
||||
style={{
|
||||
['--legacy-icon-hover-bg' as any]: hoverBgCompact,
|
||||
}}
|
||||
>
|
||||
{tool.icon ? (
|
||||
<span
|
||||
className="tool-panel__legacy-list-icon"
|
||||
className={iconClasses}
|
||||
aria-hidden
|
||||
style={{
|
||||
background: `linear-gradient(135deg,
|
||||
color-mix(in srgb, ${categoryColor} 15%, var(--legacy-bg-icon-compact)),
|
||||
color-mix(in srgb, ${categoryColor} 6%, var(--legacy-bg-icon-compact))
|
||||
)`,
|
||||
color: categoryColor
|
||||
background: iconBg,
|
||||
...getIconStyle(),
|
||||
}}
|
||||
>
|
||||
{iconNode}
|
||||
@@ -278,14 +334,25 @@ const LegacyToolList = ({
|
||||
<section className="tool-panel__legacy-group tool-panel__legacy-group--special">
|
||||
<header className="tool-panel__legacy-section-header">
|
||||
<div className="tool-panel__legacy-section-title">
|
||||
<span className="tool-panel__legacy-section-icon" style={{ color: '#FFC107' }} aria-hidden>
|
||||
<span
|
||||
className="tool-panel__legacy-section-icon"
|
||||
style={{
|
||||
color: legacyToolSettings.headerIconColor === 'colored' ? '#FFC107' : 'var(--mantine-color-dimmed)',
|
||||
...getIconStyle(),
|
||||
}}
|
||||
aria-hidden
|
||||
>
|
||||
<StarRoundedIcon />
|
||||
</span>
|
||||
<Text size="sm" fw={600} tt="uppercase" lts={0.5} c="dimmed">
|
||||
{t('toolPanel.legacy.favorites', 'Favourites')}
|
||||
</Text>
|
||||
</div>
|
||||
<Badge size="sm" variant="light" color="yellow">
|
||||
<Badge
|
||||
size="sm"
|
||||
variant="light"
|
||||
color={legacyToolSettings.headerBadgeColor === 'colored' ? 'yellow' : 'gray'}
|
||||
>
|
||||
{favoriteToolItems.length}
|
||||
</Badge>
|
||||
</header>
|
||||
@@ -305,14 +372,25 @@ const LegacyToolList = ({
|
||||
<section className="tool-panel__legacy-group tool-panel__legacy-group--special">
|
||||
<header className="tool-panel__legacy-section-header">
|
||||
<div className="tool-panel__legacy-section-title">
|
||||
<span className="tool-panel__legacy-section-icon" style={{ color: '#1BB1D4' }} aria-hidden>
|
||||
<span
|
||||
className="tool-panel__legacy-section-icon"
|
||||
style={{
|
||||
color: legacyToolSettings.headerIconColor === 'colored' ? '#1BB1D4' : 'var(--mantine-color-dimmed)',
|
||||
...getIconStyle(),
|
||||
}}
|
||||
aria-hidden
|
||||
>
|
||||
<HistoryRoundedIcon />
|
||||
</span>
|
||||
<Text size="sm" fw={600} tt="uppercase" lts={0.5} c="dimmed">
|
||||
{t('toolPanel.legacy.recent', 'Recently used')}
|
||||
</Text>
|
||||
</div>
|
||||
<Badge size="sm" variant="light" color="cyan">
|
||||
<Badge
|
||||
size="sm"
|
||||
variant="light"
|
||||
color={legacyToolSettings.headerBadgeColor === 'colored' ? 'cyan' : 'gray'}
|
||||
>
|
||||
{recentToolItems.length}
|
||||
</Badge>
|
||||
</header>
|
||||
@@ -345,20 +423,37 @@ const LegacyToolList = ({
|
||||
<div className="tool-panel__legacy-section-title">
|
||||
<span
|
||||
className="tool-panel__legacy-section-icon"
|
||||
style={{ color: categoryColor }}
|
||||
style={{
|
||||
color: legacyToolSettings.sectionTitleColor === 'colored' ? categoryColor : 'var(--mantine-color-dimmed)',
|
||||
...getIconStyle(),
|
||||
}}
|
||||
aria-hidden
|
||||
>
|
||||
{getSubcategoryIcon(subcategoryId)}
|
||||
</span>
|
||||
<Text size="sm" fw={600} tt="uppercase" lts={0.5} style={{ color: categoryColor }}>
|
||||
<Text
|
||||
size="sm"
|
||||
fw={600}
|
||||
tt="uppercase"
|
||||
lts={0.5}
|
||||
style={{
|
||||
color: legacyToolSettings.sectionTitleColor === 'colored' ? categoryColor : undefined,
|
||||
}}
|
||||
c={legacyToolSettings.sectionTitleColor === 'neutral' ? 'dimmed' : undefined}
|
||||
>
|
||||
{getSubcategoryLabel(t, subcategoryId)}
|
||||
</Text>
|
||||
</div>
|
||||
<Badge size="sm" variant="light" style={{
|
||||
backgroundColor: `color-mix(in srgb, ${categoryColor} 15%, transparent)`,
|
||||
color: categoryColor,
|
||||
borderColor: `color-mix(in srgb, ${categoryColor} 30%, transparent)`
|
||||
}}>
|
||||
<Badge
|
||||
size="sm"
|
||||
variant="light"
|
||||
style={legacyToolSettings.sectionTitleColor === 'colored' ? {
|
||||
backgroundColor: `color-mix(in srgb, ${categoryColor} 15%, transparent)`,
|
||||
color: categoryColor,
|
||||
borderColor: `color-mix(in srgb, ${categoryColor} 30%, transparent)`
|
||||
} : undefined}
|
||||
color={legacyToolSettings.sectionTitleColor === 'neutral' ? 'gray' : undefined}
|
||||
>
|
||||
{tools.length}
|
||||
</Badge>
|
||||
</header>
|
||||
|
||||
252
frontend/src/components/tools/LegacyToolSettings.tsx
Normal file
252
frontend/src/components/tools/LegacyToolSettings.tsx
Normal file
@@ -0,0 +1,252 @@
|
||||
import { ActionIcon, Drawer, Radio, SegmentedControl, Stack, Text } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import TuneRoundedIcon from '@mui/icons-material/TuneRounded';
|
||||
import { useState } from 'react';
|
||||
|
||||
export interface LegacyToolStyleSettings {
|
||||
iconBackground: 'none' | 'hover' | 'always';
|
||||
iconColorScheme: 'colored' | 'vibrant' | 'monochrome';
|
||||
sectionTitleColor: 'colored' | 'neutral';
|
||||
headerIconColor: 'colored' | 'monochrome';
|
||||
headerBadgeColor: 'colored' | 'neutral';
|
||||
toolItemBorder: 'visible' | 'hidden';
|
||||
hoverIntensity: 'subtle' | 'moderate' | 'prominent';
|
||||
}
|
||||
|
||||
export const defaultLegacyToolSettings: LegacyToolStyleSettings = {
|
||||
iconBackground: 'always',
|
||||
iconColorScheme: 'colored',
|
||||
sectionTitleColor: 'colored',
|
||||
headerIconColor: 'colored',
|
||||
headerBadgeColor: 'colored',
|
||||
toolItemBorder: 'visible',
|
||||
hoverIntensity: 'moderate',
|
||||
};
|
||||
|
||||
interface LegacyToolSettingsProps {
|
||||
settings: LegacyToolStyleSettings;
|
||||
onChange: (settings: LegacyToolStyleSettings) => void;
|
||||
}
|
||||
|
||||
const LegacyToolSettings = ({ settings, onChange }: LegacyToolSettingsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
const updateSetting = <K extends keyof LegacyToolStyleSettings>(
|
||||
key: K,
|
||||
value: LegacyToolStyleSettings[K]
|
||||
) => {
|
||||
onChange({ ...settings, [key]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
radius="xl"
|
||||
size="md"
|
||||
onClick={() => setOpened(true)}
|
||||
aria-label={t('toolPanel.legacy.settings.title', 'Customize appearance')}
|
||||
>
|
||||
<TuneRoundedIcon fontSize="small" />
|
||||
</ActionIcon>
|
||||
|
||||
<Drawer
|
||||
opened={opened}
|
||||
onClose={() => setOpened(false)}
|
||||
title={t('toolPanel.legacy.settings.title', 'Customize appearance')}
|
||||
position="right"
|
||||
size="md"
|
||||
styles={{
|
||||
root: { zIndex: 1300 },
|
||||
overlay: { zIndex: 1300 },
|
||||
inner: { zIndex: 1300 },
|
||||
}}
|
||||
>
|
||||
<Stack gap="xl">
|
||||
<div>
|
||||
<Text size="sm" fw={600} mb="xs">
|
||||
{t('toolPanel.legacy.settings.iconBackground.label', 'Tool icon background')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mb="sm">
|
||||
{t('toolPanel.legacy.settings.iconBackground.description', 'When to show colored backgrounds behind tool icons')}
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
fullWidth
|
||||
value={settings.iconBackground}
|
||||
onChange={(value) => updateSetting('iconBackground', value as any)}
|
||||
data={[
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.iconBackground.none', 'None'),
|
||||
value: 'none',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.iconBackground.hover', 'On hover'),
|
||||
value: 'hover',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.iconBackground.always', 'Always'),
|
||||
value: 'always',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text size="sm" fw={600} mb="xs">
|
||||
{t('toolPanel.legacy.settings.iconColor.label', 'Tool icon color')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mb="sm">
|
||||
{t('toolPanel.legacy.settings.iconColor.description', 'Color scheme for tool icons')}
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
fullWidth
|
||||
value={settings.iconColorScheme}
|
||||
onChange={(value) => updateSetting('iconColorScheme', value as any)}
|
||||
data={[
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.iconColor.colored', 'Colored'),
|
||||
value: 'colored',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.iconColor.vibrant', 'Vibrant'),
|
||||
value: 'vibrant',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.iconColor.monochrome', 'Monochrome'),
|
||||
value: 'monochrome',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text size="sm" fw={600} mb="xs">
|
||||
{t('toolPanel.legacy.settings.sectionTitle.label', 'Section titles')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mb="sm">
|
||||
{t('toolPanel.legacy.settings.sectionTitle.description', 'Color for category section titles')}
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
fullWidth
|
||||
value={settings.sectionTitleColor}
|
||||
onChange={(value) => updateSetting('sectionTitleColor', value as any)}
|
||||
data={[
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.sectionTitle.colored', 'Colored'),
|
||||
value: 'colored',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.sectionTitle.neutral', 'Neutral'),
|
||||
value: 'neutral',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text size="sm" fw={600} mb="xs">
|
||||
{t('toolPanel.legacy.settings.headerIcon.label', 'Section header icons')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mb="sm">
|
||||
{t('toolPanel.legacy.settings.headerIcon.description', 'Color for Favorites/Recent icons')}
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
fullWidth
|
||||
value={settings.headerIconColor}
|
||||
onChange={(value) => updateSetting('headerIconColor', value as any)}
|
||||
data={[
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.headerIcon.colored', 'Colored'),
|
||||
value: 'colored',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.headerIcon.monochrome', 'Monochrome'),
|
||||
value: 'monochrome',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text size="sm" fw={600} mb="xs">
|
||||
{t('toolPanel.legacy.settings.headerBadge.label', 'Section header badges')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mb="sm">
|
||||
{t('toolPanel.legacy.settings.headerBadge.description', 'Color for count badges in section headers')}
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
fullWidth
|
||||
value={settings.headerBadgeColor}
|
||||
onChange={(value) => updateSetting('headerBadgeColor', value as any)}
|
||||
data={[
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.headerBadge.colored', 'Colored'),
|
||||
value: 'colored',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.headerBadge.neutral', 'Neutral'),
|
||||
value: 'neutral',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text size="sm" fw={600} mb="xs">
|
||||
{t('toolPanel.legacy.settings.border.label', 'Tool item borders')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mb="sm">
|
||||
{t('toolPanel.legacy.settings.border.description', 'Show borders around tool items')}
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
fullWidth
|
||||
value={settings.toolItemBorder}
|
||||
onChange={(value) => updateSetting('toolItemBorder', value as any)}
|
||||
data={[
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.border.visible', 'Visible'),
|
||||
value: 'visible',
|
||||
},
|
||||
{
|
||||
label: t('toolPanel.legacy.settings.border.hidden', 'Hidden'),
|
||||
value: 'hidden',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Text size="sm" fw={600} mb="xs">
|
||||
{t('toolPanel.legacy.settings.hover.label', 'Hover effect intensity')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mb="sm">
|
||||
{t('toolPanel.legacy.settings.hover.description', 'How prominent the hover effect should be')}
|
||||
</Text>
|
||||
<Radio.Group
|
||||
value={settings.hoverIntensity}
|
||||
onChange={(value) => updateSetting('hoverIntensity', value as any)}
|
||||
>
|
||||
<Stack gap="xs">
|
||||
<Radio
|
||||
value="subtle"
|
||||
label={t('toolPanel.legacy.settings.hover.subtle', 'Subtle')}
|
||||
/>
|
||||
<Radio
|
||||
value="moderate"
|
||||
label={t('toolPanel.legacy.settings.hover.moderate', 'Moderate')}
|
||||
/>
|
||||
<Radio
|
||||
value="prominent"
|
||||
label={t('toolPanel.legacy.settings.hover.prominent', 'Prominent')}
|
||||
/>
|
||||
</Stack>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
</Stack>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LegacyToolSettings;
|
||||
@@ -4,9 +4,11 @@ import ViewSidebarRoundedIcon from '@mui/icons-material/ViewSidebarRounded';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ToolSearch from './toolPicker/ToolSearch';
|
||||
import LegacyToolList from './LegacyToolList';
|
||||
import LegacyToolSettings from './LegacyToolSettings';
|
||||
import { ToolRegistryEntry } from '../../data/toolsTaxonomy';
|
||||
import { ToolId } from '../../types/toolId';
|
||||
import { useFocusTrap } from '../../hooks/tools/useFocusTrap';
|
||||
import { useToolWorkflow } from '../../contexts/ToolWorkflowContext';
|
||||
import { BASE_PATH } from '../../constants/app';
|
||||
import './ToolPanel.css';
|
||||
|
||||
@@ -46,6 +48,7 @@ const LegacyToolSurface = ({
|
||||
}: LegacyToolSurfaceProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const { legacyToolSettings, setLegacyToolSettings } = useToolWorkflow();
|
||||
const [isExiting, setIsExiting] = useState(false);
|
||||
const surfaceRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -110,17 +113,23 @@ const LegacyToolSurface = ({
|
||||
<img src={brandIconSrc} alt="" className="tool-panel__legacy-brand-icon" />
|
||||
<img src={brandTextSrc} alt={brandAltText} className="tool-panel__legacy-brand-text" />
|
||||
</div>
|
||||
<Tooltip label={toggleLabel} position="bottom" withArrow>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
radius="xl"
|
||||
size="md"
|
||||
onClick={handleExit}
|
||||
aria-label={toggleLabel}
|
||||
>
|
||||
<ViewSidebarRoundedIcon fontSize="small" />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
<LegacyToolSettings
|
||||
settings={legacyToolSettings}
|
||||
onChange={setLegacyToolSettings}
|
||||
/>
|
||||
<Tooltip label={toggleLabel} position="bottom" withArrow>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
radius="xl"
|
||||
size="md"
|
||||
onClick={handleExit}
|
||||
aria-label={toggleLabel}
|
||||
>
|
||||
<ViewSidebarRoundedIcon fontSize="small" />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="tool-panel__legacy-controls">
|
||||
|
||||
@@ -530,3 +530,42 @@
|
||||
column-width: 14rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dynamic settings support */
|
||||
|
||||
/* No border variant */
|
||||
.tool-panel__legacy-item--no-border,
|
||||
.tool-panel__legacy-list-item--no-border {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/* Hover intensity variants */
|
||||
.tool-panel__legacy-item--hover-subtle:hover,
|
||||
.tool-panel__legacy-list-item--hover-subtle:hover {
|
||||
background: var(--legacy-hover-subtle);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.tool-panel__legacy-item--hover-moderate:hover,
|
||||
.tool-panel__legacy-list-item--hover-moderate:hover {
|
||||
background: var(--legacy-hover);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.tool-panel__legacy-item--hover-prominent:hover,
|
||||
.tool-panel__legacy-list-item--hover-prominent:hover {
|
||||
background: var(--legacy-hover-prominent);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Hover-only icon background */
|
||||
.tool-panel__legacy-icon--hover-bg,
|
||||
.tool-panel__legacy-list-icon--hover-bg {
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.tool-panel__legacy-item:hover .tool-panel__legacy-icon--hover-bg,
|
||||
.tool-panel__legacy-list-item:hover .tool-panel__legacy-list-icon--hover-bg {
|
||||
background: var(--legacy-icon-hover-bg) !important;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useNavigationUrlSync } from '../hooks/useUrlSync';
|
||||
import { getDefaultWorkbench } from '../types/workbench';
|
||||
import { filterToolRegistryByQuery } from '../utils/toolSearch';
|
||||
import { useToolHistory } from '../hooks/tools/useToolHistory';
|
||||
import { LegacyToolStyleSettings, defaultLegacyToolSettings } from '../components/tools/LegacyToolSettings';
|
||||
|
||||
// State interface
|
||||
type ToolPanelMode = 'sidebar' | 'legacy';
|
||||
@@ -23,6 +24,7 @@ interface ToolWorkflowState {
|
||||
leftPanelView: 'toolPicker' | 'toolContent' | 'hidden';
|
||||
readerMode: boolean;
|
||||
toolPanelMode: ToolPanelMode;
|
||||
legacyToolSettings: LegacyToolStyleSettings;
|
||||
|
||||
// File/Preview State
|
||||
previewFile: File | null;
|
||||
@@ -38,6 +40,7 @@ type ToolWorkflowAction =
|
||||
| { type: 'SET_LEFT_PANEL_VIEW'; payload: 'toolPicker' | 'toolContent' | 'hidden' }
|
||||
| { type: 'SET_READER_MODE'; payload: boolean }
|
||||
| { type: 'SET_TOOL_PANEL_MODE'; payload: ToolPanelMode }
|
||||
| { type: 'SET_LEGACY_TOOL_SETTINGS'; payload: LegacyToolStyleSettings }
|
||||
| { type: 'SET_PREVIEW_FILE'; payload: File | null }
|
||||
| { type: 'SET_PAGE_EDITOR_FUNCTIONS'; payload: PageEditorFunctions | null }
|
||||
| { type: 'SET_SEARCH_QUERY'; payload: string }
|
||||
@@ -45,6 +48,7 @@ type ToolWorkflowAction =
|
||||
|
||||
// Initial state
|
||||
export const TOOL_PANEL_MODE_STORAGE_KEY = 'toolPanelModePreference';
|
||||
export const LEGACY_TOOL_SETTINGS_STORAGE_KEY = 'legacyToolStyleSettings';
|
||||
|
||||
const getStoredToolPanelMode = (): ToolPanelMode => {
|
||||
if (typeof window === 'undefined') {
|
||||
@@ -59,7 +63,24 @@ const getStoredToolPanelMode = (): ToolPanelMode => {
|
||||
return 'sidebar';
|
||||
};
|
||||
|
||||
const baseState: Omit<ToolWorkflowState, 'toolPanelMode'> = {
|
||||
const getStoredLegacyToolSettings = (): LegacyToolStyleSettings => {
|
||||
if (typeof window === 'undefined') {
|
||||
return defaultLegacyToolSettings;
|
||||
}
|
||||
|
||||
try {
|
||||
const stored = window.localStorage.getItem(LEGACY_TOOL_SETTINGS_STORAGE_KEY);
|
||||
if (stored) {
|
||||
return { ...defaultLegacyToolSettings, ...JSON.parse(stored) };
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to parse legacy tool settings:', e);
|
||||
}
|
||||
|
||||
return defaultLegacyToolSettings;
|
||||
};
|
||||
|
||||
const baseState: Omit<ToolWorkflowState, 'toolPanelMode' | 'legacyToolSettings'> = {
|
||||
sidebarsVisible: true,
|
||||
leftPanelView: 'toolPicker',
|
||||
readerMode: false,
|
||||
@@ -71,6 +92,7 @@ const baseState: Omit<ToolWorkflowState, 'toolPanelMode'> = {
|
||||
const createInitialState = (): ToolWorkflowState => ({
|
||||
...baseState,
|
||||
toolPanelMode: getStoredToolPanelMode(),
|
||||
legacyToolSettings: getStoredLegacyToolSettings(),
|
||||
});
|
||||
|
||||
// Reducer
|
||||
@@ -84,6 +106,8 @@ function toolWorkflowReducer(state: ToolWorkflowState, action: ToolWorkflowActio
|
||||
return { ...state, readerMode: action.payload };
|
||||
case 'SET_TOOL_PANEL_MODE':
|
||||
return { ...state, toolPanelMode: action.payload };
|
||||
case 'SET_LEGACY_TOOL_SETTINGS':
|
||||
return { ...state, legacyToolSettings: action.payload };
|
||||
case 'SET_PREVIEW_FILE':
|
||||
return { ...state, previewFile: action.payload };
|
||||
case 'SET_PAGE_EDITOR_FUNCTIONS':
|
||||
@@ -94,6 +118,7 @@ function toolWorkflowReducer(state: ToolWorkflowState, action: ToolWorkflowActio
|
||||
return {
|
||||
...baseState,
|
||||
toolPanelMode: state.toolPanelMode,
|
||||
legacyToolSettings: state.legacyToolSettings,
|
||||
searchQuery: state.searchQuery,
|
||||
};
|
||||
default:
|
||||
@@ -114,6 +139,7 @@ interface ToolWorkflowContextValue extends ToolWorkflowState {
|
||||
setLeftPanelView: (view: 'toolPicker' | 'toolContent' | 'hidden') => void;
|
||||
setReaderMode: (mode: boolean) => void;
|
||||
setToolPanelMode: (mode: ToolPanelMode) => void;
|
||||
setLegacyToolSettings: (settings: LegacyToolStyleSettings) => void;
|
||||
setPreviewFile: (file: File | null) => void;
|
||||
setPageEditorFunctions: (functions: PageEditorFunctions | null) => void;
|
||||
setSearchQuery: (query: string) => void;
|
||||
@@ -200,6 +226,10 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
|
||||
dispatch({ type: 'SET_TOOL_PANEL_MODE', payload: mode });
|
||||
}, []);
|
||||
|
||||
const setLegacyToolSettings = useCallback((settings: LegacyToolStyleSettings) => {
|
||||
dispatch({ type: 'SET_LEGACY_TOOL_SETTINGS', payload: settings });
|
||||
}, []);
|
||||
|
||||
const setPreviewFile = useCallback((file: File | null) => {
|
||||
dispatch({ type: 'SET_PREVIEW_FILE', payload: file });
|
||||
if (file) {
|
||||
@@ -223,6 +253,14 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
|
||||
window.localStorage.setItem(TOOL_PANEL_MODE_STORAGE_KEY, state.toolPanelMode);
|
||||
}, [state.toolPanelMode]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
window.localStorage.setItem(LEGACY_TOOL_SETTINGS_STORAGE_KEY, JSON.stringify(state.legacyToolSettings));
|
||||
}, [state.legacyToolSettings]);
|
||||
|
||||
// Tool reset methods
|
||||
const registerToolReset = useCallback((toolId: string, resetFunction: () => void) => {
|
||||
setToolResetFunctions(prev => ({ ...prev, [toolId]: resetFunction }));
|
||||
@@ -327,6 +365,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
|
||||
setLeftPanelView,
|
||||
setReaderMode,
|
||||
setToolPanelMode,
|
||||
setLegacyToolSettings,
|
||||
setPreviewFile,
|
||||
setPageEditorFunctions,
|
||||
setSearchQuery,
|
||||
@@ -363,6 +402,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
|
||||
setLeftPanelView,
|
||||
setReaderMode,
|
||||
setToolPanelMode,
|
||||
setLegacyToolSettings,
|
||||
setPreviewFile,
|
||||
setPageEditorFunctions,
|
||||
setSearchQuery,
|
||||
|
||||
Reference in New Issue
Block a user