[bug]: v1.3.1 web app unusable on iOS/WebKit: unguarded requestIdleCallback crashes workspace pages; expanded sidebar overlays the board and swallows all taps
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 59.6k
- Forks
- 5.8k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 49
Description
Environment
Self-hosted CE v1.3.1 (docker compose deploy). Reproduced on real iPhone Safari (iOS 26) and with Playwright WebKit (iPhone 13 device profile). Desktop browsers are unaffected (both bugs are WebKit/viewport-specific).
Two independent bugs make the v1.3.1 web app effectively unusable on iOS. Root-cause analysis for both is included below (file/line refs are against the v1.3.1 tag).
Bug 1 — unguarded requestIdleCallback crashes every workspace page on WebKit
Symptom: any workspace page (kanban, list, …) immediately shows the "🚧 Looks like something went wrong!" error boundary.
Console:
TypeError: window.requestIdleCallback is not a function.
(In 'window.requestIdleCallback(()=>{h.current&&(S.current=`${h.current.offsetHeight}px`)})')
React Router caught the following error during render TypeError: window.requestIdleCallback is not a function.
Root cause: Safari/WebKit still does not ship requestIdleCallback (it remains behind an experimental flag), and a layout component rendered by workspace pages calls window.requestIdleCallback(...) unguarded, throwing during render.
Suggested fix: feature-guard the call (window.requestIdleCallback ?? setTimeout fallback) or add a polyfill to the app entry.
Workaround we're running: a setTimeout-based polyfill injected into index.html ahead of the bundle — with it, the pages render fine, which confirms this is the only fatal error on the path.
(While debugging we also consistently see React hydration errors #418/#423 on the prerendered shell in WebKit — non-fatal since React recovers, but noisy and possibly related to Bug 2's state confusion.)
Bug 2 — on <768px viewports the expanded sidebar overlays the entire board and swallows every tap
Symptom: tapping any kanban card does nothing — users report "opening/modifying a card never loads". The peek overlay itself is healthy: programmatically force-clicking a card through the overlay opens it normally.
Evidence: Playwright cannot deliver a tap to any card:
<div id="main-sidebar" ... class="z-20 ... translate-x-0 opacity-100 absolute"> subtree intercepts pointer events
Root cause chain (v1.3.1):
apps/web/core/components/sidebar/resizable-sidebar.tsx(~line 185): when not collapsed the sidebar renderstranslate-x-0 opacity-100, plusabsolutewhenisMobile— i.e. a full-height z-20 overlay on phones.- The mobile auto-collapse lives in
apps/web/core/components/sidebar/sidebar-wrapper.tsx(~line 46):if (windowSize[0] < 768 && !sidebarCollapsed) toggleSidebar(). On project/workspace issue pages this component's effect does not end up collapsing the sidebar (and a syntheticresizeevent doesn't either), so the overlay stays up. - That effect also calls
toggleSidebar()(toggle) instead oftoggleSidebar(true)(set): if it runs more than once (two wrapper instances / re-mounts), the state flips collapsed → expanded again. We observedapp_sidebar_collapsedbeing written"true"then"false"during a single boot on a fresh profile. store-wrapper.tsx(~line 48) only applieslocalStorage.app_sidebar_collapsedwhen it exists, and there is no width-aware default — so a fresh mobile visitor always starts expanded/overlaying.
Suggested fix: default sidebarCollapsed to true when the viewport is <768px, and make the auto-collapse effect use toggleSidebar(true) so repeated runs are idempotent.
Workaround we're running: setting localStorage.app_sidebar_collapsed = "true" for narrow screens in a script before the bundle boots. (Gotcha for anyone reproducing: that script runs before the viewport meta is parsed, so window.innerWidth still reports iOS's legacy 980px layout viewport — screen.width must be used.)
Steps to reproduce
- Self-host CE v1.3.1, log in on an iPhone (or Playwright WebKit with an iPhone descriptor).
- Open any project's work-items page → error boundary (Bug 1).
- Apply a
requestIdleCallbackpolyfill so the page renders → tap any kanban card → nothing happens (Bug 2).
Repro harness (Playwright):
import { webkit, devices } from 'playwright';
const browser = await webkit.launch();
const ctx = await browser.newContext({ ...devices['iPhone 13'] });
// + authenticated session cookie
const page = await ctx.newPage();
page.on('pageerror', e => console.log('PAGEERROR:', e.message));
await page.goto('https://<instance>/<workspace>/projects/<id>/issues/');
await page.waitForTimeout(10000);
// Bug 1: pageerror = requestIdleCallback TypeError
// Bug 2 (after polyfill): tap times out with "subtree intercepts pointer events" from #main-sidebar
await (await page.$('[id^="issue-"]')).tap({ timeout: 10000 });
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with apps/web/core/components/sidebar/resizable-sidebar.tsx, sidebar-wrapper.tsx, and store-wrapper.tsx, then run the provided Playwright WebKit harness on an iPhone profile. Done means workspace pages render without a requestIdleCallback error and narrow viewports keep the sidebar from intercepting taps on kanban cards.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- playwright, react, typescript
- Domain
- frontend, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100