mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Five layout fixes across Explorer chat, notebooks, and the sidebar. ### Chat - **Conversation fade overlapped the scrollbar.** The top and bottom gradients are positioned against the conversation's padding box, which includes the scroll container's scrollbar gutter, so `inset-x-0` painted them over the scrollbar. They now stop at the conversation's content gutter, which `Conversation` owns for both the content and the fades. - **Composer background bled past the input's radius.** The form paints the surface behind the textarea but had no radius of its own, so its square corners showed outside the `rounded-lg` input. It now shares the radius. - **Message parts used two different widths.** Wide parts come down to `max-w-3xl` so every part shares a column, matching `AssistantQueryCell` and `AssistantNotebookPreview`. `isWide` / `isWideMessagePart` stay in place with both widths equal, so a part can diverge again later without rebuilding the mechanism. ### Notebooks - **Cell controls sat at the container edge.** Each cell centred itself at its own max width while the grip and add-cell button stayed at the far left of the full-width row, leaving a large gap. `SortableSection` takes a `sectionWidth` and carries its control gutter twice — once as the controls, once as padding on the other side — so the section stays centred with its controls immediately beside it. Cell widths are unchanged (prose `48rem`, query `72rem`); set them equal and the two cell types' controls line up on their own. The controls stay in flow rather than floating in an outside gutter, so on a viewport narrower than the cap the row just fills the space instead of clipping the controls into the padding. ### Sidebar - **Search icon didn't line up with the menu row icons.** The row box already sits flush with the search input's box, so rows moved from `pl-3` to `pl-2` to put their icons on the same 8px offset the search icon uses. Spacing between the input and the list now matches the 12px side padding. ### Testing `pnpm --filter studio run typecheck`, Prettier, and 378 tests across `Explorer`, `ProjectHome`, `AIAssistantPanel`, and `ExplorerLayout` pass. ESLint warning counts are unchanged from master. These were reasoned from layout rather than checked in a browser, so they're worth a look on a preview before merge. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **UI Improvements** * Updated Explorer layouts with flexible, configurable widths for notebook and query sections. * Refined navigation spacing and padding across Explorer views. * Centered and standardized AI Assistant preview, query, and message content widths. * Improved chat form styling with rounded corners. * Adjusted conversation spacing and fade overlays to avoid overlapping the scrollbar. * Preserved full-width behavior where appropriate while keeping controls aligned. * **Tests** * Updated layout tests to reflect revised width and alignment behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
import { motion } from 'framer-motion'
|
|
import { MessageSquare, NotebookText } from 'lucide-react'
|
|
import { type ComponentType, type PropsWithChildren } from 'react'
|
|
import { cn } from 'ui'
|
|
import { InnerSideBarFilters, InnerSideBarFilterSearchInput } from 'ui-patterns/InnerSideMenu'
|
|
|
|
export type ExplorerResourceType = 'notebook' | 'chat'
|
|
|
|
export const LEVEL_OFFSET = 8
|
|
export const LEVEL_TRANSITION = { duration: 0.09, ease: 'easeOut' } as const
|
|
|
|
export const EXPLORER_SECTIONS: Array<{
|
|
type: ExplorerResourceType
|
|
label: string
|
|
icon: ComponentType<{ size?: number; className?: string }>
|
|
searchPlaceholder: string
|
|
}> = [
|
|
{
|
|
type: 'notebook',
|
|
label: 'Notebooks',
|
|
icon: NotebookText,
|
|
searchPlaceholder: 'Search notebooks',
|
|
},
|
|
{ type: 'chat', label: 'Chats', icon: MessageSquare, searchPlaceholder: 'Search chats' },
|
|
]
|
|
|
|
export const rowClassName = (isActive: boolean) =>
|
|
cn(
|
|
'group relative flex h-7 w-full items-center gap-2 rounded-md pl-2 pr-2 text-sm',
|
|
isActive
|
|
? 'bg-selection text-foreground'
|
|
: 'text-foreground-light hover:bg-surface-200 hover:text-foreground'
|
|
)
|
|
|
|
export const ExplorerNavResourceWrapper = ({
|
|
type,
|
|
label,
|
|
className,
|
|
children,
|
|
search,
|
|
setSearch,
|
|
}: PropsWithChildren<{
|
|
type: ExplorerResourceType
|
|
label?: string
|
|
className?: string
|
|
search?: string
|
|
setSearch: (value: string) => void
|
|
}>) => {
|
|
const searchPlaceholder = EXPLORER_SECTIONS.find((x) => x.type === type)?.searchPlaceholder
|
|
|
|
return (
|
|
<motion.div
|
|
role="group"
|
|
aria-label={label}
|
|
initial={{ opacity: 0, x: LEVEL_OFFSET }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: LEVEL_OFFSET }}
|
|
transition={LEVEL_TRANSITION}
|
|
className={cn('absolute inset-0 flex flex-col', className)}
|
|
>
|
|
<div className="px-3 pt-3">
|
|
<span id="explorer-sidebar-search-label" className="sr-only">
|
|
{searchPlaceholder}
|
|
</span>
|
|
<InnerSideBarFilters className="w-full gap-0 p-0">
|
|
<InnerSideBarFilterSearchInput
|
|
name="explorer-sidebar-search"
|
|
value={search}
|
|
placeholder={searchPlaceholder}
|
|
aria-labelledby="explorer-sidebar-search-label"
|
|
onChange={(event) => setSearch(event.target.value)}
|
|
/>
|
|
</InnerSideBarFilters>
|
|
</div>
|
|
{children}
|
|
</motion.div>
|
|
)
|
|
}
|