feat(ui): mobile-responsive OmniBioAI Studio v0.8.0 - #43
Merged
Conversation
Additive only: desktop layout (>=768px) is byte-for-byte unchanged, since both new rules are scoped inside max-width:767px media queries. Below the breakpoint the existing inline-styled sidebar wrapper (.studio-sidebar-wrap) is force-collapsed to width:0, and a hidden-by-default hamburger trigger class (.studio-hamburger) is introduced for the next commit's MobileNav drawer to hook into. Part of the v0.8.0 mobile-responsive UI effort. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New MobileNav.jsx reuses App.jsx's existing buildNav()/step/setStep/ currentUser data verbatim (same props Sidebar already takes) -- no nav items or permission logic duplicated. Slide-out drawer + backdrop, closes on outside click, Escape, or route change (step change), close button is always visible and >=44px, nav rows are >=44px touch targets. Wired into App.jsx behind the hamburger trigger added in the previous commit; the drawer is position:fixed so it never participates in the desktop flex layout, and the hamburger that opens it stays display:none above 767px, so desktop is unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Card padding moved from an inline 2.5rem to .studio-login-card so a <=480px override (1.75rem 1.25rem) can reclaim usable width on a 390px viewport; desktop value is unchanged (same 2.5rem, just as a class default instead of inline). Submit/OAuth buttons and the password/license tabs get a 44px min-height under 768px only — desktop button sizing untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
.app-grid's existing breakpoint ladder (6/4/3/2 cols) already handled down to 600px; verified at 390/428px the 2-col floor wraps longer plugin names (e.g. 'Multi-Agent Orchestrator') to 3 lines, so add a tighter <=420px rule dropping to 1 column. Scoped narrower than the existing 600px rule, so 421-600px is unaffected. Also bumps the header action buttons (Refresh / Catalog / Launch Workbench) to a 44px min-height under 768px only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…g page .omni-table-wrap had overflow:hidden (both axes, for its rounded-corner border) but no scroll axis of its own, so any consumer's table wider than its container (e.g. RoleManagement's RolesTable) had nowhere to go except overflow the page horizontally at narrow widths. Adds overflow-x:auto (vertical clipping for the rounded corners is preserved); a no-op on any table that already fits, so desktop is unaffected. @omnibioai/ui's main.jsx import point is the prebuilt packages/omnibioai-ui/dist bundle, not src directly, so dist/index.css is regenerated via 'npm run build' in that package and committed alongside the source change (same pattern as its prior commit 701e38b, which tracks dist/ as regular files despite the generic dist/ gitignore rule). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wraps the two raw <table>s (Run History, Execution Servers) in .studio-table-scroll (overflow-x:auto) so they scroll inside their own box instead of overflowing the page. Collapses the submit-form 3-col grid, the 4-stat KPI row (2-col, then 1-col under 400px), the runs/detail 'selected ? 1fr 1fr : 1fr' grid, and the servers/tools 'info' grid all to 1 column below 768px. Every rule is scoped inside a max-width media query, so desktop's exact current layout is unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wraps each of the 6 per-group tables (Service/Status/Port/Image/Actions) in .studio-table-scroll so the wide Image column scrolls inside its own box on narrow viewports instead of overflowing the page. No layout change above the viewport width where the table already fits (which is most/all desktop widths). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
OAuthLinkConfirm (380px), RequirePermission's AccessDenied (360px), RoleManagement's own duplicate AccessDenied (360px), and GrafanaViewer's connection-error card (380px) all had a literal pixel width with no maxWidth fallback and, for three of the four, no side padding on their container — on a 390px viewport (or GrafanaViewer's zero-padding service-view host) that overflows or touches the screen edge. Switches each to width:100% + maxWidth:<same px value> (desktop size unchanged) and adds container padding where none existed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…elds Settings (2-col), LLM (x2, 2-col), Cloud (2-col), HPC (2-col + 3-col), Launch's Summary+Logs (2-col), and IdeServices (3-col) all collapse to a single column below 768px via the new .studio-grid-1 class. Mode's mode-selector cards use their own .studio-mode-grid (3->2->1 cols, since each card carries a 2-line description and needs more room than a status tile). The HealthCard status-tile rows on Mode and Launch use .studio-health-grid (5->3->2 cols — compact enough to stay multi-column). Also gives UI.jsx's shared Input/Select/Btn (used throughout these seven pages) a 44px min-height below 768px via .studio-field, so config-page form controls hit the touch-target minimum without a per-page pass. All rules are media-scoped >=768px cutoffs; desktop is byte-for-byte unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The 60px/80px/80px/1fr fixed-pixel row grid ate ~220px on fixed columns regardless of viewport, crushing the message column on narrow screens. Below 640px, .studio-log-row keeps time/level/source on one compact auto-sized row and drops the message span (4th child) to its own full-width row underneath via grid-column:1/-1 — no JSX restructuring, just a class hook + CSS. Desktop grid (60px 80px 80px 1fr) is untouched above the breakpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Summary
Mobile-first responsive UI for OmniBioAI Studio's web build, targeting the v0.8.0 launch. Mobile-first per the brief's breakpoints (base=mobile, sm=640, md=768, lg=1024, xl=1280); desktop behavior at >=768px is preserved exactly — every new rule is scoped inside a
max-widthmedia query, verified during audit.10 commits, one logical change each:
.studio-sidebar-wrap); hidden-by-default hamburger trigger added for mobile only.MobileNav.jsx, reusesApp.jsx's existingbuildNav()/step/setStep/currentUserdata verbatim (same props<Sidebar>already takes), so nav items andmanage_rolespermission filtering are never duplicated. Closes on backdrop click, Escape, or route/step change. Close button always visible, nav rows and close button >=44px touch targets..app-gridbreakpoint ladder with a sub-420px 1-column step; header action buttons bumped to 44px on mobile.@omnibioai/ui<Table>and every raw<table>(Jobs, Services) now scroll horizontally inside their own box (overflow-x:auto) instead of overflowing the page. No table converted to cards.Nfr/repeat(N,1fr)CSS grids across Settings, LLM, Cloud, HPC, Launch, IdeServices, Mode collapse to 1-3 columns below 768px depending on content density. SharedInput/Select/Btnprimitives get a 44px min-height floor on mobile.OAuthLinkConfirm,RequirePermission/RoleManagement'sAccessDenied, andGrafanaViewer's error card all switch from a fixed pixel width towidth:100% + maxWidth:<same px>, with container padding added where none existed, so none can overflow or touch the viewport edge on a 390px screen.60px 80px 80px 1fr) that crushed the message column on narrow screens now drops the message to its own full-width row below 640px.Not in scope / explicitly excluded
omnibioai-rag), embedded at runtime viaServiceViewer's iframe/webview, already full-width/height. Nothing to make responsive here.Build verification
npx vite build --mode webrun and passed after every one of the 10 commits — zero errors.packages/omnibioai-ui'snpm run buildwas run once to regeneratedist/index.cssafter the sharedTable.cssfix (that package'smain.jsximport point is the prebuiltdistbundle, notsrc), and the rebuilt bundle was verified to contain the fix before committing. No lint config or JS test framework exists in this repo (confirmed during scan), so neither applies here.Post-merge validation still needed
Live browser/device QA has not been performed — Chrome automation tooling wasn't available this session, and every page except Login sits behind a JWT session gate that needs real backend credentials this environment doesn't have. All correctness claims above are from static CSS/JSX review plus confirming the expected class names ship in the production CSS bundle, not from rendered pixels. Recommend a manual pass at 390/428/768/1024/1280px on at least Jobs, Services, and one config page before or shortly after merge.
A full pre-merge audit (git scope, commit-by-commit diff review, MobileNav RBAC/close-behavior trace, CSS scoping verification, dist/generated-file check, remaining-offender sweep) was completed separately and came back with no blockers — see conversation history for the full findings (a few low-severity a11y/polish follow-ups noted, none affecting merge readiness).
🤖 Generated with Claude Code