fix(ui): replace in compress/booklet front-end with Mantine's Checkbox component

- Updated `BookletImpositionSettings` to use Mantine's `Checkbox` for better UI consistency
- Replaced manual checkbox implementations with Mantine's `Checkbox` in `CompressSettings`
- Added labels and tooltips for enhanced accessibility and usability

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
This commit is contained in:
Balázs Szücs 2025-11-12 22:44:33 +01:00
parent eb5f36aa15
commit 4708f92145
2 changed files with 86 additions and 88 deletions

View File

@ -1,6 +1,6 @@
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Stack, Text, Divider, Collapse, Button, NumberInput } from "@mantine/core"; import { Stack, Text, Divider, Collapse, Button, NumberInput, Checkbox } from "@mantine/core";
import { BookletImpositionParameters } from "@app/hooks/tools/bookletImposition/useBookletImpositionParameters"; import { BookletImpositionParameters } from "@app/hooks/tools/bookletImposition/useBookletImpositionParameters";
import ButtonSelector from "@app/components/shared/ButtonSelector"; import ButtonSelector from "@app/components/shared/ButtonSelector";
@ -21,28 +21,27 @@ const BookletImpositionSettings = ({ parameters, onParameterChange, disabled = f
{/* Double Sided */} {/* Double Sided */}
<Stack gap="sm"> <Stack gap="sm">
<label <Checkbox
style={{ display: 'flex', alignItems: 'center', gap: 'var(--mantine-spacing-xs)' }} checked={parameters.doubleSided}
title={t('bookletImposition.doubleSided.tooltip', 'Creates both front and back sides for proper booklet printing')} onChange={(event) => {
> const isDoubleSided = event.currentTarget.checked;
<input onParameterChange('doubleSided', isDoubleSided);
type="checkbox" // Reset to BOTH when turning double-sided back on
checked={parameters.doubleSided} if (isDoubleSided) {
onChange={(e) => { onParameterChange('duplexPass', 'BOTH');
const isDoubleSided = e.target.checked; } else {
onParameterChange('doubleSided', isDoubleSided); // Default to FIRST pass when going to manual duplex
// Reset to BOTH when turning double-sided back on onParameterChange('duplexPass', 'FIRST');
if (isDoubleSided) { }
onParameterChange('duplexPass', 'BOTH'); }}
} else { disabled={disabled}
// Default to FIRST pass when going to manual duplex label={
onParameterChange('duplexPass', 'FIRST'); <div>
} <Text size="sm">{t('bookletImposition.doubleSided.label', 'Double-sided printing')}</Text>
}} <Text size="xs" c="dimmed">{t('bookletImposition.doubleSided.tooltip', 'Creates both front and back sides for proper booklet printing')}</Text>
disabled={disabled} </div>
/> }
<Text size="sm">{t('bookletImposition.doubleSided.label', 'Double-sided printing')}</Text> />
</label>
{/* Manual Duplex Pass Selection - only show when double-sided is OFF */} {/* Manual Duplex Pass Selection - only show when double-sided is OFF */}
{!parameters.doubleSided && ( {!parameters.doubleSided && (
@ -90,47 +89,44 @@ const BookletImpositionSettings = ({ parameters, onParameterChange, disabled = f
<Collapse in={advancedOpen}> <Collapse in={advancedOpen}>
<Stack gap="md" mt="md"> <Stack gap="md" mt="md">
{/* Right-to-Left Binding */} {/* Right-to-Left Binding */}
<label <Checkbox
style={{ display: 'flex', alignItems: 'center', gap: 'var(--mantine-spacing-xs)' }} checked={parameters.spineLocation === 'RIGHT'}
title={t('bookletImposition.rtlBinding.tooltip', 'For Arabic, Hebrew, or other right-to-left languages')} onChange={(event) => onParameterChange('spineLocation', event.currentTarget.checked ? 'RIGHT' : 'LEFT')}
> disabled={disabled}
<input label={
type="checkbox" <div>
checked={parameters.spineLocation === 'RIGHT'} <Text size="sm">{t('bookletImposition.rtlBinding.label', 'Right-to-left binding')}</Text>
onChange={(e) => onParameterChange('spineLocation', e.target.checked ? 'RIGHT' : 'LEFT')} <Text size="xs" c="dimmed">{t('bookletImposition.rtlBinding.tooltip', 'For Arabic, Hebrew, or other right-to-left languages')}</Text>
disabled={disabled} </div>
/> }
<Text size="sm">{t('bookletImposition.rtlBinding.label', 'Right-to-left binding')}</Text> />
</label>
{/* Add Border Option */} {/* Add Border Option */}
<label <Checkbox
style={{ display: 'flex', alignItems: 'center', gap: 'var(--mantine-spacing-xs)' }} checked={parameters.addBorder}
title={t('bookletImposition.addBorder.tooltip', 'Adds borders around each page section to help with cutting and alignment')} onChange={(event) => onParameterChange('addBorder', event.currentTarget.checked)}
> disabled={disabled}
<input label={
type="checkbox" <div>
checked={parameters.addBorder} <Text size="sm">{t('bookletImposition.addBorder.label', 'Add borders around pages')}</Text>
onChange={(e) => onParameterChange('addBorder', e.target.checked)} <Text size="xs" c="dimmed">{t('bookletImposition.addBorder.tooltip', 'Adds borders around each page section to help with cutting and alignment')}</Text>
disabled={disabled} </div>
/> }
<Text size="sm">{t('bookletImposition.addBorder.label', 'Add borders around pages')}</Text> />
</label>
{/* Gutter Margin */} {/* Gutter Margin */}
<Stack gap="xs"> <Stack gap="xs">
<label <Checkbox
style={{ display: 'flex', alignItems: 'center', gap: 'var(--mantine-spacing-xs)' }} checked={parameters.addGutter}
title={t('bookletImposition.addGutter.tooltip', 'Adds inner margin space for binding')} onChange={(event) => onParameterChange('addGutter', event.currentTarget.checked)}
> disabled={disabled}
<input label={
type="checkbox" <div>
checked={parameters.addGutter} <Text size="sm">{t('bookletImposition.addGutter.label', 'Add gutter margin')}</Text>
onChange={(e) => onParameterChange('addGutter', e.target.checked)} <Text size="xs" c="dimmed">{t('bookletImposition.addGutter.tooltip', 'Adds inner margin space for binding')}</Text>
disabled={disabled} </div>
/> }
<Text size="sm">{t('bookletImposition.addGutter.label', 'Add gutter margin')}</Text> />
</label>
{parameters.addGutter && ( {parameters.addGutter && (
<NumberInput <NumberInput
@ -147,23 +143,24 @@ const BookletImpositionSettings = ({ parameters, onParameterChange, disabled = f
</Stack> </Stack>
{/* Flip on Short Edge */} {/* Flip on Short Edge */}
<label <Checkbox
style={{ display: 'flex', alignItems: 'center', gap: 'var(--mantine-spacing-xs)' }} checked={parameters.flipOnShortEdge}
title={!parameters.doubleSided onChange={(event) => onParameterChange('flipOnShortEdge', event.currentTarget.checked)}
? t('bookletImposition.flipOnShortEdge.manualNote', 'Not needed in manual mode - you flip the stack yourself') disabled={disabled || !parameters.doubleSided}
: t('bookletImposition.flipOnShortEdge.tooltip', 'Enable for short-edge duplex printing (automatic duplex only - ignored in manual mode)') label={
<div>
<Text size="sm" c={!parameters.doubleSided ? "dimmed" : undefined}>
{t('bookletImposition.flipOnShortEdge.label', 'Flip on short edge')}
</Text>
<Text size="xs" c="dimmed">
{!parameters.doubleSided
? t('bookletImposition.flipOnShortEdge.manualNote', 'Not needed in manual mode - you flip the stack yourself')
: t('bookletImposition.flipOnShortEdge.tooltip', 'Enable for short-edge duplex printing (automatic duplex only - ignored in manual mode)')
}
</Text>
</div>
} }
> />
<input
type="checkbox"
checked={parameters.flipOnShortEdge}
onChange={(e) => onParameterChange('flipOnShortEdge', e.target.checked)}
disabled={disabled || !parameters.doubleSided}
/>
<Text size="sm" c={!parameters.doubleSided ? "dimmed" : undefined}>
{t('bookletImposition.flipOnShortEdge.label', 'Flip on short edge')}
</Text>
</label>
{/* Paper Size Note */} {/* Paper Size Note */}
<Text size="xs" c="dimmed" fs="italic"> <Text size="xs" c="dimmed" fs="italic">

View File

@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { Stack, Text, NumberInput, Select, Divider } from "@mantine/core"; import { Stack, Text, NumberInput, Select, Divider, Checkbox } from "@mantine/core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { CompressParameters } from "@app/hooks/tools/compress/useCompressParameters"; import { CompressParameters } from "@app/hooks/tools/compress/useCompressParameters";
import ButtonSelector from "@app/components/shared/ButtonSelector"; import ButtonSelector from "@app/components/shared/ButtonSelector";
@ -123,18 +123,19 @@ const CompressSettings = ({ parameters, onParameterChange, disabled = false }: C
{/* Compression Options */} {/* Compression Options */}
<Stack gap="sm"> <Stack gap="sm">
<label <Checkbox
style={{ display: 'flex', alignItems: 'center', gap: '8px' }} checked={parameters.grayscale}
title="Converts all images in the PDF to grayscale, which can significantly reduce file size while maintaining readability" onChange={(event) => onParameterChange('grayscale', event.currentTarget.checked)}
> disabled={disabled}
<input label={
type="checkbox" <div>
checked={parameters.grayscale} <Text size="sm">{t("compress.grayscale.label", "Apply Grayscale for compression")}</Text>
onChange={(e) => onParameterChange('grayscale', e.target.checked)} <Text size="xs" c="dimmed">
disabled={disabled} {t("compress.grayscale.description", "Converts all images in the PDF to grayscale, which can significantly reduce file size while maintaining readability")}
/> </Text>
<Text size="sm">{t("compress.grayscale.label", "Apply Grayscale for compression")}</Text> </div>
</label> }
/>
</Stack> </Stack>
</Stack> </Stack>
); );