Skip to content

Conversation

@0ski
Copy link
Collaborator

@0ski 0ski commented Dec 5, 2025

Closes #

✅ Checklist

  • I have followed every step in the contributing guide
  • The PR title follows the convention.
  • I ran and tested the code works

Testing

Manual testing of the task run pages


Changelog

  • Add previous/next run navigation buttons to run detail page header

  • Support [ and ] keyboard shortcuts to jump between adjacent runs

  • Preserve runs table state (filters, pagination) when navigating

  • Preload adjacent page runs at boundaries for seamless navigation

  • Add actions prop to PageTitle component

  • Document shortcut in keyboard shortcuts panel

  • Store current filter state from runs table as tableState search param when navigating to individual run pages

  • Restore filters when navigating back from run detail view to runs list

  • Update v3RunPath and v3RunSpanPath helpers to accept optional searchParams

  • Use useOptimisticLocation to capture current search params in TaskRunsTable

  • Parse tableState param in run detail route and pass filters to back button

  • This improves UX by remembering filter selections (task, status, date range, etc.) when users click into a run and then navigate back to the runs list

  • Add new text-below variant that shows "Click to copy" tooltip on hover and "Copied" on click. Also add controlled open/onOpenChange props to SimpleTooltip for managing tooltip visibility.


Screenshots

Move.between.runs.mp4

0ski added 3 commits December 5, 2025 10:24
- Store current filter state from runs table as `tableState` search param when
  navigating to individual run pages
- Restore filters when navigating back from run detail view to runs list
- Update `v3RunPath` and `v3RunSpanPath` helpers to accept optional searchParams
- Use `useOptimisticLocation` to capture current search params in TaskRunsTable
- Parse `tableState` param in run detail route and pass filters to back button

This improves UX by remembering filter selections (task, status, date range, etc.)
when users click into a run and then navigate back to the runs list.
Add new text-below variant that shows "Click to copy" tooltip on hover and "Copied" on click. Also add controlled open/onOpenChange props to SimpleTooltip for managing tooltip visibility.
…board shortcuts)

Add previous/next run navigation buttons to run detail page header
Support [ and ] keyboard shortcuts to jump between adjacent runs
Preserve runs table state (filters, pagination) when navigating
Preload adjacent page runs at boundaries for seamless navigation
Add actions prop to PageTitle component
Document shortcut in keyboard shortcuts panel
@0ski 0ski self-assigned this Dec 5, 2025
@changeset-bot
Copy link

changeset-bot bot commented Dec 5, 2025

⚠️ No Changeset found

Latest commit: 6ee1295

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

Walkthrough

This pull request introduces adjacent-run navigation functionality across a paginated table of runs. The changes add URL state persistence to maintain table context during run inspection, implement previous/next run navigation components with keyboard shortcuts ("[" and "]" keys), and extend path builders to support URL query parameters. Supporting enhancements include new component variants for displaying UI elements (CopyableText, Tooltip), styling updates to shortcut key displays, and minor CSS adjustments.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–75 minutes

Areas requiring extra attention:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx — The most substantial file with new loader logic, adjacent-run state management, new hooks, and integration of navigation components; requires verification of run-list fetching, boundary detection, and cursor handling.
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx — URL state propagation logic using useOptimisticLocation; verify searchParams construction and consistency with path builder updates.
  • apps/webapp/app/utils/pathBuilder.ts — Parameter signature extensions for v3RunPath and v3RunSpanPath; confirm backward compatibility and correct URLSearchParams delegation.
  • apps/webapp/app/components/primitives/CopyableText.tsx — Two distinct rendering branches per variant; verify both "icon-right" and "text-below" paths function correctly with proper event handling.
  • apps/webapp/app/components/primitives/Tooltip.tsx — New controlled open-state props; ensure controlled behavior integrates correctly with existing tooltip consumers.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes—UX improvements for TaskRun page and table—encompassing navigation buttons, keyboard shortcuts, and state preservation.
Description check ✅ Passed The description follows the template structure with all required sections completed: checklist marked, testing method described, comprehensive changelog provided, and screenshots included.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch oo/feat-runs-table-ux-improvements

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
apps/webapp/app/components/runs/v3/TaskRunsTable.tsx (1)

85-86: The tableStateParam is always truthy.

The condition on line 300 if (tableStateParam) will always be true because tableStateParam is constructed as either "rt=1" or "${location.search}&rt=1", never an empty string. If the intent is to only set tableState when there's an actual search to preserve, consider checking location.search instead.

-  const tableStateParam = encodeURIComponent(location.search ? `${location.search}&rt=1` : "rt=1");
+  const tableStateParam = location.search 
+    ? encodeURIComponent(`${location.search}&rt=1`) 
+    : null;

Then adjust the condition accordingly:

-            if (tableStateParam) {
+            if (tableStateParam !== null) {
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx (3)

392-392: runsList prop is declared but unused in TraceView.

The function signature TraceView({ run, trace, maximumLiveReloadingSetting, resizable }: LoaderData) is destructuring from LoaderData but runsList is passed as a prop on line 376 yet not used in the component body. Either remove it from the call site or utilize it if needed.


486-486: runsList prop similarly unused in NoLogsView.

Same issue as TraceView - the prop is passed but not destructured or used.


1712-1748: Navigation buttons use # as href fallback.

When to is null, the buttons use to="#" which can cause the page to scroll to top or trigger navigation events. Combined with pointer-events-none on the wrapper, this should be safe, but consider using a more explicit disabled state.

The current implementation with pointer-events-none and onClick={(e) => !to && e.preventDefault()} provides double protection, which is good defensive coding.

apps/webapp/app/components/primitives/Tooltip.tsx (1)

22-27: Controlled tooltip state wiring looks correct; optionally forward the ref to TooltipPrimitive.Root

The new open / onOpenChange props on SimpleTooltip and their pass-through to Tooltip / TooltipPrimitive.Root look consistent with Radix’s controlled Tooltip API, and keep existing callers backward compatible. No changes required here.

As a small tidy-up, you could also forward the ref you receive in Tooltip down to TooltipPrimitive.Root so the forwardRef wrapper is fully honored:

 const Tooltip = React.forwardRef<
   React.ElementRef<typeof TooltipPrimitive.Root>,
   React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>
 >(({ delayDuration = 0, ...props }, ref) => (
-  <TooltipPrimitive.Root delayDuration={delayDuration} {...props} />
+  <TooltipPrimitive.Root ref={ref} delayDuration={delayDuration} {...props} />
 ));

Also applies to: 55-87

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a52566d and 4e79186.

📒 Files selected for processing (7)
  • apps/webapp/app/components/Shortcuts.tsx (1 hunks)
  • apps/webapp/app/components/primitives/CopyableText.tsx (1 hunks)
  • apps/webapp/app/components/primitives/PageHeader.tsx (2 hunks)
  • apps/webapp/app/components/primitives/Tooltip.tsx (3 hunks)
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx (3 hunks)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx (10 hunks)
  • apps/webapp/app/utils/pathBuilder.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

Files:

  • apps/webapp/app/components/Shortcuts.tsx
  • apps/webapp/app/components/primitives/PageHeader.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/components/primitives/Tooltip.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/components/Shortcuts.tsx
  • apps/webapp/app/components/primitives/PageHeader.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/components/primitives/Tooltip.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • apps/webapp/app/components/Shortcuts.tsx
  • apps/webapp/app/components/primitives/PageHeader.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/components/primitives/Tooltip.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/components/Shortcuts.tsx
  • apps/webapp/app/components/primitives/PageHeader.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/components/primitives/Tooltip.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/components/Shortcuts.tsx
  • apps/webapp/app/components/primitives/PageHeader.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/components/primitives/Tooltip.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
**/*.{js,ts,jsx,tsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier

Files:

  • apps/webapp/app/components/Shortcuts.tsx
  • apps/webapp/app/components/primitives/PageHeader.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/components/primitives/Tooltip.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties
📚 Learning: 2025-07-12T18:00:06.163Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/utils/searchParams.ts:16-18
Timestamp: 2025-07-12T18:00:06.163Z
Learning: The `objectToSearchParams` function in `apps/webapp/app/utils/searchParams.ts` is used to generate URL parameters from objects and is separate from code that parses incoming search parameters. Changes to this function only affect places where it's used to create URLs, not places that parse search parameters from external sources.

Applied to files:

  • apps/webapp/app/utils/pathBuilder.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution

Applied to files:

  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions

Applied to files:

  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Subscribe to run updates using `runs.subscribeToRun()` for realtime monitoring of task execution

Applied to files:

  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.

Applied to files:

  • apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Use the Run Engine 2.0 from `internal/run-engine` for new run lifecycle code in the webapp instead of the legacy run engine

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Use `useRun`, `useRealtimeRun` and other SWR/realtime hooks from `trigger.dev/react-hooks` for data fetching

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Use `trigger.dev/react-hooks` package for realtime subscriptions in React components

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.trigger()` with type-only imports to trigger tasks from backend code without importing the task implementation

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: The SDK at packages/trigger-sdk is an isomorphic TypeScript SDK

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Specify runtime environment (node or bun) in trigger.config.ts using the `runtime` property

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use logger methods (debug, log, info, warn, error) from `trigger.dev/sdk/v3` for structured logging in tasks

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use lifecycle functions (init, cleanup, onStart, onSuccess, onFailure, handleError) for task event handling

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
🧬 Code graph analysis (3)
apps/webapp/app/components/Shortcuts.tsx (2)
apps/webapp/app/hooks/useShortcutKeys.tsx (1)
  • Shortcut (7-12)
apps/webapp/app/components/primitives/ShortcutKey.tsx (1)
  • ShortcutKey (38-55)
apps/webapp/app/components/runs/v3/TaskRunsTable.tsx (1)
apps/webapp/app/utils/pathBuilder.ts (1)
  • v3RunSpanPath (310-321)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx (2)
apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts (1)
  • NextRunListPresenter (48-277)
apps/webapp/app/utils/pathBuilder.ts (2)
  • v3RunsPath (256-265)
  • v3RunPath (287-296)
🪛 Biome (2.1.2)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx

[error] 1551-1551: Unexpected empty object pattern.

(lint/correctness/noEmptyPattern)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (23)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (7)
apps/webapp/app/components/primitives/PageHeader.tsx (1)

33-60: LGTM!

Clean addition of the optional actions prop. The layout using ml-auto correctly positions actions on the right side of the header.

apps/webapp/app/components/Shortcuts.tsx (1)

137-140: LGTM!

The new "Jump to adjacent" keyboard shortcut documentation is correctly placed under the Run page section and follows the existing pattern.

apps/webapp/app/components/runs/v3/TaskRunsTable.tsx (1)

299-305: Verify intent of always including tableState.

Given the current logic, tableState is always set on every row link. If this is intentional to always enable adjacent-run navigation, it looks correct. The searchParams construction and usage with v3RunSpanPath is properly integrated with the updated path builder signature.

apps/webapp/app/utils/pathBuilder.ts (1)

287-296: LGTM!

The optional searchParams parameter extension to v3RunPath is backward compatible and correctly appends query parameters when provided.

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx (3)

179-253: Loader makes multiple database calls for adjacent run preloading.

The loader can make up to 3 separate calls to runsListPresenter.call() when at page boundaries. While this enables seamless navigation, consider:

  1. The performance impact of these additional queries on page load
  2. Error handling currently logs and continues silently, which is appropriate for non-critical navigation data

The implementation correctly isolates the adjacent-run loading in a try-catch to avoid breaking the main run page load.


1640-1708: LGTM - Well-structured adjacent run path computation.

The useAdjacentRunPaths hook correctly:

  • Handles null/empty runsList gracefully
  • Finds current run index and computes adjacent runs
  • Updates cursor/direction in tableState for cross-page navigation
  • Uses useMemo with appropriate dependencies for performance

The logic for boundary detection and page-crossing navigation is sound.


278-283: getRunFiltersFromSearchParams already handles empty/invalid tableState safely.

The function uses TaskRunListSearchFilters.safeParse() and returns an empty object {} on validation failure, ensuring malformed or empty input is handled gracefully without throwing.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e79186 and 6ee1295.

📒 Files selected for processing (5)
  • apps/webapp/app/components/primitives/Buttons.tsx (1 hunks)
  • apps/webapp/app/components/primitives/CopyableText.tsx (1 hunks)
  • apps/webapp/app/components/primitives/ShortcutKey.tsx (2 hunks)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx (11 hunks)
  • apps/webapp/app/utils/pathBuilder.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

Files:

  • apps/webapp/app/components/primitives/Buttons.tsx
  • apps/webapp/app/components/primitives/ShortcutKey.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
  • apps/webapp/app/utils/pathBuilder.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/components/primitives/Buttons.tsx
  • apps/webapp/app/components/primitives/ShortcutKey.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
  • apps/webapp/app/utils/pathBuilder.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • apps/webapp/app/components/primitives/Buttons.tsx
  • apps/webapp/app/components/primitives/ShortcutKey.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
  • apps/webapp/app/utils/pathBuilder.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/components/primitives/Buttons.tsx
  • apps/webapp/app/components/primitives/ShortcutKey.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
  • apps/webapp/app/utils/pathBuilder.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/components/primitives/Buttons.tsx
  • apps/webapp/app/components/primitives/ShortcutKey.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
  • apps/webapp/app/utils/pathBuilder.ts
**/*.{js,ts,jsx,tsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier

Files:

  • apps/webapp/app/components/primitives/Buttons.tsx
  • apps/webapp/app/components/primitives/ShortcutKey.tsx
  • apps/webapp/app/components/primitives/CopyableText.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
  • apps/webapp/app/utils/pathBuilder.ts
🧠 Learnings (15)
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Subscribe to run updates using `runs.subscribeToRun()` for realtime monitoring of task execution

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Use `useRun`, `useRealtimeRun` and other SWR/realtime hooks from `trigger.dev/react-hooks` for data fetching

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Use `trigger.dev/react-hooks` package for realtime subscriptions in React components

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.trigger()` with type-only imports to trigger tasks from backend code without importing the task implementation

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: The SDK at packages/trigger-sdk is an isomorphic TypeScript SDK

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Specify runtime environment (node or bun) in trigger.config.ts using the `runtime` property

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use logger methods (debug, log, info, warn, error) from `trigger.dev/sdk/v3` for structured logging in tasks

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use lifecycle functions (init, cleanup, onStart, onSuccess, onFailure, handleError) for task event handling

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
📚 Learning: 2025-07-12T18:00:06.163Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/utils/searchParams.ts:16-18
Timestamp: 2025-07-12T18:00:06.163Z
Learning: The `objectToSearchParams` function in `apps/webapp/app/utils/searchParams.ts` is used to generate URL parameters from objects and is separate from code that parses incoming search parameters. Changes to this function only affect places where it's used to create URLs, not places that parse search parameters from external sources.

Applied to files:

  • apps/webapp/app/utils/pathBuilder.ts
📚 Learning: 2024-09-17T16:37:27.060Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 1313
File: apps/webapp/app/hooks/useSearchParam.ts:21-21
Timestamp: 2024-09-17T16:37:27.060Z
Learning: When using `URLSearchParams.set` followed by `.toString()`, values are automatically URL-encoded. Manually encoding these values can lead to double encoding issues.

Applied to files:

  • apps/webapp/app/utils/pathBuilder.ts
📚 Learning: 2025-09-03T14:35:52.384Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2464
File: apps/webapp/app/utils/pathBuilder.ts:144-146
Timestamp: 2025-09-03T14:35:52.384Z
Learning: In the trigger.dev codebase, organization slugs are safe for URL query parameters and don't require URL encoding, as confirmed by the maintainer in apps/webapp/app/utils/pathBuilder.ts.

Applied to files:

  • apps/webapp/app/utils/pathBuilder.ts
🧬 Code graph analysis (3)
apps/webapp/app/components/primitives/Buttons.tsx (1)
apps/webapp/app/utils/cn.ts (1)
  • cn (77-79)
apps/webapp/app/components/primitives/CopyableText.tsx (5)
apps/webapp/app/hooks/useCopy.ts (1)
  • useCopy (3-22)
apps/webapp/app/utils/cn.ts (1)
  • cn (77-79)
packages/core/src/v3/apiClient/stream.ts (1)
  • e (216-222)
apps/webapp/app/components/primitives/Tooltip.tsx (1)
  • SimpleTooltip (132-132)
apps/webapp/app/components/primitives/Buttons.tsx (1)
  • Button (296-329)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx (5)
apps/webapp/app/models/project.server.ts (1)
  • findProjectBySlug (136-147)
apps/webapp/app/models/runtimeEnvironment.server.ts (1)
  • findEnvironmentBySlug (116-145)
apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts (1)
  • NextRunListPresenter (48-277)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs._index/route.tsx (2)
  • loader (71-109)
  • Page (111-181)
apps/webapp/app/utils/pathBuilder.ts (2)
  • v3RunsPath (256-265)
  • v3RunPath (287-296)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (23)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
apps/webapp/app/components/primitives/ShortcutKey.tsx (1)

11-19: LGTM! Consistent shortcut key styling.

The styling updates to use monospace font and adjusted sizing improve visual consistency across shortcut key displays.

apps/webapp/app/utils/pathBuilder.ts (2)

287-296: LGTM! Clean extension of path builders with optional search params.

The addition of the optional searchParams parameter to v3RunPath enables passing table state and other context when navigating between runs. The implementation correctly delegates to URLSearchParams.toString() for encoding.


310-321: LGTM! Correct URLSearchParams usage.

The v3RunSpanPath extension properly uses URLSearchParams.set() without manual encoding, which avoids double-encoding issues. The function correctly initializes a URLSearchParams instance when not provided and delegates to v3RunPath.

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx (3)

179-253: Well-structured adjacent run preloading logic.

The loader correctly:

  • Parses tableState from search params
  • Fetches the current page of runs
  • Preloads adjacent page runs when the current run is at a page boundary
  • Handles errors gracefully by returning null runsList

The boundary detection logic (lines 210-246) efficiently minimizes additional queries by only fetching when needed.


1639-1708: LGTM! Robust adjacent run path calculation.

The useAdjacentRunPaths hook correctly:

  • Handles edge cases (empty list, run not found)
  • Constructs separate tableState params for previous/next navigation
  • Updates cursor and direction when crossing page boundaries
  • Uses useMemo for performance optimization with appropriate dependencies

1550-1558: LGTM! Keyboard shortcuts display for adjacent runs.

The AdjacentRunsShortcuts function correctly displays the "[" and "]" shortcut keys. The empty destructuring issue from the previous review has been fixed.

<NavLink
to={to}
className={cn("group/button outline-none", props.fullWidth ? "w-full" : "")}
className={cn("group/button outline-none display-block", props.fullWidth ? "w-full" : "")}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix invalid Tailwind class name.

display-block is not a valid Tailwind CSS class. The correct class is block.

Apply this diff:

-      className={cn("group/button outline-none display-block", props.fullWidth ? "w-full" : "")}
+      className={cn("group/button outline-none block", props.fullWidth ? "w-full" : "")}
📝 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.

Suggested change
className={cn("group/button outline-none display-block", props.fullWidth ? "w-full" : "")}
className={cn("group/button outline-none block", props.fullWidth ? "w-full" : "")}
🤖 Prompt for AI Agents
In apps/webapp/app/components/primitives/Buttons.tsx around line 411, the
Tailwind class "display-block" is invalid; replace it with the correct Tailwind
class "block" so the className becomes cn("group/button outline-none block",
props.fullWidth ? "w-full" : "") to restore proper styling.

Comment on lines +69 to +94
if (resolvedVariant === "text-below") {
return (
<SimpleTooltip
button={
<Button
variant="minimal/small"
onClick={(e) => {
e.stopPropagation();
copy();
}}
className={cn(
"cursor-pointer bg-transparent py-0 px-1 text-left text-text-bright transition-colors hover:text-white hover:bg-transparent",
className
)}
>
<span className="text-text-white">{value}</span>
</Button>
}
content={copied ? "Copied" : "Click to copy"}
className="font-sans px-2 py-1"
disableHoverableContent
open={isHovered || copied}
onOpenChange={setIsHovered}
/>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Good accessibility improvements, but check the text color class.

The "text-below" variant now uses a proper Button component which addresses the keyboard accessibility concern from the previous review. The controlled tooltip with open={isHovered || copied} is well implemented.

However, line 84 uses text-text-white which appears to be a typo—it should likely be text-white.

Apply this diff if text-text-white is a typo:

-            <span className="text-text-white">{value}</span>
+            <span className="text-white">{value}</span>
📝 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.

Suggested change
if (resolvedVariant === "text-below") {
return (
<SimpleTooltip
button={
<Button
variant="minimal/small"
onClick={(e) => {
e.stopPropagation();
copy();
}}
className={cn(
"cursor-pointer bg-transparent py-0 px-1 text-left text-text-bright transition-colors hover:text-white hover:bg-transparent",
className
)}
>
<span className="text-text-white">{value}</span>
</Button>
}
content={copied ? "Copied" : "Click to copy"}
className="font-sans px-2 py-1"
disableHoverableContent
open={isHovered || copied}
onOpenChange={setIsHovered}
/>
);
}
if (resolvedVariant === "text-below") {
return (
<SimpleTooltip
button={
<Button
variant="minimal/small"
onClick={(e) => {
e.stopPropagation();
copy();
}}
className={cn(
"cursor-pointer bg-transparent py-0 px-1 text-left text-text-bright transition-colors hover:text-white hover:bg-transparent",
className
)}
>
<span className="text-white">{value}</span>
</Button>
}
content={copied ? "Copied" : "Click to copy"}
className="font-sans px-2 py-1"
disableHoverableContent
open={isHovered || copied}
onOpenChange={setIsHovered}
/>
);
}
🤖 Prompt for AI Agents
In apps/webapp/app/components/primitives/CopyableText.tsx around lines 69 to 94,
the span uses the class "text-text-white" which appears to be a typo; change it
to "text-white" so the correct Tailwind text color utility is applied (update
the className on the Button/span accordingly), and run a quick search to ensure
no other instances of "text-text-white" remain.

Comment on lines +278 to +281
const { value } = useSearchParams();
const tableState = decodeURIComponent(value("tableState") ?? "");
const tableStateSearchParams = new URLSearchParams(tableState);
const filters = getRunFiltersFromSearchParams(tableStateSearchParams);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n apps/webapp/app/hooks/useSearchParam.ts

Repository: triggerdotdev/trigger.dev

Length of output: 2675


🏁 Script executed:

rg -B 5 -A 5 "tableState" apps/webapp/app/routes/_app.orgs.\$organizationSlug.projects.\$projectParam.env.\$envParam.runs.\$runParam/route.tsx | head -50

Repository: triggerdotdev/trigger.dev

Length of output: 1941


🏁 Script executed:

# Check if there are other uses of tableState being set to understand the encoding flow
rg -B 3 -A 3 'tableState.*=' apps/webapp/app/routes/_app.orgs.\$organizationSlug.projects.\$projectParam.env.\$envParam.runs.\$runParam/route.tsx

Repository: triggerdotdev/trigger.dev

Length of output: 1311


🏁 Script executed:

# Find where tableState is set/encoded when creating URLs
rg -B 5 -A 5 "tableState.*=" apps/webapp/app/routes/_app.orgs.\$organizationSlug.projects.\$projectParam.env.\$envParam.runs.\$runParam/ | grep -A 10 -B 10 "previousRunPath\|nextRunPath\|to=" | head -60

Repository: triggerdotdev/trigger.dev

Length of output: 3637


🏁 Script executed:

# Find the useAdjacentRunPaths implementation
rg -l "useAdjacentRunPaths" apps/webapp/app/routes/_app.orgs.\$organizationSlug.projects.\$projectParam.env.\$envParam.runs.\$runParam/ --type ts --type tsx

Repository: triggerdotdev/trigger.dev

Length of output: 96


🏁 Script executed:

# Find the useAdjacentRunPaths implementation
rg "useAdjacentRunPaths" apps/webapp/app/routes/_app.orgs.\$organizationSlug.projects.\$projectParam.env.\$envParam.runs.\$runParam/ -A 50

Repository: triggerdotdev/trigger.dev

Length of output: 15637


🏁 Script executed:

# Get the rest of the useAdjacentRunPaths function to see how paths are constructed
rg "useAdjacentRunPaths" apps/webapp/app/routes/_app.orgs.\$organizationSlug.projects.\$projectParam.env.\$envParam.runs.\$runParam/route.tsx -A 100 | tail -60

Repository: triggerdotdev/trigger.dev

Length of output: 2336


🏁 Script executed:

# Verify by checking the v3RunPath function to understand the complete encoding flow
rg "function v3RunPath|export.*v3RunPath" apps/webapp -A 10

Repository: triggerdotdev/trigger.dev

Length of output: 808


Remove the unnecessary decodeURIComponent() call; URLSearchParams.get() already returns decoded values.

Line 279 calls decodeURIComponent() on value("tableState"), which is redundant. The useSearchParams().value() function uses URLSearchParams.get(), which automatically URL-decodes the parameter value. Calling decodeURIComponent() on an already-decoded string can cause issues with special characters and is inconsistent with how search parameters are handled elsewhere in the codebase. Remove the decodeURIComponent() call:

const tableState = value("tableState") ?? "";
🤖 Prompt for AI Agents
In
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
around lines 278 to 281, remove the unnecessary decodeURIComponent call when
reading the tableState search param because useSearchParams().value()
(URLSearchParams.get()) already returns a decoded string; change the assignment
to use the raw value with a fallback (i.e. use value("tableState") ?? "") and
pass that to URLSearchParams so special characters aren't double-decoded.

Comment on lines +1711 to +1729
function PreviousRunButton({ to }: { to: string | null }) {
return (
<div className={cn("peer/prev order-1", !to && "pointer-events-none")}>
<LinkButton
to={to ? to : '#'}
variant={"minimal/small"}
LeadingIcon={ChevronUpIcon}
className={cn(
"flex items-center rounded-r-none border-r-0 pl-2 pr-[0.5625rem]",
!to && "cursor-not-allowed opacity-50"
)}
onClick={(e) => !to && e.preventDefault()}
shortcut={{ key: "[" }}
tooltip="Previous Run"
disabled={!to}
/>
</div>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid using '#' as href for disabled links.

Lines 1715 and 1735 use '#' as a fallback href when to is null. Even with preventDefault(), this creates a misleading href attribute and could cause unexpected behavior if the click handler fails.

Consider using undefined or an empty string, or conditionally rendering the LinkButton only when to is truthy.

Apply this diff:

 function PreviousRunButton({ to }: { to: string | null }) {
+  if (!to) {
+    return (
+      <div className="peer/prev order-1 pointer-events-none">
+        <div
+          className="flex items-center rounded-r-none border-r-0 pl-2 pr-[0.5625rem] cursor-not-allowed opacity-50"
+        >
+          <ChevronUpIcon className="h-4 w-4" />
+        </div>
+      </div>
+    );
+  }
   return (
-    <div className={cn("peer/prev order-1", !to && "pointer-events-none")}>
+    <div className="peer/prev order-1">
       <LinkButton
-        to={to ? to : '#'}
+        to={to}
         variant={"minimal/small"}
         LeadingIcon={ChevronUpIcon}
-        className={cn(
-          "flex items-center rounded-r-none border-r-0 pl-2 pr-[0.5625rem]",
-          !to && "cursor-not-allowed opacity-50"
-        )}
-        onClick={(e) => !to && e.preventDefault()}
+        className="flex items-center rounded-r-none border-r-0 pl-2 pr-[0.5625rem]"
         shortcut={{ key: "[" }}
         tooltip="Previous Run"
-        disabled={!to}
       />
     </div>
   );
 }

Apply a similar pattern to NextRunButton.

📝 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.

Suggested change
function PreviousRunButton({ to }: { to: string | null }) {
return (
<div className={cn("peer/prev order-1", !to && "pointer-events-none")}>
<LinkButton
to={to ? to : '#'}
variant={"minimal/small"}
LeadingIcon={ChevronUpIcon}
className={cn(
"flex items-center rounded-r-none border-r-0 pl-2 pr-[0.5625rem]",
!to && "cursor-not-allowed opacity-50"
)}
onClick={(e) => !to && e.preventDefault()}
shortcut={{ key: "[" }}
tooltip="Previous Run"
disabled={!to}
/>
</div>
);
}
function PreviousRunButton({ to }: { to: string | null }) {
if (!to) {
return (
<div className="peer/prev order-1 pointer-events-none">
<div
className="flex items-center rounded-r-none border-r-0 pl-2 pr-[0.5625rem] cursor-not-allowed opacity-50"
>
<ChevronUpIcon className="h-4 w-4" />
</div>
</div>
);
}
return (
<div className="peer/prev order-1">
<LinkButton
to={to}
variant={"minimal/small"}
LeadingIcon={ChevronUpIcon}
className="flex items-center rounded-r-none border-r-0 pl-2 pr-[0.5625rem]"
shortcut={{ key: "[" }}
tooltip="Previous Run"
/>
</div>
);
}
🤖 Prompt for AI Agents
In
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx
around lines 1711 to 1729, the PreviousRunButton uses '#' as a fallback href
when `to` is null; change this to avoid a misleading href by either
conditionally rendering the LinkButton only when `to` is truthy (and render a
non-interactive placeholder div when false) or pass `undefined`/empty string
instead of '#'; remove reliance on preventing default for clicks (keep disabled
prop and styling) and apply the same change to the corresponding NextRunButton
to ensure disabled navigation links do not contain '#' hrefs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants