diff --git a/frontend/src/components/tools/convert/ConvertSettings.tsx b/frontend/src/components/tools/convert/ConvertSettings.tsx
index 568eeb744..36cc9b76d 100644
--- a/frontend/src/components/tools/convert/ConvertSettings.tsx
+++ b/frontend/src/components/tools/convert/ConvertSettings.tsx
@@ -1,6 +1,8 @@
import React from "react";
-import { Stack, Text, Select, NumberInput, Group, Divider } from "@mantine/core";
+import { Stack, Text, Select, NumberInput, Group, Divider, UnstyledButton, useMantineTheme, useMantineColorScheme } from "@mantine/core";
+import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import { useTranslation } from "react-i18next";
+import GroupedFormatDropdown from "./GroupedFormatDropdown";
import { ConvertParameters } from "../../../hooks/tools/convert/useConvertParameters";
import {
FROM_FORMAT_OPTIONS,
@@ -23,6 +25,8 @@ const ConvertSettings = ({
disabled = false
}: ConvertSettingsProps) => {
const { t } = useTranslation();
+ const theme = useMantineTheme();
+ const { colorScheme } = useMantineColorScheme();
const handleFromExtensionChange = (value: string | null) => {
if (value) {
@@ -38,18 +42,17 @@ const ConvertSettings = ({
}
};
- const handleToExtensionChange = (value: string | null) => {
- if (value) {
- onParameterChange('toExtension', value);
- // Reset format-specific options when target extension changes
- onParameterChange('imageOptions', {
- colorType: COLOR_TYPES.COLOR,
- dpi: 300,
- singleOrMultiple: OUTPUT_OPTIONS.MULTIPLE,
- });
- }
+ const handleToExtensionChange = (value: string) => {
+ onParameterChange('toExtension', value);
+ // Reset format-specific options when target extension changes
+ onParameterChange('imageOptions', {
+ colorType: COLOR_TYPES.COLOR,
+ dpi: 300,
+ singleOrMultiple: OUTPUT_OPTIONS.MULTIPLE,
+ });
};
+
return (
{/* Format Selection */}
@@ -72,15 +75,37 @@ const ConvertSettings = ({
{t("convert.convertTo", "Convert to")}:
-
{/* Format-specific options */}
diff --git a/frontend/src/components/tools/convert/GroupedFormatDropdown.tsx b/frontend/src/components/tools/convert/GroupedFormatDropdown.tsx
new file mode 100644
index 000000000..2d17b0750
--- /dev/null
+++ b/frontend/src/components/tools/convert/GroupedFormatDropdown.tsx
@@ -0,0 +1,143 @@
+import React, { useState, useMemo } from "react";
+import { Stack, Text, Group, Button, Box, Popover, UnstyledButton, useMantineTheme, useMantineColorScheme } from "@mantine/core";
+import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
+
+interface FormatOption {
+ value: string;
+ label: string;
+ group: string;
+}
+
+interface GroupedFormatDropdownProps {
+ value?: string;
+ placeholder?: string;
+ options: FormatOption[];
+ onChange: (value: string) => void;
+ disabled?: boolean;
+ minWidth?: string;
+}
+
+const GroupedFormatDropdown = ({
+ value,
+ placeholder = "Select an option",
+ options,
+ onChange,
+ disabled = false,
+ minWidth = "300px"
+}: GroupedFormatDropdownProps) => {
+ const [dropdownOpened, setDropdownOpened] = useState(false);
+ const theme = useMantineTheme();
+ const { colorScheme } = useMantineColorScheme();
+
+ // Group options by category
+ const groupedOptions = useMemo(() => {
+ const groups: Record = {};
+
+ options.forEach(option => {
+ if (!groups[option.group]) {
+ groups[option.group] = [];
+ }
+ groups[option.group].push(option);
+ });
+
+ return groups;
+ }, [options]);
+
+ // Get selected option label for display
+ const selectedLabel = useMemo(() => {
+ if (!value) return placeholder;
+ const selected = options.find(opt => opt.value === value);
+ return selected ? selected.label : value;
+ }, [value, options, placeholder]);
+
+ const handleOptionSelect = (selectedValue: string) => {
+ onChange(selectedValue);
+ setDropdownOpened(false);
+ };
+
+ return (
+ setDropdownOpened(false)}
+ position="bottom-start"
+ withArrow
+ shadow="sm"
+ disabled={disabled}
+ >
+
+ setDropdownOpened(!dropdownOpened)}
+ disabled={disabled}
+ style={{
+ padding: '8px 12px',
+ border: `1px solid ${theme.colors.gray[4]}`,
+ borderRadius: theme.radius.sm,
+ backgroundColor: disabled
+ ? theme.colors.gray[1]
+ : colorScheme === 'dark'
+ ? theme.colors.dark[6]
+ : theme.white,
+ cursor: disabled ? 'not-allowed' : 'pointer',
+ width: '100%',
+ color: colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.dark[9]
+ }}
+ >
+
+
+ {selectedLabel}
+
+
+
+
+
+
+
+ {Object.entries(groupedOptions).map(([groupName, groupOptions]) => (
+
+
+ {groupName}
+
+
+ {groupOptions.map((option) => (
+
+ ))}
+
+
+ ))}
+
+
+
+ );
+};
+
+export default GroupedFormatDropdown;
\ No newline at end of file