feat: close a page item tab from its editor header

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Diego Imbert
2026-09-17 18:06:57 +02:00
co-authored by Claude Opus 5
parent 6fb48c64df
commit 83778f571f
15 changed files with 73 additions and 29 deletions
@@ -28,6 +28,7 @@
workspace = undefined,
disableChatOffset = false,
inline = false,
onClose = undefined,
onRestored = undefined,
onSaved = undefined
}: {
@@ -39,6 +40,8 @@
* that gives the editor a whole pane. Saving and restoring then leave it open: the
* host remounts it on what was written. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
onRestored?: () => void
/** Fires after Save has written, for a caller showing state derived from the
* resource — `onRestored` only covers restoring an old version. `path` is where the
@@ -163,9 +166,9 @@
<DrawerContent
title={mode == 'edit' ? 'Edit ' + path : addResourceTitle(resource_type)}
bannerReserved={mode == 'edit'}
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet titleExtra()}
{#if mode == 'new' && resource_type}
@@ -44,12 +44,15 @@
let {
workspace = undefined,
inline = false,
onClose = undefined,
onSaved = undefined
}: {
workspace?: string
/** Render in place, filling the parent, with no drawer or close button — for a host
* that gives the editor a whole pane. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
/** Fires once a save lands, with the path the variable now lives at in `workspace` —
* not in the workspace-specific version selected, which can be another's. */
onSaved?: (path: string) => void
@@ -340,9 +343,9 @@
<DrawerContent
title={edit ? `Update variable at ${initialPath}` : 'Add a variable'}
bannerReserved={edit}
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet banner()}
<LocalDraftBanner
@@ -138,12 +138,19 @@
{:else}
{#key `${item.kind}:${triggerKey}:${item.path}:${workspaceId}:${reloadNonce}:${savedNonce}`}
{#if item.kind === 'variable'}
<VariableEditor bind:this={variableEditor} inline workspace={workspaceId} {onSaved} />
<VariableEditor
bind:this={variableEditor}
inline
workspace={workspaceId}
{onSaved}
onClose={closeTab}
/>
{:else if item.kind === 'resource'}
<ResourceEditorDrawer
bind:this={resourceEditor}
inline
workspace={workspaceId}
onClose={closeTab}
onSaved={(path) => {
if (path !== undefined) onSaved(path)
}}
@@ -157,6 +164,7 @@
bind:this={triggerEditor}
useDrawer
inline
onClose={closeTab}
onUpdate={(path?: string) => onSaved(path)}
/>
{/await}
@@ -48,6 +48,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -67,6 +69,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -406,7 +409,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -414,7 +417,7 @@
? `Edit AMQP trigger ${initialPath}`
: `AMQP trigger ${initialPath}`
: 'New AMQP trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsSnippet()}
@@ -85,6 +85,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -103,6 +104,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -363,7 +366,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -371,7 +374,7 @@
? `Edit Azure trigger ${initialPath}`
: `Azure trigger ${initialPath}`
: 'New Azure trigger'}
on:close={drawer?.closeDrawer}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsButtons()}
@@ -46,6 +46,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
hideTarget = false,
description = undefined,
isEditor = false,
@@ -499,7 +500,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -507,7 +508,7 @@
? `Edit email trigger ${initialPath}`
: `Email trigger ${initialPath}`
: 'New email trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render saveButton()}
@@ -95,6 +95,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -113,6 +114,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -418,7 +421,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -426,7 +429,7 @@
? `Edit GCP Pub/Sub trigger ${initialPath}`
: `GCP Pub/Sub trigger ${initialPath}`
: 'New GCP Pub/Sub trigger'}
on:close={drawer?.closeDrawer}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsButtons()}
@@ -85,6 +85,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
hideTarget = false,
description = undefined,
isEditor = false,
@@ -1069,11 +1070,11 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit ? (can_write ? `Edit route ${initialPath}` : `Route ${initialPath}`) : 'New route'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render saveButton()}
@@ -46,6 +46,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -65,6 +67,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -430,7 +433,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -438,7 +441,7 @@
? `Edit Kafka trigger ${initialPath}`
: `Kafka trigger ${initialPath}`
: 'New Kafka trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsButtons('sm')}
@@ -55,6 +55,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -74,6 +76,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -404,7 +407,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -412,7 +415,7 @@
? `Edit MQTT trigger ${initialPath}`
: `MQTT trigger ${initialPath}`
: 'New MQTT trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsSnippet()}
@@ -41,6 +41,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -61,6 +63,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -401,7 +404,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -409,7 +412,7 @@
? `Edit NATS trigger ${initialPath}`
: `NATS trigger ${initialPath}`
: 'New NATS trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsSnippet()}
@@ -63,6 +63,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
isEditor?: boolean
@@ -82,6 +84,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
isEditor = false,
@@ -585,7 +588,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -593,7 +596,7 @@
? `Edit Postgres trigger ${initialPath}`
: `Postgres trigger ${initialPath}`
: 'New Postgres trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}{@render actionsSnippet()}{/snippet}
{#snippet banner()}
@@ -56,6 +56,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
hideTarget = false,
docDescription = undefined,
allowDraft = false,
@@ -1425,7 +1426,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -1433,7 +1434,7 @@
? `Edit schedule ${initialPath}`
: `View schedule ${initialPath}`
: 'New schedule'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
<div class="flex flex-row gap-4 items-center">
@@ -47,6 +47,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -66,6 +68,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -383,7 +386,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -391,7 +394,7 @@
? `Edit SQS trigger ${initialPath}`
: `SQS trigger ${initialPath}`
: 'New SQS trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsSnippet()}
@@ -63,6 +63,8 @@
useDrawer?: boolean
/** With `useDrawer`, render the drawer's content in place, filling the parent, with no drawer or close button. */
inline?: boolean
/** With `inline`, closes whatever hosts the editor; the header has a close button only when set. */
onClose?: () => void
description?: Snippet | undefined
hideTarget?: boolean
hideTooltips?: boolean
@@ -83,6 +85,7 @@
let {
useDrawer = true,
inline = false,
onClose = undefined,
description = undefined,
hideTarget = false,
hideTooltips = false,
@@ -474,7 +477,7 @@
{#snippet drawerBody()}
<DrawerContent
hideClose={inline}
hideClose={inline && !onClose}
fullScreen={!inline}
bannerReserved={draftSync.hasBaseline}
title={edit
@@ -482,7 +485,7 @@
? `Edit WebSocket trigger ${initialPath}`
: `WebSocket trigger ${initialPath}`
: 'New WebSocket trigger'}
on:close={() => drawer?.closeDrawer()}
on:close={() => (inline ? onClose?.() : drawer?.closeDrawer())}
>
{#snippet actions()}
{@render actionsButtons()}