fix: collection settings access, UI overflow fixes, and auto-focus URL bar (#7861)

* fix: collection settings access, UI overflow fixes, and auto-focus URL bar

- Move collection icon outside dropdown; clicking it opens collection
  settings/overview, clicking the name opens the switcher dropdown
- Auto-focus URL bar when creating a transient request (#2919)
- Fix long collection/folder name overflow with ellipsis truncation
- Reduce dropdown width and truncate large collection names
- Simplify breadcrumb collapse: show collection name and last folder,
  collapse middle items into a dropdown
- Fix modal width to prevent shrinking with short collection names
- Show "Create Collection" option when saving a draft with zero collections
- Use IconBox consistently for collection icons

* Replace Chevron component with IconChevronRight

---------

Co-authored-by: Chirag Chandrashekhar <cchirag85@gmail.com>
Co-authored-by: Sid <siddharth@usebruno.com>
This commit is contained in:
Chirag Chandrashekhar
2026-04-30 17:05:40 +05:30
committed by GitHub
parent 8269d51df4
commit 118ba801aa
10 changed files with 222 additions and 75 deletions

View File

@@ -1,6 +1,6 @@
import React, { useMemo, useCallback, memo } from 'react';
import { useSelector } from 'react-redux';
import { IconDatabase, IconLoader2 } from '@tabler/icons';
import { IconBox, IconLoader2 } from '@tabler/icons';
import { areItemsLoading } from 'utils/collections';
const CollectionListItem = memo(({ collectionUid, collectionPath, collectionName, isSelected, onSelect }) => {
@@ -26,7 +26,7 @@ const CollectionListItem = memo(({ collectionUid, collectionPath, collectionName
onClick={handleClick}
>
<div className="collection-item-content">
<IconDatabase size={16} strokeWidth={1.5} />
<IconBox size={16} strokeWidth={1.5} />
<span className="collection-item-name">{collectionName}</span>
</div>
{isLoading && (

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { IconChevronRight } from '@tabler/icons';
import { IconChevronRight, IconDots } from '@tabler/icons';
import Dropdown from 'components/Dropdown';
const FolderBreadcrumbs = ({
collectionName,
@@ -8,30 +9,64 @@ const FolderBreadcrumbs = ({
onNavigateToRoot,
onNavigateToBreadcrumb
}) => {
const collapsed = breadcrumbs.length > 1 ? breadcrumbs.slice(0, -1) : [];
const last = breadcrumbs.length > 0 ? breadcrumbs[breadcrumbs.length - 1] : null;
return (
<>
<div className="breadcrumb-container">
<span
className={!isAtRoot ? 'collection-name-breadcrumb' : ''}
className={`breadcrumb-collection-name ${!isAtRoot ? 'collection-name-breadcrumb' : ''}`}
onClick={!isAtRoot ? onNavigateToRoot : undefined}
title={collectionName}
>
{collectionName}
</span>
{breadcrumbs.map((breadcrumb, index) => (
<React.Fragment key={breadcrumb.uid}>
{collapsed.length > 0 && (
<>
<IconChevronRight size={16} strokeWidth={1.5} className="collection-name-chevron" />
<Dropdown
placement="bottom-start"
icon={(
<span className="breadcrumb-ellipsis-btn">
<IconDots size={16} strokeWidth={2} />
</span>
)}
>
<div className="breadcrumb-collapsed-dropdown">
{collapsed.map((breadcrumb, i) => (
<div
key={breadcrumb.uid}
className="dropdown-item breadcrumb-collapsed-item"
onClick={() => onNavigateToBreadcrumb(i)}
title={breadcrumb.name}
>
{breadcrumb.name}
</div>
))}
</div>
</Dropdown>
</>
)}
{last && (
<>
<IconChevronRight size={16} strokeWidth={1.5} className="collection-name-chevron" />
<span
className="collection-name-breadcrumb"
className="collection-name-breadcrumb breadcrumb-last"
onClick={(e) => {
e.stopPropagation();
onNavigateToBreadcrumb(index);
onNavigateToBreadcrumb(breadcrumbs.length - 1);
}}
title={last.name}
>
{breadcrumb.name}
{last.name}
</span>
</React.Fragment>
))}
</>
)}
{isAtRoot && <IconChevronRight size={16} strokeWidth={1.5} className="collection-name-chevron" />}
</>
</div>
);
};

View File

@@ -1,6 +1,10 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
.bruno-modal-card.modal-sm {
width: 500px;
}
.save-request-form {
display: flex;
flex-direction: column;
@@ -54,6 +58,7 @@ const StyledWrapper = styled.div`
font-size: 14px;
margin-bottom: 12px;
color: ${(props) => props.theme.colors.text.muted};
min-width: 0;
}
.collection-name-clickable {
@@ -66,6 +71,49 @@ const StyledWrapper = styled.div`
.collection-name-chevron {
margin: 0 4px;
flex-shrink: 0;
}
.breadcrumb-container {
display: flex;
align-items: center;
overflow: hidden;
white-space: nowrap;
min-width: 0;
}
.breadcrumb-collection-name,
.breadcrumb-last {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 40px;
flex: 0 1 auto;
}
.breadcrumb-ellipsis-btn {
display: flex;
align-items: center;
cursor: pointer;
padding: 2px 4px;
border-radius: ${(props) => props.theme.border.radius.sm};
flex-shrink: 0;
color: ${(props) => props.theme.colors.text.yellow};
&:hover {
background-color: ${(props) => props.theme.plainGrid.hoverBg};
}
}
.breadcrumb-dropdown {
min-width: 120px;
max-width: 250px;
.dropdown-item {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.search-container {
@@ -114,10 +162,19 @@ const StyledWrapper = styled.div`
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
overflow: hidden;
svg {
flex-shrink: 0;
}
}
.folder-item-name {
color: ${(props) => props.theme.text};
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.folder-empty-state {
@@ -157,6 +214,7 @@ const StyledWrapper = styled.div`
border-radius: ${(props) => props.theme.border.radius.sm};
user-select: none;
border: 1px solid ${(props) => props.theme.border.border1};
overflow: hidden;
&:hover {
background-color: ${(props) => props.theme.plainGrid.hoverBg};
@@ -168,11 +226,20 @@ const StyledWrapper = styled.div`
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
overflow: hidden;
svg {
flex-shrink: 0;
}
}
.collection-item-name {
color: ${(props) => props.theme.text};
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.collection-empty-state {

View File

@@ -361,7 +361,7 @@ const SaveTransientRequest = ({ item: itemProp, collection: collectionProp, isOp
return (
<StyledWrapper>
<Modal
size="md"
size="sm"
title={isSelectingCollection ? 'Select Collection' : 'Save Request'}
handleCancel={handleCancel}
handleConfirm={handleConfirm}