Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions components/navbar/ProjectNavbar.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,6 @@
background-color: var(--secondary-hover);
}

/* The "leave edit mode" checkmark: a filled pill that reads as the primary
* action of the edit-mode island, standing apart from the ghost undo/redo icons
* beside it via the inverted text colour. */
.edit_done {
color: var(--main-bg);
background-color: var(--primary-text);
}

/* The global `svg { color: var(--primary-text) }` rule targets the icon element
* directly, so it overrides the inverted `color` inherited from this pill and
* paints the checkmark the same shade as the pill's background (invisible in
* dark mode). Re-inherit the button's colour so the icon stays legible. */
.edit_done svg {
color: inherit;
}

.edit_done:hover {
background-color: var(--primary-text);
opacity: 0.85;
}

@media (max-width: 767px) {
.container {
/* Push the bar below the status bar / Dynamic Island. --navbar-height
Expand Down
2 changes: 1 addition & 1 deletion components/navbar/ProjectNavbarMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const ProjectNavbarMobile = () => {
keeps the left side empty. */}
{isInProject && projectId && mobileEditMode && (
<div className={navbar.mobile_left}>
<div className={`${navBtn.button} ${navbar.edit_done}`} onClick={exitEditMode}>
<div className={`${navBtn.button} ${navbar.mobile_icon}`} onClick={exitEditMode}>
<Check size={18} />
</div>
<div className={`${navBtn.button} ${navbar.mobile_icon}`} onClick={() => runHistory("undo")}>
Expand Down
15 changes: 15 additions & 0 deletions components/project/EditorFooter.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,19 @@
transform: translateX(-50%);
bottom: calc(16px + var(--safe-bottom));
}

/* Drop the page count on phone: it's redundant in the default endless-scroll
* reader and is the pill's widest element. Hiding it keeps the row a compact
* cluster of toggles that clears the bottom-left Edit (pen) button — without a
* width cap, which would clip the timer's live readout when it's running. */
.pages,
.divider {
display: none;
}

/* Roomier, thumb-friendly tap targets now that the row is short. */
.action {
width: 34px;
height: 32px;
}
}
20 changes: 19 additions & 1 deletion components/project/ProjectWorkspace.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useContext, useState } from "react";
import { useContext, useEffect, useState } from "react";
import { useViewContext } from "@src/context/ViewContext";
import { ProjectContext } from "@src/context/ProjectContext";
import { useActiveEditor } from "@src/lib/editor/use-active-editor";
Expand Down Expand Up @@ -31,6 +31,24 @@ const ProjectWorkspace = () => {
const isPhone = useIsPhone();
const activeEditor = useActiveEditor();

// iOS WKWebView anchoring guard. The app shell is pinned to the viewport
// (100vh, overflow hidden) and only the inner editor container is meant to
// scroll. But with the on-screen keyboard up, a contenteditable edit — most
// reproducibly deleting/joining an empty node — can make WebKit scroll the
// *document itself* to chase the caret. That drags the whole shell up: the
// (relatively positioned) navbar slides off the top and the editor looks
// unanchored. Nothing at the window level is ever supposed to scroll here, so
// snap it straight back to the top. The listener is on window and
// non-capturing, so it never fires for the inner container's own scroll.
useEffect(() => {
if (!isPhone) return;
const anchor = () => {
if (window.scrollY !== 0 || window.scrollX !== 0) window.scrollTo(0, 0);
};
window.addEventListener("scroll", anchor, { passive: true });
return () => window.removeEventListener("scroll", anchor);
}, [isPhone]);

// Enter edit mode and drop the caret into the reader's current editor so the
// keyboard comes up straight away. Focus must happen SYNCHRONOUSLY inside this
// tap gesture — iOS only raises the keyboard when focus() runs in the same
Expand Down
Loading