mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 17:00:15 +01:00
🛠️ fix: enhance UI/UX and address a11y issues in SetKeyDialog (#5672)
* ✨ refactor: Improve UI consistency and accessibility in SetKeyDialog components * 🎨 style: Add cursor pointer to Slider component for better UX * 🐛 chore: Remove unnecessary console log from SetKeyDialog component
This commit is contained in:
parent
73fe0835cf
commit
5f9543f6fc
7 changed files with 25 additions and 40 deletions
|
|
@ -28,9 +28,9 @@ const GoogleConfig = ({ userKey, setUserKey }: Pick<TConfigProps, 'userKey' | 's
|
||||||
<Label htmlFor={AuthKeys.GOOGLE_SERVICE_KEY} className="text-left text-sm font-medium">
|
<Label htmlFor={AuthKeys.GOOGLE_SERVICE_KEY} className="text-left text-sm font-medium">
|
||||||
{localize('com_endpoint_config_google_service_key')}
|
{localize('com_endpoint_config_google_service_key')}
|
||||||
</Label>
|
</Label>
|
||||||
<div className="mx-1 text-left text-sm text-gray-700 dark:text-gray-400">
|
<Label className="mx-1 text-right text-sm text-text-secondary">
|
||||||
{localize('com_endpoint_config_google_cloud_platform')}
|
{localize('com_endpoint_config_google_cloud_platform')}
|
||||||
</div>
|
</Label>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
<FileUpload
|
<FileUpload
|
||||||
|
|
|
||||||
|
|
@ -5,34 +5,9 @@ import { useLocalize } from '~/hooks';
|
||||||
function HelpText({ endpoint }: { endpoint: string }) {
|
function HelpText({ endpoint }: { endpoint: string }) {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const textMap = {
|
const textMap = {
|
||||||
[EModelEndpoint.chatGPTBrowser]: (
|
|
||||||
<small className="break-all text-gray-500">
|
|
||||||
{localize('com_endpoint_config_key_chatgpt')}{' '}
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
href="https://chat.openai.com"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="text-blue-600 underline"
|
|
||||||
>
|
|
||||||
https://chat.openai.com
|
|
||||||
</a>
|
|
||||||
{', '}
|
|
||||||
{localize('com_endpoint_config_key_chatgpt_then_visit')}{' '}
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
href="https://chat.openai.com/api/auth/session"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="text-blue-600 underline"
|
|
||||||
>
|
|
||||||
https://chat.openai.com/api/auth/session
|
|
||||||
</a>
|
|
||||||
{'. '}
|
|
||||||
{localize('com_endpoint_config_key_chatgpt_copy_token')}
|
|
||||||
</small>
|
|
||||||
),
|
|
||||||
[EModelEndpoint.google]: (
|
[EModelEndpoint.google]: (
|
||||||
<>
|
<>
|
||||||
<small className="break-all text-gray-500">
|
<small className="mt-4 break-all text-text-secondary">
|
||||||
{localize('com_endpoint_config_google_service_key')}
|
{localize('com_endpoint_config_google_service_key')}
|
||||||
{': '}
|
{': '}
|
||||||
{localize('com_endpoint_config_key_google_need_to')}{' '}
|
{localize('com_endpoint_config_key_google_need_to')}{' '}
|
||||||
|
|
@ -40,7 +15,7 @@ function HelpText({ endpoint }: { endpoint: string }) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://console.cloud.google.com/vertex-ai"
|
href="https://console.cloud.google.com/vertex-ai"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="text-blue-600 underline"
|
className="text-blue-700 underline dark:text-blue-400"
|
||||||
>
|
>
|
||||||
{localize('com_endpoint_config_key_google_vertex_ai')}
|
{localize('com_endpoint_config_key_google_vertex_ai')}
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
|
|
@ -49,14 +24,14 @@ function HelpText({ endpoint }: { endpoint: string }) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://console.cloud.google.com/projectselector/iam-admin/serviceaccounts/create?walkthrough_id=iam--create-service-account#step_index=1"
|
href="https://console.cloud.google.com/projectselector/iam-admin/serviceaccounts/create?walkthrough_id=iam--create-service-account#step_index=1"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="text-blue-600 underline"
|
className="text-blue-700 underline dark:text-blue-400"
|
||||||
>
|
>
|
||||||
{localize('com_endpoint_config_key_google_service_account')}
|
{localize('com_endpoint_config_key_google_service_account')}
|
||||||
</a>
|
</a>
|
||||||
{'. '}
|
{'. '}
|
||||||
{localize('com_endpoint_config_key_google_vertex_api_role')}
|
{localize('com_endpoint_config_key_google_vertex_api_role')}
|
||||||
</small>
|
</small>
|
||||||
<small className="break-all text-gray-500">
|
<small className="break-all text-text-secondary">
|
||||||
{localize('com_endpoint_config_google_api_key')}
|
{localize('com_endpoint_config_google_api_key')}
|
||||||
{': '}
|
{': '}
|
||||||
{localize('com_endpoint_config_google_api_info')}{' '}
|
{localize('com_endpoint_config_google_api_info')}{' '}
|
||||||
|
|
@ -64,7 +39,7 @@ function HelpText({ endpoint }: { endpoint: string }) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://makersuite.google.com/app/apikey"
|
href="https://makersuite.google.com/app/apikey"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="text-blue-600 underline"
|
className="text-blue-700 underline dark:text-blue-400"
|
||||||
>
|
>
|
||||||
{localize('com_endpoint_config_click_here')}
|
{localize('com_endpoint_config_click_here')}
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,11 @@ const InputWithLabel: FC<InputWithLabelProps> = forwardRef((props, ref) => {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={cn('flex flex-row', labelClassName)}>
|
<div className={cn('mt-4 flex flex-row', labelClassName)}>
|
||||||
<Label htmlFor={id} className="text-left text-sm font-medium">
|
<Label htmlFor={id} className="text-left text-sm font-medium">
|
||||||
{label}
|
{label}
|
||||||
</Label>
|
</Label>
|
||||||
{subLabel && (
|
{Label && <Label className="mx-1 text-right text-sm text-text-secondary">{subLabel}</Label>}
|
||||||
<div className="mx-1 text-left text-sm text-gray-700 dark:text-gray-400">{subLabel}</div>
|
|
||||||
)}
|
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
<div className="h-1" />
|
<div className="h-1" />
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ const SetKeyDialog = ({
|
||||||
<OGDialog open={open} onOpenChange={onOpenChange}>
|
<OGDialog open={open} onOpenChange={onOpenChange}>
|
||||||
<OGDialogTemplate
|
<OGDialogTemplate
|
||||||
title={`${localize('com_endpoint_config_key_for')} ${alternateName[endpoint] ?? endpoint}`}
|
title={`${localize('com_endpoint_config_key_for')} ${alternateName[endpoint] ?? endpoint}`}
|
||||||
className="w-11/12 max-w-[650px] sm:w-3/4 md:w-3/4 lg:w-3/4"
|
className="w-11/12 max-w-2xl"
|
||||||
showCancelButton={false}
|
showCancelButton={false}
|
||||||
main={
|
main={
|
||||||
<div className="grid w-full items-center gap-2">
|
<div className="grid w-full items-center gap-2">
|
||||||
|
|
@ -180,6 +180,7 @@ const SetKeyDialog = ({
|
||||||
onChange={handleExpirationChange}
|
onChange={handleExpirationChange}
|
||||||
options={expirationOptions.map((option) => option.label)}
|
options={expirationOptions.map((option) => option.label)}
|
||||||
sizeClasses="w-[185px]"
|
sizeClasses="w-[185px]"
|
||||||
|
portal={false}
|
||||||
/>
|
/>
|
||||||
<div className="mt-2" />
|
<div className="mt-2" />
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ interface DropdownProps {
|
||||||
iconOnly?: boolean;
|
iconOnly?: boolean;
|
||||||
renderValue?: (option: Option) => React.ReactNode;
|
renderValue?: (option: Option) => React.ReactNode;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
|
portal?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isDivider = (item: string | Option | { divider: true }): item is { divider: true } =>
|
const isDivider = (item: string | Option | { divider: true }): item is { divider: true } =>
|
||||||
|
|
@ -35,6 +36,7 @@ const Dropdown: React.FC<DropdownProps> = ({
|
||||||
iconOnly = false,
|
iconOnly = false,
|
||||||
renderValue,
|
renderValue,
|
||||||
ariaLabel,
|
ariaLabel,
|
||||||
|
portal = true,
|
||||||
}) => {
|
}) => {
|
||||||
const handleChange = (value: string) => {
|
const handleChange = (value: string) => {
|
||||||
onChange(value);
|
onChange(value);
|
||||||
|
|
@ -93,7 +95,7 @@ const Dropdown: React.FC<DropdownProps> = ({
|
||||||
{!iconOnly && <Select.SelectArrow />}
|
{!iconOnly && <Select.SelectArrow />}
|
||||||
</Select.Select>
|
</Select.Select>
|
||||||
<Select.SelectPopover
|
<Select.SelectPopover
|
||||||
portal
|
portal={portal}
|
||||||
store={selectProps}
|
store={selectProps}
|
||||||
className={cn('popover-ui', sizeClasses, className, 'max-h-[80vh] overflow-y-auto')}
|
className={cn('popover-ui', sizeClasses, className, 'max-h-[80vh] overflow-y-auto')}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,13 @@ const OGDialogTemplate = forwardRef((props: DialogTemplateProps, ref: Ref<HTMLDi
|
||||||
</OGDialogHeader>
|
</OGDialogHeader>
|
||||||
<div className={cn('px-0 py-2', mainClassName)}>{main != null ? main : null}</div>
|
<div className={cn('px-0 py-2', mainClassName)}>{main != null ? main : null}</div>
|
||||||
<OGDialogFooter className={footerClassName}>
|
<OGDialogFooter className={footerClassName}>
|
||||||
<div>{leftButtons != null ? <div className="mt-3 sm:mt-0">{leftButtons}</div> : null}</div>
|
<div>
|
||||||
|
{leftButtons != null ? (
|
||||||
|
<div className="mt-3 flex h-auto gap-3 max-sm:w-full max-sm:flex-col sm:mt-0 sm:flex-row">
|
||||||
|
{leftButtons}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
<div className="flex h-auto gap-3 max-sm:w-full max-sm:flex-col sm:flex-row">
|
<div className="flex h-auto gap-3 max-sm:w-full max-sm:flex-col sm:flex-row">
|
||||||
{buttons != null ? buttons : null}
|
{buttons != null ? buttons : null}
|
||||||
{showCancelButton && (
|
{showCancelButton && (
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ const Slider = React.forwardRef<
|
||||||
>(({ className, onDoubleClick, ...props }, ref) => (
|
>(({ className, onDoubleClick, ...props }, ref) => (
|
||||||
<SliderPrimitive.Root
|
<SliderPrimitive.Root
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('relative flex w-full touch-none select-none items-center', className)}
|
className={cn(
|
||||||
|
'relative flex w-full cursor-pointer touch-none select-none items-center',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
onDoubleClick={onDoubleClick}
|
onDoubleClick={onDoubleClick}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue