Skip to content

Add mobile web responsive layout#5

Merged
auerbachb merged 5 commits into
mainfrom
issue-2-mobile-responsive
Feb 26, 2026
Merged

Add mobile web responsive layout#5
auerbachb merged 5 commits into
mainfrom
issue-2-mobile-responsive

Conversation

@auerbachb
Copy link
Copy Markdown
Owner

@auerbachb auerbachb commented Feb 26, 2026

Summary

  • Fixes Mobile web optimized layout #2
  • Hybrid approach: CSS min() for fluid maxWidths (~25 one-line fixes) + useIsMobile() hook for structural layout changes (nav, block grid, history rows)
  • 600px breakpoint targets all phones, leaves tablets/desktop untouched
  • 13 files changed, 1 new file (useIsMobile.ts)

Key changes

  • useIsMobile hook: matchMedia-based, SSR-safe (defaults false, hydrates client-side)
  • Nav bar: Fixed bottom bar on mobile with backdrop-filter: blur, env(safe-area-inset-bottom), space-around layout. Username badge hidden on mobile.
  • BlockTimer: Fluid countdown font (min(120px, 18vw)), progress bar, and block grid (56px blocks on mobile vs 75px desktop)
  • HistoryView (most complex): Date column hidden on mobile, stats row wraps 2x2, expanded thoughts margin reduced
  • SessionView: Button row wraps, touchstart listener added for mobile auto-hide
  • All components: maxWidth values use min() to prevent overflow on 375px screens

Test plan

  • npm run build passes (verified locally)
  • Chrome DevTools device toolbar: iPhone SE (375px) — all views render without horizontal overflow
  • Auth, home, session/timer, completion, history, journal, board, settings all usable on mobile
  • Desktop layout unchanged at full width
  • Bottom nav bar visible and functional on mobile, hidden on desktop
  • Timer blocks display 4-per-row on mobile, normal grid on desktop

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Mobile-aware UI: fixed, blurred bottom navigation on small screens; desktop retains top-right nav.
    • Client-side mobile detection powering conditional UI (hides username badge and some date labels on mobile).
  • Improvements

    • Responsive layouts and typography across views, timers, progress bars and blocks for better small-screen fit.
    • Condensed spacing, wrapping behavior, and improved touch responsiveness in session controls.

Hybrid approach: CSS min() for fluid maxWidths + useIsMobile() hook
for structural layout changes. 600px breakpoint targets phones only.

Key changes:
- New useIsMobile hook (matchMedia-based, SSR-safe)
- Mobile fixed bottom nav bar with backdrop blur + safe-area-inset
- Fluid countdown font, progress bar, and block grid sizing
- History view: hidden date column, wrapped stats, smaller margins
- All component maxWidths use min() to prevent overflow on 375px screens
- Added touchstart listener for mobile auto-hide controls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de88e25 and 09ca422.

📒 Files selected for processing (13)
  • src/app/page.tsx
  • src/components/AuthScreen.tsx
  • src/components/BlockTimer.tsx
  • src/components/CompletionScreen.tsx
  • src/components/HistoryView.tsx
  • src/components/HomeView.tsx
  • src/components/MindStateBar.tsx
  • src/components/PublicBoard.tsx
  • src/components/SessionView.tsx
  • src/components/SettingsView.tsx
  • src/components/ThoughtCapture.tsx
  • src/components/ThoughtJournal.tsx
  • src/lib/useIsMobile.ts

📝 Walkthrough

Walkthrough

Adds a client-side useIsMobile hook and applies mobile-aware responsive sizing and conditional UI across multiple components; moves the top-right navigation to a fixed, blurred bottom bar on mobile, hides the username badge on small screens, and adjusts touch targets, widths, and typography for narrow viewports.

Changes

Cohort / File(s) Summary
Mobile Detection Infrastructure
src/lib/useIsMobile.ts
New client hook useIsMobile() using window.matchMedia("(max-width: 600px)") with a change listener; returns boolean isMobile.
App Shell / Navigation
src/app/page.tsx
Imports useIsMobile; makes container padding mobile-aware; top-right nav becomes a fixed, blurred bottom bar on mobile with safe-area padding; username badge hidden when isMobile.
Timer & Progress UI
src/components/BlockTimer.tsx, src/components/MindStateBar.tsx
Replaced fixed block sizes, large countdown font, and fixed bar widths with isMobile-derived sizes or min(..., calc(100vw - ...)) expressions for responsive sizing.
History & Day Lists
src/components/HistoryView.tsx
Adds useIsMobile; converts fixed widths/gaps to responsive values; hides date/today labels on mobile; adjusts margins, column widths, and gaps for narrow screens.
Content / Forms Responsive Constraints
src/components/AuthScreen.tsx, src/components/CompletionScreen.tsx, src/components/HomeView.tsx, src/components/SettingsView.tsx, src/components/ThoughtCapture.tsx
Replaced fixed maxWidth values with responsive min(..., calc(100vw - ...)) constraints to allow shrinking on small viewports.
Thought & Public Boards
src/components/ThoughtJournal.tsx, src/components/PublicBoard.tsx
Converted fixed max-widths to viewport-aware expressions; PublicBoard added a containerStyle constant and applies it to wrapper elements.
Session Interaction Tweaks
src/components/SessionView.tsx
Adds a passive touchstart listener for resetTimer on mount/cleanup and updates bottom control layout to reduce gaps and enable wrapping.
Minor UI tweaks / consistency
src/components/CompletionScreen.tsx, src/components/HomeView.tsx, src/components/AuthScreen.tsx
Various typography and layout adjustments to align with mobile sizing changes (see individual files).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped through pixels, soft and small,

nudged nav below for phones that call,
shrank the bars, widened the tap,
snugged each block, adjusted gap,
a little hop — the layout's all.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add mobile web responsive layout' accurately describes the primary objective of the changeset, which implements responsive design changes across the codebase.
Linked Issues check ✅ Passed The PR successfully addresses all main coding requirements from issue #2: responsive block sizing, adaptive font scaling, fixed bottom nav on mobile with badge hiding, responsive progress bars, mobile-optimized history view, wrappable controls, responsive container widths, and SSR-safe mobile detection.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #2 requirements: responsive layout adjustments, mobile hook implementation, and viewport-aware styling. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue-2-mobile-responsive

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/page.tsx`:
- Around line 226-236: The mobile flash happens because isMobile (from
useIsMobile) is false during SSR and flips on mount; to fix, either (A) move
positioning out of JS and into CSS media queries (replace the inline style logic
on the div with className toggles and create CSS rules that position the nav at
bottom for small screens and top-right for large screens), or (B) delay the
mobile/desktop switch until after hydration by adding a local hydrated flag
(e.g., const [hydrated, setHydrated] = useState(false); useEffect(() =>
setHydrated(true), [])) and only apply the isMobile-based styles when hydrated
(leave a neutral hidden/placeholder state or the CSS default during SSR). Update
the div that currently uses isMobile inline styles to use the chosen approach so
initial SSR output matches hydrated layout and avoids the layout jump.

In `@src/components/BlockTimer.tsx`:
- Around line 45-47: BlockTimer currently computes blockSize and blockLabelSize
using useIsMobile (isMobile) which is false during SSR, causing a hydration
flash from desktop to mobile sizes; remove the JS-driven sizing and move sizes
into CSS via custom properties and media queries instead: stop using
blockSize/blockLabelSize for layout, add CSS custom properties (e.g.,
--block-size, --block-label-size) with desktop defaults and override them in a
`@media` (max-width:...) rule, and have the BlockTimer markup (component using
useIsMobile) read sizes from CSS (or simply rely on CSS rules) so hydration uses
the same sizes as the client; update references to blockSize/blockLabelSize in
the BlockTimer component to use CSS-based sizing.

In `@src/components/PublicBoard.tsx`:
- Around line 30-31: PublicBoard duplicates the same inline wrapper style at two
places (around the loading and loaded layouts); extract that shared style into a
single constant (e.g., wrapperStyle or containerStyle) at the top of the
PublicBoard component file and replace both inline style occurrences with that
constant so the loading and loaded UIs stay aligned; update any JSX that
currently sets style={{ gap: "32px", animation: "fadeIn 0.6s ease", width:
"100%", maxWidth: "min(560px, calc(100vw - 24px))" }} to use the new shared
identifier.

In `@src/components/SessionView.tsx`:
- Around line 57-63: The touchstart listener in SessionView.tsx is added without
the passive option; update the window.addEventListener("touchstart", resetTimer)
call to use a passive listener (e.g., window.addEventListener("touchstart",
resetTimer, { passive: true })) and ensure the corresponding cleanup uses the
same options object when calling window.removeEventListener("touchstart",
resetTimer, { passive: true }) so the listener is removed correctly; locate
references to resetTimer and hideTimerRef.current in the file to apply this
change.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de88e25 and 0d51bce.

📒 Files selected for processing (13)
  • src/app/page.tsx
  • src/components/AuthScreen.tsx
  • src/components/BlockTimer.tsx
  • src/components/CompletionScreen.tsx
  • src/components/HistoryView.tsx
  • src/components/HomeView.tsx
  • src/components/MindStateBar.tsx
  • src/components/PublicBoard.tsx
  • src/components/SessionView.tsx
  • src/components/SettingsView.tsx
  • src/components/ThoughtCapture.tsx
  • src/components/ThoughtJournal.tsx
  • src/lib/useIsMobile.ts

Comment thread src/app/page.tsx
Comment thread src/components/BlockTimer.tsx
Comment thread src/components/PublicBoard.tsx Outdated
Comment thread src/components/SessionView.tsx Outdated
Comment on lines 57 to 63
window.addEventListener("touchstart", resetTimer);
return () => {
window.removeEventListener("mousemove", resetTimer);
window.removeEventListener("mousedown", resetTimer);
window.removeEventListener("keydown", resetTimer);
window.removeEventListener("touchstart", resetTimer);
if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/components/SessionView.tsx | sed -n '50,70p'

Repository: auerbachb/still-point

Length of output: 1078


🏁 Script executed:

cat -n src/components/SessionView.tsx | sed -n '1,100p'

Repository: auerbachb/still-point

Length of output: 4673


🏁 Script executed:

rg "touchstart" --type=ts --type=tsx -A 2 -B 2

Repository: auerbachb/still-point

Length of output: 92


🏁 Script executed:

web_search
removeEventListener options parameter typescript

Repository: auerbachb/still-point

Length of output: 173


🏁 Script executed:

rg "touchstart" -t ts -A 2 -B 2

Repository: auerbachb/still-point

Length of output: 864


🌐 Web query:

removeEventListener options parameter removeEventListener with passive option

💡 Result:

removeEventListener() does not need (and does not match on) the passive flag. To remove a listener, browsers/spec only match on:

  • type
  • the same function reference (listener)
  • capture (aka useCapture) only (must match) [1][2]

So these are equivalent for removal (as long as capture: false was used when adding):

el.addEventListener("touchmove", onMove, { passive: true });

el.removeEventListener("touchmove", onMove);                 // OK
el.removeEventListener("touchmove", onMove, { passive: true }); // OK (passive ignored)
el.removeEventListener("touchmove", onMove, { capture: false }); // OK
el.removeEventListener("touchmove", onMove, { capture: true });  // NOT removed

If you added with capture: true, you must remove with capture: true [1][2].

Sources: MDN removeEventListener() (matching rules) [1]; WHATWG DOM Standard (removal uses only flattened capture) [2].


Add passive option to touchstart listener to prevent scroll-blocking warnings on mobile.

Line 57 adds a touchstart handler without the passive option. Since resetTimer doesn't call preventDefault(), this handler should be marked passive to avoid scroll-jank warnings and improve responsiveness on mobile devices.

🔧 Suggested fix
-    window.addEventListener("touchstart", resetTimer);
+    window.addEventListener("touchstart", resetTimer, { passive: true });
     return () => {
       window.removeEventListener("mousemove", resetTimer);
       window.removeEventListener("mousedown", resetTimer);
       window.removeEventListener("keydown", resetTimer);
-      window.removeEventListener("touchstart", resetTimer);
+      window.removeEventListener("touchstart", resetTimer, false);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
window.addEventListener("touchstart", resetTimer);
return () => {
window.removeEventListener("mousemove", resetTimer);
window.removeEventListener("mousedown", resetTimer);
window.removeEventListener("keydown", resetTimer);
window.removeEventListener("touchstart", resetTimer);
if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
window.addEventListener("touchstart", resetTimer, { passive: true });
return () => {
window.removeEventListener("mousemove", resetTimer);
window.removeEventListener("mousedown", resetTimer);
window.removeEventListener("keydown", resetTimer);
window.removeEventListener("touchstart", resetTimer, false);
if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/SessionView.tsx` around lines 57 - 63, The touchstart listener
in SessionView.tsx is added without the passive option; update the
window.addEventListener("touchstart", resetTimer) call to use a passive listener
(e.g., window.addEventListener("touchstart", resetTimer, { passive: true })) and
ensure the corresponding cleanup uses the same options object when calling
window.removeEventListener("touchstart", resetTimer, { passive: true }) so the
listener is removed correctly; locate references to resetTimer and
hideTimerRef.current in the file to apply this change.

- Add { passive: true } to touchstart listener in SessionView
- Extract shared containerStyle in PublicBoard to avoid drift

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Full review triggered.

@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/PublicBoard.tsx (1)

63-66: 🧹 Nitpick | 🔵 Trivial

Consider responsive grid columns for very narrow viewports.

The grid's fixed column widths (32px 1fr 64px 64px 64px + 48px gaps + 24px padding ≈ 296px minimum) leave only ~55px for the username column on 375px screens. This works but may truncate longer usernames.

If mobile usability testing reveals issues, consider using useIsMobile to conditionally hide a column (e.g., streak) or reduce column widths on mobile, consistent with how HistoryView hides the date column. Based on learnings, hook-based responsive logic is preferred for structural layout changes in this codebase.

Also applies to: 83-86

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/PublicBoard.tsx` around lines 63 - 66, The grid in the
PublicBoard component uses fixed column widths via the inline style
gridTemplateColumns (currently "32px 1fr 64px 64px 64px"), which can squeeze the
username column on small screens; update PublicBoard to use the useIsMobile hook
to compute a responsive gridTemplateColumns string or conditionally hide the
less-important column(s) (e.g., the streak column) when isMobile is true, and
apply that computed value to the same div style where gridTemplateColumns is set
(also update the corresponding row rendering code that shows the streak column
so it is omitted when hidden), mirroring the pattern used in HistoryView for
hiding the date column on mobile.
src/components/HistoryView.tsx (1)

269-275: 🧹 Nitpick | 🔵 Trivial

Verify expanded thoughts alignment when date column is hidden.

The left margin for expanded thoughts changes from 216px (desktop) to 44px (mobile). The desktop value (216px) accounts for the 160px date label + 32px day number + gaps, but the mobile value (44px) should align with just the 32px day number column plus the 8px gap (= 40px). Consider adjusting to 40px for pixel-perfect alignment, though the 4px difference is minor.

💅 Optional alignment fix
                  <div style={{
-                    marginLeft: isMobile ? "44px" : "216px", marginTop: "4px", marginBottom: "8px",
+                    marginLeft: isMobile ? "40px" : "216px", marginTop: "4px", marginBottom: "8px",
                     padding: "10px 14px", background: "rgba(232,228,222,0.02)",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/HistoryView.tsx` around lines 269 - 275, The expanded thoughts
container uses marginLeft: isMobile ? "44px" : "216px" which misaligns the
mobile view; update the mobile marginLeft to "40px" so the expanded thoughts
align with the 32px day-number column plus the 8px gap. Locate the JSX block
that checks expandedDay === entry.day and uses dayThoughts.length > 0 (the
inline style object) and change the isMobile ? "44px" value to "40px" while
keeping the desktop 216px value unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/SettingsView.tsx`:
- Line 49: The inline style for the SettingsView width uses maxWidth:
"min(400px, calc(100vw - 24px))" which creates 12px horizontal margins
inconsistent with the app's standard calc(100vw - 40px) (20px margins); update
the maxWidth expression in the SettingsView component to "min(400px, calc(100vw
- 40px))" so it matches the other components and maintains consistent horizontal
spacing.

---

Outside diff comments:
In `@src/components/HistoryView.tsx`:
- Around line 269-275: The expanded thoughts container uses marginLeft: isMobile
? "44px" : "216px" which misaligns the mobile view; update the mobile marginLeft
to "40px" so the expanded thoughts align with the 32px day-number column plus
the 8px gap. Locate the JSX block that checks expandedDay === entry.day and uses
dayThoughts.length > 0 (the inline style object) and change the isMobile ?
"44px" value to "40px" while keeping the desktop 216px value unchanged.

In `@src/components/PublicBoard.tsx`:
- Around line 63-66: The grid in the PublicBoard component uses fixed column
widths via the inline style gridTemplateColumns (currently "32px 1fr 64px 64px
64px"), which can squeeze the username column on small screens; update
PublicBoard to use the useIsMobile hook to compute a responsive
gridTemplateColumns string or conditionally hide the less-important column(s)
(e.g., the streak column) when isMobile is true, and apply that computed value
to the same div style where gridTemplateColumns is set (also update the
corresponding row rendering code that shows the streak column so it is omitted
when hidden), mirroring the pattern used in HistoryView for hiding the date
column on mobile.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de88e25 and f138ae3.

📒 Files selected for processing (13)
  • src/app/page.tsx
  • src/components/AuthScreen.tsx
  • src/components/BlockTimer.tsx
  • src/components/CompletionScreen.tsx
  • src/components/HistoryView.tsx
  • src/components/HomeView.tsx
  • src/components/MindStateBar.tsx
  • src/components/PublicBoard.tsx
  • src/components/SessionView.tsx
  • src/components/SettingsView.tsx
  • src/components/ThoughtCapture.tsx
  • src/components/ThoughtJournal.tsx
  • src/lib/useIsMobile.ts

Comment thread src/components/SettingsView.tsx Outdated
Align SettingsView with other narrow components using 40px margin
pattern instead of 24px (which is reserved for wider layouts).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/HistoryView.tsx`:
- Line 94: The inline style in HistoryView.tsx uses maxWidth: "min(720px,
calc(100vw - 24px))" (seen in the style object around the HistoryView component)
which is inconsistent with the calc(100vw - 40px) used elsewhere; update both
occurrences (the one at the gap/width line and the second at line ~111) to use
calc(100vw - 40px) for consistent 20px side margins (or explicitly document why
HistoryView should be wider if you want to keep 24px).

In `@src/components/ThoughtJournal.tsx`:
- Line 36: The inline style for the ThoughtJournal component uses maxWidth:
"min(560px, calc(100vw - 24px))" which mismatches the app's common margin
pattern; update the maxWidth expression in the ThoughtJournal styles (look for
the style object in the ThoughtJournal component) to use calc(100vw - 40px) so
it reads maxWidth: "min(560px, calc(100vw - 40px))" for consistency with other
components, or if the 24px value is intentional add a brief comment in the
component explaining the different margin choice.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de88e25 and 84d944b.

📒 Files selected for processing (13)
  • src/app/page.tsx
  • src/components/AuthScreen.tsx
  • src/components/BlockTimer.tsx
  • src/components/CompletionScreen.tsx
  • src/components/HistoryView.tsx
  • src/components/HomeView.tsx
  • src/components/MindStateBar.tsx
  • src/components/PublicBoard.tsx
  • src/components/SessionView.tsx
  • src/components/SettingsView.tsx
  • src/components/ThoughtCapture.tsx
  • src/components/ThoughtJournal.tsx
  • src/lib/useIsMobile.ts

<div style={{
display: "flex", flexDirection: "column", alignItems: "center",
gap: "32px", animation: "fadeIn 0.6s ease", width: "100%", maxWidth: "720px",
gap: "32px", animation: "fadeIn 0.6s ease", width: "100%", maxWidth: "min(720px, calc(100vw - 24px))",
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Minor margin inconsistency.

The calc(100vw - 24px) pattern (12px margins) differs from the calc(100vw - 40px) (20px margins) used in most other components. This appears on lines 94 and 111. Consider aligning for consistency, or document as intentional if wider content is desired for the history view.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/HistoryView.tsx` at line 94, The inline style in
HistoryView.tsx uses maxWidth: "min(720px, calc(100vw - 24px))" (seen in the
style object around the HistoryView component) which is inconsistent with the
calc(100vw - 40px) used elsewhere; update both occurrences (the one at the
gap/width line and the second at line ~111) to use calc(100vw - 40px) for
consistent 20px side margins (or explicitly document why HistoryView should be
wider if you want to keep 24px).

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional — this is a two-tier margin system: wider layout components (HistoryView 720px, PublicBoard 560px, ThoughtJournal 560px, BlockTimer row 505px) all consistently use calc(100vw - 24px) (12px margins) because they have denser content that benefits from the extra horizontal space on small screens. Narrower components (≤400px) use calc(100vw - 40px) (20px margins) for more breathing room.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@auerbachb, thank you for clarifying! That makes perfect sense—the two-tier margin system provides a more spacious layout for denser content on wider components while maintaining breathing room on narrower ones. I appreciate the detailed explanation of the design rationale.


✏️ Learnings added
Learnt from: auerbachb
Repo: auerbachb/still-point PR: 5
File: src/components/HistoryView.tsx:94-94
Timestamp: 2026-02-26T18:16:28.000Z
Learning: In the still-point repository, a two-tier responsive margin system is used intentionally: wider layout components (HistoryView 720px, PublicBoard 560px, ThoughtJournal 560px, BlockTimer row 505px) consistently use `calc(100vw - 24px)` (12px side margins) because their denser content benefits from extra horizontal space on small screens, while narrower components (≤400px) use `calc(100vw - 40px)` (20px side margins) for more breathing room. This is not an inconsistency but a deliberate design pattern.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: auerbachb
Repo: auerbachb/still-point PR: 5
File: src/app/page.tsx:226-236
Timestamp: 2026-02-26T17:56:03.752Z
Learning: In TypeScript React components (any .tsx file), prefer hook-based responsive logic (e.g., useIsMobile) over CSS media query classes to maintain pattern consistency and keep styling logic co-located with components. During reviews, look for inline styles or CSS class utilities driven by media queries and consider refactoring to component-scoped responsive hooks; avoid spreading responsive decisions across global styles. This guideline applies broadly to TSX files, not just the specific file mentioned.

Comment thread src/components/ThoughtJournal.tsx
@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/page.tsx`:
- Around line 226-233: The mobile bottom nav's inline style (the isMobile ? {
... } : { ... } block) currently sets layout but doesn't ensure touch-safe hit
areas; update the styles for the nav buttons inside that container (e.g., the
elements rendered as primary nav buttons within the isMobile branch) to
guarantee a minimum touch target of 44x44px—either by adding
padding/min-width/min-height or explicit width/height on the button elements and
centering their content (use minWidth: 44, minHeight: 44, padding: '10px',
boxSizing: 'content-box' or similar). Apply the same change to the other mobile
nav style block referenced in the file so both mobile toolbars enforce the 44×44
touch target.

In `@src/components/CompletionScreen.tsx`:
- Line 83: The inline style in CompletionScreen's container uses maxWidth:
"min(350px, calc(100vw - 48px))" which creates 24px side margins and breaks the
established pattern; update the style on the container (the object with
textAlign, maxWidth, margin) to use calc(100vw - 40px) for consistency with the
≤500px components (i.e., change the maxWidth expression from calc(100vw - 48px)
to calc(100vw - 40px)), unless the 48px value was intentionally chosen for
visual emphasis — in that case, leave a comment explaining the intent.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de88e25 and 84d944b.

📒 Files selected for processing (13)
  • src/app/page.tsx
  • src/components/AuthScreen.tsx
  • src/components/BlockTimer.tsx
  • src/components/CompletionScreen.tsx
  • src/components/HistoryView.tsx
  • src/components/HomeView.tsx
  • src/components/MindStateBar.tsx
  • src/components/PublicBoard.tsx
  • src/components/SessionView.tsx
  • src/components/SettingsView.tsx
  • src/components/ThoughtCapture.tsx
  • src/components/ThoughtJournal.tsx
  • src/lib/useIsMobile.ts

Comment thread src/app/page.tsx
Comment thread src/components/CompletionScreen.tsx Outdated
- Add 44x44px minimum touch targets for mobile nav buttons
- Fix CompletionScreen thoughts margin to match 40px pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/page.tsx`:
- Around line 222-223: The mobile root padding uses a fixed "80px" which can let
content be clipped behind the bottom nav that grows with
env(safe-area-inset-bottom); update the padding expression (where padding is
computed with isMobile) to add the safe-area inset, e.g. replace the fixed
bottom value with a calc using env(safe-area-inset-bottom, 0px) so bottom
padding becomes something like calc(80px + env(safe-area-inset-bottom, 0px)),
ensuring consistency with the nav that already uses env(safe-area-inset-bottom).

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de88e25 and 02d4ebc.

📒 Files selected for processing (13)
  • src/app/page.tsx
  • src/components/AuthScreen.tsx
  • src/components/BlockTimer.tsx
  • src/components/CompletionScreen.tsx
  • src/components/HistoryView.tsx
  • src/components/HomeView.tsx
  • src/components/MindStateBar.tsx
  • src/components/PublicBoard.tsx
  • src/components/SessionView.tsx
  • src/components/SettingsView.tsx
  • src/components/ThoughtCapture.tsx
  • src/components/ThoughtJournal.tsx
  • src/lib/useIsMobile.ts

Comment thread src/app/page.tsx Outdated
Use calc(80px + env(safe-area-inset-bottom)) so content doesn't
clip behind the nav bar on devices with larger safe areas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Full review triggered.

@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Full review triggered.

@auerbachb
Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

✅ Actions performed

Reviews resumed.

@auerbachb auerbachb merged commit b73ac74 into main Feb 26, 2026
1 check passed
@auerbachb auerbachb deleted the issue-2-mobile-responsive branch February 26, 2026 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mobile web optimized layout

1 participant