Skip to content

Commit 3b3867f

Browse files
docs: issue 62 prompt.
1 parent 43dca78 commit 3b3867f

2 files changed

Lines changed: 113 additions & 31 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Issue #62 Continuation Prompt: Pick Up Where We Left Off
2+
3+
Use this as the handoff prompt for continuing work on:
4+
https://github.com/knightedcodemonkey/develop/issues/62
5+
6+
## Prompt
7+
8+
You are resuming implementation for issue #62 in `@knighted/develop`.
9+
10+
### Goal
11+
12+
Finish the dynamic multi-tab workspace/editor refactor and close remaining
13+
behavior gaps without doing a broad visual redesign.
14+
15+
### Current project constraints
16+
17+
- Keep changes localized to `@knighted/develop`.
18+
- Preserve CDN-first runtime/fallback behavior.
19+
- Preserve existing lint/build pipeline.
20+
- Do not add dependencies without asking first.
21+
- Prefer focused, minimal diffs over broad rewrites.
22+
23+
### What is already done
24+
25+
- Dynamic workspace tabs exist with add, rename, remove, and local persistence.
26+
- Entry-role guard exists (entry tab cannot be removed).
27+
- Tab strip was moved to a dedicated full-width row in the editor area.
28+
- Tab visuals were updated toward IDE-like tabs.
29+
- Rename flow was hardened against re-entrant render races.
30+
- Add-tab naming prompt was removed in favor of generated default names.
31+
- Active tab is re-applied on startup to reduce initial-load drift.
32+
- Focus-based kind switching was removed from editor focus handlers.
33+
- `setActiveWorkspaceTabForKind` has been removed.
34+
- Lint/build were passing after the most recent structural change.
35+
36+
### Known remaining risk areas
37+
38+
- Residual component/styles lane assumptions still exist in `src/app.js`
39+
(for example cached loaded tab ids and kind-based branches).
40+
- App entry tab selection on initial load has historically been flaky.
41+
- Remove-tab fallback and active-tab/editor sync should stay strictly
42+
tab-id-driven.
43+
- Preview entry/hydration behavior must remain consistent with tab metadata.
44+
45+
### Required outcomes for this continuation
46+
47+
1. Make active tab id the single source of truth
48+
49+
- Eliminate or isolate remaining lane-coupled activation logic.
50+
- Ensure selecting a tab always controls visible editor content.
51+
52+
2. Preserve entry contract and startup determinism
53+
54+
- Entry tab path should remain `src/components/App.tsx` or `src/components/App.jsx`.
55+
- On first load/restore, App entry tab must be selectable and render correctly.
56+
57+
3. Keep one-visible-editor behavior stable
58+
59+
- Only one editor panel should be visible at a time.
60+
- Internal pooling can remain, but hidden editor focus/state must not mutate
61+
active tab.
62+
63+
4. Keep remove/add/rename flows coherent
64+
65+
- Remove fallback must be deterministic and tab-first.
66+
- Rename/add should not produce stale active state or content drift.
67+
68+
5. Clean dead branches introduced during migration
69+
70+
- Remove obsolete helpers and stale wiring once replacement paths are active.
71+
- Remove only clearly dead CSS/DOM hooks tied to removed behavior.
72+
73+
### Suggested execution sequence
74+
75+
1. Audit active-tab flow in `src/app.js`:
76+
77+
- `setActiveWorkspaceTab`
78+
- `loadWorkspaceTabIntoEditor`
79+
- remove-tab fallback logic
80+
- startup restore logic
81+
82+
2. Convert remaining kind-branch activation to tab-id-first selection.
83+
84+
3. Re-test high-risk interactions manually:
85+
86+
- initial load with App entry tab
87+
- select between multiple component and style tabs
88+
- add tab, rename tab, remove non-entry tab
89+
- switch style modes and verify preview keeps rendering
90+
91+
4. Run validation:
92+
93+
```bash
94+
npm run lint
95+
npm run build
96+
```
97+
98+
5. If behavior changed, update docs briefly in `docs/`.
99+
100+
### Definition of done
101+
102+
- App entry tab is reliably selectable on initial load.
103+
- No hidden-focus path can override active tab unexpectedly.
104+
- Active tab, visible editor, and persisted content stay in sync.
105+
- Remove/add/rename flows are stable and deterministic.
106+
- Lint/build pass.

src/app.js

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,22 +1331,6 @@ const setActiveWorkspaceTab = tabId => {
13311331
})
13321332
}
13331333

1334-
const setActiveWorkspaceTabForKind = kind => {
1335-
const normalizedKind = kind === 'styles' ? 'styles' : 'component'
1336-
const preferredId =
1337-
normalizedKind === 'styles' ? loadedStylesTabId : loadedComponentTabId
1338-
const preferredTab = workspaceTabsState.getTab(preferredId)
1339-
if (preferredTab && getTabKind(preferredTab) === normalizedKind) {
1340-
setActiveWorkspaceTab(preferredTab.id)
1341-
return
1342-
}
1343-
1344-
const fallbackTab = getWorkspaceTabByKind(normalizedKind)
1345-
if (fallbackTab) {
1346-
setActiveWorkspaceTab(fallbackTab.id)
1347-
}
1348-
}
1349-
13501334
const syncEditorFromActiveWorkspaceTab = () => {
13511335
const activeTab = getActiveWorkspaceTab()
13521336
if (!activeTab) {
@@ -1432,10 +1416,14 @@ const removeWorkspaceTab = tabId => {
14321416
const activeTab = getActiveWorkspaceTab()
14331417
if (activeTab) {
14341418
loadWorkspaceTabIntoEditor(activeTab)
1435-
} else if (removedKind === 'styles') {
1436-
setActiveWorkspaceTabForKind('component')
14371419
} else {
1438-
setActiveWorkspaceTabForKind('styles')
1420+
const fallbackTab =
1421+
getWorkspaceTabByKind(removedKind === 'styles' ? 'component' : 'styles') ||
1422+
workspaceTabsState.getTabs()[0] ||
1423+
null
1424+
if (fallbackTab) {
1425+
setActiveWorkspaceTab(fallbackTab.id)
1426+
}
14391427
}
14401428

14411429
renderWorkspaceTabs()
@@ -1996,9 +1984,6 @@ const initializeCodeEditors = async () => {
19961984
markTypeDiagnosticsStale()
19971985
markComponentLintDiagnosticsStale()
19981986
},
1999-
onFocus: () => {
2000-
setActiveWorkspaceTabForKind('component')
2001-
},
20021987
}),
20031988
createCodeMirrorEditor({
20041989
parent: cssHost,
@@ -2028,9 +2013,6 @@ const initializeCodeEditors = async () => {
20282013
maybeRender()
20292014
markStylesLintDiagnosticsStale()
20302015
},
2031-
onFocus: () => {
2032-
setActiveWorkspaceTabForKind('styles')
2033-
},
20342016
}),
20352017
])
20362018

@@ -2680,9 +2662,6 @@ jsxEditor.addEventListener('input', maybeRender)
26802662
jsxEditor.addEventListener('input', markTypeDiagnosticsStale)
26812663
jsxEditor.addEventListener('input', markComponentLintDiagnosticsStale)
26822664
jsxEditor.addEventListener('input', queueWorkspaceSave)
2683-
jsxEditor.addEventListener('focus', () => {
2684-
setActiveWorkspaceTabForKind('component')
2685-
})
26862665
jsxEditor.addEventListener('blur', () => {
26872666
void flushWorkspaceSave().catch(() => {
26882667
/* Save failures are already surfaced through saver onError. */
@@ -2691,9 +2670,6 @@ jsxEditor.addEventListener('blur', () => {
26912670
cssEditor.addEventListener('input', maybeRender)
26922671
cssEditor.addEventListener('input', markStylesLintDiagnosticsStale)
26932672
cssEditor.addEventListener('input', queueWorkspaceSave)
2694-
cssEditor.addEventListener('focus', () => {
2695-
setActiveWorkspaceTabForKind('styles')
2696-
})
26972673
cssEditor.addEventListener('blur', () => {
26982674
void flushWorkspaceSave().catch(() => {
26992675
/* Save failures are already surfaced through saver onError. */

0 commit comments

Comments
 (0)