Files
Saxon Fletcher 66c6da82fe fix(studio): refine Explorer query surfaces and tab styling (#50249)
Explorer query surfaces now use `bg-card` in light mode and `bg-muted`
in dark mode, including embedded notebook/chat queries and query tab
toolbars. Notebook Run buttons match query tabs, with `ml-1` spacing on
both. Fix doubled tab separators by applying the leading border only to
the first tab.

### How to test

1. Open Explorer with multiple query, notebook, and chat tabs. Switch,
reorder, and close tabs; confirm each separator stays one pixel wide.
2. In light and dark mode, inspect query tabs and embedded notebook/chat
queries: backgrounds should be card in light mode and muted in dark
mode, including their toolbars.
3. Compare notebook and query Run buttons: matching default styling and
spacing. Run a read-only query such as `select 1` in both and check
loading and results.
4. Check SQL Editor and Table Editor tab separators, since the tab
component is shared.

Validation: Prettier passed for all four changed files. Manual checks
above have not been run.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Style**
- Refined notebook and query run button styling, including spacing and
tooltip placement.
- Improved query editor panel backgrounds across light and dark themes.
  - Updated tab border rendering for more consistent visual alignment.


<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-11 16:53:04 +08:00

92 lines
2.9 KiB
TypeScript

import React from 'react'
import { cn } from 'ui'
const explorerQueryClassName = 'flex flex-col overflow-hidden'
export type ExplorerQueryProps = React.ComponentProps<'div'>
/**
* Framed Explorer query shell for notebooks and other embedded surfaces.
* The consuming surface owns the height; results fill whatever the toolbar,
* editor, and footer leave behind. The minimum height keeps the frame usable
* when a surface leaves the height to content.
*/
const ExplorerQuery = ({ className, ...props }: ExplorerQueryProps) => (
<div
data-slot="explorer-query"
data-variant="embedded"
className={cn(
explorerQueryClassName,
'min-h-64 rounded-md border bg-card dark:bg-muted shadow-xs',
className
)}
{...props}
/>
)
ExplorerQuery.displayName = 'ExplorerQuery'
export type ExplorerQueryViewportProps = React.ComponentProps<'div'>
/**
* Full-height Explorer query shell for a dedicated tab or another viewport.
* Fills its container so the surrounding page decides the height.
*/
const ExplorerQueryViewport = ({ className, ...props }: ExplorerQueryViewportProps) => (
<div
data-slot="explorer-query"
data-variant="viewport"
className={cn(explorerQueryClassName, 'h-full min-h-0 bg-card dark:bg-muted', className)}
{...props}
/>
)
ExplorerQueryViewport.displayName = 'ExplorerQueryViewport'
export type ExplorerQueryEditorProps = React.ComponentProps<'div'>
/** Region containing the editable or read-only SQL editor supplied by the caller. */
const ExplorerQueryEditor = ({ className, ...props }: ExplorerQueryEditorProps) => (
<div
data-slot="explorer-query-editor"
className={cn('min-h-20 shrink-0 overflow-hidden border-b', className)}
{...props}
/>
)
ExplorerQueryEditor.displayName = 'ExplorerQueryEditor'
export type ExplorerQueryResultsProps = React.ComponentProps<'div'>
/**
* Always-present result region for idle, loading, error, table, or chart content.
* Fills the height left by the toolbar, editor, and footer, and shrinks rather
* than pushing them out of the frame. Content that can overflow supplies its own
* scroll container.
*/
const ExplorerQueryResults = ({ className, ...props }: ExplorerQueryResultsProps) => (
<div
data-slot="explorer-query-results"
className={cn('flex min-h-0 w-full flex-1 flex-col overflow-hidden', className)}
{...props}
/>
)
ExplorerQueryResults.displayName = 'ExplorerQueryResults'
export type ExplorerQueryFooterProps = React.ComponentProps<'div'>
/** Optional metadata or surface-specific content below the results region. */
const ExplorerQueryFooter = ({ className, ...props }: ExplorerQueryFooterProps) => (
<div
data-slot="explorer-query-footer"
className={cn('shrink-0 border-t px-3 py-1 text-xs text-foreground-lighter', className)}
{...props}
/>
)
ExplorerQueryFooter.displayName = 'ExplorerQueryFooter'
export {
ExplorerQuery,
ExplorerQueryEditor,
ExplorerQueryFooter,
ExplorerQueryResults,
ExplorerQueryViewport,
}