Skip to content

Commit c9547dc

Browse files
waleedlatif1Waleed Latif
andauthored
fix(desktop): keep page headers clear of the traffic lights (#6098)
* fix(desktop): keep page headers clear of the traffic lights In the desktop app, collapsing the sidebar hands the top-left of the screen to the content pane — the macOS traffic lights and the sidebar expander then sit over page content rather than over the sidebar. Every top-of-page header bar drew straight underneath them, so back buttons and the integrations/skills switcher were unreadable and unclickable. The reason it hit all of them at once is that the bar's geometry was copied verbatim into seven files, so nothing could reserve that lane in one place. Extract it as PAGE_HEADER_BAR and fold the lane into its top padding via `--workspace-content-title-bar-inset`, the variable the content pane already publishes for exactly this. That variable is 0px everywhere except the macOS desktop app with the sidebar collapsed, so this is inert on the web and on an expanded sidebar, where the lights sit over sidebar chrome that already reserves its own lane. Covers the settings shell, the credential/skill detail layout, the integrations and skills switcher, integration block detail and its fallback, and both upgrade headers. A guard test fails with the file named if any page re-derives the bar instead of composing it. * fix(desktop): cover the Resource header bar too The first pass found its surfaces by grepping one exact class string, which turned up the minority header. `ResourceHeader` is the same bar written as `px-4 py-[8.5px]`, and it is the one logs, files, tables, knowledge and scheduled tasks use — plus every loading fallback. Those all still drew under the traffic lights, and on the breadcrumb surfaces the occluded element is an interactive popover button, not just a title. Share the lane math as TITLE_BAR_LANE_PT and compose it from both bar geometries, which genuinely differ (the Resource bar is bordered and has a min height). Nothing nests one bar inside the other, so no reset is needed: the only out-of-pane render is the landing tables preview. Move the variable's `0px` default to `:root` alongside the other desktop-title-bar vars, so it is defined for bars outside `.workspace-content-shell` — the standalone settings shell and that landing preview — where an undefined var() inside calc() would be invalid at computed-value time and drop padding-top entirely. That replaces the per-call fallback, leaving one default instead of two that can drift. Fold the assertions into the existing desktop title-bar surface audit rather than a second audit file with its own conventions. The standalone guard is gone: it keyed on one spelling of the geometry, so it was blind to `px-4 py-[8.5px]` — the very re-derivation that made this pass necessary. * fix(desktop): cover fullscreen routes, spare embedded panels Review round 2 found the two arrangements the collapsed-sidebar selector alone gets wrong. A fullscreen route (/upgrade) slides the sidebar to zero width without collapsing it, so `data-sidebar-collapsed` is absent and the lane stayed zero while the pane was in fact sitting under the traffic lights. The pane owns the lane whenever the sidebar is not there to own it, so the selector now matches a new `data-content-fullscreen` as well. The mirror error: the variable is inherited, and the mothership panel is the right half of the pane — never under the lights — yet it embeds whole pages (KnowledgeBase and friends) whose header bars reserve the lane. Those bars were gaining ~38px inside the panel. The panel now zeroes the variable for its subtree. I had checked for exactly this nesting and concluded it did not exist, having looked only at the settings pages that import `Resource` types without rendering `Resource.Header`. `resource-content.tsx` renders the knowledge page itself, which does. An assertion each, both verified to fail when the fix is reverted. * fix(desktop): size the peek card to its content, soften the overlay shadow The floating sidebar pinned both its top and bottom edges, so it always drew at full window height. On a short surface — the settings list — that left a tall empty slab of card hanging below the last entry. The card now hugs its content and caps at the pane height less the traffic-light lane and the bottom gutter. Dropping the bottom pin is most of it: the four `h-full` rules down the chain resolve against an auto-height parent and collapse to content on their own. But nothing would then bound the sidebar's own `flex-1 overflow-y-auto` region, so a long workflow list would be clipped by the card's `overflow-hidden` instead of scrolling. The card is therefore a capped flex column, and the shell is allowed to shrink inside it, which restores a definite height for the chain to resolve against. That rule is scoped to `[data-peek]` and is inert while docked, where the shell is not a flex item. Also eases `--shadow-overlay` in both themes (alpha ~27% lighter, bloom pulled in from 48px to 30px), keeping it clearly above `--shadow-medium` so the scale still reads in order. The peek card drops the shadow entirely and separates on the same `--border` hairline the content pane beside it uses. * fix(desktop): stop the login page scrolling, drop the pane border at the window edge Two reports against the desktop window chrome. The login page scrolled by exactly the traffic-light lane. `.desktop-title-bar-page` reserved the lane with `margin-top` plus a `calc(100vh - lane)` height, which sums to the viewport on its own — but `body` carries `min-height: 100vh`, and body is a plain block box with no padding, border, or BFC, so that top margin had nothing to collapse against and collapsed through, displacing body itself. The document came out one full lane taller than the viewport while the shell's `calc` saving was re-inflated underneath it. Reserving the lane with padding *inside* the box removes both the collapse and the `calc`: global `box-sizing: border-box` keeps the padding within the `100vh`. Measured in the Electron renderer over CDP — 40px of overflow before, 0 after, with the logo still clear of the lane. Collapsing the sidebar also left a hairline outline traced just inside the window. The shell drops to `p-0` there, but the content pane kept its border and 8px radius, so both drew flush against the square window frame. The pane now drops them exactly when it is flush. Keyed off the ancestor attributes rather than React state, because the title-bar attribute is written pre-paint and a state-driven rule would flash the border before hydration settles. * docs(desktop): correct the peek card chrome comment The card's TSDoc still listed `shadow-overlay` as part of its chrome after the shadow was deliberately dropped, so the comment contradicted the code. It now records that the card is unshadowed on purpose, and documents the content-hugging height and the flex-column cap that make the sidebar's scroll region bound itself. --------- Co-authored-by: Waleed Latif <waleed@simstudio.ai>
1 parent 811a39e commit c9547dc

12 files changed

Lines changed: 181 additions & 23 deletions

File tree

apps/sim/app/_shell/desktop-title-bar-surfaces.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ const workspaceChrome = read(
1414
)
1515
const sidebar = read('../workspace/[workspaceId]/w/components/sidebar/sidebar.tsx')
1616
const globalStyles = read('../_styles/globals.css')
17+
const pageHeaderBar = read('../../components/page-header-bar.ts')
18+
const resourceHeader = read(
19+
'../workspace/[workspaceId]/components/resource/components/resource-header/resource-header.tsx'
20+
)
21+
const mothershipView = read(
22+
'../workspace/[workspaceId]/home/components/mothership-view/mothership-view.tsx'
23+
)
1724

1825
describe('desktop title-bar surface audit', () => {
1926
it('applies the safe-area shell only when the auth route is login', () => {
@@ -65,4 +72,70 @@ describe('desktop title-bar surface audit', () => {
6572
expect(sidebar).toContain('[[data-sim-desktop-title-bar=inset]_&]:pt-[var(')
6673
expect(sidebar).not.toMatch(/\[\[data-sim-desktop-title-bar=inset\]_&\]:pt-\d/)
6774
})
75+
76+
it('defines the content-pane lane once, defaulting to zero', () => {
77+
// A `:root` default keeps the variable defined for bars that render outside
78+
// `.workspace-content-shell` (the standalone settings shell at /account,
79+
// /organization/[id], /selfhost; the landing tables preview). An undefined var()
80+
// inside calc() is invalid at computed-value time and drops padding-top entirely.
81+
expect(globalStyles).toMatch(/:root\s*\{[^}]*--workspace-content-title-bar-inset:\s*0px/s)
82+
// The pane owns the lane in both arrangements where the sidebar is not there to
83+
// own it: collapsed to zero width, and slid away for a fullscreen route (which
84+
// leaves the sidebar expanded in the store, so the collapsed selector alone misses
85+
// it and /upgrade's back chip lands under the traffic lights).
86+
expect(globalStyles).toContain('.workspace-content-shell[data-sidebar-collapsed],')
87+
expect(globalStyles).toContain('.workspace-content-shell[data-content-fullscreen] {')
88+
expect(workspaceChrome).toContain('data-content-fullscreen={isFullscreen || undefined}')
89+
})
90+
91+
it('sizes the peek card to its content, capped against the lane', () => {
92+
// Pinning both edges made the card full height, so a short list (settings) left a
93+
// tall empty slab over the content. It now hugs its content and caps at the pane
94+
// height less the lane and the bottom gutter, so a long list still scrolls.
95+
expect(workspaceChrome).toContain('max-h-[calc(100%-var(--desktop-title-bar-height)-8px)]')
96+
expect(workspaceChrome).not.toMatch(/PEEK_CARD_CHROME[\s\S]{0,240}?bottom-2/)
97+
})
98+
99+
it('reserves the login lane inside the box, never as a collapsing margin', () => {
100+
// `body` carries `min-height: 100vh`, and a `margin-top` here collapses through it
101+
// (body is a plain block box, so it opens no BFC) and displaces body itself. The
102+
// document then measured one full lane taller than the viewport, which is what made
103+
// the desktop login page scroll. Verified live: 40px of overflow, now 0.
104+
// Comments are stripped first: the rule documents why `margin-top` is wrong, and a
105+
// raw `not.toContain` would match that prose instead of a declaration.
106+
const rule = (globalStyles.match(/\.desktop-title-bar-page \{[^}]*\}/)?.[0] ?? '').replace(
107+
/\/\*[\s\S]*?\*\//g,
108+
''
109+
)
110+
expect(rule).toContain('padding-top: var(--desktop-title-bar-height)')
111+
expect(rule).toContain('min-height: 100vh')
112+
expect(rule).not.toContain('margin-top')
113+
})
114+
115+
it('drops the content pane border where the pane meets the window edge', () => {
116+
// Collapsing the sidebar in the desktop shell takes the pane's padding to 0, so a
117+
// retained border and radius drew a hairline outline inset from the square window.
118+
const flush = '[[data-sim-desktop-title-bar=inset]_[data-sidebar-collapsed]_&]:'
119+
expect(workspaceChrome).toContain(`${flush}rounded-none`)
120+
expect(workspaceChrome).toContain(`${flush}border-0`)
121+
})
122+
123+
it('clears the lane for panels that embed pages away from the lights', () => {
124+
// The mothership panel is the right half of the pane and embeds whole pages
125+
// (KnowledgeBase et al) whose header bars reserve the lane. It inherits the
126+
// variable, so without this reset those bars gain the inset while sitting nowhere
127+
// near the traffic lights.
128+
expect(mothershipView).toContain('[--workspace-content-title-bar-inset:0px]')
129+
})
130+
131+
it('reserves that lane in every top-of-pane header bar', () => {
132+
// Both top-bar geometries must compose the shared lane padding. A bare
133+
// `pt-`/`py-[8.5px]` in either is the bug: the bar then draws under the traffic
134+
// lights and the sidebar expander whenever the sidebar is collapsed on desktop.
135+
expect(pageHeaderBar).toContain('pt-[calc(8.5px+var(--workspace-content-title-bar-inset))]')
136+
expect(pageHeaderBar).toContain('TITLE_BAR_LANE_PT')
137+
138+
expect(resourceHeader).toContain('TITLE_BAR_LANE_PT')
139+
expect(resourceHeader).not.toMatch(/py-\[8\.5px\]/)
140+
})
68141
})

apps/sim/app/_styles/globals.css

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
--sidebar-collapsed-width: 51px; /* icon rail on web; desktop overrides to 0 before first paint */
1515
--sidebar-expanded-width: 248px; /* SIDEBAR_WIDTH.DEFAULT; the width to restore to, held even while collapsed */
1616
--desktop-title-bar-height: 0px; /* macOS traffic-light lane; desktop overrides before first paint */
17+
--workspace-content-title-bar-inset: 0px; /* lane the content pane must leave clear; only non-zero when the pane, not the sidebar, sits under it */
1718
--desktop-title-bar-inset-x: 0px; /* clearance past the traffic lights; desktop overrides */
1819
--desktop-title-bar-control-offset: 0px; /* centres a lane control; desktop overrides */
1920
--desktop-title-bar-control-size: 0px; /* control seated in the lane; desktop overrides */
@@ -43,7 +44,7 @@
4344
/* Shadow scale */
4445
--shadow-subtle: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
4546
--shadow-medium: 0 4px 12px rgba(0, 0, 0, 0.1);
46-
--shadow-overlay: 0 16px 48px rgba(0, 0, 0, 0.15);
47+
--shadow-overlay: 0 10px 30px rgba(0, 0, 0, 0.11);
4748
--shadow-kbd: 0 4px 0 0 rgba(48, 48, 48, 1);
4849
--shadow-kbd-sm: 0 2px 0 0 rgba(48, 48, 48, 1);
4950
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.04);
@@ -75,8 +76,14 @@ html[data-sim-desktop-title-bar="inset"] {
7576

7677
/** The macOS desktop login shell reserves the native traffic-light lane. */
7778
.desktop-title-bar-page {
78-
margin-top: var(--desktop-title-bar-height);
79-
min-height: calc(100vh - var(--desktop-title-bar-height));
79+
/* Reserve the lane with padding INSIDE the box, never `margin-top` + a
80+
`calc(100vh - lane)` height. `body` carries `min-height: 100vh` of its own, and
81+
a top margin here has nothing to collapse against (body is a block box with no
82+
padding, border, or BFC), so it collapses through and displaces body itself —
83+
leaving a document one full lane taller than the viewport. Global
84+
`box-sizing: border-box` keeps this padding inside the 100vh. */
85+
padding-top: var(--desktop-title-bar-height);
86+
min-height: 100vh;
8087
}
8188

8289
.desktop-window-drag-region {
@@ -122,11 +129,10 @@ html[data-sim-desktop-title-bar="inset"]
122129
letter-spacing: 0.02em;
123130
}
124131

125-
.workspace-content-shell {
126-
--workspace-content-title-bar-inset: 0px;
127-
}
128-
129-
.workspace-content-shell[data-sidebar-collapsed] {
132+
/* The pane owns the lane whenever the sidebar is not there to own it: collapsed to
133+
zero width, or slid away for a fullscreen route. */
134+
.workspace-content-shell[data-sidebar-collapsed],
135+
.workspace-content-shell[data-content-fullscreen] {
130136
--workspace-content-title-bar-inset: var(--desktop-title-bar-height);
131137
}
132138

@@ -173,6 +179,14 @@ html[data-sim-desktop-title-bar="inset"]
173179
transition: none;
174180
}
175181

182+
/* The card is a flex column sized to its content, so the shell must be allowed to
183+
shrink for the sidebar's own scroll region to bound itself once the card hits its
184+
max height. Docked, this element is not a flex item and the rule is inert. */
185+
.sidebar-shell-outer[data-peek] .sidebar-shell-inner {
186+
min-height: 0;
187+
flex-shrink: 1;
188+
}
189+
176190
.sidebar-container span,
177191
.sidebar-container .text-small {
178192
transition: opacity 120ms ease;
@@ -583,7 +597,7 @@ html.sidebar-booting .sidebar-shell-inner {
583597
--scrollbar-thumb-hover-color: #6a6a6a;
584598

585599
/* Shadow scale - dark */
586-
--shadow-overlay: 0 16px 48px rgba(0, 0, 0, 0.4);
600+
--shadow-overlay: 0 10px 30px rgba(0, 0, 0, 0.3);
587601
}
588602
}
589603

apps/sim/app/workspace/[workspaceId]/components/credential-detail/components/credential-detail-layout.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import type { ReactNode } from 'react'
2+
import { cn } from '@sim/emcn'
3+
import { PAGE_HEADER_BAR } from '@/components/page-header-bar'
24

35
interface CredentialDetailLayoutProps {
46
/** Back link rendered at the start of the fixed action bar. */
@@ -17,7 +19,7 @@ interface CredentialDetailLayoutProps {
1719
export function CredentialDetailLayout({ back, actions, children }: CredentialDetailLayoutProps) {
1820
return (
1921
<div className='flex h-full flex-col bg-[var(--bg)]'>
20-
<div className='flex flex-shrink-0 items-center justify-between bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
22+
<div className={cn(PAGE_HEADER_BAR, 'justify-between')}>
2123
{back}
2224
{actions ? <div className='flex items-center'>{actions}</div> : null}
2325
</div>

apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-header/resource-header.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
} from '@sim/emcn'
3232
import { ArrowUpLeft } from 'lucide-react'
3333
import { createPortal } from 'react-dom'
34+
import { TITLE_BAR_LANE_PT } from '@/components/page-header-bar'
3435
import { InlineRenameInput } from '@/app/workspace/[workspaceId]/components/inline-rename-input'
3536
import { FloatingOverflowText } from '@/app/workspace/[workspaceId]/components/resource/components/floating-overflow-text'
3637

@@ -131,7 +132,10 @@ export const ResourceHeader = memo(function ResourceHeader({
131132
return (
132133
<div
133134
ref={headerRef}
134-
className='flex min-h-[48px] items-center border-[var(--border)] border-b px-4 py-[8.5px]'
135+
className={cn(
136+
'flex min-h-[48px] items-center border-[var(--border)] border-b px-4 pb-[8.5px]',
137+
TITLE_BAR_LANE_PT
138+
)}
135139
>
136140
<div className='flex min-w-0 flex-1 items-center justify-between gap-3'>
137141
<div className='flex min-w-0 flex-1 items-center gap-2 overflow-hidden'>

apps/sim/app/workspace/[workspaceId]/components/workspace-chrome/workspace-chrome.tsx

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,26 @@ const SLIDE_TRANSITION =
2222
* The peek card's floating chrome.
2323
*
2424
* Every value is an existing token: `rounded-lg` is `--radius`, matching the content
25-
* pane it floats beside; `--border` is that pane's border; `shadow-overlay` and
26-
* `--z-modal` are what the app's other edge-anchored panels use. The card's fill is
27-
* the sidebar's own `--surface-1`, so docked and floating are the same surface.
25+
* pane it floats beside; `--border` is that pane's border; `--z-modal` is what the
26+
* app's other edge-anchored panels use. The card's fill is the sidebar's own
27+
* `--surface-1`, so docked and floating are the same surface.
28+
*
29+
* Deliberately unshadowed. It separates on the same `--border` hairline the content
30+
* pane beside it uses; `--shadow-overlay` reads as too heavy at this size, where the
31+
* card abuts the window edge rather than floating over the middle of the page.
32+
*
33+
* The card hugs its content and caps at the pane height less the lane and the bottom
34+
* gutter — pinning both edges left a tall empty slab below short lists. It is a flex
35+
* column so the shell can shrink inside that cap and the sidebar's own scroll region
36+
* still bounds itself; see the `[data-peek]` rule in `globals.css`.
2837
*
2938
* `w-auto` shrink-wraps the inner shell, which `[data-peek]` has already put at the
3039
* expanded width. It must not be a length: `width` cannot interpolate to or from
3140
* `auto`, so entering and leaving the peek snap instead of animating — otherwise the
3241
* card widens as it appears and leaves a shrinking ghost on retract.
3342
*/
3443
const PEEK_CARD_CHROME =
35-
'absolute top-[var(--desktop-title-bar-height)] bottom-2 left-2 z-[var(--z-modal)] w-auto origin-top-left rounded-lg border border-[var(--border)] shadow-overlay'
44+
'absolute top-[var(--desktop-title-bar-height)] left-2 z-[var(--z-modal)] flex max-h-[calc(100%-var(--desktop-title-bar-height)-8px)] w-auto flex-col origin-top-left rounded-lg border border-[var(--border)]'
3645

3746
/**
3847
* Peek card enter/exit — the popper idiom rather than a slide, since the card is
@@ -57,6 +66,20 @@ const PEEK_CARD_EXIT = cn(
5766
/** The docked rail: in flow, width-animated by the collapse toggle. */
5867
const SIDEBAR_SHELL_IN_FLOW = cn('transition-[width]', SLIDE_TRANSITION)
5968

69+
/**
70+
* The content pane's own chrome, dropped when the pane sits flush to the window.
71+
*
72+
* Collapsing the sidebar in the desktop shell takes the surrounding padding to `0`,
73+
* which puts the pane hard against the window edge — and its border and radius then
74+
* draw a hairline outline with rounded corners inset from the square window frame.
75+
*
76+
* Keyed off the ancestor attributes rather than React state on purpose: the title-bar
77+
* attribute is written pre-paint, so a state-driven rule would flash the border on
78+
* first paint before hydration settles.
79+
*/
80+
const CONTENT_PANE_FLUSH =
81+
'[[data-sim-desktop-title-bar=inset]_[data-sidebar-collapsed]_&]:rounded-none [[data-sim-desktop-title-bar=inset]_[data-sidebar-collapsed]_&]:border-0'
82+
6083
interface WorkspaceChromeProps {
6184
children: React.ReactNode
6285
/** Cookie-derived collapse state from the server layout; seeds the sidebar's first render. */
@@ -295,8 +318,16 @@ export function WorkspaceChrome({
295318
isCollapsed && '[[data-sim-desktop-title-bar=inset]_&]:p-0'
296319
)}
297320
data-sidebar-collapsed={isCollapsed || undefined}
321+
/* A fullscreen route slides the sidebar away without collapsing it, so the pane
322+
inherits the traffic-light lane the same way a collapsed sidebar does. */
323+
data-content-fullscreen={isFullscreen || undefined}
298324
>
299-
<div className='flex-1 overflow-hidden rounded-[8px] border border-[var(--border)] bg-[var(--bg)]'>
325+
<div
326+
className={cn(
327+
'flex-1 overflow-hidden rounded-[8px] border border-[var(--border)] bg-[var(--bg)]',
328+
CONTENT_PANE_FLUSH
329+
)}
330+
>
300331
{children}
301332
</div>
302333
</div>

apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/mothership-view.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ export const MothershipView = memo(
137137
className={cn(
138138
'relative z-10 flex h-full flex-col overflow-hidden border-[var(--border)] bg-[var(--bg)] transition-[width,min-width,border-width] duration-200 ease-[cubic-bezier(0.25,0.1,0.25,1)]',
139139
isCollapsed ? 'w-0 min-w-0 border-l-0' : 'w-1/2 border-l',
140+
/* This panel is the right half of the pane, never under the traffic lights,
141+
yet it embeds whole pages whose header bars reserve that lane. Zeroing the
142+
inherited variable here keeps their top bars flush inside the panel. */
143+
'[--workspace-content-title-bar-inset:0px]',
140144
className
141145
)}
142146
>

apps/sim/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail-fallback.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { ChipLink } from '@sim/emcn'
44
import { ArrowLeft } from 'lucide-react'
5+
import { PAGE_HEADER_BAR } from '@/components/page-header-bar'
56

67
interface IntegrationBlockDetailFallbackProps {
78
workspaceId: string
@@ -23,7 +24,7 @@ export function IntegrationBlockDetailFallback({
2324
}: IntegrationBlockDetailFallbackProps) {
2425
return (
2526
<div className='flex h-full flex-col bg-[var(--bg)]'>
26-
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
27+
<div className={PAGE_HEADER_BAR}>
2728
<ChipLink href={`/workspace/${workspaceId}/integrations`} leftIcon={ArrowLeft}>
2829
Integrations
2930
</ChipLink>

apps/sim/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ArrowLeft, ArrowRight, Plus } from 'lucide-react'
66
import Link from 'next/link'
77
import { useRouter } from 'next/navigation'
88
import { useQueryState } from 'nuqs'
9+
import { PAGE_HEADER_BAR } from '@/components/page-header-bar'
910
import {
1011
blockTypeToIconMap,
1112
type Integration,
@@ -138,7 +139,7 @@ export function IntegrationBlockDetail({ integration, workspaceId }: Integration
138139

139140
return (
140141
<div className='flex h-full flex-col bg-[var(--bg)]'>
141-
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
142+
<div className={PAGE_HEADER_BAR}>
142143
<ChipLink href={`/workspace/${workspaceId}/integrations`} leftIcon={ArrowLeft}>
143144
Integrations
144145
</ChipLink>

apps/sim/app/workspace/[workspaceId]/integrations/components/integration-tabs-header/integration-tabs-header.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ReactNode } from 'react'
22
import { ChipLink } from '@sim/emcn'
3+
import { PAGE_HEADER_BAR } from '@/components/page-header-bar'
34

45
interface IntegrationTabsHeaderProps {
56
active: 'integrations' | 'skills'
@@ -18,7 +19,7 @@ export function IntegrationTabsHeader({
1819
rightSlot,
1920
}: IntegrationTabsHeaderProps) {
2021
return (
21-
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
22+
<div className={PAGE_HEADER_BAR}>
2223
<ChipLink href={`/workspace/${workspaceId}/integrations`} active={active === 'integrations'}>
2324
Integrations
2425
</ChipLink>

apps/sim/app/workspace/[workspaceId]/upgrade/upgrade.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ArrowLeft, Chip, toast } from '@sim/emcn'
55
import { getErrorMessage } from '@sim/utils/errors'
66
import { useRouter } from 'next/navigation'
77
import { useQueryState } from 'nuqs'
8+
import { PAGE_HEADER_BAR } from '@/components/page-header-bar'
89
import { useSession } from '@/lib/auth/auth-client'
910
import {
1011
getUpgradeCardCta,
@@ -99,7 +100,7 @@ export function Upgrade({ workspaceId }: UpgradeProps) {
99100

100101
return (
101102
<div className='flex h-full flex-col bg-[var(--bg)]'>
102-
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
103+
<div className={PAGE_HEADER_BAR}>
103104
<Chip leftIcon={ArrowLeft} onClick={handleBack}>
104105
Back
105106
</Chip>
@@ -192,7 +193,7 @@ export function Upgrade({ workspaceId }: UpgradeProps) {
192193

193194
return (
194195
<div className='flex h-full flex-col bg-[var(--bg)]'>
195-
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
196+
<div className={PAGE_HEADER_BAR}>
196197
<Chip leftIcon={ArrowLeft} onClick={handleBack}>
197198
Back
198199
</Chip>

0 commit comments

Comments
 (0)