Redesign dropdowns (#6235)

* redesign dropdowns

* fix: colors

---------

Co-authored-by: Anoop M D <anoop@usebruno.com>
This commit is contained in:
naman-bruno
2025-11-27 22:20:51 +05:30
committed by GitHub
parent 59514127d5
commit 7ee366eb81
5 changed files with 289 additions and 81 deletions

View File

@@ -4,7 +4,22 @@ import range from 'lodash/range';
import filter from 'lodash/filter';
import classnames from 'classnames';
import { useDrag, useDrop } from 'react-dnd';
import { IconChevronRight, IconDots } from '@tabler/icons';
import {
IconChevronRight,
IconDots,
IconFilePlus,
IconFolderPlus,
IconPlayerPlay,
IconEdit,
IconCopy,
IconClipboard,
IconCode,
IconPhoto,
IconFolder,
IconTrash,
IconSettings,
IconInfoCircle
} from '@tabler/icons';
import { useSelector, useDispatch } from 'react-redux';
import { addTab, focusTab, makeTabPermanent } from 'providers/ReduxStore/slices/tabs';
import { handleCollectionItemDrop, sendRequest, showInFolder, pasteItem, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
@@ -489,6 +504,18 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
</div>
<div className="menu-icon pr-2">
<Dropdown onCreate={onDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
<div
className="dropdown-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
setItemInfoModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconInfoCircle size={16} strokeWidth={2} />
</span>
Info
</div>
{isFolder && (
<>
<div
@@ -498,6 +525,9 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
setNewRequestModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconFilePlus size={16} strokeWidth={2} />
</span>
New Request
</div>
<div
@@ -507,6 +537,9 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
setNewFolderModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconFolderPlus size={16} strokeWidth={2} />
</span>
New Folder
</div>
<div
@@ -516,19 +549,13 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
setRunCollectionModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconPlayerPlay size={16} strokeWidth={2} />
</span>
Run
</div>
</>
)}
<div
className="dropdown-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
setRenameItemModalOpen(true);
}}
>
Rename
</div>
<div
className="dropdown-item"
onClick={(e) => {
@@ -536,6 +563,9 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
setCloneItemModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconCopy size={16} strokeWidth={2} />
</span>
Clone
</div>
{!isFolder && (
@@ -543,6 +573,9 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
className="dropdown-item"
onClick={handleCopyRequest}
>
<span className="dropdown-icon">
<IconCopy size={16} strokeWidth={2} />
</span>
Copy
</div>
)}
@@ -551,21 +584,36 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
className="dropdown-item"
onClick={handlePasteRequest}
>
<span className="dropdown-icon">
<IconClipboard size={16} strokeWidth={2} />
</span>
Paste
</div>
)}
{!isFolder && (
<div
className="dropdown-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
handleClick(null);
handleRun();
}}
>
Run
</div>
)}
<div
className="dropdown-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
setRenameItemModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconEdit size={16} strokeWidth={2} />
</span>
Rename
</div>
<div
className="dropdown-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
handleShowInFolder();
}}
>
<span className="dropdown-icon">
<IconFolder size={16} strokeWidth={2} />
</span>
Show in Folder
</div>
{!isFolder && (item.type === 'http-request' || item.type === 'graphql-request') && (
<div
className="dropdown-item"
@@ -573,6 +621,9 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
handleGenerateCode(e);
}}
>
<span className="dropdown-icon">
<IconCode size={16} strokeWidth={2} />
</span>
Generate Code
</div>
)}
@@ -584,27 +635,13 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
setCreateExampleModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconPhoto size={16} strokeWidth={2} />
</span>
Create Example
</div>
)}
<div
className="dropdown-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
handleShowInFolder();
}}
>
Show in Folder
</div>
<div
className="dropdown-item delete-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
setDeleteItemModalOpen(true);
}}
>
Delete
</div>
<div className="dropdown-separator"></div>
{isFolder && (
<div
className="dropdown-item"
@@ -613,17 +650,23 @@ const CollectionItem = ({ item, collectionUid, collectionPathname, searchText })
viewFolderSettings();
}}
>
<span className="dropdown-icon">
<IconSettings size={16} strokeWidth={2} />
</span>
Settings
</div>
)}
<div
className="dropdown-item item-info"
className="dropdown-item delete-item"
onClick={(e) => {
dropdownTippyRef.current.hide();
setItemInfoModalOpen(true);
setDeleteItemModalOpen(true);
}}
>
Info
<span className="dropdown-icon">
<IconTrash size={16} strokeWidth={2} />
</span>
Delete
</div>
</Dropdown>
</div>

View File

@@ -4,7 +4,21 @@ import classnames from 'classnames';
import { uuid } from 'utils/common';
import filter from 'lodash/filter';
import { useDrop, useDrag } from 'react-dnd';
import { IconChevronRight, IconDots, IconLoader2 } from '@tabler/icons';
import {
IconChevronRight,
IconDots,
IconLoader2,
IconFilePlus,
IconFolderPlus,
IconCopy,
IconClipboard,
IconPlayerPlay,
IconEdit,
IconShare,
IconFoldDown,
IconX,
IconSettings
} from '@tabler/icons';
import Dropdown from 'components/Dropdown';
import { toggleCollection, collapseFullCollection } from 'providers/ReduxStore/slices/collections';
import { mountCollection, moveCollectionAndPersist, handleCollectionItemDrop, pasteItem } from 'providers/ReduxStore/slices/collections/actions';
@@ -277,6 +291,9 @@ const Collection = ({ collection, searchText }) => {
setShowNewRequestModal(true);
}}
>
<span className="dropdown-icon">
<IconFilePlus size={16} strokeWidth={2} />
</span>
New Request
</div>
<div
@@ -286,8 +303,24 @@ const Collection = ({ collection, searchText }) => {
setShowNewFolderModal(true);
}}
>
<span className="dropdown-icon">
<IconFolderPlus size={16} strokeWidth={2} />
</span>
New Folder
</div>
<div
className="dropdown-item"
onClick={(_e) => {
menuDropdownTippyRef.current.hide();
ensureCollectionIsMounted();
handleRun();
}}
>
<span className="dropdown-icon">
<IconPlayerPlay size={16} strokeWidth={2} />
</span>
Run
</div>
<div
className="dropdown-item"
data-testid="clone-collection"
@@ -296,6 +329,9 @@ const Collection = ({ collection, searchText }) => {
setShowCloneCollectionModalOpen(true);
}}
>
<span className="dropdown-icon">
<IconCopy size={16} strokeWidth={2} />
</span>
Clone
</div>
{hasCopiedItems && (
@@ -303,19 +339,12 @@ const Collection = ({ collection, searchText }) => {
className="dropdown-item"
onClick={handlePasteRequest}
>
<span className="dropdown-icon">
<IconClipboard size={16} strokeWidth={2} />
</span>
Paste
</div>
)}
<div
className="dropdown-item"
onClick={(_e) => {
menuDropdownTippyRef.current.hide();
ensureCollectionIsMounted();
handleRun();
}}
>
Run
</div>
<div
className="dropdown-item"
onClick={(_e) => {
@@ -323,6 +352,9 @@ const Collection = ({ collection, searchText }) => {
setShowRenameCollectionModal(true);
}}
>
<span className="dropdown-icon">
<IconEdit size={16} strokeWidth={2} />
</span>
Rename
</div>
<div
@@ -333,6 +365,9 @@ const Collection = ({ collection, searchText }) => {
setShowShareCollectionModal(true);
}}
>
<span className="dropdown-icon">
<IconShare size={16} strokeWidth={2} />
</span>
Share
</div>
<div
@@ -342,8 +377,24 @@ const Collection = ({ collection, searchText }) => {
handleCollapseFullCollection();
}}
>
<span className="dropdown-icon">
<IconFoldDown size={16} strokeWidth={2} />
</span>
Collapse
</div>
<div className="dropdown-separator"></div>
<div
className="dropdown-item"
onClick={(_e) => {
menuDropdownTippyRef.current.hide();
viewCollectionSettings();
}}
>
<span className="dropdown-icon">
<IconSettings size={16} strokeWidth={2} />
</span>
Settings
</div>
<div
className="dropdown-item"
onClick={(_e) => {
@@ -351,17 +402,11 @@ const Collection = ({ collection, searchText }) => {
setShowRemoveCollectionModal(true);
}}
>
<span className="dropdown-icon">
<IconX size={16} strokeWidth={2} />
</span>
Close
</div>
<div
className="dropdown-item"
onClick={(_e) => {
menuDropdownTippyRef.current.hide();
viewCollectionSettings();
}}
>
Settings
</div>
</Dropdown>
</div>
</div>

View File

@@ -5,7 +5,7 @@ import CreateCollection from '../CreateCollection';
import ImportCollection from 'components/Sidebar/ImportCollection';
import ImportCollectionLocation from 'components/Sidebar/ImportCollectionLocation';
import { IconDots } from '@tabler/icons';
import { IconDots, IconPlus, IconFolder, IconDownload, IconDeviceDesktop } from '@tabler/icons';
import { useState, forwardRef, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { showHomePage } from 'providers/ReduxStore/slices/app';
@@ -90,6 +90,7 @@ const TitleBar = () => {
</button>
<div className="collection-dropdown flex flex-grow items-center justify-end">
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
<div className="label-item">Collections</div>
<div
className="dropdown-item"
onClick={(e) => {
@@ -97,6 +98,9 @@ const TitleBar = () => {
menuDropdownTippyRef.current.hide();
}}
>
<span className="dropdown-icon">
<IconPlus size={16} strokeWidth={2} />
</span>
Create Collection
</div>
<div
@@ -106,7 +110,10 @@ const TitleBar = () => {
menuDropdownTippyRef.current.hide();
}}
>
Open Collection
<span className="dropdown-icon">
<IconFolder size={16} strokeWidth={2} />
</span>
Open
</div>
<div
className="dropdown-item"
@@ -115,8 +122,37 @@ const TitleBar = () => {
setImportCollectionModalOpen(true);
}}
>
Import Collection
<span className="dropdown-icon">
<IconDownload size={16} strokeWidth={2} />
</span>
Import
</div>
<div className="label-item">API Specs</div>
<div
className="dropdown-item"
onClick={(e) => {
setCreateCollectionModalOpen(true);
menuDropdownTippyRef.current.hide();
}}
>
<span className="dropdown-icon">
<IconPlus size={16} strokeWidth={2} />
</span>
Create Collection
</div>
<div
className="dropdown-item"
onClick={(e) => {
handleOpenCollection();
menuDropdownTippyRef.current.hide();
}}
>
<span className="dropdown-icon">
<IconFolder size={16} strokeWidth={2} />
</span>
Open
</div>
<div className="dropdown-separator"></div>
<div
className="dropdown-item"
onClick={(e) => {
@@ -124,6 +160,9 @@ const TitleBar = () => {
openDevTools();
}}
>
<span className="dropdown-icon">
<IconDeviceDesktop size={16} strokeWidth={2} />
</span>
Devtools
</div>
</Dropdown>