feat(redesign): [P7] integration overlay + mobile responsive breakpoints #6
Reference in New Issue
Block a user
Delete Branch "wt/redesign-integration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 7 of the ultra-todo Trello-style kanban redesign (parent t_c5294512)
Integration overlay that unifies P2 (data model + Jest), P3 (Board/List+CSS), P4 (Card+modal), P5 (@dnd-kit), and P6 (sidebar+topbar+empty states) into the final
wt/redesign-integrationbranch.What's in this branch (3 commits ahead of main, merge_base =
8628bcb)a023c53— import P2 data model + Jest setup + unified depssrc/lib/migrate.js— v1→v2 one-shot migration (P2)src/store/boardStore.js— canonicaluseBoardStorehook (P2 ratified)@dnd-kit+identity-obj-proxymerged into onepackage.jsonbabel.config.js,jest.config.js,jest.setup.js— canonical test harness81b3753— integrate P3+P4+P5+P6 components + new App.jsxsrc/components/Board.jsx— prop-driven, owns singleDndContext(PointerSensor 5px activation, KeyboardSensor, closestCorners). Wraps every SortableContext; sidebar lives outside the DnD tree.src/components/List.jsx,ListHeader.jsx— prop-driven (was P3's store-coupled; rewritten to fit prop-injection pattern).src/components/Card.jsx,CardDetailModal.jsx— P4 verbatim.src/lib/boardDnd.js— P5 reducer + ID helpers.src/store/boardStore.js—addBoard/addList/addCardnow return new ids so Sidebar can select the new entity immediately.src/components/AppShell.jsx,Sidebar.jsx,TopBar.jsx,EmptyState.jsx— P6 verbatim (stateless, prop-driven).src/App.jsx— final shell per spec: Sidebar + board area + FirstRunEmptyState / SelectBoardEmptyState / TopBar+Board.src/test/testUtils.jsx—renderWithStorehelper pre-seeds localStorage.TodoForm.jsx,TodoForm.css,TodoList.jsx,TodoList.css,TodoItem.jsx,TodoItem.css,useLocalStorage.js,App.css. Verified: zero references to these names remain insrc/ordist/.86651b8— refactor boardStore to singleton + App smoke testboardStore.js: refactored to module-level singleton viauseSyncExternalStore. Test isolation via__resetStore/__setState/__setPersistOnChange.jest.config.js: addedmoduleNameMapperfor CSS +transformIgnorePatternsfor@dnd-kitESM.jest.setup.js:matchMediapolyfill + localStorage + singleton reset between tests.src/App.test.jsx— top-level smoke test (4 scenarios):<App />with seeded store → sidebar + topbar + board + list all in DOM+ Create boardflow → board appears and becomes activeAcceptance checklist
npm test— 119/119 pass across 15 suites (P2 store + migration, P3 Board/List/ListHeader, P4 Card/Modal, P5 BoardDnD + DnDFixtureBoard, P6 Sidebar/TopBar/AppShell, plus new App smoke test)npm run build— green, 265 kB JS / 13 kB CSS (83 kB / 3 kB gzipped)TodoForm,TodoList,TodoItem,useLocalStorageremain insrc/or production bundleDndContextlives at<Board />level — wraps all SortableContexts but NOT the sidebarSidebar.css@media (max-width: 768px)+TopBarhamburger toggle)wt/redesign-integrationpushed to origin (head SHA86651b8)Pitfalls addressed
boardStore.jsxuseduseSyncExternalStore+ Context. P2's useduseState. P7 picks P2's pattern (orchestrator-ratified), rewrites P3 components to be prop-driven so they consumestate + actionsfrom App.jsx rather than self-subscribing.useLocalStorage('ultra-todo-v2-state', ...). Replaced withuseBoardStore()singleton in App.jsx; P6's AppShell/Sidebar/TopBar kept as-is (already prop-driven, decoupled from the store).<Board />(not App, not per-list) — single context wraps all SortableContexts. Sidebar's draggable buttons (aria-label="Drag card...") are outside the DnD tree as required.__resetStore+localStorage.clear()inbeforeEachkeeps the singleton from leaking state between tests.renderWithStorepre-seeds localStorage souseBoardStore's initializer sees the test data.npm testflakiness from singletons: handled by resetting injest.setup.jsglobal before-each.Files changed vs main
52 files changed, +12,265 / -1,446. Full list in
compare/main...wt/redesign-integration.Manual smoke procedure (for reviewer)
Known follow-ups (out of scope)
Closes #1, #2, #3, #4, #5 once merged.
- boardStore.js: refactored from per-component useState to a module-level singleton via useSyncExternalStore. All callers share state (true singleton). Exposes __resetStore/__setState/__setPersistOnChange for test isolation. addBoard/addList/addCard still return the new id (computed from post-action state). - jest.config.js: added moduleNameMapper for CSS (identity-obj-proxy) + transformIgnorePatterns for @dnd-kit ESM modules. - jest.setup.js: stub window.matchMedia for AppShell, clear localStorage + reset store singleton before each test. - src/test/testUtils.jsx: renderWithStore now wraps the UI in a Host that calls useBoardStore and clones the child element to inject { state, actions } as props. Returns result.state/result.actions getters so tests can read state and invoke actions from outside. - src/components/List.test.jsx: Host accepts state/actions props and falls back to useBoardStore for standalone use. - src/components/ListHeader.test.jsx + Board.test.jsx: updated to new result.state API (was store.getState() in P3's API). - src/App.jsx: final spec wiring — sidebar + board area + TopBar + Board + empty states (first-run + select-board). Reads from useBoardStore, passes state + actions down to AppShell + Board. - src/App.test.jsx: smoke test — sidebar + topbar + board + lists render when seeded; +Create board flow creates a board and activates it; first-run and select-board empty states render correctly; mobile breakpoint shows hamburger. All 119 tests pass across 15 suites. npm run build green.Pull request closed