mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-21 21:50:49 +02:00
🎨 style: Unify Styles across Themes and Improve Accessibility (#7783)
* style: update button styles for improved hover effects and accessibility * style: enhance CustomMenuItem styling for improved visual feedback * style: improved accessibility and visual consistency * chore: add missing localization in ActionsPanel --------- Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
parent
c22d74d41e
commit
cd7dd576c1
9 changed files with 38 additions and 66 deletions
|
@ -159,7 +159,7 @@ export const CustomMenuItem = React.forwardRef<HTMLDivElement, CustomMenuItemPro
|
|||
blurOnHoverEnd: false,
|
||||
...props,
|
||||
className: cn(
|
||||
'flex cursor-default items-center gap-2 rounded-lg p-2 outline-none! scroll-m-1 scroll-mt-[calc(var(--combobox-height,0px)+var(--label-height,4px))] aria-disabled:opacity-25 border-l-2 border-transparent data-[active-item]:border-black data-[active-item]:rounded-l-none data-[active-item]:bg-black/[0.075] data-[active-item]:text-black dark:data-[active-item]:bg-white/10 dark:data-[active-item]:text-white dark:data-[active-item]:border-white sm:py-1 sm:text-sm min-w-0 w-full',
|
||||
'relative flex cursor-default items-center gap-2 rounded-lg p-2 outline-none! scroll-m-1 scroll-mt-[calc(var(--combobox-height,0px)+var(--label-height,4px))] aria-disabled:opacity-25 data-[active-item]:bg-black/[0.075] data-[active-item]:text-black dark:data-[active-item]:bg-white/10 dark:data-[active-item]:text-white sm:py-1 sm:text-sm min-w-0 w-full before:absolute before:left-0 before:top-1 before:bottom-1 before:w-0.5 before:bg-transparent before:rounded-full data-[active-item]:before:bg-black dark:data-[active-item]:before:bg-white',
|
||||
props.className,
|
||||
),
|
||||
};
|
||||
|
|
|
@ -68,7 +68,7 @@ export default function DialogImage({ isOpen, onOpenChange, src = '', downloadIm
|
|||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
<TooltipAnchor
|
||||
description={localize('com_ui_save')}
|
||||
description={localize('com_ui_download')}
|
||||
render={
|
||||
<Button onClick={() => downloadImage()} variant="ghost" className="h-10 w-10 p-0">
|
||||
<ArrowDownToLine className="size-6" />
|
||||
|
@ -108,7 +108,7 @@ export default function DialogImage({ isOpen, onOpenChange, src = '', downloadIm
|
|||
alt="Image"
|
||||
className="max-h-full max-w-full object-contain"
|
||||
style={{
|
||||
maxHeight: 'calc(100vh - 6rem)', // Account for header and padding
|
||||
maxHeight: 'calc(100vh - 6rem)',
|
||||
maxWidth: '100%',
|
||||
}}
|
||||
/>
|
||||
|
@ -117,7 +117,7 @@ export default function DialogImage({ isOpen, onOpenChange, src = '', downloadIm
|
|||
|
||||
{/* Side Panel */}
|
||||
<div
|
||||
className={`shadow-l-lg fixed right-0 top-0 z-20 h-full w-80 transform rounded-l-2xl border-l border-border-light bg-surface-secondary transition-transform duration-500 ease-in-out ${
|
||||
className={`shadow-l-lg fixed right-0 top-0 z-20 h-full w-80 transform rounded-l-2xl border-l border-border-light bg-surface-primary transition-transform duration-500 ease-in-out ${
|
||||
isPromptOpen ? 'translate-x-0' : 'translate-x-full'
|
||||
}`}
|
||||
>
|
||||
|
@ -132,7 +132,7 @@ export default function DialogImage({ isOpen, onOpenChange, src = '', downloadIm
|
|||
<div className="space-y-6">
|
||||
{/* Prompt Section */}
|
||||
<div>
|
||||
<h4 className="mb-2 text-sm font-medium text-text-secondary">
|
||||
<h4 className="mb-2 text-sm font-medium text-text-primary">
|
||||
{localize('com_ui_prompt')}
|
||||
</h4>
|
||||
<div className="rounded-md bg-surface-tertiary p-3">
|
||||
|
@ -144,20 +144,18 @@ export default function DialogImage({ isOpen, onOpenChange, src = '', downloadIm
|
|||
|
||||
{/* Generation Settings */}
|
||||
<div>
|
||||
<h4 className="mb-3 text-sm font-medium text-text-secondary">
|
||||
<h4 className="mb-3 text-sm font-medium text-text-primary">
|
||||
{localize('com_ui_generation_settings')}
|
||||
</h4>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-text-secondary">{localize('com_ui_size')}:</span>
|
||||
<span className="text-sm text-text-primary">{localize('com_ui_size')}:</span>
|
||||
<span className="text-sm font-medium text-text-primary">
|
||||
{args?.size || 'Unknown'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-text-secondary">
|
||||
{localize('com_ui_quality')}:
|
||||
</span>
|
||||
<span className="text-sm text-text-primary">{localize('com_ui_quality')}:</span>
|
||||
<span
|
||||
className={`rounded px-2 py-1 text-xs font-medium capitalize ${
|
||||
args?.quality === 'high'
|
||||
|
@ -171,7 +169,7 @@ export default function DialogImage({ isOpen, onOpenChange, src = '', downloadIm
|
|||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-text-secondary">
|
||||
<span className="text-sm text-text-primary">
|
||||
{localize('com_ui_file_size')}:
|
||||
</span>
|
||||
<span className="text-sm font-medium text-text-primary">
|
||||
|
|
|
@ -178,17 +178,6 @@ export default function OpenAIImageGen({
|
|||
<div className="relative my-2.5 flex size-5 shrink-0 items-center gap-2.5">
|
||||
<ProgressText progress={progress} error={cancelled} toolName={toolName} />
|
||||
</div>
|
||||
|
||||
{/* {showInfo && hasInfo && (
|
||||
<ToolCallInfo
|
||||
key="tool-call-info"
|
||||
input={args ?? ''}
|
||||
output={output}
|
||||
function_name={function_name}
|
||||
pendingAuth={authDomain.length > 0 && !cancelled && initialProgress < 1}
|
||||
/>
|
||||
)} */}
|
||||
|
||||
<div className="relative mb-2 flex w-full justify-start">
|
||||
<div ref={containerRef} className="w-full max-w-lg">
|
||||
{dimensions.width !== 'auto' && progress < 1 && (
|
||||
|
|
|
@ -216,18 +216,12 @@ function FeedbackButtons({
|
|||
|
||||
function buttonClasses(isActive: boolean, isLast: boolean) {
|
||||
return cn(
|
||||
'hover-button rounded-lg p-1.5',
|
||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black dark:focus-visible:ring-white',
|
||||
'hover:bg-gray-100 hover:text-gray-500',
|
||||
'data-[state=open]:active data-[state=open]:bg-gray-100 data-[state=open]:text-gray-500',
|
||||
isActive ? 'text-gray-500 dark:text-gray-200 font-bold' : 'dark:text-gray-400/70',
|
||||
'dark:hover:bg-gray-700 dark:hover:text-gray-200',
|
||||
'data-[state=open]:dark:bg-gray-700 data-[state=open]:dark:text-gray-200',
|
||||
'disabled:dark:hover:text-gray-400',
|
||||
isLast
|
||||
? ''
|
||||
: 'data-[state=open]:opacity-100 md:opacity-0 md:group-focus-within:opacity-100 md:group-hover:opacity-100',
|
||||
'md:group-focus-within:visible md:group-hover:visible md:group-[.final-completion]:visible',
|
||||
'hover-button rounded-lg p-1.5 text-text-secondary-alt transition-colors duration-200',
|
||||
'hover:text-text-primary hover:bg-surface-hover',
|
||||
'md:group-hover:visible md:group-focus-within:visible md:group-[.final-completion]:visible',
|
||||
!isLast && 'md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100',
|
||||
'focus-visible:ring-2 focus-visible:ring-black dark:focus-visible:ring-white focus-visible:outline-none',
|
||||
isActive && 'active text-text-primary bg-surface-hover',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -211,14 +211,12 @@ export default function Fork({
|
|||
});
|
||||
|
||||
const buttonStyle = cn(
|
||||
'hover-button rounded-lg p-1.5',
|
||||
'hover:bg-gray-100 hover:text-gray-500',
|
||||
'dark:text-gray-400/70 dark:hover:bg-gray-700 dark:hover:text-gray-200',
|
||||
'disabled:dark:hover:text-gray-400',
|
||||
'hover-button rounded-lg p-1.5 text-text-secondary-alt transition-colors duration-200',
|
||||
'hover:text-text-primary hover:bg-surface-hover',
|
||||
'md:group-hover:visible md:group-focus-within:visible md:group-[.final-completion]:visible',
|
||||
!isLast && 'md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100',
|
||||
'focus-visible:ring-2 focus-visible:ring-black dark:focus-visible:ring-white focus-visible:outline-none',
|
||||
isActive && 'active text-gray-700 dark:text-gray-200 bg-gray-100 bg-gray-700',
|
||||
isActive && 'active text-text-primary bg-surface-hover',
|
||||
);
|
||||
|
||||
const forkConvo = useForkConvoMutation({
|
||||
|
|
|
@ -77,21 +77,13 @@ const HoverButton = memo(
|
|||
className = '',
|
||||
}: HoverButtonProps) => {
|
||||
const buttonStyle = cn(
|
||||
'hover-button rounded-lg p-1.5',
|
||||
|
||||
'hover:bg-gray-100 hover:text-gray-500',
|
||||
|
||||
'dark:text-gray-400/70 dark:hover:bg-gray-700 dark:hover:text-gray-200',
|
||||
'disabled:dark:hover:text-gray-400',
|
||||
|
||||
'hover-button rounded-lg p-1.5 text-text-secondary-alt transition-colors duration-200',
|
||||
'hover:text-text-primary hover:bg-surface-hover',
|
||||
'md:group-hover:visible md:group-focus-within:visible md:group-[.final-completion]:visible',
|
||||
!isLast && 'md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100',
|
||||
!isVisible && 'opacity-0',
|
||||
|
||||
'focus-visible:ring-2 focus-visible:ring-black dark:focus-visible:ring-white focus-visible:outline-none',
|
||||
|
||||
isActive && isVisible && 'active text-gray-700 dark:text-gray-200 bg-gray-100 bg-gray-700',
|
||||
|
||||
isActive && isVisible && 'active text-text-primary bg-surface-hover',
|
||||
className,
|
||||
);
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ export default function ActionsPanel({
|
|||
selectHandler: () => {
|
||||
if (!agent_id) {
|
||||
return showToast({
|
||||
message: 'No agent_id found, is the agent created?',
|
||||
message: localize('com_agents_no_agent_id_error'),
|
||||
status: 'error',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"com_agents_missing_provider_model": "Please select a provider and model before creating an agent.",
|
||||
"com_agents_name_placeholder": "Optional: The name of the agent",
|
||||
"com_agents_no_access": "You don't have access to edit this agent.",
|
||||
"com_agents_no_agent_id_error": "No agent ID found. Please ensure the agent is created first.",
|
||||
"com_agents_not_available": "Agent Not Available",
|
||||
"com_agents_search_info": "When enabled, allows your agent to search the web for up-to-date information. Requires a valid API key.",
|
||||
"com_agents_search_name": "Search agents by name",
|
||||
|
@ -970,4 +971,4 @@
|
|||
"com_ui_zoom": "Zoom",
|
||||
"com_user_message": "You",
|
||||
"com_warning_resubmit_unsupported": "Resubmitting the AI message is not supported for this endpoint."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2720,6 +2720,20 @@ html {
|
|||
.shimmer {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgb(33, 33, 33) 25%,
|
||||
rgba(129, 130, 134, 0.18) 50%,
|
||||
rgb(33, 33, 33) 75%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
animation: shimmer 4s linear infinite;
|
||||
}
|
||||
|
||||
.dark .shimmer {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0.8) 25%,
|
||||
|
@ -2733,20 +2747,6 @@ html {
|
|||
animation: shimmer 4s linear infinite;
|
||||
}
|
||||
|
||||
:global(.dark) .shimmer {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255) 25%,
|
||||
rgba(129, 130, 134, 0.18) 50%,
|
||||
rgb(255, 255, 255) 75%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
animation: shimmer 4s linear infinite;
|
||||
}
|
||||
|
||||
.custom-style-2 {
|
||||
padding: 12px;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue