Files
Alaister Young 5c0b627904 fix(studio): fix GraphiQL editor layout, gutter bleed and spacing (#47334)
Fixes three GraphiQL/integrations layout issues introduced by the
Marketplace layout change (#45856), which dropped the height passthrough
on the integration page content wrapper.

**Changed:**
- **Full-height integration pages** — the content wrapper had no height,
so GraphiQL's `h-full` editor collapsed instead of filling the page.
Added `flex-1 min-h-0` to the wrapper in both the legacy
(`LegacyIntegrationPage`) and marketplace (`MarketplaceDetail`) render
paths.
- **GraphiQL gutter bleed** — Monaco's `.overflow-guard` was ending up
`overflow: visible` (an inline style Monaco sets at runtime), so the
oversized opaque line-number gutter escaped the editor and painted over
the page above it. Re-asserted the clip, scoped to GraphiQL so the SQL
editor is untouched.
- **GraphiQL editor spacing** — removed GraphiQL's default 16px
query-editor padding so the scroll shadow sits flush, and restored the
content's breathing room via Monaco's own `padding` (top/bottom) and
`glyphMargin` (line-number left inset) options, which leave the scroll
shadow pinned to the top edge.

Before:
<img width="2056" height="814" alt="Screenshot 2026-06-26 at 5 27 24 PM"
src="https://github.com/user-attachments/assets/573856bf-2bfb-4bf2-9dd7-59c29b423ec9"
/>

## To test

- Open a project → **Integrations → GraphiQL** (the `graphiql` tab). The
editor should fill the full page height.
- Scroll the query editor — the scroll shadow should sit flush at the
top edge, not float inset, and the white gutter should not bleed over
the page header above.
- Confirm line numbers have left padding and content has top/bottom
padding.
- Trigger autocomplete in the editor — the suggestion popup should still
appear (not clipped by the gutter `overflow: hidden`).
- Toggle the **Marketplace** feature preview (Account dropdown → Feature
Previews) and re-check the GraphiQL page in both states, since it
renders through two different page components.


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

* **Bug Fixes**
* Improved the GraphQL in-browser editor layout to prevent the editor
gutter from overlapping surrounding content.
* Removed unnecessary query-editor padding so scrolling and shadow
effects display correctly in the available space.
* Ensured Monaco editor spacing/settings are applied consistently to
both existing and newly created editors.
* Fixed full-height sizing for integration pages so content stays
correctly constrained and doesn’t collapse or overflow.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <[email protected]>
2026-06-26 18:17:10 +08:00

126 lines
4.3 KiB
CSS

@reference "../../../../styles/globals.css";
.root :global(.graphiql-sidebar) {
@apply border-r border-default;
overflow-x: hidden;
}
.root :global(.graphiql-sidebar [data-value='settings']),
.root :global(.graphiql-sidebar [data-value='short-keys']) {
display: none;
}
.root :global(.graphiql-sessions) {
@apply m-0;
}
.root :global(#graphiql-session) {
@apply p-0;
}
.root :global(.graphiql-session-header) {
display: none;
}
.root :global(.graphiql-horizontal-drag-bar) {
@apply border-l border-default;
}
.root :global(.graphiql-horizontal-drag-bar:hover::after) {
@apply rounded-full;
}
.root :global(.graphiql-plugin) {
border-left: 0;
}
/* Restore Monaco's intended clipping of the editor body. Monaco renders the gutter as an
* oversized, scroll-offset `.margin` (absolutely positioned, opaque background) and relies
* on `.overflow-guard { overflow: hidden }` to clip it to the editor box. Here the guard
* ends up `overflow: visible` via an inline style Monaco's layout sets at runtime, so the
* white gutter escapes the editor and paints over the page above it. An inline style beats
* any external selector regardless of specificity, so `!important` is required to win — it
* is not a specificity shortcut here. Scoped to `.root` so the SQL editor's Monaco is
* untouched. Autocomplete/hover popups live in `.overflowingContentWidgets` (a sibling of
* `.overflow-guard`), so they are not clipped. */
.root :global(.monaco-editor .overflow-guard) {
@apply !overflow-hidden;
}
/* Drop GraphiQL's default 16px padding around the query editor so the editor sits flush to
* its container. This keeps Monaco's scroll shadow (`.scroll-decoration`, pinned to the
* editor's top edge) full-bleed instead of floating inset. The content's own breathing room
* is restored via Monaco's `padding`/`glyphMargin` options in GraphiQLTab.tsx. */
.root :global(.graphiql-query-editor) {
@apply p-0;
}
/* Lift the response panel above the editor surface so the two read as separate panes.
* The token differs per theme because the editor sits at a different baseline lightness
* in each (~12% L in dark, ~94% L in light), so a single surface token can't lift it
* meaningfully in both directions. */
.root :global(.graphiql-response),
.root :global(.graphiql-response .monaco-editor),
.root :global(.graphiql-response .monaco-editor .margin),
.root :global(.graphiql-response .monaco-editor .monaco-editor-background) {
background-color: var(--graphiql-response-bg) !important;
}
/* Editor-to-response drag bar: blend it into the response side so it doesn't read as
* a third color sandwiched between the two panes. The plugin-to-main drag bar is left
* alone — it sits next to the editor surface and our default border there is fine. */
.root :global(.graphiql-editors + .graphiql-horizontal-drag-bar) {
background-color: var(--graphiql-response-bg);
border-left: 0;
}
.root :global(.graphiql-button),
.root :global(button.graphiql-button),
.root :global(.graphiql-un-styled),
.root :global(button.graphiql-un-styled),
.root :global(button.graphiql-execute-button) {
@apply rounded-md;
}
.root :global(.graphiql-button-group) {
@apply rounded-lg;
}
.root :global(.graphiql-doc-explorer-search),
.root :global(.graphiql-doc-explorer-search-input) {
@apply rounded-md;
}
.root :global(.graphiql-doc-explorer-search [role='listbox']) {
@apply rounded-b-md;
}
/* Theme variable overrides */
.root {
--font-family: theme(fontFamily.sans);
--font-family-mono: theme(fontFamily.mono);
--border-radius-2: 0;
--border-radius-4: 0;
--border-radius-8: 0;
--border-radius-12: 0;
--popover-box-shadow: none;
}
:global(body.graphiql-dark) .root {
/* HSL form of #1f1f1f, matches the editor.background returned by getTheme('dark') */
--color-base: 0, 0%, 12%;
--color-primary: 153, 50%, 50%;
--graphiql-response-bg: hsl(var(--background-surface-300));
}
:global(body.graphiql-light) .root {
/* HSL form of #fcfcfc, matches the dashboard bg-default and the editor.background
* we override to in GraphiQLTab.tsx so the editor reads as part of the surrounding UI. */
--color-base: 0, 0%, 98.8%;
--color-primary: 153, 50%, 50%;
/* Drop the response below the editor in light mode (inverse of dark) so it reads as
* the lower / "data" surface rather than the lifted one. */
--graphiql-response-bg: hsl(var(--background-surface-300));
}