feat: implement empty state view when the last empty tab is closed#3796
feat: implement empty state view when the last empty tab is closed#3796
Conversation
|
@codex review |
There was a problem hiding this comment.
Pull request overview
Implements a “zero tabs” state in the tenant SQL editor so that closing the last tab results in a dedicated empty-state view (instead of leaving the editor in an unclear state), and updates persistence + tests to support restoring this state across reloads/mode switches.
Changes:
- Add a new zero-tabs UI view and render it when the multi-tab editor has no open tabs.
- Update query tab persistence/state to allow
activeTabIdto be absent and represent a “zero tabs” state. - Extend E2E/unit test coverage (including screenshots) for zero-tabs behavior, reload restore, and single-tab recovery.
Reviewed changes
Copilot reviewed 16 out of 21 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/utils/queryHotkeys.ts | Adjusts modifier detection and key handling for tab hotkey E2E helpers. |
| tests/suites/tenant/queryEditor/queryEditorModes.test.ts | Adds coverage for recovering from zero-tabs when switching to single-tab mode. |
| tests/suites/tenant/queryEditor/models/QueryEditor.ts | Adds page-object helpers/locators for zero-tabs state and improves safety around active tab id usage. |
| tests/suites/tenant/queryEditor/editorTabs.test.ts-snapshots/query-editor-zero-tabs-state-safari-linux.png | Adds zero-tabs visual regression snapshot (Safari/WebKit). |
| tests/suites/tenant/queryEditor/editorTabs.test.ts-snapshots/query-editor-zero-tabs-state-hover-safari-linux.png | Adds zero-tabs hover visual regression snapshot (Safari/WebKit). |
| tests/suites/tenant/queryEditor/editorTabs.test.ts-snapshots/query-editor-zero-tabs-state-hover-chromium-linux.png | Adds zero-tabs hover visual regression snapshot (Chromium). |
| tests/suites/tenant/queryEditor/editorTabs.test.ts-snapshots/query-editor-zero-tabs-state-chromium-linux.png | Adds zero-tabs visual regression snapshot (Chromium). |
| tests/suites/tenant/queryEditor/editorTabs.test.ts | Adds E2E coverage for entering/exiting/restoring zero-tabs state and related flows. |
| src/types/assets.d.ts | Adds TypeScript module declarations for .scss/.css imports. |
| src/store/reducers/query/utils.ts | Updates persisted-state typing/guards to allow optional activeTabId. |
| src/store/reducers/query/types.ts | Updates QueryState.activeTabId typing to be optional. |
| src/store/reducers/query/slice.ts | Implements zero-tabs reducer behavior + persistence and updates selectors for optional active tab. |
| src/store/reducers/query/test/zeroTabsState.test.ts | Adds unit tests validating reducer + persistence behavior for zero-tabs. |
| src/store/reducers/query/test/SessionStorageMigration.test.ts | Adjusts migration tests to avoid relying on always-present activeTabId. |
| src/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx | Guards streaming abort logic when no active tab exists. |
| src/containers/Tenant/Query/QueryEditor/YqlEditor/YqlEditor.tsx | Adds guards for optional activeTabId in multi-tab editor effects/actions. |
| src/containers/Tenant/Query/QueryEditor/QueryEditorZeroTabsState.tsx | Adds the zero-tabs empty-state component. |
| src/containers/Tenant/Query/QueryEditor/QueryEditorZeroTabsState.scss | Styles for the zero-tabs empty-state component. |
| src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx | Switches between editor view and zero-tabs view based on tab presence; auto-creates tab in single-tab mode. |
| src/containers/Tenant/Query/QueryEditor/hooks/useQueryTabsActions.tsx | Makes tab action handlers resilient to missing active tab id (zero-tabs state). |
| src/containers/Tenant/Query/i18n/en.json | Adds i18n string for the zero-tabs empty-state CTA. |
|
Codex Review: Didn't find any major issues. Swish! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Closes #3767
Stand
CI Results
Test Status: ✅ PASSED
📊 Full Report
Test Changes Summary ✨10 🗑️1
✨ New Tests (10)
🗑️ Deleted Tests (1)
Bundle Size: 🔺
Current: 63.41 MB | Main: 63.40 MB
Diff: +7.39 KB (0.01%)
ℹ️ CI Information
Greptile Summary
This PR implements a zero-tabs empty state for the multi-tab query editor: when the last tab is closed, the editor area is replaced with a "Create new query" card instead of keeping a blank cleared tab. The change correctly makes
activeTabIdoptional throughout the state layer, adds defensivenullguards whereveractiveTabIdwas previously assumed to be present, persists and restores the zero-tabs state via session storage, and auto-recreates a tab in single-tab mode viauseLayoutEffect. Test coverage is thorough — 10 new E2E tests plus 3 new unit tests cover all key paths.Confidence Score: 5/5
Safe to merge — all logic paths are correctly guarded and covered by tests
The only finding is a P2 style concern (hardcoded waitForTimeout in a test utility). All state mutations, persistence, and UI rendering logic are correct and validated by both unit and E2E tests.
tests/utils/queryHotkeys.ts — minor: hardcoded sleep for KeyR+Alt synthetic event path
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[User closes tab] --> B{Is it the last tab?} B -- No --> C[Remove tab, switch to adjacent] B -- Yes --> D[Reset: activeTabId=undefined, tabsOrder empty, newTabCounter=0] D --> E[Persist zero-tabs state to sessionStorage] E --> F{isMultiTabEnabled?} F -- Yes --> G[Show ZeroTabsState card] F -- No --> H[useLayoutEffect calls handleNewTabClick] H --> I[New tab auto-created] G --> J{User action} J -- Click card --> K[handleNewTabClick dispatch] J -- Hotkey --> K K --> L[addQueryTab with title New Query] L --> M[hasTabs=true, render SplitPane editor] N[Page reload] --> O[Read sessionStorage] O --> P{activeTabId undefined AND tabsOrder empty?} P -- Yes --> Q[Restore zero-tabs state] P -- No --> R[Restore normal tabs]Comments Outside Diff (1)
tests/utils/queryHotkeys.ts, line 1291-1293 (link)page.waitForTimeout(300)is a fixed sleep added to let the syntheticKeyRevents propagate. A fixed pause can make the test suite unnecessarily slow and may still flake in heavily loaded CI environments. Consider replacing it with an explicit condition to wait on — e.g., polling for the rename dialog to appear — which is both faster and more robust.Prompt To Fix With AI
src/containers/Tenant/Query/QueryEditor/QueryEditorZeroTabsState.scss, line 300-301 (link)padding: 1px 5pxuses literal pixel values rather than design-token CSS variables (e.g.var(--g-spacing-1)/var(--g-spacing-2)). Using tokens keeps sizing consistent with the rest of the Gravity UI design system and makes theme-wide adjustments easier.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix All With AI
Reviews (2): Last reviewed commit: "fix: style" | Re-trigger Greptile