LibreChat/client/src/components/Prompts/DeleteVersion.tsx
Daniel Lew 1143f73f59
Some checks failed
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Has been cancelled
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Has been cancelled
🔇 fix: Hide Button Icons from Screen Readers (#10776)
If you've got a screen reader that is reading out the whole page,
each icon button (i.e., `<button><SVG></button>`) will have both
the button's aria-label read out as well as the title from the
SVG (which is usually just "image").

Since we are pretty good about setting aria-labels, we should instead
use `aria-hidden="true"` on these images, since they are not useful
to be read out.

I don't consider this a comprehensive review of all icons in the app,
but I knocked out all the low hanging fruit in this commit.
2025-12-11 16:35:17 -05:00

101 lines
2.6 KiB
TypeScript

import React, { useCallback } from 'react';
import { Trash2 } from 'lucide-react';
import { useDeletePrompt } from '~/data-provider';
import { Button, OGDialog, OGDialogTrigger, Label, OGDialogTemplate } from '@librechat/client';
import { useLocalize } from '~/hooks';
const DeleteConfirmDialog = ({
name,
disabled,
selectHandler,
}: {
name: string;
disabled?: boolean;
selectHandler: () => void;
}) => {
const localize = useLocalize();
return (
<OGDialog>
<OGDialogTrigger asChild>
<Button
variant="destructive"
size="sm"
aria-label="Delete version"
className="h-10 w-10 p-0.5"
disabled={disabled}
onClick={(e) => {
e.stopPropagation();
}}
>
<Trash2 className="size-5 cursor-pointer text-white" aria-hidden="true" />
</Button>
</OGDialogTrigger>
<OGDialogTemplate
showCloseButton={false}
title={localize('com_ui_delete_prompt')}
className="max-w-[450px]"
main={
<>
<div className="flex w-full flex-col items-center gap-2">
<div className="grid w-full items-center gap-2">
<Label
htmlFor="dialog-delete-confirm-prompt"
className="text-left text-sm font-medium"
>
{localize('com_ui_delete_confirm_prompt_version_var', { 0: name })}
</Label>
</div>
</div>
</>
}
selection={{
selectHandler,
selectClasses:
'bg-surface-destructive hover:bg-surface-destructive-hover transition-colors duration-200 text-white',
selectText: localize('com_ui_delete'),
}}
/>
</OGDialog>
);
};
interface DeletePromptProps {
promptId?: string;
groupId: string;
promptName: string;
disabled: boolean;
}
const DeletePrompt = React.memo(
({ promptId, groupId, promptName, disabled }: DeletePromptProps) => {
const deletePromptMutation = useDeletePrompt();
const handleDelete = useCallback(() => {
if (!promptId) {
console.warn('No prompt ID provided for deletion');
return;
}
deletePromptMutation.mutate({
_id: promptId,
groupId,
});
}, [promptId, groupId, deletePromptMutation]);
if (!promptId) {
return null;
}
return (
<DeleteConfirmDialog
name={promptName}
disabled={disabled || !promptId}
selectHandler={handleDelete}
/>
);
},
);
DeletePrompt.displayName = 'DeletePrompt';
export default DeletePrompt;