style: refactor dialog components to use OGDialogFooter for improved layout consistency

This commit is contained in:
Marco Beretta 2026-01-06 12:09:34 +01:00
parent b5094d8ce4
commit 1effbf1313
No known key found for this signature in database
GPG key ID: D918033D8E74CC11
4 changed files with 96 additions and 82 deletions

View file

@ -10,6 +10,7 @@ import {
OGDialogClose,
OGDialogTitle,
OGDialogHeader,
OGDialogFooter,
OGDialogContent,
useToastContext,
} from '@librechat/client';
@ -96,7 +97,7 @@ export function DeleteConversationDialog({
components={{ strong: <strong /> }}
/>
</div>
<div className="flex justify-end gap-4 pt-4">
<OGDialogFooter className="pt-4">
<OGDialogClose asChild>
<Button aria-label="cancel" variant="outline">
{localize('com_ui_cancel')}
@ -105,7 +106,7 @@ export function DeleteConversationDialog({
<Button variant="destructive" onClick={confirmDelete} disabled={deleteMutation.isLoading}>
{deleteMutation.isLoading ? <Spinner /> : localize('com_ui_delete')}
</Button>
</div>
</OGDialogFooter>
</OGDialogContent>
);
}

View file

@ -10,8 +10,9 @@ import {
TooltipAnchor,
OGDialogTitle,
OGDialogHeader,
useToastContext,
OGDialogFooter,
OGDialogContent,
useToastContext,
} from '@librechat/client';
import type { TSharedLinkGetResponse } from 'librechat-data-provider';
import {
@ -132,12 +133,6 @@ export default function SharedLinkButton({
return (
<>
<div className="flex gap-2">
{!shareId && (
<Button disabled={isCreateLoading} variant="submit" onClick={createShareLink}>
{!isCreateLoading && localize('com_ui_create_link')}
{isCreateLoading && <Spinner className="size-4" />}
</Button>
)}
{shareId && (
<div className="flex items-center gap-2">
<TooltipAnchor
@ -194,6 +189,14 @@ export default function SharedLinkButton({
/>
</div>
)}
{!shareId && (
<OGDialogFooter>
<Button disabled={isCreateLoading} variant="submit" onClick={createShareLink}>
{!isCreateLoading && localize('com_ui_create_link')}
{isCreateLoading && <Spinner className="size-4" />}
</Button>
</OGDialogFooter>
)}
<OGDialog
open={showDeleteDialog}
triggerRef={deleteButtonRef}
@ -214,7 +217,7 @@ export default function SharedLinkButton({
</Label>
</div>
</div>
<div className="flex justify-end gap-4 pt-4">
<OGDialogFooter className="pt-4">
<OGDialogClose asChild>
<Button variant="outline">{localize('com_ui_cancel')}</Button>
</OGDialogClose>
@ -229,7 +232,7 @@ export default function SharedLinkButton({
localize('com_ui_delete')
)}
</Button>
</div>
</OGDialogFooter>
</OGDialogContent>
</OGDialog>
</div>

View file

@ -1,9 +1,32 @@
import { OGDialogTemplate, Input, Button, OGDialog } from '@librechat/client';
import {
Button,
OGDialog,
SecretInput,
OGDialogClose,
OGDialogTitle,
OGDialogFooter,
OGDialogHeader,
OGDialogContent,
OGDialogDescription,
} from '@librechat/client';
import type { UseFormRegister, UseFormHandleSubmit } from 'react-hook-form';
import type { ApiKeyFormData } from '~/common';
import type { RefObject } from 'react';
import { useLocalize } from '~/hooks';
const languageIcons = [
'python.svg',
'nodedotjs.svg',
'tsnode.svg',
'rust.svg',
'go.svg',
'c.svg',
'cplusplus.svg',
'php.svg',
'fortran.svg',
'r.svg',
];
export default function ApiKeyDialog({
isOpen,
onSubmit,
@ -28,18 +51,6 @@ export default function ApiKeyDialog({
triggerRefs?: RefObject<HTMLInputElement | HTMLButtonElement>[];
}) {
const localize = useLocalize();
const languageIcons = [
'python.svg',
'nodedotjs.svg',
'tsnode.svg',
'rust.svg',
'go.svg',
'c.svg',
'cplusplus.svg',
'php.svg',
'fortran.svg',
'r.svg',
];
return (
<OGDialog
@ -48,70 +59,69 @@ export default function ApiKeyDialog({
triggerRef={triggerRef}
triggerRefs={triggerRefs}
>
<OGDialogTemplate
className="w-11/12 sm:w-[450px]"
title=""
main={
<>
<div className="mb-4 text-center font-medium">
{localize('com_ui_librechat_code_api_title')}
</div>
<div className="mb-4 text-center text-sm">
{localize('com_ui_librechat_code_api_subtitle')}
</div>
{/* Language Icons Stack */}
<div className="mb-6">
<div className="mx-auto mb-4 flex max-w-[400px] flex-wrap justify-center gap-3">
{languageIcons.map((icon) => (
<div key={icon} className="h-6 w-6">
<img
src={`assets/${icon}`}
alt=""
className="h-full w-full object-contain opacity-[0.85] dark:invert"
/>
</div>
))}
<OGDialogContent
showCloseButton={false}
className="w-11/12 max-w-md border-none bg-surface-primary"
>
<OGDialogHeader className="gap-2 py-2">
<OGDialogTitle className="text-center text-lg font-semibold">
{localize('com_ui_librechat_code_api_title')}
</OGDialogTitle>
<div className="mx-auto flex max-w-[350px] flex-wrap justify-center gap-3">
{languageIcons.map((icon) => (
<div key={icon} className="size-6">
<img
src={`assets/${icon}`}
alt=""
className="size-full object-contain opacity-85 dark:invert"
/>
</div>
<a
href="https://code.librechat.ai/pricing"
target="_blank"
rel="noopener noreferrer"
className="block text-center text-[15px] font-medium text-blue-500 underline decoration-1 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300"
>
{localize('com_ui_librechat_code_api_key')}
</a>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<Input
type="password"
placeholder={localize('com_ui_enter_api_key')}
autoComplete="one-time-code"
readOnly={true}
onFocus={(e) => (e.target.readOnly = false)}
{...register('apiKey', { required: true })}
/>
</form>
</>
}
selection={{
selectHandler: handleSubmit(onSubmit),
selectClasses: 'bg-green-500 hover:bg-green-600 text-white',
selectText: localize('com_ui_save'),
}}
buttons={
isUserProvided &&
isToolAuthenticated && (
))}
</div>
<OGDialogDescription className="text-center">
{localize('com_ui_librechat_code_api_subtitle')}
</OGDialogDescription>
</OGDialogHeader>
<div className="space-y-4">
<a
href="https://code.librechat.ai/pricing"
target="_blank"
rel="noopener noreferrer"
className="block text-center text-sm font-medium text-blue-500 underline decoration-1 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300"
>
{localize('com_ui_librechat_code_api_key')}
</a>
<form onSubmit={handleSubmit(onSubmit)}>
<SecretInput
placeholder={localize('com_ui_enter_api_key')}
{...register('apiKey', { required: true })}
/>
</form>
</div>
<OGDialogFooter className="mt-6">
<OGDialogClose asChild>
<Button variant="outline" className="h-10">
{localize('com_ui_cancel')}
</Button>
</OGDialogClose>
{isUserProvided && isToolAuthenticated && (
<Button
variant="destructive"
onClick={onRevoke}
className="bg-destructive text-white transition-all duration-200 hover:bg-destructive/80"
className="h-10"
aria-label={localize('com_ui_revoke')}
>
{localize('com_ui_revoke')}
</Button>
)
}
showCancelButton={true}
/>
)}
<Button variant="submit" onClick={handleSubmit(onSubmit)} className="h-10">
{localize('com_ui_save')}
</Button>
</OGDialogFooter>
</OGDialogContent>
</OGDialog>
);
}

View file

@ -168,7 +168,7 @@ DialogHeader.displayName = 'DialogHeader';
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
className={cn('flex w-full flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
{...props}
/>
);