Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/arverma/Bihar-Police-Notebook/llms.txt

Use this file to discover all available pages before exploring further.

The editor shell is the fixed application chrome that wraps the A4 page preview. Every pixel of the UI lives in editor/index.html, styled by editor/css/tokens.css, layout-shell.css, and header-responsive.css. There is no server-side rendering — the shell is a static HTML file that main.js brings to life entirely in the browser.

Layout Regions

The DOM tree resolves into five named regions, each with a distinct responsibility:
body.app-shell
├── Fixed header
└── .app-body
    ├── #sidebar  (History sidebar)
    └── main.main-content
        └── #editorStage  (editor-stage)

Fixed Header

Contains the History toggle button, brand mark, document name input (#filenameInput), Letter / Diary template switcher (#templateSegment), PDF export button (#exportBtn), and — on screens wider than 768 px — the Hindi Typing toggle (#translitToggle).

History Sidebar

Houses the document list (.history-list), the Drive backup icon (#backupBtn) with its dropdown menu (#driveMenu), and the New document button (.add-template-btn).

main-content

The vertical scroll port on desktop. Receives top-padding equal to --chrome-top so content is never hidden behind the fixed header. syncChromeTop() in main.js keeps this custom property in sync with the header’s actual rendered height via ResizeObserver.

editor-stage

Hosts the page preview (page-scale.js scale wrapper). On mobile it also owns scroll and pinch-zoom; see Page Preview.

Orchestration via main.js

editor/js/main.js is the single entry point. On DOMContentLoaded it calls initApp(), which:
  1. Initialises Letter (initPagedSheet) and Diary (initDiarySheet) template modules.
  2. Wires autosave, template switching, filename resizing, and page indicator updates.
  3. Boots Drive auth (initDriveAuth) and subscribes to onAuthChange / onSyncStatusChange.
  4. Restores the last-active document from localStorage keys lastActiveDocId / lastActiveDocType.
  5. Attaches the attachTransliteration listener to every editable field.
  6. Initialises the page-scale controller and dictation FAB.

Header Controls

The #templateSegment segmented control contains two .segment-btn elements with data-template="letter" and data-template="diary". Clicking one calls switchTemplate(template) in main.js, which flushes any pending autosave, then calls startNewDocument(template) and reloads the history list.
document.querySelectorAll('#templateSegment .segment-btn').forEach((btn) => {
  btn.addEventListener('click', () => {
    switchTemplate(btn.dataset.template);
  });
});

History Sidebar

Opening and Closing

The sidebar opens and closes only through the .switch-btn panel toggle, Ctrl/Cmd+H, or Ctrl/Cmd+B. There is no outside-click-to-close — a deliberate UX choice to prevent accidental dismissal while typing.
// Keyboard shortcut (main.js)
if (e.key === 'h' || e.key === 'H' || e.key === 'b' || e.key === 'B') {
  if (typing) return;
  e.preventDefault();
  setSidebarOpen(!isToggled);
}
Opening the sidebar adds .sidebar-open to body and .open to #sidebar. The layout shell CSS nudges the workspace slightly to accommodate the panel width — main content is not shifted via a class; the recentering is handled by CSS grid/flex rules in layout-shell.css. The last state is persisted in localStorage (historySidebarOpen).

Document Grouping

Documents are fetched via getDocuments(type) (see Storage) and grouped by created_at date. The renderHistory(docs) function in main.js builds collapsible date sections:
  • The most recent day group starts expanded (arrow points down ▼).
  • Older day groups start collapsed (arrow points right ▶).
  • Each document row shows filename, updated_at time (or a short date if different from the group date), a previewText snippet, and a Drive sync badge when Drive is connected.
const isRecentGroup = groupIndex === 0;
itemsContainer.classList[isRecentGroup ? 'remove' : 'add']('collapsed');

Drive Backup Menu

The #backupBtn in the sidebar header has four visual states driven by data-backup:
data-backup valueMeaning
needs-authNot connected — clicking starts OAuth flow then runs syncAll()
readyConnected and idle — clicking opens the dropdown menu
syncingOperation in progress — spinner shown, button disabled
errorLast operation failed — clicking retries connect+sync
The dropdown offers Sync all (syncAll()), Sync new (pushPending()), and Disconnect (disconnectDrive()).

Scroll Ownership

Scroll behavior is split by breakpoint to give the best experience on each device class.
.editor-stage has overflow: visible. Mouse-wheel events propagate up to .main-content, which is the actual scrolling container. This means the entire page (header, stage, footer) scrolls as one unit.
/* layout-shell.css (desktop) */
.main-content { overflow-y: auto; }
#editorStage  { overflow: visible; }
The pageScale.refresh() call in loadDocumentState and startNewDocument re-computes the fit-to-width scale after the content changes, keeping the scroll geometry consistent.

CSS Architecture

FileScope
tokens.cssDesign tokens: colors, spacing, font sizes, z-index ladder
layout-shell.cssBody grid, sidebar dimensions, main-content / editor-stage layout rules, breakpoint overrides
header-responsive.cssHeader flex layout, hide/show rules for the translit toggle and page indicator at various breakpoints
The --chrome-top CSS custom property must always reflect the header’s current rendered height. If you add content to the header that changes its height, call syncChromeTop() — or rely on the ResizeObserver that already watches .header-frame.

Build docs developers (and LLMs) love