Skip to content

Commit 55f5270

Browse files
committed
Panel styles
1 parent 58cdafc commit 55f5270

7 files changed

Lines changed: 167 additions & 133 deletions

File tree

x-pack/platform/packages/shared/agent-builder/agent-builder-browser/attachments/contract.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,14 @@ export interface AttachmentUIDefinition<TAttachment extends UnknownAttachment =
115115
getLabel: (attachment: TAttachment) => string;
116116
/**
117117
* Returns the icon type to display for the attachment.
118+
* When provided, the icon is rendered in the inline attachment header alongside the title.
118119
*/
119120
getIcon?: () => IconType;
121+
/**
122+
* Optional badge or content rendered below the title in the inline attachment header.
123+
* Use for status indicators such as Draft/Created state.
124+
*/
125+
getHeaderBadge?: (attachment: TAttachment) => ReactNode;
120126
/**
121127
* Optional custom click handler for attachment pills.
122128
* When provided, pills will invoke this instead of the default behavior.

x-pack/platform/plugins/shared/agent_builder/public/application/components/conversations/conversation_rounds/round_response/attachments/attachment_header.tsx

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@
66
*/
77

88
import React from 'react';
9+
import type { ReactNode } from 'react';
910
import {
1011
EuiBadge,
1112
EuiButtonIcon,
1213
EuiFlexGroup,
1314
EuiFlexItem,
15+
EuiIcon,
1416
EuiSplitPanel,
15-
EuiText,
17+
EuiTitle,
1618
useEuiTheme,
1719
} from '@elastic/eui';
20+
import type { IconType } from '@elastic/eui';
1821
import { css } from '@emotion/react';
1922
import type { ActionButton } from '@kbn/agent-builder-browser/attachments';
2023
import { i18n } from '@kbn/i18n';
@@ -39,6 +42,10 @@ export const HEADER_HEIGHT = 72;
3942

4043
interface AttachmentHeaderProps {
4144
title: string;
45+
/** Optional icon rendered to the left of the title, sized to span title + badge height. */
46+
icon?: IconType;
47+
/** Optional badge or content rendered below the title, inside the header. */
48+
headerBadge?: ReactNode;
4249
actionButtons?: ActionButton[];
4350
onClose?: () => void;
4451
/**
@@ -52,19 +59,14 @@ interface AttachmentHeaderProps {
5259

5360
export const AttachmentHeader: React.FC<AttachmentHeaderProps> = ({
5461
title,
62+
icon,
63+
headerBadge,
5564
actionButtons,
5665
onClose,
5766
previewBadgeState = 'none',
5867
}) => {
5968
const { euiTheme } = useEuiTheme();
6069

61-
const textStyles = css`
62-
font-weight: ${euiTheme.font.weight.semiBold};
63-
overflow: hidden;
64-
white-space: nowrap;
65-
text-overflow: ellipsis;
66-
`;
67-
6870
const headerStyles = css`
6971
position: relative;
7072
display: flex;
@@ -82,7 +84,17 @@ export const AttachmentHeader: React.FC<AttachmentHeaderProps> = ({
8284
z-index: ${euiTheme.levels.content};
8385
`;
8486

85-
if (!actionButtons || actionButtons.length === 0) {
87+
const iconContainerStyles = css`
88+
border-right: ${euiTheme.border.thin};
89+
padding: ${euiTheme.size.m};
90+
padding-left: 0;
91+
display: flex;
92+
align-items: center;
93+
justify-content: center;
94+
flex-shrink: 0;
95+
`;
96+
97+
if (!actionButtons?.length && !icon && !headerBadge) {
8698
return null;
8799
}
88100

@@ -98,17 +110,36 @@ export const AttachmentHeader: React.FC<AttachmentHeaderProps> = ({
98110
justifyContent="spaceBetween"
99111
alignItems="center"
100112
style={{ width: '100%' }}
113+
gutterSize="s"
101114
>
115+
{icon && (
116+
<EuiFlexItem grow={false}>
117+
<div css={iconContainerStyles}>
118+
<EuiIcon type={icon} size="l" color="subdued" aria-hidden={true} />
119+
</div>
120+
</EuiFlexItem>
121+
)}
102122
<EuiFlexItem grow={true} style={{ minWidth: 0 }}>
103-
<EuiText css={textStyles} size="s">
104-
{title}
105-
</EuiText>
123+
<EuiFlexGroup
124+
direction="column"
125+
gutterSize="xs"
126+
alignItems="flexStart"
127+
responsive={false}
128+
>
129+
<EuiFlexItem grow={false}>
130+
<EuiTitle size="xs">
131+
{/* h3 would be semantically preferred, but browser UA styles override EuiTitle's size prop here; h5 native size is close enough to xs that it doesn't. */}
132+
<h5>{title}</h5>
133+
</EuiTitle>
134+
</EuiFlexItem>
135+
{headerBadge && <EuiFlexItem grow={false}>{headerBadge}</EuiFlexItem>}
136+
</EuiFlexGroup>
106137
</EuiFlexItem>
107-
{previewBadgeState !== 'previewing' && (
138+
{previewBadgeState !== 'previewing' && actionButtons?.length ? (
108139
<EuiFlexItem grow={false} style={{ flexShrink: 0 }}>
109140
<AttachmentActions buttons={actionButtons} />
110141
</EuiFlexItem>
111-
)}
142+
) : null}
112143
{previewBadgeState === 'previewing' && (
113144
<EuiFlexItem grow={false} style={{ flexShrink: 0 }}>
114145
<EuiBadge iconType="eye" color="success">

x-pack/platform/plugins/shared/agent_builder/public/application/components/conversations/conversation_rounds/round_response/attachments/inline_attachment_with_actions.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ export const InlineAttachmentWithActions: React.FC<InlineAttachmentWithActionsPr
115115
}
116116

117117
const title = uiDefinition?.getLabel?.(attachment) ?? attachment.type.toUpperCase();
118+
const icon = uiDefinition?.getIcon?.();
119+
const headerBadge = uiDefinition?.getHeaderBadge?.(attachment);
118120

119121
return (
120122
<EuiSplitPanel.Outer
@@ -127,6 +129,8 @@ export const InlineAttachmentWithActions: React.FC<InlineAttachmentWithActionsPr
127129
>
128130
<AttachmentHeader
129131
title={title}
132+
icon={icon}
133+
headerBadge={headerBadge}
130134
actionButtons={inlineActionButtons}
131135
previewBadgeState={resolvedPreviewBadgeState}
132136
/>

x-pack/platform/plugins/shared/agent_builder_platform/common/attachments/skill_draft.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@ export const SKILL_DRAFT_ATTACHMENT_TYPE = 'skill_draft' as const;
2626
* Mirrors `PersistedSkillCreateRequest` exactly so the same draft can be
2727
* shipped straight to the create endpoint without remapping. Keep this in
2828
* sync with `skillCreateRequestSchema` from `@kbn/agent-builder-common`.
29-
*
30-
* `is_latest` is set to `true` by `propose_skill` and maintained by
31-
* `patch_skill_draft`. It drives the "Latest" / "Outdated" badge on the card,
32-
* signalling to the user which draft card in the conversation thread is
33-
* current. When the architecture shifts to creating a new attachment per patch
34-
* (rather than mutating in-place), the previous attachment's `is_latest` will
35-
* be set to `false` server-side, making the Outdated state fully automatic.
3629
*/
3730
export interface SkillDraftAttachmentData {
3831
id: string;
@@ -41,8 +34,6 @@ export interface SkillDraftAttachmentData {
4134
content: string;
4235
tool_ids: string[];
4336
referenced_content?: SkillReferencedContent[];
44-
/** Whether this is the most recent draft in the conversation thread. */
45-
is_latest?: boolean;
4637
}
4738

4839
export type SkillDraftAttachment = Attachment<

0 commit comments

Comments
 (0)