New UI components for the S3 explorer with Codex#1058
New UI components for the S3 explorer with Codex#1058garronej merged 56 commits intoexplorer_deep_reworkfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a large set of UI features: S3 path and URI bars with edit/validation flows, bookmarks UI (chips, rows, pinned bar, modals, lists), an S3 profile selector, S3 URI utilities/types, Storybook stories for many components, a small placeholder navigation file, and a VSCode MCP config. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant UI as S3PathControl / S3UriBar
participant Validator as validatePath (async)
participant Host as Host App (callbacks)
rect rgba(200,220,255,0.5)
User->>UI: enter edit / click validate / select hint
UI->>Validator: validatePath(draft) / parse prefix / request hints
Validator-->>UI: validation result or hints
UI->>Host: onNavigate / onS3UriPrefixChange / onIsEditingChange
Host-->>UI: state update / navigation confirmation
end
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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.
🧹 Nitpick comments (1)
.vscode/mcp.json (1)
2-8: Consider making this VSCode MCP config opt-in for contributors.This hardcodes a local endpoint (
127.0.0.1:3845) in a repo-tracked.vscodefile, which can be noisy/non-functional for teammates who don’t run that local MCP server. Prefer documenting it inREADME(or committing a sample file) so local workspace setup remains explicit and portable.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.vscode/mcp.json around lines 2 - 8, The .vscode/mcp.json currently hardcodes a local MCP endpoint under the "servers" -> "figma" -> "url" key which can be noisy for contributors; change this to an opt-in setup by removing or replacing the concrete URL in .vscode/mcp.json and instead commit a template (e.g., .vscode/mcp.json.sample) with a placeholder for "url" and add the real .vscode/mcp.json to .gitignore, and update README to document how to enable/configure the "figma" MCP server and the expected "servers" / "inputs" keys so contributors can opt-in safely.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In @.vscode/mcp.json:
- Around line 2-8: The .vscode/mcp.json currently hardcodes a local MCP endpoint
under the "servers" -> "figma" -> "url" key which can be noisy for contributors;
change this to an opt-in setup by removing or replacing the concrete URL in
.vscode/mcp.json and instead commit a template (e.g., .vscode/mcp.json.sample)
with a placeholder for "url" and add the real .vscode/mcp.json to .gitignore,
and update README to document how to enable/configure the "figma" MCP server and
the expected "servers" / "inputs" keys so contributors can opt-in safely.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/ui/shared/S3PathControl.atoms.stories.tsx`:
- Around line 14-17: The BackButton story is failing TS2322 because
StoryObj<typeof meta> derives props from meta.component (S3PathBackButton) which
requires classes, cx, canGoBack, and onBack but the story's args only provides
canGoBack; fix by giving the story a custom args type that relaxes or narrows
the component props (for example use StoryObj<React.ComponentProps<typeof
S3PathBackButton>> with Partial or pick only canGoBack) so the args: {
canGoBack: true } type-checks; update the BackButton story declaration to use
that custom StoryObj type (referencing meta, S3PathBackButton, and the
BackButton story name) and/or explicitly type args as Partial<...> to satisfy
strict TypeScript.
In `@web/src/ui/shared/S3PathControl.tsx`:
- Around line 1081-1088: The current copy logic calls
setInfoMessage(copyMessage) and onCopy(value) regardless of whether
navigator.clipboard?.writeText(value) succeeds; change the flow in S3PathControl
(the block using navigator.clipboard?.writeText, setInfoMessage and onCopy) so
that setInfoMessage(copyMessage) and onCopy?.(value) are executed only inside
the try after await navigator.clipboard?.writeText(value) completes
successfully, and keep the catch block for silently ignoring or optionally
setting an error message; this ensures "Path copied." is only shown when the
clipboard write actually succeeds.
- Line 1067: The forEach callback on tailIndices is using a single-expression
arrow which implicitly returns the result of collapsed.push(crumbs[index]) and
triggers the lint rule; change the callback to a block-bodied arrow (e.g.,
tailIndices.forEach(index => { collapsed.push(crumbs[index]); });) so the push
call is executed without an implicit return. Ensure you update the invocation
where tailIndices, collapsed, and crumbs are used in S3PathControl to use the
braced callback form.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
web/src/ui/shared/S3ExplorerNavigationBar.tsxweb/src/ui/shared/S3PathControl.atoms.stories.tsxweb/src/ui/shared/S3PathControl.stories.tsxweb/src/ui/shared/S3PathControl.tsx
✅ Files skipped from review due to trivial changes (1)
- web/src/ui/shared/S3ExplorerNavigationBar.tsx
| const meta = { | ||
| title: "Shared/S3PathControl/Atoms", | ||
| component: S3PathBackButton | ||
| } satisfies Meta<typeof S3PathBackButton>; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "S3PathControl.atoms.stories.tsx" | head -20Repository: InseeFrLab/onyxia
Length of output: 112
🏁 Script executed:
cat -n ./web/src/ui/shared/S3PathControl.atoms.stories.tsxRepository: InseeFrLab/onyxia
Length of output: 9853
🏁 Script executed:
find . -type f -name "S3PathControl.ts*" -o -name "S3PathControl.tsx" | grep -v storiesRepository: InseeFrLab/onyxia
Length of output: 98
🏁 Script executed:
cat -n ./web/src/ui/shared/S3PathControl.tsxRepository: InseeFrLab/onyxia
Length of output: 50373
🏁 Script executed:
find . -name "tsconfig*" -type f | head -5Repository: InseeFrLab/onyxia
Length of output: 133
🏁 Script executed:
cat ./web/tsconfig.json | head -50Repository: InseeFrLab/onyxia
Length of output: 821
🏁 Script executed:
rg "TS2322" . --type-list 2>/dev/null | head -20Repository: InseeFrLab/onyxia
Length of output: 43
🏁 Script executed:
head -100 ./web/src/ui/shared/S3PathControl.atoms.stories.tsx | tail -60Repository: InseeFrLab/onyxia
Length of output: 1503
🏁 Script executed:
find . -type f -name "*.log" -o -name ".github" -type d | grep -E "(workflow|action|log)" | head -20Repository: InseeFrLab/onyxia
Length of output: 43
🏁 Script executed:
find .github -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -10Repository: InseeFrLab/onyxia
Length of output: 133
🏁 Script executed:
cat .github/workflows/ci.yaml | grep -A 20 -B 5 "typescript\|tsc\|type"Repository: InseeFrLab/onyxia
Length of output: 1161
🏁 Script executed:
cat .github/workflows/ci.yaml | head -150Repository: InseeFrLab/onyxia
Length of output: 4742
🏁 Script executed:
cat ./web/package.json | grep -A 5 '"build"'Repository: InseeFrLab/onyxia
Length of output: 414
🏁 Script executed:
cd ./web && yarn tsc --noEmit 2>&1 | grep -A 5 "S3PathControl.atoms.stories"Repository: InseeFrLab/onyxia
Length of output: 43
🏁 Script executed:
cd ./web && yarn tsc --noEmit 2>&1 | head -100Repository: InseeFrLab/onyxia
Length of output: 491
🏁 Script executed:
find ./web/src -name "*.stories.tsx" -o -name "*.stories.ts" | head -5Repository: InseeFrLab/onyxia
Length of output: 350
Fix TS2322 in BackButton story typing (blocks build with strict TypeScript).
BackButton uses StoryObj<typeof meta> where meta.component is S3PathBackButton, which requires props classes, cx, canGoBack, and onBack. The args: { canGoBack: true } at line 32 omits required props, causing a type mismatch despite the render function providing them. Storybook enforces args type compatibility at compilation time.
Suggested fix (custom args type for this story)
type Story = StoryObj<typeof meta>;
+type BackButtonStoryArgs = { canGoBack: boolean };
+type BackButtonStory = StoryObj<BackButtonStoryArgs>;
-export const BackButton: Story = {
+export const BackButton: BackButtonStory = {
args: {
canGoBack: true
},🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/ui/shared/S3PathControl.atoms.stories.tsx` around lines 14 - 17, The
BackButton story is failing TS2322 because StoryObj<typeof meta> derives props
from meta.component (S3PathBackButton) which requires classes, cx, canGoBack,
and onBack but the story's args only provides canGoBack; fix by giving the story
a custom args type that relaxes or narrows the component props (for example use
StoryObj<React.ComponentProps<typeof S3PathBackButton>> with Partial or pick
only canGoBack) so the args: { canGoBack: true } type-checks; update the
BackButton story declaration to use that custom StoryObj type (referencing meta,
S3PathBackButton, and the BackButton story name) and/or explicitly type args as
Partial<...> to satisfy strict TypeScript.
web/src/ui/shared/S3PathControl.tsx
Outdated
| collapsed.push(ellipsisCrumb); | ||
| } | ||
|
|
||
| tailIndices.forEach(index => collapsed.push(crumbs[index])); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "S3PathControl.tsx" -type fRepository: InseeFrLab/onyxia
Length of output: 98
🏁 Script executed:
head -1070 web/src/ui/shared/S3PathControl.tsx | tail -10Repository: InseeFrLab/onyxia
Length of output: 352
🏁 Script executed:
# Get exact content around line 1067
sed -n '1060,1075p' web/src/ui/shared/S3PathControl.tsxRepository: InseeFrLab/onyxia
Length of output: 521
🏁 Script executed:
# Check if there's a Biome/linter configuration
find . -name "biome.json" -o -name ".biomerc*" -o -name "biome.jsonc" | head -5Repository: InseeFrLab/onyxia
Length of output: 73
🏁 Script executed:
# Search for similar forEach patterns in the codebase to see if this rule is being enforced
rg "forEach\s*\(\s*\w+\s*=>\s*\w+\." -t tsx -t ts --max-count=10Repository: InseeFrLab/onyxia
Length of output: 88
🏁 Script executed:
# Check Biome configuration
cat biome.jsonRepository: InseeFrLab/onyxia
Length of output: 1835
🏁 Script executed:
# Search for similar forEach patterns without file type restriction
rg "forEach\s*\(\s*\w+\s*=>\s*\w+\." --max-count=10Repository: InseeFrLab/onyxia
Length of output: 165
🏁 Script executed:
# Verify the exact line number
rg -n "tailIndices.forEach" web/src/ui/shared/S3PathControl.tsxRepository: InseeFrLab/onyxia
Length of output: 134
🏁 Script executed:
# Get broader context to understand the full function
sed -n '1050,1080p' web/src/ui/shared/S3PathControl.tsxRepository: InseeFrLab/onyxia
Length of output: 860
Fix Biome lint error: forEach callback should not implicitly return.
At line 1067, collapsed.push(...) is returned implicitly from the arrow callback, which violates lint/suspicious/useIterableCallbackReturn. The single-expression arrow function syntax causes the result of push() to be implicitly returned; this should be wrapped in braces to use block form.
Suggested fix
- tailIndices.forEach(index => collapsed.push(crumbs[index]));
+ tailIndices.forEach(index => {
+ collapsed.push(crumbs[index]);
+ });📝 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.
| tailIndices.forEach(index => collapsed.push(crumbs[index])); | |
| tailIndices.forEach(index => { | |
| collapsed.push(crumbs[index]); | |
| }); |
🧰 Tools
🪛 Biome (2.4.4)
[error] 1067-1067: This callback passed to forEach() iterable method should not return a value.
(lint/suspicious/useIterableCallbackReturn)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/ui/shared/S3PathControl.tsx` at line 1067, The forEach callback on
tailIndices is using a single-expression arrow which implicitly returns the
result of collapsed.push(crumbs[index]) and triggers the lint rule; change the
callback to a block-bodied arrow (e.g., tailIndices.forEach(index => {
collapsed.push(crumbs[index]); });) so the push call is executed without an
implicit return. Ensure you update the invocation where tailIndices, collapsed,
and crumbs are used in S3PathControl to use the braced callback form.
web/src/ui/shared/S3PathControl.tsx
Outdated
| try { | ||
| await navigator.clipboard?.writeText(value); | ||
| } catch { | ||
| // Ignore clipboard errors. | ||
| } | ||
|
|
||
| setInfoMessage(copyMessage); | ||
| onCopy?.(value); |
There was a problem hiding this comment.
Only show copy success when clipboard write actually succeeds.
At Lines [1081]-[1088], "Path copied." is shown even when clipboard write fails, which can mislead users.
Suggested fix
- try {
- await navigator.clipboard?.writeText(value);
- } catch {
- // Ignore clipboard errors.
- }
-
- setInfoMessage(copyMessage);
+ let copied = false;
+ try {
+ await navigator.clipboard?.writeText(value);
+ copied = true;
+ } catch {
+ // Ignore clipboard errors.
+ }
+
+ if (copied) {
+ setInfoMessage(copyMessage);
+ }
onCopy?.(value);📝 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.
| try { | |
| await navigator.clipboard?.writeText(value); | |
| } catch { | |
| // Ignore clipboard errors. | |
| } | |
| setInfoMessage(copyMessage); | |
| onCopy?.(value); | |
| let copied = false; | |
| try { | |
| await navigator.clipboard?.writeText(value); | |
| copied = true; | |
| } catch { | |
| // Ignore clipboard errors. | |
| } | |
| if (copied) { | |
| setInfoMessage(copyMessage); | |
| } | |
| onCopy?.(value); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/ui/shared/S3PathControl.tsx` around lines 1081 - 1088, The current
copy logic calls setInfoMessage(copyMessage) and onCopy(value) regardless of
whether navigator.clipboard?.writeText(value) succeeds; change the flow in
S3PathControl (the block using navigator.clipboard?.writeText, setInfoMessage
and onCopy) so that setInfoMessage(copyMessage) and onCopy?.(value) are executed
only inside the try after await navigator.clipboard?.writeText(value) completes
successfully, and keep the catch block for silently ignoring or optionally
setting an error message; this ensures "Path copied." is only shown when the
clipboard write actually succeeds.
There was a problem hiding this comment.
🧹 Nitpick comments (5)
web/src/ui/shared/S3UriBar.tsx (4)
502-518: Consider clarifying the object hint behavior.When selecting an object hint, the code creates a
NonTerminatedByDelimiterprefix rather than anS3Uri.Object. This is likely intentional for the navigation/autocomplete UX, but a brief comment would help clarify this design choice for future maintainers.📝 Suggested comment
const nextPrefix: S3Uri.Prefix = hint.type === "key-segment" ? { type: "prefix", bucket: sourcePrefix.bucket, delimiter: sourcePrefix.delimiter, keySegments: [...sourcePrefix.keySegments, hint.name], isDelimiterTerminated: true } - : { + : // Object hints are treated as non-terminated prefixes for navigation purposes + { type: "prefix", bucket: sourcePrefix.bucket, delimiter: sourcePrefix.delimiter, keySegments: [...sourcePrefix.keySegments], isDelimiterTerminated: false, nextKeySegmentPrefix: hint.name };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/ui/shared/S3UriBar.tsx` around lines 502 - 518, The selection of an object hint currently constructs a non-terminated prefix (S3Uri.Prefix) with isDelimiterTerminated:false and nextKeySegmentPrefix set (in the branch where hint.type !== "key-segment") instead of constructing an S3Uri.Object; add a concise comment above this conditional (near the S3Uri.Prefix construction) explaining that this is intentional for navigation/autocomplete UX—we keep a NonTerminatedByDelimiter-style prefix so the UI can continue showing/expanding suggestions rather than treating the selection as a final S3Uri.Object; reference the hint.type check, isDelimiterTerminated flag and nextKeySegmentPrefix in the comment so future maintainers understand the decision.
623-628: Consider documenting the 250ms blur timing guard.The timing check prevents the blur handler from closing edit mode immediately after entering it, which handles edge cases where
relatedTargetis null. A brief comment explaining this UX protection would improve maintainability.📝 Suggested comment
+ // Guard against immediate blur when relatedTarget is null (e.g., touch devices + // or certain focus transitions). Allow a brief window after entering edit mode. if ( nextFocusedElement === null && performance.now() - lastEnterEditRequestTimeRef.current < 250 ) { return; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/ui/shared/S3UriBar.tsx` around lines 623 - 628, Add a brief inline comment explaining the 250ms blur timing guard: in the blur handler inside S3UriBar, annotate why we check nextFocusedElement === null and performance.now() - lastEnterEditRequestTimeRef.current < 250 (to avoid immediately exiting edit mode right after entering it when relatedTarget can be null), and mention that this protects against focus timing edge-cases/rapid transitions; place the comment directly above the if that uses nextFocusedElement, lastEnterEditRequestTimeRef, and performance.now().
262-262: Consider clearing stale measurement refs when crumbs change.The
measureCrumbRefsarray grows to accommodate new crumbs but isn't trimmed when the crumb count decreases. While this doesn't cause functional issues (only current indices are read), it could lead to memory overhead with many navigation changes.♻️ Proposed fix - clear refs when crumbs change
Add a cleanup in the measurement effect or reset the array length:
useEffect(() => { + // Trim stale refs when crumb count decreases + measureCrumbRefs.current.length = crumbs.length; + if (isEditing) { setDisplayCrumbs(crumbs); return; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/ui/shared/S3UriBar.tsx` at line 262, measureCrumbRefs (useRef<Array<HTMLSpanElement | null>>) currently only grows when new crumbs are added and never trimmed, which can leak stale span references; update the measurement effect that runs on crumbs changes (the effect that reads measureCrumbRefs.current) to trim or reset the ref array to match the current crumbs length (e.g., set measureCrumbRefs.current.length = crumbs.length or reassign a new array of the correct length) so entries beyond the current crumb count are released whenever crumbs change.
436-436: Static analysis:forEachcallback should not return a value.The
forEachcallback implicitly returns the result ofcollapsed.push(), which is flagged by Biome. While this doesn't affect runtime behavior, it's a code smell.♻️ Proposed fix
- tailIndices.forEach(index => collapsed.push(crumbs[index])); + for (const index of tailIndices) { + collapsed.push(crumbs[index]); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/ui/shared/S3UriBar.tsx` at line 436, The Biome warning comes from the forEach callback on tailIndices implicitly returning the value of collapsed.push(crumbs[index]); update the callback in S3UriBar (the tailIndices.forEach usage) to use a block-bodied function or a simple for...of loop so the callback does not return a value (e.g., replace the expression-bodied arrow with a block that calls collapsed.push(crumbs[index]) or iterate with for (const index of tailIndices) { collapsed.push(crumbs[index]); }).web/src/core/tools/S3Uri.ts (1)
81-85: Potential issue:match[1]could be undefined for edge case URIs.The regex
/^s3:\/\/([^/]+)(\/?.*)$/captures the bucket in group 1, but TypeScript doesn't narrow this after the null check onmatch. Ifmatchis not null,match[1]should always exist for this pattern, but adding an explicit check would make the code more defensive.🛡️ Proposed defensive check
if (match === null) { throw new Error(`Malformed S3 URI: ${value}`); } - const bucket = match[1]; + const bucket = match[1]; + + if (bucket === undefined || bucket === "") { + throw new Error(`Malformed S3 URI (missing bucket): ${value}`); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/core/tools/S3Uri.ts` around lines 81 - 85, The current S3 URI parsing uses const match = value.match(/^s3:\/\/([^/]+)(\/?.*)$/) and only checks for match === null; add a defensive check that ensures the bucket capture (match[1]) is defined and non-empty before using it (e.g., if (!match || !match[1]) throw new Error(`Malformed S3 URI: ${value}`)); update the code paths in the S3Uri parsing logic that reference match[1] and match[2] (the bucket and key) to rely on this validated match so TypeScript no longer assumes undefined-safe usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@web/src/core/tools/S3Uri.ts`:
- Around line 81-85: The current S3 URI parsing uses const match =
value.match(/^s3:\/\/([^/]+)(\/?.*)$/) and only checks for match === null; add a
defensive check that ensures the bucket capture (match[1]) is defined and
non-empty before using it (e.g., if (!match || !match[1]) throw new
Error(`Malformed S3 URI: ${value}`)); update the code paths in the S3Uri parsing
logic that reference match[1] and match[2] (the bucket and key) to rely on this
validated match so TypeScript no longer assumes undefined-safe usage.
In `@web/src/ui/shared/S3UriBar.tsx`:
- Around line 502-518: The selection of an object hint currently constructs a
non-terminated prefix (S3Uri.Prefix) with isDelimiterTerminated:false and
nextKeySegmentPrefix set (in the branch where hint.type !== "key-segment")
instead of constructing an S3Uri.Object; add a concise comment above this
conditional (near the S3Uri.Prefix construction) explaining that this is
intentional for navigation/autocomplete UX—we keep a
NonTerminatedByDelimiter-style prefix so the UI can continue showing/expanding
suggestions rather than treating the selection as a final S3Uri.Object;
reference the hint.type check, isDelimiterTerminated flag and
nextKeySegmentPrefix in the comment so future maintainers understand the
decision.
- Around line 623-628: Add a brief inline comment explaining the 250ms blur
timing guard: in the blur handler inside S3UriBar, annotate why we check
nextFocusedElement === null and performance.now() -
lastEnterEditRequestTimeRef.current < 250 (to avoid immediately exiting edit
mode right after entering it when relatedTarget can be null), and mention that
this protects against focus timing edge-cases/rapid transitions; place the
comment directly above the if that uses nextFocusedElement,
lastEnterEditRequestTimeRef, and performance.now().
- Line 262: measureCrumbRefs (useRef<Array<HTMLSpanElement | null>>) currently
only grows when new crumbs are added and never trimmed, which can leak stale
span references; update the measurement effect that runs on crumbs changes (the
effect that reads measureCrumbRefs.current) to trim or reset the ref array to
match the current crumbs length (e.g., set measureCrumbRefs.current.length =
crumbs.length or reassign a new array of the correct length) so entries beyond
the current crumb count are released whenever crumbs change.
- Line 436: The Biome warning comes from the forEach callback on tailIndices
implicitly returning the value of collapsed.push(crumbs[index]); update the
callback in S3UriBar (the tailIndices.forEach usage) to use a block-bodied
function or a simple for...of loop so the callback does not return a value
(e.g., replace the expression-bodied arrow with a block that calls
collapsed.push(crumbs[index]) or iterate with for (const index of tailIndices) {
collapsed.push(crumbs[index]); }).
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
web/src/ui/assets/svg/S3UriBucket.svgis excluded by!**/*.svgweb/src/ui/assets/svg/S3UriHome.svgis excluded by!**/*.svg
📒 Files selected for processing (5)
web/src/core/tools/S3Uri.tsweb/src/ui/general.spec.mdweb/src/ui/shared/S3UriBar.spec.mdweb/src/ui/shared/S3UriBar.stories.tsxweb/src/ui/shared/S3UriBar.tsx
✅ Files skipped from review due to trivial changes (2)
- web/src/ui/general.spec.md
- web/src/ui/shared/S3UriBar.spec.md
…new editing mode with multiple hints
|




Summary by CodeRabbit
New Features
Documentation
Chores