mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-07-11 08:43:48 +00:00
style: enhance UI components and improve layout consistency across various dialogs
This commit is contained in:
parent
e5e5663ca9
commit
0fe503e12a
16 changed files with 180 additions and 186 deletions
|
|
@ -11,6 +11,7 @@ import {
|
|||
Spinner,
|
||||
OGDialog,
|
||||
Dropdown,
|
||||
OGDialogClose,
|
||||
OGDialogTitle,
|
||||
OGDialogHeader,
|
||||
OGDialogFooter,
|
||||
|
|
@ -104,43 +105,41 @@ const RevokeKeysButton = ({
|
|||
const isLoading = revokeKeyMutation.isLoading || revokeKeysMutation.isLoading;
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<OGDialog open={open} onOpenChange={setOpen}>
|
||||
<OGDialogTrigger asChild>
|
||||
<OGDialog open={open} onOpenChange={setOpen}>
|
||||
<OGDialogTrigger asChild>
|
||||
<Button
|
||||
variant="destructive"
|
||||
className="flex w-full items-center justify-center rounded-lg transition-colors duration-200"
|
||||
onClick={() => setOpen(true)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{localize('com_ui_revoke')}
|
||||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogContent className="max-w-[450px]">
|
||||
<OGDialogHeader>
|
||||
<OGDialogTitle>{localize('com_ui_revoke_key_endpoint', { 0: endpoint })}</OGDialogTitle>
|
||||
</OGDialogHeader>
|
||||
<div className="py-4">
|
||||
<Label className="text-left text-sm font-medium">
|
||||
{localize('com_ui_revoke_key_confirm')}
|
||||
</Label>
|
||||
</div>
|
||||
<OGDialogFooter>
|
||||
<Button variant="outline" onClick={() => setOpen(false)}>
|
||||
{localize('com_ui_cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
className="flex items-center justify-center rounded-lg transition-colors duration-200"
|
||||
onClick={() => setOpen(true)}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
disabled={isLoading}
|
||||
className="bg-destructive text-white transition-all duration-200 hover:bg-destructive/80"
|
||||
>
|
||||
{localize('com_ui_revoke')}
|
||||
{isLoading ? <Spinner /> : localize('com_ui_revoke')}
|
||||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogContent className="max-w-[450px]">
|
||||
<OGDialogHeader>
|
||||
<OGDialogTitle>{localize('com_ui_revoke_key_endpoint', { 0: endpoint })}</OGDialogTitle>
|
||||
</OGDialogHeader>
|
||||
<div className="py-4">
|
||||
<Label className="text-left text-sm font-medium">
|
||||
{localize('com_ui_revoke_key_confirm')}
|
||||
</Label>
|
||||
</div>
|
||||
<OGDialogFooter>
|
||||
<Button variant="outline" onClick={() => setOpen(false)}>
|
||||
{localize('com_ui_cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={onClick}
|
||||
disabled={isLoading}
|
||||
className="bg-destructive text-white transition-all duration-200 hover:bg-destructive/80"
|
||||
>
|
||||
{isLoading ? <Spinner /> : localize('com_ui_revoke')}
|
||||
</Button>
|
||||
</OGDialogFooter>
|
||||
</OGDialogContent>
|
||||
</OGDialog>
|
||||
</div>
|
||||
</OGDialogFooter>
|
||||
</OGDialogContent>
|
||||
</OGDialog>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -276,7 +275,7 @@ const SetKeyDialog = ({
|
|||
|
||||
return (
|
||||
<OGDialog open={open} onOpenChange={onOpenChange}>
|
||||
<OGDialogContent className="w-11/12 max-w-2xl">
|
||||
<OGDialogContent className="w-11/12 max-w-2xl" showCloseButton={false}>
|
||||
<OGDialogHeader>
|
||||
<OGDialogTitle>
|
||||
{`${localize('com_endpoint_config_key_for')} ${alternateName[endpoint] ?? endpoint}`}
|
||||
|
|
@ -310,11 +309,16 @@ const SetKeyDialog = ({
|
|||
<HelpText endpoint={endpoint} />
|
||||
</div>
|
||||
<OGDialogFooter>
|
||||
<RevokeKeysButton
|
||||
endpoint={endpoint}
|
||||
disabled={!(expiryTime ?? '')}
|
||||
setDialogOpen={onOpenChange}
|
||||
/>
|
||||
<OGDialogClose asChild>
|
||||
<Button variant="outline">{localize('com_ui_cancel')}</Button>
|
||||
</OGDialogClose>
|
||||
{expiryTime && (
|
||||
<RevokeKeysButton
|
||||
endpoint={endpoint}
|
||||
disabled={!expiryTime}
|
||||
setDialogOpen={onOpenChange}
|
||||
/>
|
||||
)}
|
||||
<Button variant="submit" onClick={submit}>
|
||||
{localize('com_ui_submit')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { Button, Spinner } from '@librechat/client';
|
|||
import { useLocalize, useMCPServerManager, useMCPConnectionStatus } from '~/hooks';
|
||||
|
||||
interface ServerInitializationSectionProps {
|
||||
sidePanel?: boolean;
|
||||
serverName: string;
|
||||
requiresOAuth: boolean;
|
||||
hasCustomUserVars?: boolean;
|
||||
|
|
@ -15,7 +14,6 @@ export default function ServerInitializationSection({
|
|||
serverName,
|
||||
requiresOAuth,
|
||||
conversationId,
|
||||
sidePanel = false,
|
||||
hasCustomUserVars = false,
|
||||
}: ServerInitializationSectionProps) {
|
||||
const localize = useLocalize();
|
||||
|
|
@ -106,10 +104,10 @@ export default function ServerInitializationSection({
|
|||
</Button>
|
||||
)}
|
||||
<Button
|
||||
size="sm"
|
||||
variant={buttonVariant}
|
||||
onClick={() => initializeServer(serverName, false)}
|
||||
disabled={isServerInitializing}
|
||||
size={sidePanel ? 'sm' : 'default'}
|
||||
className="flex-1"
|
||||
>
|
||||
{icon}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ const AdminSettings = () => {
|
|||
}}
|
||||
>
|
||||
<OGDialogTemplate
|
||||
showCloseButton={true}
|
||||
showCloseButton={false}
|
||||
title={localize('com_ui_confirm_change')}
|
||||
className="w-11/12 max-w-lg"
|
||||
main={<p className="mb-4">{localize('com_ui_confirm_admin_use_change')}</p>}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
OGDialog,
|
||||
OGDialogTitle,
|
||||
OGDialogClose,
|
||||
OGDialogFooter,
|
||||
OGDialogContent,
|
||||
OGDialogTrigger,
|
||||
useToastContext,
|
||||
|
|
@ -277,7 +278,7 @@ export default function GenericGrantAccessDialog({
|
|||
</div>
|
||||
</OGDialogTitle>
|
||||
|
||||
<div className="space-y-6 p-2">
|
||||
<div className="space-y-6 py-2">
|
||||
{/* Unified Search and Management Section */}
|
||||
<div className="space-y-4">
|
||||
{/* Search Bar with Default Permission Setting */}
|
||||
|
|
@ -359,68 +360,53 @@ export default function GenericGrantAccessDialog({
|
|||
)}
|
||||
|
||||
{/* Footer Actions */}
|
||||
<div className="flex justify-between pt-4">
|
||||
<div className="flex gap-2">
|
||||
{resourceId && resourceUrl && (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
if (isCopying) return;
|
||||
copyResourceUrl(setIsCopying);
|
||||
showToast({
|
||||
message: localize('com_ui_agent_url_copied'),
|
||||
status: 'success',
|
||||
});
|
||||
}}
|
||||
disabled={isCopying}
|
||||
className={cn('shrink-0', isCopying ? 'cursor-default' : '')}
|
||||
aria-label={localize('com_ui_copy_url_to_clipboard')}
|
||||
title={
|
||||
isCopying
|
||||
? config?.getCopyUrlMessage()
|
||||
: localize('com_ui_copy_url_to_clipboard')
|
||||
}
|
||||
>
|
||||
{isCopying ? (
|
||||
<CopyCheck className="h-4 w-4" aria-hidden="true" />
|
||||
) : (
|
||||
<Link className="h-4 w-4" aria-hidden="true" />
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<PeoplePickerAdminSettings />
|
||||
<OGDialogClose asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleCancel}
|
||||
aria-label={localize('com_ui_cancel')}
|
||||
>
|
||||
{localize('com_ui_cancel')}
|
||||
</Button>
|
||||
</OGDialogClose>
|
||||
<OGDialogFooter className="pt-4">
|
||||
{resourceId && resourceUrl && (
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={
|
||||
updatePermissionsMutation.isLoading ||
|
||||
!submitButtonActive ||
|
||||
(hasChanges && !hasAtLeastOneOwner)
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
if (isCopying) return;
|
||||
copyResourceUrl(setIsCopying);
|
||||
showToast({
|
||||
message: localize('com_ui_agent_url_copied'),
|
||||
status: 'success',
|
||||
});
|
||||
}}
|
||||
disabled={isCopying}
|
||||
className={cn('shrink-0', isCopying ? 'cursor-default' : '')}
|
||||
aria-label={localize('com_ui_copy_url_to_clipboard')}
|
||||
title={
|
||||
isCopying ? config?.getCopyUrlMessage() : localize('com_ui_copy_url_to_clipboard')
|
||||
}
|
||||
className="min-w-[120px]"
|
||||
aria-label={localize('com_ui_save_changes')}
|
||||
>
|
||||
{updatePermissionsMutation.isLoading ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Spinner className="h-4 w-4" />
|
||||
{localize('com_ui_saving')}
|
||||
</div>
|
||||
{isCopying ? (
|
||||
<CopyCheck className="h-4 w-4" aria-hidden="true" />
|
||||
) : (
|
||||
localize('com_ui_save_changes')
|
||||
<Link className="h-4 w-4" aria-hidden="true" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<PeoplePickerAdminSettings />
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={
|
||||
updatePermissionsMutation.isLoading ||
|
||||
!submitButtonActive ||
|
||||
(hasChanges && !hasAtLeastOneOwner)
|
||||
}
|
||||
className="min-w-[120px]"
|
||||
aria-label={localize('com_ui_save_changes')}
|
||||
>
|
||||
{updatePermissionsMutation.isLoading ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Spinner className="h-4 w-4" />
|
||||
{localize('com_ui_saving')}
|
||||
</div>
|
||||
) : (
|
||||
localize('com_ui_save_changes')
|
||||
)}
|
||||
</Button>
|
||||
</OGDialogFooter>
|
||||
</div>
|
||||
</OGDialogContent>
|
||||
</OGDialog>
|
||||
|
|
|
|||
|
|
@ -180,9 +180,11 @@ export function SearchPicker<TOption extends { key: string; value: string }>({
|
|||
)}
|
||||
>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<Search className="h-8 w-8 text-text-tertiary opacity-50" />
|
||||
<div className="font-medium">{localize('com_ui_no_results_found')}</div>
|
||||
<div className="text-xs text-text-tertiary">
|
||||
<Search className="h-8 w-8 text-text-primary opacity-50" />
|
||||
<div className="font-medium text-text-primary">
|
||||
{localize('com_ui_no_results_found')}
|
||||
</div>
|
||||
<div className="text-xs text-text-secondary">
|
||||
{localize('com_ui_try_adjusting_search')}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,12 +42,12 @@ export default function MCPIcon({ icon, onIconChange }: MCPIconProps) {
|
|||
onClick={handleClick}
|
||||
onKeyDown={handleKeyDown}
|
||||
aria-label={localize('com_ui_upload_icon')}
|
||||
className="bg-token-surface-secondary dark:bg-token-surface-tertiary border-token-border-medium flex h-16 w-16 shrink-0 cursor-pointer items-center justify-center rounded-xl border-2 border-dashed focus:outline-none focus-visible:ring-2 focus-visible:ring-border-heavy"
|
||||
className="flex h-16 w-16 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-dashed border-border-heavy focus:outline-none focus-visible:ring-2 focus-visible:ring-border-heavy"
|
||||
>
|
||||
{previewUrl ? (
|
||||
<img
|
||||
src={previewUrl}
|
||||
className="h-full w-full rounded-xl object-cover"
|
||||
className="h-full w-full rounded-full object-cover"
|
||||
alt="MCP Icon"
|
||||
width="64"
|
||||
height="64"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Copy, CopyCheck } from 'lucide-react';
|
||||
import {
|
||||
OGDialog,
|
||||
OGDialogTemplate,
|
||||
OGDialogContent,
|
||||
OGDialogHeader,
|
||||
OGDialogTitle,
|
||||
Label,
|
||||
Input,
|
||||
Button,
|
||||
TrashIcon,
|
||||
Spinner,
|
||||
TrashIcon,
|
||||
useToastContext,
|
||||
OGDialog,
|
||||
OGDialogTitle,
|
||||
OGDialogHeader,
|
||||
OGDialogContent,
|
||||
OGDialogTemplate,
|
||||
} from '@librechat/client';
|
||||
import {
|
||||
SystemRoles,
|
||||
|
|
@ -16,10 +20,10 @@ import {
|
|||
PermissionBits,
|
||||
PermissionTypes,
|
||||
} from 'librechat-data-provider';
|
||||
import { GenericGrantAccessDialog } from '~/components/Sharing';
|
||||
import { useAuthContext, useHasAccess, useResourcePermissions, MCPServerDefinition } from '~/hooks';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { GenericGrantAccessDialog } from '~/components/Sharing';
|
||||
import { useMCPServerForm } from './hooks/useMCPServerForm';
|
||||
import { useLocalize, useCopyToClipboard } from '~/hooks';
|
||||
import MCPServerForm from './MCPServerForm';
|
||||
|
||||
interface MCPServerDialogProps {
|
||||
|
|
@ -39,8 +43,10 @@ export default function MCPServerDialog({
|
|||
}: MCPServerDialogProps) {
|
||||
const localize = useLocalize();
|
||||
const { user } = useAuthContext();
|
||||
const { showToast } = useToastContext();
|
||||
|
||||
// State for dialogs
|
||||
const [isCopying, setIsCopying] = useState(false);
|
||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||
const [showRedirectUriDialog, setShowRedirectUriDialog] = useState(false);
|
||||
const [createdServerId, setCreatedServerId] = useState<string | null>(null);
|
||||
|
|
@ -99,6 +105,8 @@ export default function MCPServerDialog({
|
|||
? `${window.location.origin}/api/mcp/${createdServerId}/oauth/callback`
|
||||
: '';
|
||||
|
||||
const copyLink = useCopyToClipboard({ text: redirectUri });
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Delete confirmation dialog */}
|
||||
|
|
@ -127,48 +135,50 @@ export default function MCPServerDialog({
|
|||
}
|
||||
}}
|
||||
>
|
||||
<OGDialogContent className="w-full max-w-lg border-none bg-surface-primary text-text-primary">
|
||||
<OGDialogHeader className="border-b border-border-light px-4 py-3">
|
||||
<OGDialogContent showCloseButton={false} className="w-11/12 max-w-lg">
|
||||
<OGDialogHeader>
|
||||
<OGDialogTitle>{localize('com_ui_mcp_server_created')}</OGDialogTitle>
|
||||
</OGDialogHeader>
|
||||
<div className="space-y-4 p-4">
|
||||
<p className="text-sm text-text-secondary">
|
||||
{localize('com_ui_redirect_uri_instructions')}
|
||||
</p>
|
||||
<div className="rounded-lg border border-border-medium bg-surface-secondary p-3">
|
||||
<label className="mb-2 block text-xs font-medium text-text-secondary">
|
||||
{localize('com_ui_redirect_uri')}
|
||||
</label>
|
||||
<div className="space-y-4">
|
||||
<Label className="text-sm">{localize('com_ui_redirect_uri_instructions')}</Label>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label className="text-sm font-medium">{localize('com_ui_redirect_uri')}</Label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
className="flex-1 rounded border border-border-medium bg-surface-primary px-3 py-2 text-sm"
|
||||
value={redirectUri}
|
||||
<Input
|
||||
type="text"
|
||||
readOnly
|
||||
value={redirectUri}
|
||||
className="flex-1 text-text-secondary"
|
||||
/>
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(redirectUri);
|
||||
}}
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="whitespace-nowrap"
|
||||
onClick={() => {
|
||||
if (isCopying) return;
|
||||
showToast({ message: localize('com_ui_copied_to_clipboard') });
|
||||
copyLink(setIsCopying);
|
||||
}}
|
||||
disabled={isCopying}
|
||||
className="p-0"
|
||||
aria-label={localize('com_ui_copy_link')}
|
||||
>
|
||||
{localize('com_ui_copy_link')}
|
||||
{isCopying ? <CopyCheck className="size-4" /> : <Copy className="size-4" />}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-end">
|
||||
<OGDialogHeader>
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={() => {
|
||||
setShowRedirectUriDialog(false);
|
||||
onOpenChange(false);
|
||||
setCreatedServerId(null);
|
||||
}}
|
||||
variant="submit"
|
||||
className="text-white"
|
||||
>
|
||||
{localize('com_ui_done')}
|
||||
</Button>
|
||||
</div>
|
||||
</OGDialogHeader>
|
||||
</div>
|
||||
</OGDialogContent>
|
||||
</OGDialog>
|
||||
|
|
@ -187,6 +197,7 @@ export default function MCPServerDialog({
|
|||
})
|
||||
: undefined
|
||||
}
|
||||
showCloseButton={false}
|
||||
className="w-11/12 md:max-w-3xl"
|
||||
main={<MCPServerForm formHook={formHook} />}
|
||||
footerClassName="sm:justify-between"
|
||||
|
|
@ -218,10 +229,9 @@ export default function MCPServerDialog({
|
|||
buttons={
|
||||
<Button
|
||||
type="button"
|
||||
variant="submit"
|
||||
variant={isEditMode ? 'default' : 'submit'}
|
||||
onClick={onSubmit}
|
||||
disabled={isSubmitting}
|
||||
className="text-white"
|
||||
>
|
||||
{isSubmitting ? (
|
||||
<Spinner className="size-4" />
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { useMemo, useState } from 'react';
|
||||
import { Copy, CopyCheck } from 'lucide-react';
|
||||
import { useFormContext, useWatch } from 'react-hook-form';
|
||||
import { Label, Input, Checkbox, SecretInput, Radio, useToastContext } from '@librechat/client';
|
||||
import { Copy, CopyCheck } from 'lucide-react';
|
||||
import { useLocalize, useCopyToClipboard } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
import { AuthTypeEnum, AuthorizationTypeEnum } from '../hooks/useMCPServerForm';
|
||||
import type { MCPServerFormData } from '../hooks/useMCPServerForm';
|
||||
import { useLocalize, useCopyToClipboard } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
interface AuthSectionProps {
|
||||
isEditMode: boolean;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { useFormContext } from 'react-hook-form';
|
||||
import { Input, Label, TextareaAutosize } from '@librechat/client';
|
||||
import { Input, Label, Textarea } from '@librechat/client';
|
||||
import type { MCPServerFormData } from '../hooks/useMCPServerForm';
|
||||
import MCPIcon from '~/components/SidePanel/Agents/MCPIcon';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
import MCPIcon from '~/components/SidePanel/Agents/MCPIcon';
|
||||
import type { MCPServerFormData } from '../hooks/useMCPServerForm';
|
||||
|
||||
export default function BasicInfoSection() {
|
||||
const localize = useLocalize();
|
||||
|
|
@ -50,26 +50,23 @@ export default function BasicInfoSection() {
|
|||
message: localize('com_ui_mcp_title_invalid'),
|
||||
},
|
||||
})}
|
||||
className={cn(errors.title && 'border-red-500 focus:border-red-500')}
|
||||
className={cn(errors.title && 'border-text-destructive')}
|
||||
/>
|
||||
{errors.title && <p className="text-xs text-red-500">{errors.title.message}</p>}
|
||||
{errors.title && <p className="text-xs text-text-destructive">{errors.title.message}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Description - always visible, full width */}
|
||||
{/* Description */}
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="description" className="text-sm font-medium">
|
||||
{localize('com_ui_description')}{' '}
|
||||
<span className="text-xs text-text-secondary">{localize('com_ui_optional')}</span>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
<Textarea
|
||||
id="description"
|
||||
aria-label={localize('com_ui_description')}
|
||||
placeholder={localize('com_agents_mcp_description_placeholder')}
|
||||
{...register('description')}
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
className="w-full resize-none rounded-lg border border-input bg-transparent px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -918,7 +918,7 @@
|
|||
"com_ui_edit": "Edit",
|
||||
"com_ui_edit_editing_image": "Editing image",
|
||||
"com_ui_edit_mcp_server": "Edit MCP Server",
|
||||
"com_ui_edit_mcp_server_dialog_description": "Unique Server Identifier: {{serverName}}",
|
||||
"com_ui_edit_mcp_server_dialog_description": "Server ID: {{serverName}}",
|
||||
"com_ui_edit_memory": "Edit Memory",
|
||||
"com_ui_edit_preset_title": "Edit Preset - {{title}}",
|
||||
"com_ui_edit_prompt_page": "Edit Prompt Page",
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ html {
|
|||
--text-secondary-alt: var(--gray-500);
|
||||
--text-tertiary: var(--gray-500);
|
||||
--text-warning: var(--amber-500);
|
||||
--text-destructive: var(--red-600);
|
||||
--ring-primary: var(--gray-500);
|
||||
--header-primary: var(--white);
|
||||
--header-hover: var(--gray-50);
|
||||
|
|
@ -131,6 +132,7 @@ html {
|
|||
--text-secondary-alt: var(--gray-400);
|
||||
--text-tertiary: var(--gray-500);
|
||||
--text-warning: var(--amber-500);
|
||||
--text-destructive: var(--red-600);
|
||||
--header-primary: var(--gray-700);
|
||||
--header-hover: var(--gray-600);
|
||||
--header-button-hover: var(--gray-700);
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ module.exports = {
|
|||
'text-secondary-alt': 'var(--text-secondary-alt)',
|
||||
'text-tertiary': 'var(--text-tertiary)',
|
||||
'text-warning': 'var(--text-warning)',
|
||||
'text-destructive': 'var(--text-destructive)',
|
||||
'ring-primary': 'var(--ring-primary)',
|
||||
'header-primary': 'var(--header-primary)',
|
||||
'header-hover': 'var(--header-hover)',
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const Label = React.forwardRef<
|
|||
{...props}
|
||||
{...{
|
||||
className: cn(
|
||||
'block w-full break-all text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 dark:text-gray-200',
|
||||
'block w-full text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 text-text-primary',
|
||||
className,
|
||||
),
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -75,38 +75,32 @@ const OGDialogTemplate = forwardRef((props: DialogTemplateProps, ref: Ref<HTMLDi
|
|||
</OGDialogHeader>
|
||||
<div className={cn('px-0 py-2', mainClassName)}>{main != null ? main : null}</div>
|
||||
<OGDialogFooter className={footerClassName}>
|
||||
<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">
|
||||
{showCancelButton && (
|
||||
<OGDialogClose asChild>
|
||||
<Button variant="outline" aria-label={localize('com_ui_cancel')}>
|
||||
{localize('com_ui_cancel')}
|
||||
</Button>
|
||||
</OGDialogClose>
|
||||
)}
|
||||
{buttons != null ? buttons : null}
|
||||
{selection ? (
|
||||
<OGDialogClose
|
||||
onClick={selectHandler}
|
||||
disabled={isLoading}
|
||||
className={`${
|
||||
selectClasses ?? defaultSelect
|
||||
} flex h-10 items-center justify-center rounded-lg border-none px-4 py-2 text-sm disabled:opacity-80 max-sm:order-first max-sm:w-full sm:order-none`}
|
||||
>
|
||||
{isLoading === true ? (
|
||||
<Spinner className="size-4 text-white" />
|
||||
) : (
|
||||
(selectText as React.JSX.Element)
|
||||
)}
|
||||
</OGDialogClose>
|
||||
) : null}
|
||||
</div>
|
||||
{leftButtons != null ? (
|
||||
<div className="mr-auto flex flex-row gap-2">{leftButtons}</div>
|
||||
) : null}
|
||||
{showCancelButton && (
|
||||
<OGDialogClose asChild>
|
||||
<Button variant="outline" aria-label={localize('com_ui_cancel')}>
|
||||
{localize('com_ui_cancel')}
|
||||
</Button>
|
||||
</OGDialogClose>
|
||||
)}
|
||||
{buttons != null ? buttons : null}
|
||||
{selection ? (
|
||||
<OGDialogClose
|
||||
onClick={selectHandler}
|
||||
disabled={isLoading}
|
||||
className={`${
|
||||
selectClasses ?? defaultSelect
|
||||
} flex h-10 items-center justify-center rounded-lg border-none px-4 py-2 text-sm disabled:opacity-80`}
|
||||
>
|
||||
{isLoading === true ? (
|
||||
<Spinner className="size-4 text-white" />
|
||||
) : (
|
||||
(selectText as React.JSX.Element)
|
||||
)}
|
||||
</OGDialogClose>
|
||||
) : null}
|
||||
</OGDialogFooter>
|
||||
</OGDialogContent>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ DialogHeader.displayName = 'DialogHeader';
|
|||
|
||||
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn('flex w-full flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
|
||||
className={cn('flex w-full gap-2', 'flex-col sm:flex-row', 'sm:justify-end', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|||
return (
|
||||
<textarea
|
||||
className={cn(
|
||||
'flex h-20 w-full resize-none rounded-md border border-gray-300 bg-transparent px-3 py-2 text-sm placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-700 dark:text-gray-50 dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900',
|
||||
'flex h-20 w-full resize-none rounded-md border border-border-light bg-transparent px-3 py-2 text-sm placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:text-gray-50 dark:focus-visible:ring-gray-400 dark:focus-visible:ring-offset-gray-900',
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue