mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
fix(modals): center modals in visible content area accounting for sidebar and panel (#3934)
* fix(modals): center modals in visible content area accounting for sidebar and panel * fix(modals): address pr feedback — comment clarity and document panel assumption
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
* @see stores/constants.ts for the source of truth
|
||||
*/
|
||||
:root {
|
||||
--sidebar-width: 248px; /* SIDEBAR_WIDTH.DEFAULT */
|
||||
--sidebar-width: 0px; /* 0 outside workspace; blocking script always sets actual value on workspace pages */
|
||||
--panel-width: 320px; /* PANEL_WIDTH.DEFAULT */
|
||||
--toolbar-triggers-height: 300px; /* TOOLBAR_TRIGGERS_HEIGHT.DEFAULT */
|
||||
--editor-connections-height: 172px; /* EDITOR_CONNECTIONS_HEIGHT.DEFAULT */
|
||||
|
||||
@@ -90,6 +90,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
}
|
||||
|
||||
// Sidebar width
|
||||
var defaultSidebarWidth = '248px';
|
||||
try {
|
||||
var stored = localStorage.getItem('sidebar-state');
|
||||
if (stored) {
|
||||
@@ -108,11 +109,15 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
document.documentElement.style.setProperty('--sidebar-width', width + 'px');
|
||||
} else if (width > maxSidebarWidth) {
|
||||
document.documentElement.style.setProperty('--sidebar-width', maxSidebarWidth + 'px');
|
||||
} else {
|
||||
document.documentElement.style.setProperty('--sidebar-width', defaultSidebarWidth);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
document.documentElement.style.setProperty('--sidebar-width', defaultSidebarWidth);
|
||||
}
|
||||
} catch (e) {
|
||||
// Fallback handled by CSS defaults
|
||||
document.documentElement.style.setProperty('--sidebar-width', defaultSidebarWidth);
|
||||
}
|
||||
|
||||
// Panel width and active tab
|
||||
|
||||
@@ -343,7 +343,11 @@ export function SearchModal({
|
||||
'-translate-x-1/2 fixed top-[15%] z-50 w-[500px] rounded-xl border-[4px] border-black/[0.06] bg-[var(--bg)] shadow-[0_24px_80px_-16px_rgba(0,0,0,0.15)] dark:border-white/[0.06] dark:shadow-[0_24px_80px_-16px_rgba(0,0,0,0.4)]',
|
||||
open ? 'visible opacity-100' : 'invisible opacity-0'
|
||||
)}
|
||||
style={{ left: 'calc(var(--sidebar-width) / 2 + 50%)' }}
|
||||
style={{
|
||||
left: isOnWorkflowPage
|
||||
? 'calc(50% + (var(--sidebar-width) - var(--panel-width)) / 2)'
|
||||
: 'calc(var(--sidebar-width) / 2 + 50%)',
|
||||
}}
|
||||
>
|
||||
<Command label='Search' shouldFilter={false}>
|
||||
<div className='mx-2 mt-2 mb-1 flex items-center gap-1.5 rounded-lg border border-[var(--border-1)] bg-[var(--surface-5)] px-2 dark:bg-[var(--surface-4)]'>
|
||||
|
||||
@@ -40,6 +40,7 @@ import * as React from 'react'
|
||||
import * as DialogPrimitive from '@radix-ui/react-dialog'
|
||||
import * as TabsPrimitive from '@radix-ui/react-tabs'
|
||||
import { X } from 'lucide-react'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { cn } from '@/lib/core/utils/cn'
|
||||
import { Button } from '../button/button'
|
||||
|
||||
@@ -55,7 +56,7 @@ const ANIMATION_CLASSES =
|
||||
* We keep only the slide animations (no zoom) to stabilize positioning while avoiding scale effects.
|
||||
*/
|
||||
const CONTENT_ANIMATION_CLASSES =
|
||||
'data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[50%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[50%] motion-reduce:animate-none'
|
||||
'data-[state=closed]:slide-out-to-top-[50%] data-[state=open]:slide-in-from-top-[50%] motion-reduce:animate-none'
|
||||
|
||||
/**
|
||||
* Root modal component. Manages open state.
|
||||
@@ -145,6 +146,8 @@ const ModalContent = React.forwardRef<
|
||||
ModalContentProps
|
||||
>(({ className, children, showClose = true, size = 'md', style, ...props }, ref) => {
|
||||
const [isInteractionReady, setIsInteractionReady] = React.useState(false)
|
||||
const pathname = usePathname()
|
||||
const isWorkflowPage = pathname?.includes('/w/') ?? false
|
||||
|
||||
React.useEffect(() => {
|
||||
const timer = setTimeout(() => setIsInteractionReady(true), 100)
|
||||
@@ -164,7 +167,10 @@ const ModalContent = React.forwardRef<
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
left: '50%',
|
||||
left: isWorkflowPage
|
||||
? // --panel-width is always the rendered panel width on /w/ routes (panel is never hidden/collapsed)
|
||||
'calc(50% + (var(--sidebar-width) - var(--panel-width)) / 2)'
|
||||
: 'calc(var(--sidebar-width) / 2 + 50%)',
|
||||
...style,
|
||||
}}
|
||||
onEscapeKeyDown={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user