mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-08 22:45:25 +00:00
* style: enhance button layout and input styles across multiple components for improved UI consistency * style: update RequestsNotLoaded component with new warning styles and enhance theme color definitions for status indicators * refactor: update theme usage across components for consistency - Changed color references from theme.brand to theme.primary.text in various StyledWrapper components. - Added hover effects to enhance UI interactivity in CollectionSettings and FolderSettings. - Removed unnecessary margin and padding adjustments in several components for cleaner layout. - Improved accessibility by ensuring aria attributes are correctly set in MenuDropdown. - Standardized styling for method indicators in RequestPane components. These changes aim to create a more cohesive look and feel across the application while adhering to the updated theme guidelines. * refactor: clean up method selector styling in NewRequest component * chore: temp playwright test fixes * refactor: update modal sizes across various components for consistency - Changed modal size from "sm" to "md" in RenameWorkspace, CreateApiSpec, CloneCollection, DeleteCollectionItem, and RenameCollection components. - Improved styling in HttpMethodSelector by adding padding for better layout. - Updated theme color references in multiple theme files to use a new palette structure for consistency and maintainability. * refactor: enhance styling and theme integration in TimelineItem components - Updated HttpMethodSelector to clarify padding calculation in comments. - Integrated theme colors for OAuth2 indicator and timestamp in TimelineItem for better visual consistency. - Adjusted Method component to use uppercase styling for method display. - Modified RelativeTime component to apply muted text color for improved readability. - Updated INFO color in dark and light themes for better contrast and accessibility. * refactor: remove duplicate import statements in theme files - Cleaned up import statements in vscode.js and light-pastel.js by removing redundant lines for improved code clarity and maintainability. * refactor: improve styling and theme integration in various components - Added accent color and cursor style for checkbox inputs in Modal's StyledWrapper. - Updated border-radius values in HttpMethodSelector and NewRequest StyledWrapper components to use theme variables for consistency. - Introduced a new textbox class in NewRequest StyledWrapper for better styling control. - Changed modal size from "sm" to "md" in CreateEnvironment for improved layout. --------- Co-authored-by: Bijin A B <bijin@usebruno.com>
190 lines
5.6 KiB
JavaScript
190 lines
5.6 KiB
JavaScript
import React, { useState, useRef, useMemo, useCallback } from 'react';
|
|
import { IconCaretDown } from '@tabler/icons';
|
|
import MenuDropdown from 'ui/MenuDropdown';
|
|
import StyledWrapper from './StyledWrapper';
|
|
import { useTheme } from 'providers/Theme';
|
|
|
|
const STANDARD_METHODS = Object.freeze(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD', 'TRACE', 'CONNECT']);
|
|
|
|
const KEY = Object.freeze({ ENTER: 'Enter', ESCAPE: 'Escape' });
|
|
|
|
const DEFAULT_METHOD = 'GET';
|
|
|
|
const TriggerButton = ({ method, methodSpanRef, showCaret, ...props }) => {
|
|
return (
|
|
<button
|
|
type="button"
|
|
className="cursor-pointer flex items-center gap-2 text-left w-full select-none px-2"
|
|
{...props}
|
|
>
|
|
<span
|
|
ref={methodSpanRef}
|
|
className="truncate method-span"
|
|
id="create-new-request-method"
|
|
title={method}
|
|
>
|
|
{method}
|
|
</span>
|
|
{showCaret && <IconCaretDown className="caret" size={14} strokeWidth={2} />}
|
|
</button>
|
|
);
|
|
};
|
|
|
|
const HttpMethodSelector = ({ method = DEFAULT_METHOD, onMethodSelect, showCaret = false }) => {
|
|
const [isCustomMode, setIsCustomMode] = useState(false);
|
|
const inputRef = useRef();
|
|
const selectedMethodRef = useRef(method);
|
|
const methodSpanRef = useRef();
|
|
const [previousMethodWidth, setPreviousMethodWidth] = useState(null);
|
|
|
|
const { theme } = useTheme();
|
|
const methodColor = useMemo(() => {
|
|
const colorMap = {
|
|
...theme.request.methods,
|
|
...theme.request
|
|
};
|
|
return colorMap[method.toLocaleLowerCase()];
|
|
}, [method, theme]);
|
|
|
|
const blurInput = () => inputRef.current?.blur();
|
|
|
|
const handleInputChange = (e) => {
|
|
const val = e.target.value.toUpperCase();
|
|
onMethodSelect(val);
|
|
};
|
|
|
|
const handleMethodSelect = useCallback((verb) => {
|
|
onMethodSelect(verb);
|
|
selectedMethodRef.current = verb;
|
|
setIsCustomMode(false);
|
|
blurInput();
|
|
}, [onMethodSelect]);
|
|
|
|
const handleBlur = (e) => {
|
|
// Keep the current value when blurring
|
|
let currentValue = '';
|
|
if (e.target.value && e.target.value.length > 0) {
|
|
currentValue = e.target.value.toUpperCase();
|
|
selectedMethodRef.current = currentValue;
|
|
} else {
|
|
currentValue = selectedMethodRef.current;
|
|
}
|
|
onMethodSelect(currentValue);
|
|
setIsCustomMode(false);
|
|
};
|
|
|
|
const handleAddCustomMethod = useCallback(() => {
|
|
// Capture the width of the current method span before switching to custom mode
|
|
if (methodSpanRef.current) {
|
|
setPreviousMethodWidth(methodSpanRef.current.offsetWidth);
|
|
}
|
|
setIsCustomMode(true);
|
|
onMethodSelect('');
|
|
|
|
setTimeout(() => {
|
|
inputRef.current?.focus();
|
|
inputRef.current?.select();
|
|
}, 0);
|
|
}, [onMethodSelect]);
|
|
|
|
const handleKeyDown = (e) => {
|
|
switch (e.key) {
|
|
case KEY.ESCAPE: {
|
|
setIsCustomMode(false);
|
|
blurInput();
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
return;
|
|
}
|
|
case KEY.ENTER: {
|
|
onMethodSelect(e.target.value ? e.target.value.toUpperCase() : DEFAULT_METHOD);
|
|
setIsCustomMode(false);
|
|
blurInput();
|
|
return;
|
|
}
|
|
default: {
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Convert STANDARD_METHODS to MenuDropdown items format
|
|
const menuItems = useMemo(() => {
|
|
const items = STANDARD_METHODS.map((verb) => ({
|
|
id: verb.toLowerCase(),
|
|
label: verb,
|
|
onClick: () => handleMethodSelect(verb)
|
|
}));
|
|
|
|
// Add "Add Custom" item
|
|
items.push({
|
|
id: 'add-custom',
|
|
label: '+ Add Custom',
|
|
onClick: handleAddCustomMethod,
|
|
className: 'font-normal mt-1 text-link'
|
|
});
|
|
|
|
return items;
|
|
}, [handleMethodSelect, handleAddCustomMethod]);
|
|
|
|
// Determine selected item ID (only if method is a standard method)
|
|
const selectedItemId = useMemo(() => {
|
|
if (isCustomMode || !STANDARD_METHODS.includes(method)) {
|
|
return null;
|
|
}
|
|
return method.toLowerCase();
|
|
}, [method, isCustomMode]);
|
|
|
|
// If in custom mode, render input field instead of dropdown
|
|
if (isCustomMode) {
|
|
// Calculate width based on content length (in ch units), clamped to max 16ch
|
|
// Add 1ch for cursor space
|
|
const contentWidth = Math.min(method.length + 1, 16);
|
|
// Use previous method width as minimum, content-based width as current
|
|
const minWidthPx = previousMethodWidth ? `${previousMethodWidth}px` : '5ch';
|
|
// Use calc to add padding space (px-2 = 0.5rem per side = 1rem total) to the ch width
|
|
const currentWidth = `calc(${Math.max(contentWidth, 1)}ch + 1rem)`;
|
|
|
|
return (
|
|
<StyledWrapper>
|
|
<div className="flex method-selector custom-input-mode" style={{ color: methodColor }}>
|
|
<div className="flex flex-col w-full">
|
|
<input
|
|
ref={inputRef}
|
|
type="text"
|
|
className="px-2 focus:bg-transparent"
|
|
style={{
|
|
minWidth: minWidthPx,
|
|
width: currentWidth,
|
|
maxWidth: 'calc(16ch + 1rem)',
|
|
fontSize: '12px'
|
|
}}
|
|
value={method}
|
|
onChange={handleInputChange}
|
|
onBlur={handleBlur}
|
|
onKeyDown={handleKeyDown}
|
|
title={method}
|
|
autoFocus
|
|
/>
|
|
</div>
|
|
</div>
|
|
</StyledWrapper>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<StyledWrapper>
|
|
<div className="flex method-selector" style={{ color: methodColor }}>
|
|
<MenuDropdown
|
|
items={menuItems}
|
|
placement="bottom-start"
|
|
selectedItemId={selectedItemId}
|
|
>
|
|
<TriggerButton method={method} showCaret={showCaret} methodSpanRef={methodSpanRef} />
|
|
</MenuDropdown>
|
|
</div>
|
|
</StyledWrapper>
|
|
);
|
|
};
|
|
export default HttpMethodSelector;
|