feat: scroll into view if needed

This commit is contained in:
Curry Yang
2024-11-27 11:39:09 +08:00
committed by Curry Yang
parent f7fb6e3165
commit 8ff85a9a68
4 changed files with 31 additions and 5 deletions

View File

@@ -1,6 +1,7 @@
import React from 'react';
import React, { useCallback } from 'react';
import { Button, GridListItem } from 'react-aria-components';
import { scrollElementIntoView } from '../../../utils';
import { useInsomniaTabContext } from '../../context/app/insomnia-tab-context';
import { Icon } from '../icon';
import { Tooltip } from '../tooltip';
@@ -73,7 +74,7 @@ const WORKSPACE_TAB_UI_MAP: Record<string, any> = {
export const InsomniaTab = ({ tab }: { tab: BaseTab }) => {
const { closeTabById } = useInsomniaTabContext();
const { closeTabById, currentOrgTabs } = useInsomniaTabContext();
const renderTabIcon = (type: TabEnum) => {
if (WORKSPACE_TAB_UI_MAP[type]) {
@@ -126,11 +127,18 @@ export const InsomniaTab = ({ tab }: { tab: BaseTab }) => {
});
};
const scrollIntoView = useCallback((node: HTMLDivElement) => {
if (node && currentOrgTabs.activeTabId === tab.id) {
scrollElementIntoView(node, { behavior: 'instant' });
}
}, [currentOrgTabs.activeTabId, tab.id]);
return (
<GridListItem
textValue='tab'
id={tab.id}
className="outline-none aria-selected:text-[--color-font] aria-selected:bg-[--hl-sm] hover:bg-[--hl-xs]"
ref={scrollIntoView}
>
{({ isSelected, isHovered }) => (
<Tooltip delay={1000} message={`${tab.projectName} / ${tab.workspaceName}`} className='h-full'>

View File

@@ -1,4 +1,4 @@
import _ from 'lodash';
import _, { set } from 'lodash';
import React, { useCallback, useEffect, useState } from 'react';
import { Button, GridList, Menu, MenuItem, MenuTrigger, Popover, type Selection } from 'react-aria-components';
import { useFetcher, useNavigate } from 'react-router-dom';
@@ -188,14 +188,18 @@ export const OrganizationTabList = ({ showActiveStatus = true, currentPage = ''
if (!tabListWrapperRef.current) {
return;
}
tabListWrapperRef.current.style.scrollBehavior = 'smooth';
tabListWrapperRef.current.scrollLeft -= 150;
tabListWrapperRef.current.style.scrollBehavior = 'auto';
};
const scrollRight = () => {
if (!tabListWrapperRef.current) {
return;
}
tabListWrapperRef.current.style.scrollBehavior = 'smooth';
tabListWrapperRef.current.scrollLeft += 150;
tabListWrapperRef.current.style.scrollBehavior = 'auto';
};
useEffect(() => {
@@ -254,7 +258,7 @@ export const OrganizationTabList = ({ showActiveStatus = true, currentPage = ''
<Button onPress={scrollLeft} isDisabled={leftScrollDisable} className={`${leftScrollDisable && 'cursor-not-allowed'}`}>
<Icon icon="chevron-left" className={`w-[30px] ${isOverFlow ? 'block' : 'hidden'}`} />
</Button>
<div className='max-w-[calc(100%-40px)] overflow-x-scroll hide-scrollbars scroll-smooth' ref={tabListWrapperRef} onScroll={handleScroll}>
<div className='max-w-[calc(100%-40px)] overflow-x-scroll hide-scrollbars' ref={tabListWrapperRef} onScroll={handleScroll}>
<GridList
aria-label="Insomnia Tabs"
onSelectionChange={handleSelectionChange}

View File

@@ -1,7 +1,7 @@
import type { IconName } from '@fortawesome/fontawesome-svg-core';
import type { ServiceError, StatusObject } from '@grpc/grpc-js';
import { useVirtualizer } from '@tanstack/react-virtual';
import React, { type FC, Fragment, useEffect, useLayoutEffect, useRef, useState } from 'react';
import React, { type FC, Fragment, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import {
Breadcrumb,
Breadcrumbs,
@@ -69,6 +69,7 @@ import {
type WebSocketRequest,
} from '../../models/websocket-request';
import { isDesign, isScratchpad } from '../../models/workspace';
import { scrollElementIntoView } from '../../utils';
import { getGrpcConnectionErrorDetails, isGrpcConnectionError } from '../../utils/grpc';
import { invariant } from '../../utils/invariant';
import { DropdownHint } from '../components/base/dropdown/dropdown-hint';
@@ -1271,6 +1272,12 @@ const CollectionGridListItem = ({
const isSelected = item.doc._id === params.requestId || item.doc._id === params.requestGroupId;
const scrollIntoView = useCallback((node: HTMLDivElement) => {
if (isSelected && node) {
scrollElementIntoView(node, { behavior: 'instant' });
}
}, [isSelected]);
return (
<GridListItem
id={item.doc._id}
@@ -1280,6 +1287,7 @@ const CollectionGridListItem = ({
style={style}
>
<div
ref={scrollIntoView}
onContextMenu={e => {
e.preventDefault();
setIsContextMenuOpen(true);

View File

@@ -0,0 +1,6 @@
export const scrollElementIntoView = (element: HTMLElement, options?: ScrollIntoViewOptions) => {
if (element) {
// @ts-expect-error -- scrollIntoViewIfNeeded is not a standard method
element.scrollIntoViewIfNeeded ? element.scrollIntoViewIfNeeded() : element.scrollIntoView(options);
}
};