mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 00:40:14 +01:00
⌨️ style(a11y): kb access for LLM endpoint menu; refactor: style (#3714)
This commit is contained in:
parent
98b437edd5
commit
0c5568b80b
6 changed files with 48 additions and 50 deletions
|
|
@ -84,14 +84,13 @@ export default function HeaderOptions({
|
|||
)}
|
||||
{!noSettings[endpoint] && interfaceConfig?.parameters && (
|
||||
<Button
|
||||
type="button"
|
||||
className={cn(
|
||||
cardStyle,
|
||||
'z-50 flex h-[40px] min-w-4 flex-none items-center justify-center px-3 focus:ring-0 focus:ring-offset-0',
|
||||
'hover:bg-gray-50 radix-state-open:bg-gray-50 dark:hover:bg-gray-700 dark:radix-state-open:bg-gray-700',
|
||||
)}
|
||||
onClick={triggerAdvancedMode}
|
||||
aria-label="Settings/parameters"
|
||||
id="parameters-button"
|
||||
data-testid="parameters-button"
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={triggerAdvancedMode}
|
||||
className="flex h-[40px] min-w-4 px-3 radix-state-open:bg-surface-hover"
|
||||
>
|
||||
<Settings2 className="w-4 text-gray-600 dark:text-white" />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -97,11 +97,8 @@ const MenuItem: FC<MenuItemProps> = ({
|
|||
<div
|
||||
role="menuitem"
|
||||
className={cn(
|
||||
'group m-1.5 flex max-h-[40px] cursor-pointer gap-2 rounded px-5 py-2.5 !pr-3 text-sm !opacity-100',
|
||||
'hover:bg-black/5 dark:hover:bg-gray-600',
|
||||
'group m-1.5 flex max-h-[40px] cursor-pointer gap-2 rounded px-5 py-2.5 !pr-3 text-sm !opacity-100 hover:bg-surface-hover',
|
||||
'radix-disabled:pointer-events-none radix-disabled:opacity-50',
|
||||
'focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2',
|
||||
'dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900',
|
||||
)}
|
||||
tabIndex={0}
|
||||
{...rest}
|
||||
|
|
@ -138,10 +135,7 @@ const MenuItem: FC<MenuItemProps> = ({
|
|||
className={cn(
|
||||
'invisible flex gap-x-1 group-hover:visible',
|
||||
selected ? 'visible' : '',
|
||||
expiryTime
|
||||
? 'w-full rounded-lg p-2 hover:text-gray-400 dark:hover:text-gray-400'
|
||||
: '',
|
||||
'focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900',
|
||||
expiryTime ? 'text-token-text-primary w-full rounded-lg p-2' : '',
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Content, Portal, Root, Trigger } from '@radix-ui/react-popover';
|
|||
import { EditPresetDialog, PresetItems } from './Presets';
|
||||
import { useLocalize, usePresets } from '~/hooks';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import { cn } from '~/utils';
|
||||
import { Button } from '~/components/ui';
|
||||
|
||||
const PresetsMenu: FC = () => {
|
||||
const localize = useLocalize();
|
||||
|
|
@ -25,19 +25,17 @@ const PresetsMenu: FC = () => {
|
|||
return (
|
||||
<Root>
|
||||
<Trigger asChild>
|
||||
<button
|
||||
className={cn(
|
||||
'pointer-cursor relative flex flex-col rounded-md border border-gray-100 bg-white text-left focus:ring-0 focus:ring-offset-0 dark:border-gray-700 dark:bg-gray-800 sm:text-sm',
|
||||
'hover:bg-gray-50 radix-state-open:bg-gray-50 dark:hover:bg-gray-700 dark:radix-state-open:bg-gray-700',
|
||||
'z-50 flex h-[40px] min-w-4 flex-none items-center justify-center px-3',
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="flex h-[40px] min-w-4 px-3 radix-state-open:bg-surface-hover"
|
||||
id="presets-button"
|
||||
data-testid="presets-button"
|
||||
title={localize('com_endpoint_examples')}
|
||||
aria-label={localize('com_endpoint_examples')}
|
||||
>
|
||||
<BookCopy className="icon-sm" id="presets-button" />
|
||||
</button>
|
||||
</Button>
|
||||
</Trigger>
|
||||
<Portal>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,32 +1,25 @@
|
|||
import { useState } from 'react';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import { Trigger } from '@radix-ui/react-popover';
|
||||
|
||||
export default function TitleButton({ primaryText = '', secondaryText = '' }) {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
|
||||
return (
|
||||
<Trigger asChild>
|
||||
<button
|
||||
className="group flex cursor-pointer items-center gap-1 rounded-xl px-3 py-2 text-lg font-medium hover:bg-gray-50 radix-state-open:bg-gray-50 dark:hover:bg-gray-700 dark:radix-state-open:bg-gray-700"
|
||||
type="button"
|
||||
className="group flex cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 text-lg font-medium transition-colors duration-200 hover:bg-surface-hover radix-state-open:bg-surface-hover"
|
||||
aria-label={`Select ${primaryText}`}
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded={isExpanded}
|
||||
aria-controls="radix-:r6:"
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
>
|
||||
<div>
|
||||
{primaryText}{' '}
|
||||
<span className="text-token-text-secondary"> {primaryText} </span>
|
||||
{!!secondaryText && <span className="text-token-text-secondary">{secondaryText}</span>}
|
||||
</div>
|
||||
<svg
|
||||
width="16"
|
||||
height="17"
|
||||
viewBox="0 0 16 17"
|
||||
fill="none"
|
||||
className="text-token-text-tertiary"
|
||||
>
|
||||
<path
|
||||
d="M11.3346 7.83203L8.00131 11.1654L4.66797 7.83203"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<ChevronDown className="text-token-text-secondary size-4" />
|
||||
</button>
|
||||
</Trigger>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ function PluginStoreDialog({ isOpen, setIsOpen }: TPluginStoreDialogProps) {
|
|||
(error: TError) => {
|
||||
setError(true);
|
||||
if (error.response?.data?.message) {
|
||||
setErrorMessage(error.response?.data?.message);
|
||||
setErrorMessage(error.response.data.message);
|
||||
}
|
||||
setTimeout(() => {
|
||||
setError(false);
|
||||
|
|
@ -187,7 +187,8 @@ function PluginStoreDialog({ isOpen, setIsOpen }: TPluginStoreDialogProps) {
|
|||
value={searchValue}
|
||||
onChange={handleSearch}
|
||||
placeholder={localize('com_nav_plugin_search')}
|
||||
className="flex rounded-md border border-gray-200 bg-transparent py-2 pl-10 pr-2 shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:border-gray-400 focus:bg-gray-50 focus:outline-none focus:ring-0 focus:ring-gray-400 focus:ring-opacity-0 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-500 focus:dark:bg-gray-600 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-500 dark:focus:ring-offset-0 dark:focus:ring-offset-gray-900"
|
||||
className="
|
||||
text-token-text-primary flex rounded-md border border-border-heavy bg-surface-tertiary py-2 pl-10 pr-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2271,30 +2271,30 @@ button.scroll-convo {
|
|||
}
|
||||
|
||||
.moon-rise {
|
||||
animation: moonRise 4s ease-in-out infinite; /* 'forwards' mantém a lua na posição final após a animação */
|
||||
transform-origin: 45% 50%; /* Ajuste dependendo da posição relativa do morro */
|
||||
animation: moonRise 4s ease-in-out infinite;
|
||||
transform-origin: 45% 50%;
|
||||
}
|
||||
|
||||
@keyframes moveUp {
|
||||
0% {
|
||||
transform: translateY(0.5px); /* Move um pouco para cima */
|
||||
transform: translateY(0.5px);
|
||||
opacity: 0.8;
|
||||
}
|
||||
10% {
|
||||
transform: translateY(0.5px); /* Move um pouco para cima */
|
||||
transform: translateY(0.5px);
|
||||
opacity: 1;
|
||||
}
|
||||
20% {
|
||||
transform: translateY(0px); /* Move um pouco para cima */
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: translateY(0px); /* Move um pouco para cima */
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
60%,
|
||||
100% {
|
||||
transform: translateY(0px); /* Move um pouco para cima */
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -2341,3 +2341,16 @@ button.scroll-convo {
|
|||
line-height: inherit;
|
||||
}
|
||||
|
||||
:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid #000;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.dark :focus-visible {
|
||||
outline: 2px solid #fff;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue