mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-08 22:45:25 +00:00
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:
committed by
GitHub
parent
8269d51df4
commit
118ba801aa
@@ -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 && (
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user