mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-09-04 05:28:30 +00:00
* refactor(AdminSettings): consolidate every admin dialog on one implementation The People Picker admin dialog was a standalone reimplementation of the shared AdminSettingsDialog with a better layout, leaving two components to keep in sync by hand. Port that layout into the shared component and rewrite People Picker to configure it, so all eight admin dialogs render from one place. The shared dialog gains the icon-tile header, the role selector and permission switches as bordered cards, and a real footer. Its header row was also top-aligning the 40px icon tile against a single-line title, leaving the icon hanging 6px low; it now centers. Both behaviors the standalone version lacked are preserved: the admin access warning and the confirm-before-disable flow used by Prompts. Adds an optional descriptionKey for a screen-reader description, and closes the dialog when the mutation reports success, which is how People Picker kept its auto-close. Permission switch ids are prefixed with useId so two mounted dialogs cannot collide. Marketplace dropped its dialogContentClassName override because the max-w-md and background it set conflicted with the new padding. * feat(ui): add FieldMessage for helper text that never shifts layout Form fields across the app render their validation error conditionally, so the error appearing pushes every field below it down. FieldMessage always occupies one line and only swaps its content and color between a resting hint, an error, and nothing, so the surrounding layout is fixed by construction rather than by whichever message happens to be showing. * fix(Memories): validate the key and value on the client Creating or updating a memory only learned that its key was malformed or already taken after the request came back, and the failure arrived as a toast. getMemoryKeyError mirrors the schema validator in data-schemas and checks for a duplicate within the same agent partition, so both dialogs resolve the outcome before sending anything. Errors render inline under the field instead of as a toast, live from the first character typed, and Create and Save stay disabled while any error stands. A pristine empty field shows only its hint, so the form does not report a problem before there is one. The edit dialog also closed itself in onMutate, discarding the user's edits whenever the server rejected the write and leaving the error toast to land on a dialog that was already gone. It now closes on success. This drops six toasts to two: the field-required and duplicate-key toasts are covered inline, leaving one generic toast per dialog for unexpected server failures alongside the existing success toast. * fix(Bookmarks): consolidate title validation and show it inline The duplicate-title check ran from three sources against two different strings: an inline validator reading the bookmark context, plus two warning toasts in onSubmit reading the tags prop and the conversationTags cache. All three now feed one helper behind the single inline validator, so both toasts are gone and the message is always com_ui_bookmarks_tag_exists. The title error was rendered conditionally, so it pushed the description field down as it appeared and disappeared; it now uses FieldMessage. The description registered a maxLength rule but rendered its error nowhere, so exceeding 1048 characters silently refused to submit with nothing on screen. It now reports like the title does. Submitting also closed the dialog immediately, throwing away what the user typed if the request failed, even though the mutation's onSuccess already closed it. Dropping that leaves the form with no reason to take setOpen. Renaming is no longer blocked when the title is unchanged: the tags-prop check had no exemption for the bookmark's own title, so editing just the description of a bookmark attached to the current conversation reported a duplicate and refused to save. The two tests that asserted the removed toasts now assert the inline error and that no toast fires. * feat(Skills): label the availability toggle and drop the detail icon The toggle in the skill detail header was a bare switch whose only name was an aria-label reading "Toggle skill active state", so nothing on screen said what it did, and "active" did not say active for what. It now carries a visible "Available to agent" label bound to the switch, plus a tooltip stating the effect: when on, the agent can use this skill in new messages. The label text stays fixed while the switch carries the state, so flipping it cannot resize the action row and nudge the buttons beside it. Also removes the decorative ScrollText circle from the detail header. It conveyed nothing the heading did not already say, and dropping it lets the title block sit at the top level instead of nested inside a flex row that now has a single child. * feat(Settings): move file management into Data Controls and clarify its labels Files were reachable only from the account dropdown, away from the other data-management entries. A Manage files row now sits in Data Controls beside Import conversations and Shared links, opening the same modal, and the account menu item is gone so there is one place to look. Two labels renamed for accuracy and consistency: - "Revoke all user provided credentials" becomes "Revoke all provider API keys". It sits in the API keys section beside Provider API keys and Agent API keys, so it should name what it revokes; "credentials" was vague and "user provided" described the system's perspective rather than the user's. - "Clear all chats" becomes "Delete all chats", matching its own Delete button and the "Delete TTS cache storage" row beside it. The action is irreversible, which delete states more plainly than clear. The TTS cache row gains an InfoHoverCard, the same explanation affordance used by the API keys dialog. Nothing previously said what the cache held or why its button is so often greyed out, which happens whenever the cache is empty, including for anyone who has never used text-to-speech. * feat(Shortcuts): add a switch that disables every keyboard shortcut There was no way to turn shortcuts off short of rebinding each one to nothing, which loses the bindings. A switch at the top of the shortcuts dialog now suppresses all of them at once while keeping every custom binding intact, so turning it back on restores the previous setup. The preference persists per browser in localStorage next to the custom bindings. Enforcement is a single guard in the window keydown handler, which already owns every shortcut, so nothing dispatches while it is on. Nothing is exempt, including the chord that opens this dialog. The dialog is still reachable from the account menu, so the switch cannot lock anyone out, and an exception would contradict what it says. useShortcutDisplay and useShortcutAriaKey return empty while it is on, so tooltips and aria-keyshortcuts across the app stop naming chords that would not fire. The binding rows stay editable, so shortcuts can be configured before turning them back on. * style(Skills,Prompts): align side panel spacing with the other panels Memories and Bookmarks share one spacing contract: 8px above the header, 12px down each side, and 12px under the last row. Skills and Prompts each drifted from it, so switching panels nudged the content. Skills sat at 16px per side and 12px on top, with the list running flush into the bottom edge. Its top padding now comes from the panel root like the other panels, its header and list use the shared 12px sides, and the list gets the same bottom inset. Prompts was applying the top padding twice, once on the panel root from the accordion and again on its own header, for 16px, and its list also ran flush into the bottom. The header no longer adds its own, and the list gets the bottom inset. Its asymmetric pl-3 pr-1 is left alone: the list reserves an 8px scrollbar gutter, so those values already render as an even 12px on both sides. Squaring the padding numbers would have made the panel visibly lopsided. Measured after the change, all four panels report 8px top, 12px bottom, and 12px on each side. * refactor(Shortcuts): invert the switch to an enabled-by-default control The control read "Disable keyboard shortcuts", so it was on when the feature was off. Inverting it makes the switch agree with the thing it names: it now reads "Keyboard Shortcuts", ships on, and turning it off is what stops the shortcuts. The stored value follows, from keyboardShortcutsDisabled to keyboardShortcutsEnabled defaulting to true. Nothing migrates the old key because the previous shape never shipped, and an absent value now means enabled, which is the default anyway. The row loses its filled card and sits as a plain bottom-bordered row under the title, reading as a section header for the list rather than a block competing with it. Every binding row now renders as disabled while the switch is off, dimmed with its edit and reset buttons actually disabled rather than merely looking inert. Any row left mid-edit is closed when the switch goes off, so the recorder cannot keep capturing keys for a shortcut that would not fire. * style(Shortcuts): fit the dialog on desktop without a scrollbar Open panels was a full-width block stacked under the two shortcut columns, so opening the dialog on a desktop viewport always started with a scrollbar, at about 100px of overflow. It becomes the third column instead. That removes the stacked block entirely, the three columns land at comparable heights, and the content now fits with nothing to scroll. The dialog widens on large screens to hold the extra column. Narrower viewports are unchanged in spirit: the panels list spans both columns below the shortcuts at tablet width and everything stacks into one column on a phone, scrolling as it did before. Reflowing the groups with CSS multi-column was the other option and looked worse: the short groups left a tall void beside Chat, and squeezing the panel rows into four columns truncated their labels. * style(Skills): make Edit an icon button and drop the detail text below the actions Edit was the only text button in a row of icon buttons, so it read as a different kind of control than Share and Delete beside it. It becomes a pencil icon at the same 36px size, carrying its label through a tooltip and an aria-label so the accessible name survives. The header row also centred its two halves against each other, which pinned the title level with the action buttons. The actions now pin to the top of the row and the text column starts below them, giving the title, author, date, and description a little room without moving the controls. * test: mock shortcut setting in expanded panel * remove unused com_ui_skill_toggle_active i18n key Superseded by com_ui_skill_available and com_ui_skill_available_hint in SkillToggle.tsx, but the old key was left behind in the locale files. * fix: honor shortcut switch in composer * fix: defer file loading until dialog opens * fix: preserve memory API errors * chore: restore automated locale entries * fix: honor shortcut switch during generation * refactor: share field message primitive * fix: reserve helper height for wrapping field messages * fix: wrap skill detail actions at narrow widths * fix: reset the memory create dialog when it closes |
||
|---|---|---|
| .. | ||
| src | ||
| babel.config.js | ||
| jest.config.js | ||
| jest.resolver.cjs | ||
| jest.setup.ts | ||
| package.json | ||
| tailwind.config.js | ||
| tailwind.preset.cjs | ||
| tsconfig.json | ||
| tsconfig.test.json | ||
| tsdown.config.mjs | ||