feat(conversation): provide the session header corner slot

This commit is contained in:
imccyu committed 2026-09-07 21:29:40 +08:00
1 parent 9241e10a47
commit 4909550782
5 files changed
+40 -1

No files matched your search

@@ -279,6 +279,7 @@ export function apply(ctx: Context, config: Config = Config({})): void {
'conversation.session.header.lineage': { kind: 'single', scope: 'session' },
'conversation.session.header.actions': { kind: 'list', scope: 'session' },
'conversation.session.header.utilities': { kind: 'list', scope: 'session' },
'conversation.session.header.corner': { kind: 'single', scope: 'session' },
},
store: conversationStore,
inject: (sessionId: SessionId, actions: BoundActions<typeof conversationStore>): ConversationSessionHeaderInjected => ({
@@ -139,6 +139,18 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
scope: 'session'
owner: ConversationHeaderActionOwnerProps
}
/**
* The header's far-right corner, past the utilities' edge and into the
* header's own padding, for one control that must keep its place whether or
* not it currently shows anything. The corner reserves its width while an
* occupant is registered, so the utilities beside it never move; an
* occupant with nothing to show renders a same-size placeholder.
*/
'conversation.session.header.corner': {
kind: 'single'
scope: 'session'
owner: ConversationHeaderCornerOwnerProps
}
/** Registered Conversation target Views, rendered one at a time. */
'conversation.view': { kind: 'list'; scope: 'session'; owner: ConvViewOwnerProps }
/** Selector-routed replacements for the current Session's resident composer. */
@@ -209,6 +221,12 @@ export interface ConversationHeaderActionOwnerProps {
children?: never
}
/** The header corner's occupant derives its state from standard Session props. */
export interface ConversationHeaderCornerOwnerProps {
/** Marker field: the occupant receives no owner-specific values. */
children?: never
}
/** Plain breadcrumb data handed to the optional lineage renderer. */
export interface ConversationHeaderLineageOwnerProps {
/** Session represented by this breadcrumb title. */
@@ -375,6 +393,7 @@ export type ConversationSessionHeaderSlotProps =
'conversation.session.header.lineage'
| 'conversation.session.header.actions'
| 'conversation.session.header.utilities'
| 'conversation.session.header.corner'
>
& PropsStore<ConversationStore>
& InjectFace<ConversationSessionHeaderInjected>
@@ -51,7 +51,7 @@ export type {
ComposerAttachment, ComposerAttachmentsOwnerProps, ComposerAttachmentsProps,
ComposerFileAttachment, ComposerImageAttachment, DraftFileUpload, DraftFileUploads,
ComposerBarInjected, ComposerBarOwnerProps, ComposerBarProps, ComposerChainProps,
ConversationHeaderActionOwnerProps, ConversationHeaderLineageOwnerProps,
ConversationHeaderActionOwnerProps, ConversationHeaderCornerOwnerProps, ConversationHeaderLineageOwnerProps,
ConversationInjected, ConversationSessionHeaderInjected, ConversationSessionHeaderSlotProps,
ConversationSessionInjected, ConversationSessionSlotProps, ConversationSlotProps,
ConversationStore, ConvViewOwnerProps, ConvViewProps, EmptyWorkspaceOwnerProps,
@@ -146,6 +146,22 @@
display: none;
}
/* The far-right corner seat reaches 16px into the header's 28px right padding,
so its control sits past the utilities' edge; it is laid out only while an
occupant is registered, and the occupant keeps its width while hidden, so the
utilities never move because of it. */
.headerCorner {
display: flex;
flex: none;
align-items: center;
margin-left: 12px;
margin-right: -16px;
}
.headerCorner:empty {
display: none;
}
/* figma Tab_Group 34:11441: 35px strip, gap 36, pad-left 8, tabs bottom-aligned. */
.tabs {
position: relative;
@@ -133,6 +133,9 @@ export function ConversationSessionHeader({
<div className={css.headerUtilities}>
{renderSlot('conversation.session.header.utilities', {})}
</div>
<div className={css.headerCorner} data-conversation-header-corner="">
{renderSlot('conversation.session.header.corner', {})}
</div>
</div>
{tabs.length > 1 && (
<div className={css.tabs} role="tablist">