feat(#304) Environments color 🎨 (#1053)#6970
Conversation
WalkthroughThis PR introduces environment color functionality to Bruno. It adds new UI components for color selection, updates Redux state management for environment colors (both collection and global), extends environment file parsing/serialization to support color metadata, adds IPC handlers for color persistence, and includes comprehensive tests validating the color picker feature. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as Environment UI
participant Redux as Redux Store
participant IPC as IPC Channel
participant FS as File System
User->>UI: Select/change environment color
UI->>Redux: Dispatch updateEnvironmentColor(uid, color, collectionUid)
Redux->>Redux: Clone collection, update color in state
Redux->>IPC: renderer:update-environment-color(pathname, name, color)
IPC->>FS: Read environment file
FS-->>IPC: Current environment data
IPC->>IPC: Parse, update color, stringify
IPC->>FS: Write updated environment file
FS-->>IPC: Write complete
IPC-->>Redux: Success
Redux->>UI: State updated, ColorBadge reflects new color
UI-->>User: Color change visible in list
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ast-grep (0.40.5)packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js[] Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Extends environment support by adding an optional color attribute, persisting it to env files, and surfacing it in the UI for faster environment recognition.
Changes:
- Add
colorto the environment schema and env file (de)serialization (env.bru). - Introduce Redux plumbing + UI components/styles to view and update an environment’s color.
- Add
@uiw/react-colordependency to power the color picker.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/bruno-schema/src/collections/index.js | Extends environment schema to allow an optional color field. |
| packages/bruno-lang/v2/src/jsonToEnv.js | Writes color: to env file output when present. |
| packages/bruno-lang/v2/src/envToJson.js | Parses color: from env files into JSON representation. |
| packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js | Adds reducer to store environment color in Redux state. |
| packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js | Adds thunk to persist environment color changes to disk and update store. |
| packages/bruno-app/src/components/RequestTabs/index.js | Attempts to apply active environment color to request tabs container. |
| packages/bruno-app/src/components/RequestTabs/StyledWrapper.js | Applies environment color as a visual indicator on request tabs. |
| packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js | Refactors environment list selection logic (currently introduces syntax issues). |
| packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js | Adds environment color picker to environment details view. |
| packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentColor/index.js | New color picker component that dispatches saveEnvironmentColor. |
| packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js | Adds environment color styling to the selector trigger. |
| packages/bruno-app/src/components/Environments/EnvironmentSelector/StyledWrapper.js | Styles selector + dropdown items based on environment color. |
| packages/bruno-app/src/components/Environments/EnvironmentSelector/EnvironmentListContent/index.js | Shows a colored icon next to each environment in the dropdown. |
| packages/bruno-app/package.json | Adds @uiw/react-color dependency. |
| package-lock.json | Locks new transitive dependencies for @uiw/react-color. |
Comments suppressed due to low confidence (3)
packages/bruno-app/src/components/RequestTabs/index.js:47
- Assignment to variable activeTab, which is declared constant.
const activeTab = find(tabs, (t) => t.uid === activeTabUid);
packages/bruno-app/src/components/RequestTabs/index.js:48
- Assignment to variable activeCollection, which is declared constant.
const activeCollection = find(collections, (c) => c?.uid === activeTab?.collectionUid);
packages/bruno-app/src/components/RequestTabs/index.js:49
- Assignment to variable collectionRequestTabs, which is declared constant.
const collectionRequestTabs = filter(tabs, (t) => t.collectionUid === activeTab?.collectionUid);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
Outdated
Show resolved
Hide resolved
packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js
Outdated
Show resolved
Hide resolved
packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js
Outdated
Show resolved
Hide resolved
.../src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js
Outdated
Show resolved
Hide resolved
packages/bruno-app/src/components/Environments/EnvironmentSelector/StyledWrapper.js
Outdated
Show resolved
Hide resolved
.../src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
packages/bruno-lang/v2/src/envToJson.js (1)
15-47: Fix thecolorrule to prevent consuming subsequent blocks.The
color = "color:" any*rule will greedily match across newlines, consuming any followingvarsorsecretvarsblocks. Restrict it to the current line using the negative lookahead pattern.Suggested fix
- color = "color:" any* + color = "color:" (~nl any)*packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js (1)
250-262: Critical:coloris undefined insaveEnvironmentreducer.Line 259 assigns
environment.color = color, butcoloris not destructured fromaction.payloadat line 251. This references an undefined variable, which will setenvironment.colortoundefinedon every environment save, effectively clearing any previously set color.Either add
colorto the destructured payload, or remove this line if color should be handled separately viasaveEnvironmentColor.🐛 Proposed fix - Option A: Add color to destructuring
saveEnvironment: (state, action) => { - const { variables, environmentUid, collectionUid } = action.payload; + const { variables, environmentUid, collectionUid, color } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); if (collection) { const environment = findEnvironmentInCollection(collection, environmentUid); if (environment) { environment.variables = variables; - environment.color = color; + if (color !== undefined) { + environment.color = color; + } } } },🐛 Proposed fix - Option B: Remove color assignment
if (environment) { environment.variables = variables; - environment.color = color; }packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js (2)
16-32: Remove the duplicateEnvironmentListdeclaration at lines 16–26.The first declaration with the old prop-based signature is incomplete and conflicts with the second declaration starting at line 29. Keep only the new declaration with the updated signature.
Suggested fix
-const EnvironmentList = ({ - environments, - activeEnvironmentUid, - selectedEnvironment, - setSelectedEnvironment, - isModified, - setIsModified, - collection, - setShowExportModal -}) => { - const dispatch = useDispatch(); - - const EnvironmentList = ({ collection, isModified, setIsModified, onClose, setShowExportModal }) => { const { environments, activeEnvironmentUid } = collection; const [selectedEnvironment, setSelectedEnvironment] = useState(null);
67-72: Avoid reselecting by stale UID.
Line 72 callssetSelectedEnvironment()a second time withfindItem(environments, selectedEnvironment.uid), which overrides the correct environment set in line 69. IfselectedEnvironment.uidwas deleted or renamed,findItem()returns undefined, causing the selection to briefly null out. Additionally, line 71 uses staleselectedEnvironment?.variablesinstead of the resolved environment's variables.Use the resolved environment consistently throughout:
🛠️ Suggested fix
- const hasSelectedEnvironmentChanged = !isEqual(selectedEnvironment, _selectedEnvironment); - if (hasSelectedEnvironmentChanged || selectedEnvironment.uid !== _selectedEnvironment?.uid) { - setSelectedEnvironment(_selectedEnvironment); - } - setOriginalEnvironmentVariables(selectedEnvironment?.variables||[]); - setSelectedEnvironment(findItem(environments, selectedEnvironment.uid)); + const resolvedEnvironment = findItem(environments, _selectedEnvironment?.uid) || _selectedEnvironment; + const hasSelectedEnvironmentChanged = !isEqual(selectedEnvironment, resolvedEnvironment); + if (hasSelectedEnvironmentChanged || selectedEnvironment.uid !== resolvedEnvironment?.uid) { + setSelectedEnvironment(resolvedEnvironment); + } + setOriginalEnvironmentVariables(resolvedEnvironment?.variables || []);
🤖 Fix all issues with AI agents
In
`@packages/bruno-app/src/components/Environments/EnvironmentSelector/StyledWrapper.js`:
- Around line 8-9: The background-color ternary is inverted and emits
"undefined" when props.color is present; update the background rule in
StyledWrapper.js to use the color when provided and fall back to transparent
(e.g., background-color: ${(props) => props.color ?? 'transparent'}), or
conditionally omit/unset the property if that's preferred, and keep the border
line using props.color ?? props.theme.dropdown.selectedColor as-is.
In
`@packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js`:
- Line 14: EnvironmentDetails currently destructures only { environment,
setIsModified, collection } but passes onClose down to <EnvironmentVariables>
which is undefined; fix by adding onClose to the component props (update the
destructuring in EnvironmentDetails to include onClose) and forward that prop to
EnvironmentVariables (or if the prop is unused, remove the onClose={onClose}
from the EnvironmentVariables invocation); refer to the EnvironmentDetails
component and the EnvironmentVariables usage to locate the change.
In `@packages/bruno-app/src/components/RequestTabs/index.js`:
- Around line 90-99: The code redeclares activeTab, activeCollection, and
collectionRequestTabs which shadows earlier declarations (breaking the useEffect
that depends on the originals); remove these duplicate declarations and reuse
the existing variables instead — either move the early-return check (the
"Something went wrong!" return) to run before the initial declarations or delete
the later const declarations and update the logic to reference the original
activeTab, activeCollection and collectionRequestTabs; ensure the lookup calls
(find(...), findEnvironmentInCollection(...), filter(...)) are performed only
once and that useEffect continues to depend on the original variables.
In `@packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js`:
- Around line 38-39: The code uses the pattern "something ?? reject(...)" which
does not stop execution, so add explicit guard clauses that return immediately
after calling reject to prevent using undefined collection/environment; locate
usages in this file (e.g., action creators referencing collection and
environment, including saveEnvironmentColor/_saveEnvironmentColor and
workspaceEnvUpdateEvent) and replace the inline nullish-rejects with checks like
"if (!collection) { return reject(new Error(...)) }" and similarly for
environment so the function exits early instead of continuing to operate on
undefined values.
🧹 Nitpick comments (2)
packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js (1)
10-11: Import path issue and unused import.
- Line 10: The import path
../EnvironmentDetails/EnvironmentColorreferences the parent then re-entersEnvironmentDetails. Since this file is insideEnvironmentDetails/, use./EnvironmentColorinstead.- Line 11:
ToolHintis imported but never used.♻️ Proposed fix
-import EnvironmentColor from '../EnvironmentDetails/EnvironmentColor'; -import ToolHint from 'components/ToolHint/index'; +import EnvironmentColor from './EnvironmentColor';packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentColor/index.js (1)
11-19: Use strict equality for color comparison.Line 13 uses
==instead of===. While unlikely to cause issues with hex strings, strict equality is safer and more explicit.♻️ Proposed fix
const onColorChange = useCallback( (color) => { - if (color == environment.color) return; + if (color === environment.color) return; dispatch(saveEnvironmentColor(color, environment.uid, collectionUid)) .then(() => toast.success('Environment color changed successfully')) .catch(() => toast.error('An error occurred while changing the environment color')); }, [dispatch, environment.uid, environment.color, collectionUid] );
packages/bruno-app/src/components/Environments/EnvironmentSelector/StyledWrapper.js
Outdated
Show resolved
Hide resolved
.../src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js
Show resolved
Hide resolved
packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@packages/bruno-app/src/components/ColorPicker/index.js`:
- Around line 95-149: The slider currently only commits changes on onMouseUp,
which misses keyboard and touch inputs; update the ColorRangePicker usage to
call the existing handleSliderEnd when pointer or keyboard interaction ends by
adding onPointerUp and onKeyUp props (in addition to keeping onMouseUp), so that
handleSliderChange updates state and handleSliderEnd is invoked for mouse,
pointer (touch/pen) and keyboard events; locate the ColorRangePicker element
near sliderPosition/customColor and wire onPointerUp={handleSliderEnd} and
onKeyUp={handleSliderEnd}.
In `@packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js`:
- Around line 27-31: The helper getEnvBackgroundColor currently appends "25" to
hex strings which breaks non-hex colors; import transparentize from 'polished'
and replace the concatenation with a polished call that produces the same visual
alpha for any color format (e.g., use transparentize(0.855, color) when color is
truthy, otherwise 'transparent') so getEnvBackgroundColor reliably returns a
transparentized color for rgb(), named colors, and hex alike.
In `@packages/bruno-electron/src/store/env-secrets.js`:
- Around line 121-135: Remove the unused method updateEnvironmentColor from the
env-secrets store: delete the updateEnvironmentColor(...) implementation in
packages/bruno-electron/src/store/env-secrets.js (the function that finds a
collection/environment and sets env.color then this.store.set('collections',
collections)), and ensure no other code relies on that symbol; if the method is
exported explicitly, remove it from the export list; run lint/tests/build to
confirm there are no remaining references to updateEnvironmentColor.
🧹 Nitpick comments (7)
tests/environments/color-picker/init-user-data/preferences.json (1)
1-6: Confirm the cross-directory collection reference is intentional.This references
global-env-config-selection/collectionwhich is outside thecolor-pickertest directory. Same observation ascollection-security.json- if this is intentional reuse of an existing collection, consider adding a comment in the test spec clarifying this dependency.packages/bruno-electron/src/store/global-environments.js (1)
166-173: Avoid redundant store writes when no change is needed.If the environment isn’t found or the color is already the same, you can early-return to skip an unnecessary re-save.
♻️ Suggested tweak
updateGlobalEnvironmentColor({ environmentUid, color }) { let globalEnvironments = this.getGlobalEnvironments(); const environment = globalEnvironments.find((env) => env?.uid == environmentUid); - if (environment) { - environment.color = color; - } - this.setGlobalEnvironments(globalEnvironments); + if (!environment || environment.color === color) { + return; + } + environment.color = color; + this.setGlobalEnvironments(globalEnvironments); }packages/bruno-app/src/components/ColorPicker/StyledWrapper.js (1)
1-5: Consider documenting why this wrapper exists if it’s intentionally empty.
A brief JSDoc (or inlining the wrapper where it’s used) would clarify intent and avoid a silent extra DOM layer.As per coding guidelines, Add JSDoc comments to abstractions for additional details.
packages/bruno-app/src/components/ColorRange/index.js (1)
12-12: Minor: Guard against undefined className.If
classNameis not provided, the template literal produces"hue-slider undefined". Consider a fallback:- className={`hue-slider ${className}`} + className={`hue-slider ${className || ''}`}tests/environments/color-picker/color-picker.spec.ts (2)
28-58: Consider wrapping logical sections intest.stepfor clearer reports.Per coding guidelines,
test.stepimproves report readability. For example:test('should select a preset color for global environment', async ({ pageWithUserData: page }) => { await test.step('Open global environment configuration', async () => { await page.locator('#sidebar-collection-name').filter({ hasText: 'global-env-config-selection' }).click(); await page.getByTestId('environment-selector-trigger').click(); await page.getByTestId('env-tab-global').click(); await page.getByText('Configure', { exact: true }).click(); }); await test.step('Select preset color', async () => { // ... color picker interactions }); await test.step('Verify color badge', async () => { // ... assertions }); });
42-57: Repeated locators could be extracted to helper variables or a shared utility.
colorPickerTrigger,colorPickerDropdown,envTab, andactiveEnvItemare duplicated across all tests. Extracting them to a helper object or usingtest.beforeEachwould reduce repetition and improve maintainability. As per coding guidelines: "Prefer shared test utilities over copy-pasted setup code."packages/bruno-app/src/components/ColorPicker/index.js (1)
32-162: Add JSDoc for the new helpers and the component.
Several new abstractions (e.g.,rgbToHex,interpolateColor,findClosestPosition,ColorPicker) are undocumented.As per coding guidelines: Add JSDoc comments to abstractions for additional details.
packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js
Show resolved
Hide resolved
* associate environment to a color Signed-off-by: mathieu <mathieu.dreano@gmail.com> use StyledWrapper Signed-off-by: mathieu <mathieu.dreano@gmail.com> don't save anything for color if it is not set Signed-off-by: mathieu <mathieu.dreano@gmail.com> use redux store instead of local state remove logs fix selectedEnvironment cleanup add bottom border on active tab * associate environment to a color Signed-off-by: mathieu <mathieu.dreano@gmail.com> * move dependency to appropriate package.json Signed-off-by: mathieu <mathieu.dreano@gmail.com> * use border instead of background color Signed-off-by: mathieu <mathieu.dreano@gmail.com> * simplify onColorChange Signed-off-by: mathieu <mathieu.dreano@gmail.com> * add black, keep backgound on unselected color Signed-off-by: mathieu <mathieu.dreano@gmail.com> * fix conflicts Signed-off-by: mathieu <mathieu.dreano@gmail.com> * associate environment to a color Signed-off-by: mathieu <mathieu.dreano@gmail.com> use StyledWrapper Signed-off-by: mathieu <mathieu.dreano@gmail.com> don't save anything for color if it is not set Signed-off-by: mathieu <mathieu.dreano@gmail.com> use redux store instead of local state remove logs fix selectedEnvironment cleanup add bottom border on active tab # Conflicts: # packages/bruno-app/src/components/Environments/EnvironmentSelector/StyledWrapper.js # packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js # packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js # packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js # packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js # packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js * Update packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentColor/index.js Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * unused selectedEnvironment prop in EnvironmentList Signed-off-by: Mathieu D <mathieu.dreano@decathlon.com> * RequestTab, avoid unnecessary call if undefined activeCollection Signed-off-by: Mathieu D <mathieu.dreano@decathlon.com> * use @uiw/reac-color instead of react-color Signed-off-by: Mathieu D <mathieu.dreano@decathlon.com> --------- Signed-off-by: mathieu <mathieu.dreano@gmail.com> Signed-off-by: Mathieu D <mathieu.dreano@decathlon.com> Co-authored-by: Mathieu D <mathieu.dreano@decathlon.com> Co-authored-by: Anoop M D <anoop@usebruno.com> Co-authored-by: Mathieu DREANO <122891400+mdreano@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
4f6e571 to
a04ff3e
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@packages/bruno-app/src/components/ColorPicker/index.js`:
- Around line 20-30: Update the JSDoc for the hexToRgb function to indicate
numeric channel values instead of strings: change the `@returns` annotation to
reflect {red:number, green:number, blue:number} so it matches the numeric math
usage and the actual return object (both from parseToRgb and the fallback
{red:0, green:0, blue:0}) in hexToRgb.
- Around line 82-105: The component initializes sliderPosition and customColor
only on mount, so add a useEffect inside ColorPicker that watches the color prop
and syncs state when it changes: if color is provided and not in PRESET_COLORS,
set sliderPosition to findClosestPosition(color), set customColor to color, and
update pendingColorRef.current to color; otherwise set sliderPosition to 0,
customColor to COLOR_RANGE_SEQUENCE[0], and pendingColorRef.current accordingly;
do not call onChange from this effect. This keeps the slider (sliderPosition),
customColor state, and pendingColorRef in sync with external prop updates
without altering existing handlers like handleSliderChange or handleSliderEnd.
In `@tests/environments/color-picker/collection/test-request.bru`:
- Around line 1-17: This collection file (meta name "test-request" containing
the test "should get 200 response") is unused by color-picker.spec.ts; either
delete tests/environments/color-picker/collection/test-request.bru (or the whole
collection folder) or move it under the fixtures/collection convention and/or
update color-picker.spec.ts to import/use the "test-request" collection (or
reference {{host}}/api/echo) so the spec actually exercises this collection;
ensure the chosen fix keeps the collection path consistent with other test
fixtures and that the test name "should get 200 response" remains accurate if
reused.
🧹 Nitpick comments (3)
packages/bruno-electron/src/store/global-environments.js (1)
166-173: Add JSDoc for the new public method.✍️ Suggested JSDoc
+ /** + * Updates the color of a global environment. + * `@param` {{ environmentUid: string, color: string | null }} params + */ updateGlobalEnvironmentColor({ environmentUid, color }) { let globalEnvironments = this.getGlobalEnvironments(); const environment = globalEnvironments.find((env) => env?.uid == environmentUid); if (environment) { environment.color = color; } this.setGlobalEnvironments(globalEnvironments); }As per coding guidelines: “Add JSDoc comments to abstractions for additional details.”
packages/bruno-app/src/components/ColorBadge/index.js (1)
4-22: Add JSDoc for component props/behavior.✍️ Suggested JSDoc
+/** + * Renders a circular color badge. + * `@param` {{ color?: string, size?: number|string, showEmptyBorder?: boolean }} props + */ const ColorBadge = ({ color, size = 10, showEmptyBorder = true }) => { const sizeValue = typeof size === 'string' ? size : `${size}px`; const { theme } = useTheme();As per coding guidelines: “Add JSDoc comments to abstractions for additional details.”
packages/bruno-app/src/components/ColorPicker/index.js (1)
82-83: Add JSDoc for the exported ColorPicker component.This is a public abstraction and would benefit from a brief props doc.
As per coding guidelines: Add JSDoc comments to abstractions for additional details.📚 Example JSDoc
+/** + * Color picker dropdown for preset and custom colors. + * `@param` {Object} props + * `@param` {string | null} props.color + * `@param` {(nextColor: string | null) => void} props.onChange + * `@param` {*} [props.icon] + */ const ColorPicker = ({ color, onChange, icon }) => {
| /** | ||
| * @param {string} hex | ||
| * @returns {red:string,green:string,blue:string} | ||
| */ | ||
| const hexToRgb = (hex) => { | ||
| try { | ||
| return parseToRgb(hex); | ||
| } catch (err) { | ||
| return { red: 0, green: 0, blue: 0 }; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Fix JSDoc return types to match numeric channel usage.
The return object is used in numeric math, so the JSDoc should reflect numbers, not strings.
📝 Suggested JSDoc fix
- * `@returns` {red:string,green:string,blue:string}
+ * `@returns` {red:number,green:number,blue:number}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * @param {string} hex | |
| * @returns {red:string,green:string,blue:string} | |
| */ | |
| const hexToRgb = (hex) => { | |
| try { | |
| return parseToRgb(hex); | |
| } catch (err) { | |
| return { red: 0, green: 0, blue: 0 }; | |
| } | |
| }; | |
| /** | |
| * `@param` {string} hex | |
| * `@returns` {red:number,green:number,blue:number} | |
| */ | |
| const hexToRgb = (hex) => { | |
| try { | |
| return parseToRgb(hex); | |
| } catch (err) { | |
| return { red: 0, green: 0, blue: 0 }; | |
| } | |
| }; |
🤖 Prompt for AI Agents
In `@packages/bruno-app/src/components/ColorPicker/index.js` around lines 20 - 30,
Update the JSDoc for the hexToRgb function to indicate numeric channel values
instead of strings: change the `@returns` annotation to reflect {red:number,
green:number, blue:number} so it matches the numeric math usage and the actual
return object (both from parseToRgb and the fallback {red:0, green:0, blue:0})
in hexToRgb.
| const ColorPicker = ({ color, onChange, icon }) => { | ||
| const [sliderPosition, setSliderPosition] = useState(() => | ||
| color && !PRESET_COLORS.includes(color) ? findClosestPosition(color) : 0 | ||
| ); | ||
| const [customColor, setCustomColor] = useState(() => | ||
| color && !PRESET_COLORS.includes(color) ? color : COLOR_RANGE_SEQUENCE[0] | ||
| ); | ||
| const pendingColorRef = useRef(customColor); | ||
|
|
||
| const handleColorSelect = (selectedColor) => { | ||
| onChange(selectedColor); | ||
| }; | ||
|
|
||
| const handleSliderChange = (e) => { | ||
| const newPosition = parseInt(e.target.value, 10); | ||
| setSliderPosition(newPosition); | ||
| const newColor = interpolateColor(newPosition); | ||
| setCustomColor(newColor); | ||
| pendingColorRef.current = newColor; | ||
| }; | ||
|
|
||
| const handleSliderEnd = () => { | ||
| onChange(pendingColorRef.current); | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n packages/bruno-app/src/components/ColorPicker/index.jsRepository: usebruno/bruno
Length of output: 6256
Add useEffect to sync slider and custom color state when the color prop changes.
The component initializes slider position and custom color only on mount, but doesn't respond to external color prop updates, causing the UI to lag behind parent-driven changes.
🔧 Add useEffect hook
const [customColor, setCustomColor] = useState(() =>
color && !PRESET_COLORS.includes(color) ? color : COLOR_RANGE_SEQUENCE[0]
);
const pendingColorRef = useRef(customColor);
+
+ useEffect(() => {
+ if (!color) {
+ const defaultColor = COLOR_RANGE_SEQUENCE[0];
+ setSliderPosition(0);
+ setCustomColor(defaultColor);
+ pendingColorRef.current = defaultColor;
+ return;
+ }
+
+ const nextPosition = findClosestPosition(color);
+ setSliderPosition(nextPosition);
+ setCustomColor(color);
+ pendingColorRef.current = color;
+ }, [color]);🤖 Prompt for AI Agents
In `@packages/bruno-app/src/components/ColorPicker/index.js` around lines 82 -
105, The component initializes sliderPosition and customColor only on mount, so
add a useEffect inside ColorPicker that watches the color prop and syncs state
when it changes: if color is provided and not in PRESET_COLORS, set
sliderPosition to findClosestPosition(color), set customColor to color, and
update pendingColorRef.current to color; otherwise set sliderPosition to 0,
customColor to COLOR_RANGE_SEQUENCE[0], and pendingColorRef.current accordingly;
do not call onChange from this effect. This keeps the slider (sliderPosition),
customColor state, and pendingColorRef in sync with external prop updates
without altering existing handlers like handleSliderChange or handleSliderEnd.
| meta { | ||
| name: test-request | ||
| type: http | ||
| seq: 1 | ||
| } | ||
|
|
||
| get { | ||
| url: {{host}}/api/echo | ||
| body: none | ||
| auth: none | ||
| } | ||
|
|
||
| tests { | ||
| test("should get 200 response", function() { | ||
| expect(res.getStatus()).to.equal(200); | ||
| }); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find all references to the environments/color-picker/collection path
rg "environments/color-picker/collection" -g "*.{ts,tsx,js,jsx,json}" -B 2 -A 2Repository: usebruno/bruno
Length of output: 40
🏁 Script executed:
# Also check if there's already a fixtures/collection structure in the tests directory
fd -t d "fixtures" tests/ --exec sh -c 'echo "--- Directory: {} ---" && ls -la {} | head -20'Repository: usebruno/bruno
Length of output: 10439
🏁 Script executed:
# Check if there are any other test files in the color-picker directory
fd -t f "\.spec\." tests/environments/color-picker/ 2>/dev/null || echo "No spec files found in color-picker"Repository: usebruno/bruno
Length of output: 110
🏁 Script executed:
cat -n tests/environments/color-picker/color-picker.spec.tsRepository: usebruno/bruno
Length of output: 7912
🏁 Script executed:
# Also check the directory structure of color-picker
tree tests/environments/color-picker/ -L 3Repository: usebruno/bruno
Length of output: 308
🏁 Script executed:
# Check if the collection is referenced in init-user-data files
cat tests/environments/color-picker/init-user-data/*.json | grep -i "test-request\|color-picker.*collection" || echo "No references found in init-user-data"Repository: usebruno/bruno
Length of output: 95
🏁 Script executed:
# Check for any other references to the collection directory
rg "color-picker" tests/environments/color-picker/ -g "*.json" -A 2 -B 2Repository: usebruno/bruno
Length of output: 40
🏁 Script executed:
# Search broadly for how collections are loaded in the test infrastructure
grep -r "collection" tests/environments/color-picker/ --include="*.json" 2>/dev/null | head -20Repository: usebruno/bruno
Length of output: 532
🏁 Script executed:
# Check if test-request.bru is referenced anywhere in the codebase
rg "test-request" tests/environments/color-picker/Repository: usebruno/bruno
Length of output: 138
🏁 Script executed:
# Look at what collection is actually being used by the color-picker test
cat tests/environments/color-picker/init-user-data/collection-security.jsonRepository: usebruno/bruno
Length of output: 253
🏁 Script executed:
# Check if the collection directory name or any part of it is referenced in test setup/config
grep -r "test-request" tests/ --include="*.ts" --include="*.js" 2>/dev/null | grep -v node_modulesRepository: usebruno/bruno
Length of output: 5240
🏁 Script executed:
# Double-check: verify the init-user-data for color-picker loads the global-env-config-selection collection
cat -n tests/environments/color-picker/init-user-data/preferences.jsonRepository: usebruno/bruno
Length of output: 237
🏁 Script executed:
# Check if global-env-config-selection collection references or includes test-request.bru
find tests/environments/global-env-config-selection -type f -name "*.bru" -o -name "*.json" | xargs cat 2>/dev/null | grep -i "test-request" || echo "No references to test-request in global-env-config-selection"Repository: usebruno/bruno
Length of output: 78
🏁 Script executed:
# List the contents of the actual collection being used
ls -la tests/environments/global-env-config-selection/collection/Repository: usebruno/bruno
Length of output: 290
🏁 Script executed:
# Check if color-picker/collection is referenced as a dependency in global-env-config-selection
cat tests/environments/global-env-config-selection/collection/test-request.bruRepository: usebruno/bruno
Length of output: 276
🏁 Script executed:
# Search for any imports or references between the two collections
grep -r "color-picker" tests/environments/global-env-config-selection/ 2>/dev/null || echo "No references found"Repository: usebruno/bruno
Length of output: 77
🏁 Script executed:
# Check if the color-picker collection's bruno.json has any special configuration
cat tests/environments/color-picker/collection/bruno.jsonRepository: usebruno/bruno
Length of output: 143
Remove the unused collection or clarify its purpose.
This collection is not referenced by color-picker.spec.ts, which instead uses global-env-config-selection. Either remove tests/environments/color-picker/collection/ entirely or update the test to use it. If it's intentionally part of the test setup, it should follow the convention of being nested under fixtures/collection.
🤖 Prompt for AI Agents
In `@tests/environments/color-picker/collection/test-request.bru` around lines 1 -
17, This collection file (meta name "test-request" containing the test "should
get 200 response") is unused by color-picker.spec.ts; either delete
tests/environments/color-picker/collection/test-request.bru (or the whole
collection folder) or move it under the fixtures/collection convention and/or
update color-picker.spec.ts to import/use the "test-request" collection (or
reference {{host}}/api/echo) so the spec actually exercises this collection;
ensure the chosen fix keeps the collection path consistent with other test
fixtures and that the test name "should get 200 response" remains accurate if
reused.
Extends #1053
Summary by CodeRabbit
Release Notes
✏️ Tip: You can customize this high-level summary in your review settings.