mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-03 22:32:42 +00:00
refactor: tokenize Chat menus, popovers, and message surfaces
This commit is contained in:
parent
1d0fcef327
commit
ef3c08872b
13 changed files with 40 additions and 42 deletions
|
|
@ -87,7 +87,7 @@ export default function MCPConfigDialog({
|
|||
render={({ field }) => {
|
||||
const placeholder = localize('com_ui_mcp_enter_var', { 0: details.title });
|
||||
const className =
|
||||
'w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white sm:text-sm';
|
||||
'w-full rounded-md border-border-medium shadow-sm focus:border-border-heavy focus:ring-ring-primary dark:bg-surface-tertiary dark:text-text-primary sm:text-sm';
|
||||
if (details.sensitive === false) {
|
||||
return (
|
||||
<Input
|
||||
|
|
@ -119,21 +119,23 @@ export default function MCPConfigDialog({
|
|||
dangerouslySetInnerHTML={{ __html: sanitize(details.description) }}
|
||||
/>
|
||||
)}
|
||||
{errors[key] && <p className="text-xs text-red-500">{errors[key]?.message}</p>}
|
||||
{errors[key] && (
|
||||
<p className="text-xs text-text-destructive">{errors[key]?.message}</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</form>
|
||||
}
|
||||
selection={{
|
||||
selectHandler: handleSubmit(onFormSubmit),
|
||||
selectClasses: 'bg-green-500 hover:bg-green-600 text-white',
|
||||
selectClasses: 'bg-surface-submit text-white hover:bg-surface-submit-hover',
|
||||
selectText: isSubmitting ? localize('com_ui_saving') : localize('com_ui_save'),
|
||||
}}
|
||||
buttons={
|
||||
onRevoke && (
|
||||
<Button
|
||||
onClick={handleRevoke}
|
||||
className="bg-red-600 text-white hover:bg-red-700 dark:hover:bg-red-800"
|
||||
className="bg-surface-destructive text-white hover:bg-surface-destructive-hover"
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{localize('com_ui_revoke')}
|
||||
|
|
|
|||
|
|
@ -181,11 +181,11 @@ function MentionContent({
|
|||
|
||||
return (
|
||||
<div className="absolute bottom-28 z-10 w-full space-y-2">
|
||||
<div className="popover border-token-border-light rounded-2xl border bg-white p-2 shadow-lg dark:bg-gray-700">
|
||||
<div className="popover border-token-border-light rounded-2xl border bg-surface-secondary p-2 shadow-lg">
|
||||
<input
|
||||
ref={initInputRef}
|
||||
placeholder={localize(placeholder)}
|
||||
className="mb-1 w-full border-0 bg-white p-2 text-sm focus:outline-none dark:bg-gray-700 dark:text-gray-200"
|
||||
className="mb-1 w-full border-0 bg-surface-secondary p-2 text-sm text-text-primary focus:outline-none"
|
||||
autoComplete="off"
|
||||
value={searchValue}
|
||||
onKeyDown={(e) => {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default function OptionsPopover({
|
|||
|
||||
const localize = useLocalize();
|
||||
const cardStyle =
|
||||
'shadow-xl rounded-md min-w-[75px] font-normal bg-white border-black/10 border dark:bg-gray-700 text-black dark:text-white';
|
||||
'shadow-xl rounded-md min-w-[75px] font-normal bg-surface-secondary border-border-light border text-text-primary';
|
||||
|
||||
if (!visible) {
|
||||
return null;
|
||||
|
|
@ -57,15 +57,14 @@ export default function OptionsPopover({
|
|||
<div
|
||||
className={cn(
|
||||
cardStyle,
|
||||
'dark:bg-gray-700',
|
||||
'border-d-0 flex w-full flex-col overflow-hidden rounded-none border-s-0 border-t bg-white px-0 pb-[10px] dark:border-white/10 md:rounded-md md:border lg:w-[736px]',
|
||||
'border-d-0 flex w-full flex-col overflow-hidden rounded-none border-s-0 border-t bg-surface-secondary px-0 pb-[10px] md:rounded-md md:border lg:w-[736px]',
|
||||
)}
|
||||
>
|
||||
<div className="flex w-full items-center bg-gray-50 px-2 py-2 dark:bg-gray-700">
|
||||
<div className="flex w-full items-center bg-surface-tertiary px-2 py-2">
|
||||
{presetsDisabled ? null : (
|
||||
<Button
|
||||
type="button"
|
||||
className="h-auto w-[150px] justify-start rounded-md border border-gray-300/50 bg-transparent px-2 py-1 text-xs font-normal text-black hover:bg-gray-100 hover:text-black focus-visible:ring-1 focus-visible:ring-ring-primary dark:border-gray-600 dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:focus-visible:ring-white"
|
||||
className="h-auto w-[150px] justify-start rounded-md border border-border-medium bg-transparent px-2 py-1 text-xs font-normal text-text-primary hover:bg-surface-hover focus-visible:ring-1 focus-visible:ring-ring-primary"
|
||||
onClick={saveAsPreset}
|
||||
>
|
||||
<Save className="mr-1 w-[14px]" />
|
||||
|
|
@ -76,7 +75,7 @@ export default function OptionsPopover({
|
|||
<Button
|
||||
type="button"
|
||||
className={cn(
|
||||
'ml-auto h-auto bg-transparent px-3 py-2 text-xs font-normal text-black hover:bg-gray-100 hover:text-black dark:bg-transparent dark:text-white dark:hover:bg-gray-700 dark:hover:text-white',
|
||||
'ml-auto h-auto bg-transparent px-3 py-2 text-xs font-normal text-text-primary hover:bg-surface-hover',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
onClick={closePopover}
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ export default function PopoverButtons({
|
|||
type="button"
|
||||
className={cn(
|
||||
button.buttonClass,
|
||||
'border border-gray-300/50 focus:ring-1 focus:ring-green-500/90 dark:border-gray-500/50 dark:focus:ring-green-500',
|
||||
'ml-1 h-full bg-transparent px-2 py-1 text-xs font-normal text-black hover:bg-gray-100 hover:text-black dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-white',
|
||||
'border border-border-medium focus:ring-1 focus:ring-ring-primary',
|
||||
'ml-1 h-full bg-transparent px-2 py-1 text-xs font-normal text-text-primary hover:bg-surface-hover',
|
||||
buttonClass ?? '',
|
||||
)}
|
||||
onClick={button.handler}
|
||||
|
|
@ -121,8 +121,8 @@ export default function PopoverButtons({
|
|||
type="button"
|
||||
className={cn(
|
||||
button.buttonClass,
|
||||
'flex justify-center border border-gray-300/50 focus:ring-1 focus:ring-green-500/90 dark:border-gray-500/50 dark:focus:ring-green-500',
|
||||
'h-full w-full bg-transparent px-2 py-1 text-xs font-normal text-black hover:bg-gray-100 hover:text-black dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-white',
|
||||
'flex justify-center border border-border-medium focus:ring-1 focus:ring-ring-primary',
|
||||
'h-full w-full bg-transparent px-2 py-1 text-xs font-normal text-text-primary hover:bg-surface-hover',
|
||||
buttonClass ?? '',
|
||||
)}
|
||||
onClick={button.handler}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import ConvoIcon from '~/components/Endpoints/ConvoIcon';
|
|||
import { useLocalize, useAuthContext } from '~/hooks';
|
||||
|
||||
const containerClassName =
|
||||
'shadow-stroke relative flex h-full items-center justify-center rounded-full bg-white dark:bg-presentation dark:text-white text-black dark:after:shadow-none ';
|
||||
'shadow-stroke relative flex h-full items-center justify-center rounded-full bg-surface-primary dark:bg-presentation text-text-primary dark:after:shadow-none ';
|
||||
|
||||
function getTextSizeClass(text: string | undefined | null) {
|
||||
if (!text) {
|
||||
|
|
@ -178,7 +178,7 @@ export default function Landing({ centerFormOnLanding }: { centerFormOnLanding:
|
|||
endpointsConfig={endpointsConfig}
|
||||
containerClassName={containerClassName}
|
||||
context="landing"
|
||||
className="h-2/3 w-2/3 text-black dark:text-white"
|
||||
className="h-2/3 w-2/3 text-text-primary"
|
||||
size={41}
|
||||
/>
|
||||
{startupConfig?.showBirthdayIcon && (
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export const CustomMenuSeparator = React.forwardRef<HTMLHRElement, Ariakit.MenuS
|
|||
ref={ref}
|
||||
{...props}
|
||||
className={cn(
|
||||
'my-0.5 h-0 w-full border-t border-slate-200 dark:border-slate-700',
|
||||
'my-0.5 h-0 w-full border-t border-border-light',
|
||||
props.className,
|
||||
)}
|
||||
/>
|
||||
|
|
@ -170,7 +170,7 @@ export const CustomMenuItem = React.forwardRef<HTMLDivElement, CustomMenuItemPro
|
|||
blurOnHoverEnd: false,
|
||||
...props,
|
||||
className: cn(
|
||||
'relative flex cursor-default items-center gap-2 rounded-lg px-2 py-1 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: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',
|
||||
'relative flex cursor-default items-center gap-2 rounded-lg px-2 py-1 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-text-primary dark:data-[active-item]:bg-white/10 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-text-primary',
|
||||
props.className,
|
||||
),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ export function SearchResults({ results, localize, searchValue }: SearchResultsP
|
|||
<div className="flex items-center gap-2">
|
||||
{endpoint.icon && (
|
||||
<div
|
||||
className="flex items-center justify-center overflow-hidden rounded-full border border-gray-200 p-1 dark:border-gray-700"
|
||||
className="flex items-center justify-center overflow-hidden rounded-full border border-border-light p-1"
|
||||
style={{ borderRadius: '50%' }}
|
||||
>
|
||||
{endpoint.icon}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ const EditPresetDialog = ({
|
|||
|
||||
return (
|
||||
<OGDialog open={presetModalVisible} onOpenChange={handleOpenChange} triggerRef={triggerRef}>
|
||||
<OGDialogContent className="h-[100dvh] max-h-[100dvh] w-full max-w-full overflow-y-auto bg-white dark:border-gray-700 dark:bg-gray-850 dark:text-gray-300 md:h-auto md:max-h-[90vh] md:max-w-[75vw] md:rounded-lg lg:max-w-[950px]">
|
||||
<OGDialogContent className="h-[100dvh] max-h-[100dvh] w-full max-w-full overflow-y-auto bg-surface-dialog dark:border-border-light dark:text-text-secondary md:h-auto md:max-h-[90vh] md:max-w-[75vw] md:rounded-lg lg:max-w-[950px]">
|
||||
<OGDialogTitle>
|
||||
{localize('com_ui_edit_preset_title', { title: preset?.title })}
|
||||
</OGDialogTitle>
|
||||
|
|
@ -199,13 +199,13 @@ const EditPresetDialog = ({
|
|||
<div className="flex justify-end gap-2 border-t border-border-medium pt-2 md:pt-4">
|
||||
<button
|
||||
onClick={exportPreset}
|
||||
className="rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700 md:px-4"
|
||||
className="rounded-md border border-border-medium bg-surface-secondary px-3 py-2 text-sm font-medium text-text-primary hover:bg-surface-hover focus:outline-none focus:ring-2 focus:ring-ring-primary focus:ring-offset-2 md:px-4"
|
||||
>
|
||||
{localize('com_endpoint_export')}
|
||||
</button>
|
||||
<button
|
||||
onClick={submitPreset}
|
||||
className="rounded-md bg-green-500 px-3 py-2 text-sm font-medium text-white hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 md:px-4"
|
||||
className="rounded-md bg-surface-submit px-3 py-2 text-sm font-medium text-white hover:bg-surface-submit-hover focus:outline-none focus:ring-2 focus:ring-ring-primary focus:ring-offset-2 md:px-4"
|
||||
>
|
||||
{localize('com_ui_save')}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const PresetItems: FC<{
|
|||
<div className="flex h-full grow items-center justify-end gap-2">
|
||||
<label
|
||||
htmlFor="default-preset"
|
||||
className="w-40 truncate rounded bg-transparent py-1 text-xs font-medium text-gray-600 transition-colors dark:bg-transparent dark:text-gray-300 sm:w-72"
|
||||
className="w-40 truncate rounded bg-transparent py-1 text-xs font-medium text-text-secondary transition-colors sm:w-72"
|
||||
>
|
||||
{defaultPreset
|
||||
? `${localize('com_endpoint_preset_default_item')} ${defaultPreset.title}`
|
||||
|
|
@ -63,7 +63,7 @@ const PresetItems: FC<{
|
|||
<DialogTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="mr-1 flex h-[32px] cursor-pointer items-center rounded bg-transparent px-2 py-1 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-red-700 focus:ring-ring dark:bg-transparent dark:text-gray-300 dark:hover:bg-gray-700 dark:hover:text-red-700"
|
||||
className="mr-1 flex h-[32px] cursor-pointer items-center rounded bg-transparent px-2 py-1 text-xs font-medium text-text-secondary transition-colors hover:bg-surface-hover hover:text-text-destructive focus:ring-ring"
|
||||
aria-label={localize('com_ui_clear_all')}
|
||||
>
|
||||
<svg
|
||||
|
|
@ -100,7 +100,8 @@ const PresetItems: FC<{
|
|||
}
|
||||
selection={{
|
||||
selectHandler: clearAllPresets,
|
||||
selectClasses: 'bg-red-600 hover:bg-red-700 dark:hover:bg-red-600 text-white',
|
||||
selectClasses:
|
||||
'bg-surface-destructive text-white hover:bg-surface-destructive-hover',
|
||||
selectText: localize('com_ui_clear'),
|
||||
}}
|
||||
/>
|
||||
|
|
@ -114,7 +115,7 @@ const PresetItems: FC<{
|
|||
className="pointer-none group m-1.5 flex h-8 min-w-[170px] gap-2 rounded px-5 py-2.5 !pr-3 text-sm !opacity-100 focus:ring-0 radix-disabled:pointer-events-none radix-disabled:opacity-50 md:min-w-[240px]"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="flex h-full grow items-center justify-end gap-2 text-gray-600 dark:text-gray-300">
|
||||
<div className="flex h-full grow items-center justify-end gap-2 text-text-secondary">
|
||||
{/* TODO: Create Preset from here */}
|
||||
{localize('com_endpoint_no_presets')}
|
||||
</div>
|
||||
|
|
@ -151,7 +152,7 @@ const PresetItems: FC<{
|
|||
<Icon
|
||||
context="menu-item"
|
||||
iconURL={getEndpointField(endpointsConfig, preset.endpoint, 'iconURL')}
|
||||
className="icon-md mr-1 dark:text-white"
|
||||
className="icon-md mr-1 dark:text-text-primary"
|
||||
endpoint={preset.endpoint}
|
||||
/>
|
||||
)
|
||||
|
|
@ -174,7 +175,7 @@ const PresetItems: FC<{
|
|||
render={
|
||||
<button
|
||||
className={cn(
|
||||
'm-0 h-full rounded-md bg-transparent p-2 text-gray-400 hover:text-gray-700 focus:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 dark:focus:text-gray-200',
|
||||
'm-0 h-full rounded-md bg-transparent p-2 text-text-tertiary hover:text-text-primary focus:text-text-primary',
|
||||
defaultPreset?.presetId === presetId
|
||||
? ''
|
||||
: 'sm:invisible sm:group-focus-within:visible sm:group-hover:visible',
|
||||
|
|
@ -201,7 +202,7 @@ const PresetItems: FC<{
|
|||
aria-label={localize('com_ui_edit')}
|
||||
render={
|
||||
<button
|
||||
className="m-0 h-full rounded-md p-2 text-gray-400 hover:text-gray-700 focus:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 dark:focus:text-gray-200 sm:invisible sm:group-focus-within:visible sm:group-hover:visible"
|
||||
className="m-0 h-full rounded-md p-2 text-text-tertiary hover:text-text-primary focus:text-text-primary sm:invisible sm:group-focus-within:visible sm:group-hover:visible"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -224,7 +225,7 @@ const PresetItems: FC<{
|
|||
aria-label={localize('com_ui_delete')}
|
||||
render={
|
||||
<button
|
||||
className="m-0 h-full rounded-md p-2 text-gray-400 hover:text-gray-600 focus:text-gray-600 dark:text-gray-400 dark:hover:text-gray-200 dark:focus:text-gray-200 sm:invisible sm:group-focus-within:visible sm:group-hover:visible"
|
||||
className="m-0 h-full rounded-md p-2 text-text-tertiary hover:text-text-primary focus:text-text-primary sm:invisible sm:group-focus-within:visible sm:group-hover:visible"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const MenuItem: FC<MenuItemProps> = ({
|
|||
aria-label={title}
|
||||
data-testid="chat-menu-item"
|
||||
className={cn(
|
||||
'group m-1.5 flex cursor-pointer gap-2 rounded px-5 py-2.5 !pr-3 text-sm !opacity-100 hover:bg-black/5 focus:ring-0 radix-disabled:pointer-events-none radix-disabled:opacity-50 dark:hover:bg-gray-600 md:min-w-[240px]',
|
||||
'group m-1.5 flex cursor-pointer gap-2 rounded px-5 py-2.5 !pr-3 text-sm !opacity-100 hover:bg-surface-hover focus:ring-0 radix-disabled:pointer-events-none radix-disabled:opacity-50 md:min-w-[240px]',
|
||||
className || '',
|
||||
)}
|
||||
tabIndex={0} // Change to 0 to make it focusable
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const MenuSeparator: FC = () => (
|
|||
<div
|
||||
role="separator"
|
||||
aria-orientation="horizontal"
|
||||
className="my-1.5 border-b bg-gray-200 dark:border-gray-700"
|
||||
className="my-1.5 border-b border-border-light"
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,18 +140,14 @@ const MessageIndicator = memo(function MessageIndicator({
|
|||
<span
|
||||
className={cn(
|
||||
'block rounded-full transition-all duration-200',
|
||||
isActive
|
||||
? 'h-1.5 w-1.5 bg-gray-800 dark:bg-gray-100'
|
||||
: 'h-1 w-1 bg-gray-400 dark:bg-gray-500',
|
||||
isActive ? 'h-1.5 w-1.5 bg-text-primary' : 'h-1 w-1 bg-border-heavy',
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<span
|
||||
className={cn(
|
||||
'block w-full rounded-full transition-all duration-200',
|
||||
isActive
|
||||
? 'h-[5px] bg-gray-800 dark:bg-gray-100'
|
||||
: 'h-[3px] bg-gray-400 dark:bg-gray-500',
|
||||
isActive ? 'h-[5px] bg-text-primary' : 'h-[3px] bg-border-heavy',
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ const MinimalMessages = React.forwardRef(
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'relative flex w-full grow overflow-hidden bg-white dark:bg-gray-800',
|
||||
'relative flex w-full grow overflow-hidden bg-surface-secondary',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<div className="transition-width relative h-full w-full flex-1 overflow-auto bg-white dark:bg-gray-800">
|
||||
<div className="transition-width relative h-full w-full flex-1 overflow-auto bg-surface-secondary">
|
||||
<div className="flex h-full flex-col" role="presentation" tabIndex={0}>
|
||||
<div className="flex-1 overflow-hidden overflow-y-auto">
|
||||
<div className="dark:gpt-dark-gray relative h-full">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue