Use modals instead of tabs for web history and changes #82
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
gtfs.zone/coloring-book#82
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Summary
Replace the three right-panel DaisyUI radio tabs (Browse, Files, Changes) with a simpler layout: Browse becomes the permanent right-panel content (no tabs), Files and History are opened from the navbar via buttons. The "History" button (renamed from "Changes") sits between the undo and redo buttons. Undo/redo get grey-out state and descriptive hover tooltips. Mobile dock gets "Changes" renamed to "History" and wired to open the modal instead of switching a tab.
The approach avoids creating/destroying the modal DOM on each open (which would break CodeMirror/the table editor) — instead both modals are persistent
<dialog>elements toggled open/closed, with the existing content divs moved inside them.Relevant Context
src/index.html— all the HTML changes: right panel tab structure, navbar buttons, modal elements, mobile docksrc/modules/ui.ts—initializeTabs(),handleTabChange(),showFileList(),showFileEditor(),showFileInEditor()all need updates; these target#file-list-viewand#file-editor-viewby ID, which work as long as the IDs stay the same inside the modalsrc/modules/history-controller.ts—render()targets#changes-panel; currently triggers onchanges-tab-radiochange event; needs to trigger on modal open insteadsrc/modules/tab-manager.ts—switchToTab()/getActiveTab()/onTabChange()all queryinput[name="main_tabs"]; after the tab radio inputs are removed these become no-ops. The class can stay but methods should be safe no-ops or stubs so callers don't break.src/modules/bottom-sheet.ts—setupDock()wires dock-files/dock-changes totabManager.switchToTab(); needs to open modals insteadsrc/modules/keyboard-shortcuts.ts—ctrl+1/2/3/4shortcuts callswitchToTab(); should be removed (no longer meaningful)src/index.ts—setupNavigationTabSwitching()callsswitchToTab('browse')and listens to tab change events; both become no-ops. Also importshumanLabel— reuse for undo/redo tooltips. The undo/redo buttons are wired viaonclickin HTML; state update logic (grey-out, tooltip) goes here, listening to patchManager events.src/modules/patch-manager.ts— hascanUndo: boolean,canRedo: boolean,version: number,getHistory()(async). Events:'change','undo','redo','jump'. UsegetHistory()to find the next undo/redo patch for tooltip text.Phases
Phase 1: HTML restructure
Goal: Strip the tab scaffolding from the right panel, add persistent modal elements for Files and History, and add the three new navbar buttons (Files icon, History, the existing undo/redo are already there but need wrapping adjustments).
<div class="tabs tabs-bordered …">wrapper and all three<input type="radio" name="main_tabs" …>elements from the right panelclass="tab hidden md:flex"inputs and theclass="tab-content …"wrapper divs — keep only the content divs that were inside them:#browse-list-viewand#object-details-viewbecome direct children of#right-panel(wrapped in aflex-1 overflow-hidden h-fulldiv)#file-list-viewand#file-editor-viewmove into the Files modal (see below)#changes-panelmoves into the History modal (see below)<dialog id="files-modal" class="modal">near the bottom of<body>containing:modal-boxwithw-11/12 max-w-2xl max-h-[90vh] flex flex-col p-0(generous size)#file-list-viewand#file-editor-viewmoved inside the modal body (they keep their IDs — UIController targets them by ID and will work unchanged)<dialog id="history-modal" class="modal">similarly:modal-boxwithmax-h-[80vh] overflow-y-auto#changes-panelinside the modal bodyid="files-btn") innavbar-end, before the undo/redo group:btn btn-ghost btn-sm btn-square,title="Files"id="history-btn") labeled "History":btn btn-ghost btn-sm, small text label "History" (no icon needed per issue)<div class="tooltip" id="undo-tooltip">and<div class="tooltip" id="redo-tooltip">withdata-tipset initially to"Nothing to undo"/"Nothing to redo". Keep existing button IDs.<span class="dock-label">Changes</span>→"History"and updateid="dock-changes"→ keep ID but the label changes (id is fine to keep; code references it)Gotcha:
#table-editor(the editor mount point) is inside#file-editor-view. Moving it into the modal is safe as long as it happens beforeEditor.initialize()runs — which it will, since both happen at page load. The Editor class mounts into#table-editoronce on init.Discoveries: Undo/redo buttons were given
disabledattribute by default (since nothing is undoable on fresh load); Phase 3 will enable/disable them dynamically. Both modals include a<form method="dialog" class="modal-backdrop">so clicking the backdrop closes them (standard DaisyUI pattern). Files button ishidden md:flexsince mobile uses the dock instead. History button is alsohidden md:flexfor the same reason.Phase 2: Wire Files and History modals in TypeScript
Goal: Make the new buttons open their respective modals, update UIController to work inside the modal, update HistoryController to render on modal open.
src/modules/ui.tsinitializeTabs()andhandleTabChange()entirely (no tab radios left)initializeTabs()call frominitialize()showFileList()— no change needed (still toggles hidden on#file-list-view/#file-editor-view)showFileEditor()— no change neededshowFileInEditor()— replaced the[data-tab-name="files"]click withfiles-modalshowModal()loadGTFSFile(), addedfiles-modalshowModal() afterthis.showFileList()#files-btnclick insetupEventListeners()— opens Files modal + callsupdateFileList()#back-to-files— already wired tothis.showFileList(), no change neededsrc/modules/history-controller.tschanges-tab-radioevent listener frominitialize()index.tswires#history-btnclick →showModal()+historyController.render()src/modules/tab-manager.tsswitchToTab()— safe no-op with deprecation warninggetActiveTab()— returns'browse'alwaysonTabChange()— no-opsrc/modules/bottom-sheet.tssetupDock()now acceptsopenHistoryModal: (() => void) | nullcallback (passed via constructor)openHistoryModal?.()this.open('half')with localupdateDockActivecalltabManager.onTabChange(updateDockActive)— dock-active updated locally on each clicksrc/modules/keyboard-shortcuts.tsctrl+1,ctrl+2,ctrl+3,ctrl+4tab-switching shortcutssrc/index.tssetupNavigationTabSwitching()— removedtabManager.switchToTab('browse')andtabManager.onTabChange()listener; onlybottomSheet?.open('half')remains#history-btnclick → opens history modal +historyController.render()<form method="dialog">backdrop (no extra JS needed)Phase 3: Undo/redo button state
Goal: Grey out undo/redo when unavailable; show a descriptive tooltip on hover with what will be undone/redone.
All changes in
src/index.ts:updateUndoRedoState()that:patchManager.canUndoandpatchManager.canRedodisabledattribute on#undo-btn/#redo-btn(nobtn-disabledclass needed —disabledattribute suffices)patchManager.getHistory()async, finds:version === patchManager.version(highest applied)version === patchManager.version + 1(first unapplied)data-tipon#undo-tooltip/#redo-tooltip:"Undo: ${humanLabel(patch)}"; unavailable:"Nothing to undo""Redo: ${humanLabel(patch)}"; unavailable:"Nothing to redo"updateUndoRedoState()on these patchManager events:'change','undo','redo','jump'updateUndoRedoState()once on startup (after patchManager is initialized) so buttons start in the correct state (likely disabled since nothing has been done yet)Gotcha:
btn-disabledin DaisyUI is a CSS class that visually disables but doesn't prevent click. Also set thedisabledHTML attribute on the<button>so theonclickhandler is suppressed. The existing undo/redo buttons useonclick="window.gtfsEditor?.undoEdit()"— settingdisabledon the button will suppress this naturally.Original Issue
The tabs aren't that great of an idiom for this. Lets use buttons in the top bar to open the file view and the history.
Mobile will not change significantly, besides names and such.