diff --git a/.github/workflows/a11y.yml b/.github/workflows/a11y.yml index 58ee07b2e..a7cfd0816 100644 --- a/.github/workflows/a11y.yml +++ b/.github/workflows/a11y.yml @@ -4,15 +4,23 @@ on: pull_request: paths: - 'client/src/**' + workflow_dispatch: + inputs: + run_workflow: + description: 'Set to true to run this workflow' + required: true + default: 'false' jobs: axe-linter: runs-on: ubuntu-latest - if: github.event.pull_request.head.repo.full_name == 'danny-avila/LibreChat' + if: > + (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'danny-avila/LibreChat') || + (github.event_name == 'workflow_dispatch' && github.event.inputs.run_workflow == 'true') steps: - uses: actions/checkout@v4 - uses: dequelabs/axe-linter-action@v1 with: api_key: ${{ secrets.AXE_LINTER_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/client/src/components/Chat/Input/Files/Table/DataTable.tsx b/client/src/components/Chat/Input/Files/Table/DataTable.tsx index ee997d9af..7b16920dd 100644 --- a/client/src/components/Chat/Input/Files/Table/DataTable.tsx +++ b/client/src/components/Chat/Input/Files/Table/DataTable.tsx @@ -110,7 +110,7 @@ export default function DataTable({ columns, data }: DataTablePro placeholder={localize('com_files_filter')} value={(table.getColumn('filename')?.getFilterValue() as string) ?? ''} onChange={(event) => table.getColumn('filename')?.setFilterValue(event.target.value)} - className="max-w-sm dark:border-gray-500" + className="max-w-sm border-border-light placeholder:text-text-secondary" /> @@ -175,7 +175,7 @@ export default function DataTable({ columns, data }: DataTablePro ))} - {table.getRowModel().rows?.length ? ( + {table.getRowModel().rows.length ? ( table.getRowModel().rows.map((row) => ( ({ columns, data }: DataTablePro > {row.getVisibleCells().map((cell, index) => { const maxWidth = - (cell.column.columnDef as AugmentedColumnDef)?.meta?.size ?? + (cell.column.columnDef as AugmentedColumnDef).meta.size ?? 'auto'; const style: Style = {}; diff --git a/client/src/components/Conversations/Conversations.tsx b/client/src/components/Conversations/Conversations.tsx index 63b458f61..99ca08b79 100644 --- a/client/src/components/Conversations/Conversations.tsx +++ b/client/src/components/Conversations/Conversations.tsx @@ -10,7 +10,7 @@ const Conversations = ({ moveToTop, toggleNav, }: { - conversations: TConversation[]; + conversations: Array; moveToTop: () => void; toggleNav: () => void; }) => { @@ -33,15 +33,15 @@ const Conversations = ({ {groupedConversations.map(([groupName, convos]) => (
- {localize(groupName) || groupName} + {localize(groupName) ?? groupName}
{convos.map((convo, i) => ( ({ placeholder={localize('com_files_filter')} value={(table.getColumn('filename')?.getFilterValue() as string) ?? ''} onChange={(event) => table.getColumn('filename')?.setFilterValue(event.target.value)} - className="max-w-sm dark:border-gray-500" + className="max-w-sm border-border-light placeholder:text-text-secondary" /> { @@ -204,7 +204,7 @@ export default function DataTableFile({ ))} - {table.getRowModel().rows?.length ? ( + {table.getRowModel().rows.length ? ( table.getRowModel().rows.map((row) => ( ({ > {row.getVisibleCells().map((cell, index) => { const maxWidth = - (cell.column.columnDef as AugmentedColumnDef)?.meta?.size ?? + (cell.column.columnDef as AugmentedColumnDef).meta.size ?? 'auto'; const style: Style = {}; diff --git a/client/src/components/Files/FileList/FileSidePanel.tsx b/client/src/components/Files/FileList/FileSidePanel.tsx index cd0da48a7..e1552d2a8 100644 --- a/client/src/components/Files/FileList/FileSidePanel.tsx +++ b/client/src/components/Files/FileList/FileSidePanel.tsx @@ -164,7 +164,7 @@ export default function FileSidePanel() { onChange={() => { console.log('changed'); }} - className="max-w-sm dark:border-gray-500" + className="max-w-sm border-border-light placeholder:text-text-secondary" />
diff --git a/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx b/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx index b7afde855..b1d0fe166 100644 --- a/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx +++ b/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx @@ -232,7 +232,7 @@ export default function VectorStoreSidePanel() { onChange={() => { console.log('changed'); }} - className="max-w-sm dark:border-gray-500" + className="max-w-sm border-border-light placeholder:text-text-secondary" />
diff --git a/client/src/components/Nav/SearchBar.tsx b/client/src/components/Nav/SearchBar.tsx index 143c9818f..6efebf419 100644 --- a/client/src/components/Nav/SearchBar.tsx +++ b/client/src/components/Nav/SearchBar.tsx @@ -60,14 +60,16 @@ const SearchBar = forwardRef((props: SearchBarProps, ref: Ref) =
- {} + { + + } { diff --git a/client/src/components/Prompts/Groups/ChatGroupItem.tsx b/client/src/components/Prompts/Groups/ChatGroupItem.tsx index 5986b49da..68bf01dd6 100644 --- a/client/src/components/Prompts/Groups/ChatGroupItem.tsx +++ b/client/src/components/Prompts/Groups/ChatGroupItem.tsx @@ -2,7 +2,6 @@ import { useState, useMemo } from 'react'; import { Menu as MenuIcon, Edit as EditIcon, EarthIcon, TextSearch } from 'lucide-react'; import type { TPromptGroup } from 'librechat-data-provider'; import { - Button, DropdownMenu, DropdownMenuItem, DropdownMenuGroup, @@ -29,12 +28,12 @@ export default function ChatGroupItem({ const [isVariableDialogOpen, setVariableDialogOpen] = useState(false); const onEditClick = useCustomLink(`/d/prompts/${group._id}`); const groupIsGlobal = useMemo( - () => instanceProjectId && group.projectIds?.includes(instanceProjectId), + () => instanceProjectId != null && group.projectIds?.includes(instanceProjectId), [group, instanceProjectId], ); const isOwner = useMemo(() => user?.id === group.author, [user, group]); - const onCardClick = () => { + const onCardClick: React.MouseEventHandler = () => { const text = group.productionPrompt?.prompt ?? ''; if (!text) { return; @@ -53,23 +52,26 @@ export default function ChatGroupItem({ name={group.name} category={group.category ?? ''} onClick={onCardClick} - snippet={group.oneliner ? group.oneliner : group.productionPrompt?.prompt ?? ''} + snippet={ + typeof group.oneliner === 'string' && group.oneliner.length > 0 + ? group.oneliner + : group.productionPrompt?.prompt ?? '' + } >
- {groupIsGlobal && } + {groupIsGlobal === true && } - + + {localize('com_ui_preview')} @@ -90,7 +92,7 @@ export default function ChatGroupItem({ { e.stopPropagation(); onEditClick(e); diff --git a/client/src/components/Prompts/Groups/FilterPrompts.tsx b/client/src/components/Prompts/Groups/FilterPrompts.tsx index e19e9a3f7..3230a8e31 100644 --- a/client/src/components/Prompts/Groups/FilterPrompts.tsx +++ b/client/src/components/Prompts/Groups/FilterPrompts.tsx @@ -152,7 +152,7 @@ export default function FilterPrompts({ setDisplayName(e.target.value); setName(e.target.value); }} - className="w-full border-border-light" + className="w-full border-border-light placeholder:text-text-secondary" />
); diff --git a/client/src/components/Prompts/Groups/ListCard.tsx b/client/src/components/Prompts/Groups/ListCard.tsx index aa0db6686..b438212ad 100644 --- a/client/src/components/Prompts/Groups/ListCard.tsx +++ b/client/src/components/Prompts/Groups/ListCard.tsx @@ -10,27 +10,25 @@ export default function ListCard({ category: string; name: string; snippet: string; - onClick?: React.MouseEventHandler; + onClick?: React.MouseEventHandler; children?: React.ReactNode; }) { return ( -
-

+

{name}

{children}
-
- {snippet} -
-
+
{snippet}
+ ); } diff --git a/client/src/components/SidePanel/Bookmarks/BookmarkTable.tsx b/client/src/components/SidePanel/Bookmarks/BookmarkTable.tsx index 1ca556980..7bde788e8 100644 --- a/client/src/components/SidePanel/Bookmarks/BookmarkTable.tsx +++ b/client/src/components/SidePanel/Bookmarks/BookmarkTable.tsx @@ -50,7 +50,7 @@ const BookmarkTable = () => { placeholder={localize('com_ui_bookmarks_filter')} value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} - className="w-full border-border-light" + className="w-full border-border-light placeholder:text-text-secondary" />
diff --git a/client/src/components/SidePanel/Builder/AssistantPanel.tsx b/client/src/components/SidePanel/Builder/AssistantPanel.tsx index 621156d9a..879c69d17 100644 --- a/client/src/components/SidePanel/Builder/AssistantPanel.tsx +++ b/client/src/components/SidePanel/Builder/AssistantPanel.tsx @@ -271,7 +271,7 @@ export default function AssistantPanel({ name="id" control={control} render={({ field }) => ( -

{field.value ?? ''}

+

{field.value ?? ''}

)} />
@@ -310,7 +310,7 @@ export default function AssistantPanel({ {...field} value={field.value ?? ''} {...{ max: 32768 }} - className={cn(inputClass, 'min-h-[100px] resize-none resize-y')} + className={cn(inputClass, 'min-h-[100px] resize-y')} id="instructions" placeholder={localize('com_assistants_instructions_placeholder')} rows={3} diff --git a/client/src/components/SidePanel/Builder/CodeFiles.tsx b/client/src/components/SidePanel/Builder/CodeFiles.tsx index 2048ac176..ef0c3cc70 100644 --- a/client/src/components/SidePanel/Builder/CodeFiles.tsx +++ b/client/src/components/SidePanel/Builder/CodeFiles.tsx @@ -45,7 +45,7 @@ export default function CodeFiles({ const endpointFileConfig = fileConfig.endpoints[endpoint]; - if (endpointFileConfig?.disabled) { + if (endpointFileConfig.disabled) { return null; } @@ -60,7 +60,7 @@ export default function CodeFiles({ return (
-
+
{localize('com_assistants_code_interpreter_files')}
({ columns, data }: DataTablePro placeholder={localize('com_files_filter')} value={(table.getColumn('filename')?.getFilterValue() as string) ?? ''} onChange={(event) => table.getColumn('filename')?.setFilterValue(event.target.value)} - className="w-full border-border-light" + className="w-full border-border-light placeholder:text-text-secondary" />
@@ -102,7 +102,7 @@ export default function DataTable({ columns, data }: DataTablePro ))} - {table.getRowModel().rows?.length ? ( + {table.getRowModel().rows.length ? ( table.getRowModel().rows.map((row) => ( { return ' ' + getYear(date).toString(); }; -export const groupConversationsByDate = (conversations: TConversation[]): GroupedConversations => { +export const groupConversationsByDate = ( + conversations: Array, +): GroupedConversations => { if (!Array.isArray(conversations)) { return []; } diff --git a/client/src/utils/index.ts b/client/src/utils/index.ts index 44645fbe9..1f7b0ced5 100644 --- a/client/src/utils/index.ts +++ b/client/src/utils/index.ts @@ -60,13 +60,13 @@ export const cardStyle = 'transition-colors rounded-md min-w-[75px] border font-normal bg-white hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-700 dark:bg-gray-800 text-black dark:text-gray-600 focus:outline-none data-[state=open]:bg-gray-50 dark:data-[state=open]:bg-gray-700'; export const defaultTextProps = - 'rounded-md border border-gray-200 focus:border-gray-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-gray-700 dark:border-gray-600 dark:focus:bg-gray-600 dark:focus:border-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:outline-none'; + 'rounded-md border border-gray-200 focus:border-gray-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none focus-within:placeholder:text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-gray-700 dark:border-gray-600 dark:focus:bg-gray-600 dark:focus:border-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:outline-none'; export const optionText = 'p-0 shadow-none text-right pr-1 h-8 border-transparent hover:bg-gray-800/10 dark:hover:bg-white/10 dark:focus:bg-white/10 transition-colors'; export const defaultTextPropsLabel = - 'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-700 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-600 dark:focus:outline-none'; + 'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none focus-within:placeholder:text-text-primary placeholder:text-text-secondary focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-700 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-600 dark:focus:outline-none'; export function capitalizeFirstLetter(string: string) { return string.charAt(0).toUpperCase() + string.slice(1);