mirror of
https://github.com/Mintplex-Labs/anything-llm
synced 2026-04-25 17:15:37 +02:00
fix: scroll active sidebar items into view (#4965)
* Add centering of settings sidebar link when isActive * abstract redundant logic into a reusable hook * add jsdocs | refactor hook to consume behavior and block args * remove unused import * dev --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
This commit is contained in:
2
.github/workflows/dev-build.yaml
vendored
2
.github/workflows/dev-build.yaml
vendored
@@ -6,7 +6,7 @@ concurrency:
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["web-push-notifications-bootstrap"] # put your current branch to create a build. Core team only.
|
||||
branches: ["4963-sidebar-selection-srcoll-into-view"] # put your current branch to create a build. Core team only.
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "cloud-deployments/*"
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
|
||||
import { CaretRight } from "@phosphor-icons/react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { safeJsonParse } from "@/utils/request";
|
||||
import useScrollActiveItemIntoView from "@/hooks/useScrollActiveItemIntoView";
|
||||
|
||||
export default function MenuOption({
|
||||
btnText,
|
||||
@@ -25,6 +26,18 @@ export default function MenuOption({
|
||||
location: location.pathname,
|
||||
});
|
||||
|
||||
const isActive = hasChildren
|
||||
? (!isExpanded &&
|
||||
childOptions.some((child) => child.href === location.pathname)) ||
|
||||
location.pathname === href
|
||||
: location.pathname === href;
|
||||
|
||||
const { ref } = useScrollActiveItemIntoView({
|
||||
isActive,
|
||||
behavior: "instant",
|
||||
block: "center",
|
||||
});
|
||||
|
||||
if (hidden) return null;
|
||||
|
||||
// If this option is a parent level option
|
||||
@@ -43,12 +56,6 @@ export default function MenuOption({
|
||||
if (flex && !!user && !roles.includes(user?.role)) return null;
|
||||
}
|
||||
|
||||
const isActive = hasChildren
|
||||
? (!isExpanded &&
|
||||
childOptions.some((child) => child.href === location.pathname)) ||
|
||||
location.pathname === href
|
||||
: location.pathname === href;
|
||||
|
||||
const handleClick = (e) => {
|
||||
if (hasChildren) {
|
||||
e.preventDefault();
|
||||
@@ -73,6 +80,7 @@ export default function MenuOption({
|
||||
`}
|
||||
>
|
||||
<Link
|
||||
ref={ref}
|
||||
to={href}
|
||||
className={`flex flex-grow items-center px-[12px] h-[32px] font-medium ${
|
||||
isChild ? "hover:text-white" : "text-white light:text-black"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import useScrollActiveItemIntoView from "@/hooks/useScrollActiveItemIntoView";
|
||||
import Workspace from "@/models/workspace";
|
||||
import paths from "@/utils/paths";
|
||||
import showToast from "@/utils/toast";
|
||||
@@ -30,6 +31,11 @@ export default function ThreadItem({
|
||||
? paths.workspace.chat(slug)
|
||||
: paths.workspace.thread(slug, thread.slug);
|
||||
|
||||
const { ref } = useScrollActiveItemIntoView({
|
||||
isActive,
|
||||
behavior: "instant",
|
||||
block: "center",
|
||||
});
|
||||
return (
|
||||
<div
|
||||
className="w-full relative flex h-[38px] items-center border-none rounded-lg"
|
||||
@@ -88,6 +94,7 @@ export default function ThreadItem({
|
||||
</div>
|
||||
) : (
|
||||
<a
|
||||
ref={ref}
|
||||
href={
|
||||
window.location.pathname === linkTo || ctrlPressed ? "#" : linkTo
|
||||
}
|
||||
|
||||
30
frontend/src/hooks/useScrollActiveItemIntoView.js
Normal file
30
frontend/src/hooks/useScrollActiveItemIntoView.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* Hook that scrolls an element into view when it becomes active.
|
||||
* @param {Object} options - The options for the hook.
|
||||
* @param {boolean} options.isActive - Whether the element is currently active.
|
||||
* @param {"smooth" | "instant" | "auto"} options.behavior - The scroll behavior.
|
||||
* @param {"start" | "center" | "end" | "nearest"} options.block - The vertical alignment of the element within the scrollable container.
|
||||
* @returns {{ ref: React.RefObject<HTMLElement> }} An object containing the ref to attach to the target element.
|
||||
*/
|
||||
export default function useScrollActiveItemIntoView({
|
||||
isActive,
|
||||
behavior,
|
||||
block,
|
||||
}) {
|
||||
const ref = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isActive) {
|
||||
ref.current.scrollIntoView({
|
||||
behavior,
|
||||
block,
|
||||
});
|
||||
}
|
||||
}, [isActive]);
|
||||
|
||||
return {
|
||||
ref,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user