feat(builder): make the app usable on mobile viewports - #970
Open
eduardocodes wants to merge 23 commits into
Open
feat(builder): make the app usable on mobile viewports#970eduardocodes wants to merge 23 commits into
eduardocodes wants to merge 23 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes the builder usable on a phone. Before this, the app was desktop-only in
practice: of 1137
.tsxfiles, 99 contained any responsive prefix, and of 44layout files exactly one did. The shadcn
Sidebaralready collapsed into aSheetbelowmd, but nothing in the app could open it — the only trigger isabsolutely positioned off the inset's inline edge — and no nav link closed it.
Scope is the app shell, the inbox, and the table/list surfaces. The flow
builder is deliberately out of scope and untouched; it needs its own pass.
Shell and navigation
viewportexport withviewportFit: "cover", soenv(safe-area-inset-*)reports real values.
SidebarMobileTriggerinpackages/ui— a hamburger with a full touchtarget, as opposed to
SidebarTrigger, which is a rail-collapse chevron andreads as nothing below
md. Wired into a stickymd:hiddenheader in bothshells (workspace and manage console).
NavMainnow closes the mobile sheet when a link is tapped; it used to stayopen on top of the destination page.
AppTabscrolls horizontally instead of overflowing. One file, and it unblocksthe 15 surfaces that render 4–6 tabs.
-m-6negative margin — which silently depended on the shell'sp-6— is replaced by a documentedFullBleedcomponent, so changing theshell's padding can no longer break the page from a distance.
Tables and lists
DataTablenow scrolls horizontally by default. The default wasoverflow-hiddenand only 1 of its 36 consumers opted out of it, so 35 tables silently clipped
their rightmost columns with no way to reach them.
mobileCardrender mode plus a genericDataTableRowCardthatrenders a row through the column's own
flexRender— no duplicated celllogic, and field labels come from
meta.label, so no new translation keys.Applied to contacts (bespoke card), flows and broadcasts (generic).
layout is in the first paint rather than flipping after hydration.
column;
SettingRowstacks (itsgrid-cols-4reached every settings form).Inbox
Below
mdthe inbox is a single-pane master/detail view: the conversation list,then the thread with a back control, with the contact panel behind a button in a
Sheet. Frommdup the three-columnResizablePanelGroupand its layout cookieare unchanged.
This is the one place the layout is chosen in JS rather than CSS: the three panes
are heavy and self-fetching, so rendering both arrangements would mount and fetch
everything twice.
useIsMobileStatewas added for it — it returnsundefineduntil the first measurement so the layout waits instead of guessing desktop and
remounting a frame later.
Bug fixed along the way:
<ChatRealtime />lived inside the message pane. Inthe mobile single-pane view that pane unmounts when returning to the list, which
would have taken the realtime socket down with it. It now sits at the layout root.
Dialogs
DialogContent's base width goes fromw-fulltow-[calc(100%-2rem)].tailwind-merge resolves
max-w-*by group, so the ~60 dialogs passing anunprefixed
max-w-*were replacing themax-w-[calc(100%-2rem)]guard andrendering edge-to-edge on a phone. Width is a separate group, so the gutter now
survives. One line, no consumer changes.
Verification
pnpm lintclean;check-typesclean for builder, ui, analytics-nextjs andvitest-config;
pnpm buildpasses.across 6 new files.
settings and both analytics dashboards: every route measures
scrollWidth == clientWidth, with no element outside the viewport. Re-checkedat 1440×900 to confirm desktop is unchanged.
admins-analysis.tsxcarried an unprefixedcol-span-2, which against the new one-column mobile grid created an implicitsecond column and pushed the analytics page to 471px in a 375px viewport. It
was invisible before because the grid was always two columns. Fixed here.
packages/vitest-configgainsmatchMediaandResizeObserverstubs for jsdom;without them
useIsMobile, the sidebar's mobile branch, and anything using aresizable panel throw on mount and could not be tested at all.
Not included
max-h-screenappears on 101 dialog lines. On iOS Safari100vhovershoots thevisible area, so a dialog's footer can sit under the browser chrome. Left alone
because the sweep would cross into the flow builder.
🤖 Generated with Claude Code