Skip to content

fix(modals): center modals in visible content area accounting for sidebar and panel#3933

Closed
waleedlatif1 wants to merge 1 commit intostagingfrom
fix/modal-centering
Closed

fix(modals): center modals in visible content area accounting for sidebar and panel#3933
waleedlatif1 wants to merge 1 commit intostagingfrom
fix/modal-centering

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Command K and all emcn modals now center in the visible content area (between sidebar and panel) instead of the full viewport
  • Fixed `--sidebar-width` CSS default to `0px` so non-workspace pages (login, landing) keep modals viewport-centered
  • Blocking script now always explicitly sets `--sidebar-width` on workspace pages, covering new users and error cases
  • Search modal accounts for the right panel on workflow pages using `isOnWorkflowPage` prop
  • emcn `ModalContent` uses `usePathname` to detect workflow pages and apply the panel-aware formula
  • Removed horizontal slide animation from emcn Modal (was tied to hardcoded `left: 50%`)

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 4, 2026

PR Summary

Medium Risk
Changes global CSS variables/z-index and the pre-hydration layout script that affects every workspace page, so regressions could shift UI layering/positioning across the app. The rest is contained to modal/search UI behavior and analytics instrumentation.

Overview
Modals and Command-K search are now centered within the visible workspace content area by positioning them relative to --sidebar-width (and --panel-width on workflow pages) instead of hardcoding left: 50%.

The workspace pre-hydration script now always sets a --sidebar-width fallback (248px) on workspace routes, while the global CSS default for --sidebar-width is 0px to keep non-workspace pages centered.

The Command-K search modal is refactored into group components, adds new result categories (tables, files, knowledgeBases), and emits PostHog search_result_selected events on selection. Global styling also introduces a shared z-index/shadow scale and switches scrollbar colors to use theme variables.

Reviewed by Cursor Bugbot for commit 147c89d. Configure here.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Apr 4, 2026 2:01am

Request Review

@waleedlatif1 waleedlatif1 deleted the fix/modal-centering branch April 4, 2026 02:02
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 4, 2026

Greptile Summary

This PR fixes modal centering across the workspace by replacing the previous viewport-based centering with a formula that accounts for the sidebar (always) and the right panel (workflow pages only). It does this through four coordinated changes: defaulting --sidebar-width to 0px in globals.css so non-workspace pages stay viewport-centered, adding an always-executed --sidebar-width setter in the blocking layout script for new users and error cases, wiring the same two-formula approach into the SearchModal via its isOnWorkflowPage prop, and baking identical logic into the shared ModalContent via usePathname.

Key changes:

  • --sidebar-width CSS default changed to 0px; blocking script now always explicitly sets it on workspace pages
  • Centering formula: non-workflow workspace pages → calc(var(--sidebar-width) / 2 + 50%), workflow pages → calc(50% + (var(--sidebar-width) - var(--panel-width)) / 2) — the math is correct in both cases
  • Horizontal slide animation removed from ModalContent since it was anchored to a fixed left: 50%
  • ModalContent now uses usePathname internally to detect workflow pages, coupling Next.js routing knowledge to the shared emcn component; SearchModal uses a prop instead, making the two approaches inconsistent

Confidence Score: 5/5

Safe to merge — centering math is correct, all edge cases in the blocking script are handled, and the only remaining findings are style/design suggestions.

All identified issues are P2: a custom rule flag on the globals.css edit (which is justified by necessity) and a design concern about embedding Next.js routing logic inside the shared emcn component. No correctness bugs, data integrity risks, or security issues exist.

apps/sim/components/emcn/components/modal/modal.tsx — contains the usePathname//w/ coupling that may need revisiting if the URL structure evolves.

Important Files Changed

Filename Overview
apps/sim/app/_styles/globals.css Changes --sidebar-width default to 0px so non-workspace pages keep modals viewport-centered; necessary but violates the avoid-globals.css-edits custom rule.
apps/sim/app/layout.tsx Blocking script now always explicitly sets --sidebar-width on workspace pages (including new-user fallback and catch branches), correctly avoiding any flash of the wrong centering position.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx Replaces the static left-1/2 Tailwind class with a dynamic inline style.left that accounts for both sidebar and (on workflow pages) the right panel; centering math is correct.
apps/sim/components/emcn/components/modal/modal.tsx Introduces usePathname and a hard-coded /w/ path check inside the shared emcn ModalContent to apply the panel-aware centering formula; couples Next.js routing logic to a generic component.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Page loads] --> B{pathname includes\n/workspace/?}
    B -- No --> C[CSS default:\n--sidebar-width = 0px]
    B -- Yes --> D[Blocking script runs]
    D --> E{localStorage\nsidebar-state?}
    E -- Yes, collapsed --> F[--sidebar-width = 51px]
    E -- Yes, expanded --> G[--sidebar-width = stored width]
    E -- No / error --> H[--sidebar-width = 248px]
    C & F & G & H --> I[Modal opens]
    I --> J{Which modal?}
    J -- SearchModal --> K{isOnWorkflowPage prop}
    J -- ModalContent emcn --> L{usePathname\nincludes /w/?}
    K -- Yes --> M["left: calc(50% + (sidebar - panel) / 2)"]
    K -- No --> N["left: calc(sidebar / 2 + 50%)"]
    L -- Yes --> M
    L -- No --> N
    M & N --> O[translate-x: -50%\nModal visually centered\nin available area]
Loading

Reviews (1): Last reviewed commit: "fix(modals): center modals in visible co..." | Re-trigger Greptile

Comment on lines +149 to +150
const pathname = usePathname()
const isWorkflowPage = pathname?.includes('/w/') ?? false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Application-specific routing logic inside a shared emcn component

usePathname and the hard-coded /w/ path string embed knowledge of the Sim URL structure into ModalContent, a component that is meant to be a generic, reusable primitive. If the workflow URL segment ever changes (e.g. renamed from /w/ to /workflow/), this condition silently breaks centering for all emcn modals without any compile-time signal.

A cleaner approach is to accept an explicit prop (mirroring what SearchModal already does with isOnWorkflowPage) and let the call site decide the layout context:

export interface ModalContentProps
  extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
  showClose?: boolean
  size?: ModalSize
  /** Pass true on pages that have both a sidebar and a right panel (e.g. workflow canvas). */
  hasRightPanel?: boolean
}

Then replace the usePathname call with:

const { className, children, showClose = true, size = 'md', hasRightPanel = false, style, ...props } = ...

and use hasRightPanel in the style object instead of isWorkflowPage. This removes the Next.js and URL-structure dependency from the shared component entirely.

*/
:root {
--sidebar-width: 248px; /* SIDEBAR_WIDTH.DEFAULT */
--sidebar-width: 0px; /* 0 outside workspace; blocking script sets actual value on workspace pages */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Editing globals.css — custom rule requires avoiding this unless absolutely necessary

The project rule is to avoid editing globals.css and move style changes to local component files instead. The --sidebar-width: 0px default is needed so modals on non-workspace pages don't shift, which is a valid reason, but it's worth confirming there is no alternative (e.g. declaring a scoped :root override in the workspace layout) before landing a change here.

If the edit is indeed the only clean option, the inline comment already added (/* 0 outside workspace; blocking script sets actual value on workspace pages */) documents intent well.

Rule Used: Avoid editing the globals.css file unless absolute... (source)

Learnt From
simstudioai/sim#367

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 147c89d. Configure here.

ref={ref}
className={cn(
'fixed inset-0 z-[500] bg-black/10 backdrop-blur-[2px]',
'fixed inset-0 z-[var(--z-modal)] bg-black/10 backdrop-blur-[2px]',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Overlay and SModal content z-index now mismatched

Medium Severity

ModalOverlay was changed from z-[500] to z-[var(--z-modal)] (200), but SModalContent in s-modal.tsx still uses z-[500] and imports this same ModalOverlay. This creates a z-index gap: the overlay sits at 200 while the sidebar-modal content sits at 500. Elements using --z-popover (300) or --z-tooltip (400) can now visually render between the overlay and the SModal content, breaking the expected stacking order where the overlay dims everything beneath the modal.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 147c89d. Configure here.

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.

1 participant