mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
- move navigation components to `apps/studio/components/layouts/Navigation` - add [FloatingMobileToolbar](https://github.com/supabase/supabase/pull/43444/changes#diff-3dffe47fd51ca851d612d8728e03b2dc344ec213d4f3a46a824d3fa32a7cc851) as quick access to tools such as search, assistant, inline editor, etc - behind feature flag and feature preview (true by default as it's a bit annoying to have to enable it all the time as previews are stored in local-storage) - fix sidebar panels closing on viewport resizing (regression from previous pr) https://github.com/user-attachments/assets/d6881e3b-5128-4306-bb82-3ca39c755dba <img width="986" height="697" alt="Screenshot 2026-03-12 at 12 40 11" src="https://github.com/user-attachments/assets/da8511e2-7d01-4237-b814-596031c747c5" />
110 lines
3.0 KiB
TypeScript
110 lines
3.0 KiB
TypeScript
import type { CSSProperties } from 'react'
|
|
|
|
export const DRAG_THRESHOLD_PX = 8
|
|
export const GAP_FROM_BOTTOM = 50
|
|
export const SHEET_OPEN_GAP_FRACTION = 0.15
|
|
export const DEFAULT_NAV_HEIGHT = 56
|
|
|
|
export function isMenuContent(content: unknown): boolean {
|
|
return content !== null && typeof content !== 'string'
|
|
}
|
|
|
|
export function shouldShowMenuButton(pathname: string): boolean {
|
|
return (
|
|
pathname.startsWith('/project/') ||
|
|
pathname.startsWith('/org/') ||
|
|
pathname.startsWith('/account')
|
|
)
|
|
}
|
|
|
|
export type Viewport = { width: number; height: number }
|
|
export type NavSize = { width: number; height: number }
|
|
export type Position = { x: number; y: number }
|
|
|
|
export function clampPosition(
|
|
current: Position,
|
|
delta: { dx: number; dy: number },
|
|
viewport: Viewport,
|
|
navSize: NavSize
|
|
): Position {
|
|
const maxX = Math.max(0, viewport.width - navSize.width)
|
|
const maxY = Math.max(0, viewport.height - navSize.height)
|
|
return {
|
|
x: Math.max(0, Math.min(maxX, current.x + delta.dx)),
|
|
y: Math.max(0, Math.min(maxY, current.y + delta.dy)),
|
|
}
|
|
}
|
|
|
|
export type DragStartState = {
|
|
x: number
|
|
y: number
|
|
startX: number
|
|
startY: number
|
|
}
|
|
|
|
export function getNextPosition(
|
|
dragStart: DragStartState,
|
|
clientX: number,
|
|
clientY: number,
|
|
viewport: Viewport,
|
|
navSize: NavSize,
|
|
threshold: number = DRAG_THRESHOLD_PX
|
|
): Position | null {
|
|
const dist = Math.hypot(clientX - dragStart.startX, clientY - dragStart.startY)
|
|
if (dist < threshold) return null
|
|
const dx = clientX - dragStart.startX
|
|
const dy = clientY - dragStart.startY
|
|
return clampPosition({ x: dragStart.x, y: dragStart.y }, { dx, dy }, viewport, navSize)
|
|
}
|
|
|
|
export function getToolbarStyle(params: {
|
|
position: Position | null
|
|
navSize: NavSize
|
|
isSheetOpen: boolean
|
|
viewport: Viewport
|
|
isDragging: boolean
|
|
}): CSSProperties {
|
|
const { position, navSize, isSheetOpen, viewport, isDragging } = params
|
|
const { width: navW, height: navH } = navSize
|
|
const vw = viewport.width
|
|
const vh = viewport.height
|
|
const transition = isDragging
|
|
? 'transform 0ms, z-index 0s'
|
|
: 'transform 300ms cubic-bezier(0.4, 0, 0.2, 1), z-index 0s'
|
|
const base: CSSProperties = {
|
|
zIndex: isSheetOpen ? 101 : 41,
|
|
transition,
|
|
touchAction: 'none',
|
|
}
|
|
|
|
const centerX = vw > 0 && navW > 0 ? vw / 2 - navW / 2 : 0
|
|
const sheetOpenGapPx = vh * SHEET_OPEN_GAP_FRACTION
|
|
const topWhenSheetOpen = vh > 0 ? sheetOpenGapPx / 2 - navH / 2 : 0
|
|
const defaultYClosed = vh > 0 ? vh - GAP_FROM_BOTTOM - (navH > 0 ? navH : DEFAULT_NAV_HEIGHT) : 0
|
|
|
|
if (position === null) {
|
|
return {
|
|
...base,
|
|
left: '50%',
|
|
top: 0,
|
|
transform: isSheetOpen
|
|
? `translate(-50%, ${topWhenSheetOpen}px)`
|
|
: `translate(-50%, ${defaultYClosed}px)`,
|
|
}
|
|
}
|
|
if (isSheetOpen) {
|
|
return {
|
|
...base,
|
|
left: 0,
|
|
top: 0,
|
|
transform: `translate(${centerX}px, ${topWhenSheetOpen}px)`,
|
|
}
|
|
}
|
|
return {
|
|
...base,
|
|
left: 0,
|
|
top: 0,
|
|
transform: `translate(${position.x}px, ${position.y}px)`,
|
|
}
|
|
}
|