Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 7 additions & 21 deletions web/oss/src/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -206,28 +206,14 @@ body {
}
}

/* Align the message text with the first character of the role label above it,
with the same symmetric horizontal inset on the role, the text, and the
placeholder. The single inset value lives in --ag-message-inline-pad.

Notes:
- The role label is an antd Button whose default padding is wider than the
inset (Tailwind's px-2 on it loses to antd), so it is pinned with !important.
- The text is padded here in CSS rather than via an editor prop because
ChatMessageEditor renders the Editor with `noProvider`, a mode where
`className`/`editorClassName` is currently dropped (known bug, tracked
separately). JSON/code editors are excluded; they have a line-number gutter. */
.agenta-chat-message-editor {
--ag-message-inline-pad: 8px;
}
/* Align the role label's first character with the message text below it.
The message text and placeholder are inset 8px via ChatMessageEditor's
editorClassName prop; this rule pins the role label to the same 8px. The role
label is an antd Button whose default padding is wider than 8px and ignores
Tailwind's px-2, so the override needs !important. Scoped to the message
editor via the .agenta-chat-message-editor marker class. */
.agenta-chat-message-editor .message-user-select {
padding-inline: var(--ag-message-inline-pad) !important;
}
.agenta-chat-message-editor .editor-input:not(.code-only) {
padding-inline: var(--ag-message-inline-pad);
}
.agenta-chat-message-editor .editor-placeholder {
left: var(--ag-message-inline-pad);
padding-inline: 8px !important;
}

/** Align the input search with the search box **/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,15 @@ const GenerationComparisonChatOutputCell = ({
allowFileUpload: true,
}}
messageProps={{
className:
"!p-0 [&_.agenta-editor-wrapper]:!p-3 !mt-0 [&:nth-child(1)]:!mt-0 mt-2",
className: "!p-0 !mt-0 [&:nth-child(1)]:!mt-0 mt-2",
// Comparison cells set their own editor padding via
// editorClassName (works after the noProvider className
// fix), replacing the previous
// `[&_.agenta-editor-wrapper]:!p-3` container hack.
// alignTextWithRole is off so the role-alignment inset
// does not stack on top of this padding.
editorClassName: "!p-3",
alignTextWithRole: false,
headerClassName:
"min-h-[48px] px-2 border-0 border-b border-solid border-[var(--ag-rgba-051729-06)]",
footerClassName: "px-2",
Expand Down Expand Up @@ -198,9 +204,14 @@ const GenerationComparisonChatOutputCell = ({
withControls={false}
hideUserMessage
messageProps={{
className:
"!p-0 [&_.agenta-editor-wrapper]:!p-3 !mt-0 [&:nth-child(1)]:!mt-0 mt-2",
// Padding via editorClassName only (the
// [&_.agenta-editor-wrapper]:!p-3 hack is removed so it does
// not double up now that editorClassName works), and
// alignTextWithRole off so the role-alignment inset does not
// stack on top.
className: "!p-0 !mt-0 [&:nth-child(1)]:!mt-0 mt-2",
editorClassName: "!p-3",
alignTextWithRole: false,
headerClassName:
"min-h-[48px] border-0 border-b border-solid border-[var(--ag-rgba-051729-06)]",
footerClassName: "px-2 !m-0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,14 @@ const VariableControlAdapter: React.FC<VariableControlAdapterProps> = ({
handleChange={handleChange}
initialValue={effectiveValue}
value={effectiveValue}
editorClassName={className}
// NOTE: the parent's `className` is a container/cell-strip style
// (e.g. `*:!border-none px-3`) and is applied to the container
// below. It must NOT be forwarded to the editor body, where it
// would strip the editor's own border and gutter (see the
// matching note on the code-editor branch above). It was
// previously passed as `editorClassName` but silently dropped by
// the `noProvider` className bug; now that the bug is fixed, the
// forward is removed so it stays a container-only style.
placeholder={effectivePlaceholder}
disabled={isEffectivelyDisabled}
className={clsx(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ export interface ChatMessageEditorProps {
* up via an internal synchronizer mounted inside the EditorProvider.
*/
markdownView?: boolean
/**
* Inset the message text + placeholder so they line up with the role label
* above (the default tight message layout). Set to false for surfaces that
* apply their own editor padding (e.g. the comparison view's `!p-3` cells),
* where the alignment inset would stack on top and over-pad the text.
* @default true
*/
alignTextWithRole?: boolean
}

/**
Expand Down Expand Up @@ -134,6 +142,7 @@ const ChatMessageEditorInner: React.FC<ChatMessageEditorProps> = ({
onFocusChange,
maxPasteChars = DEFAULT_MAX_TEXT_PASTE_CHARS,
onPasteLimitExceeded,
alignTextWithRole = true,
...props
}) => {
const selectOptions = useMemo(
Expand Down Expand Up @@ -210,16 +219,25 @@ const ChatMessageEditorInner: React.FC<ChatMessageEditorProps> = ({
//
// Kaosiso QA 2026-06-02 (also reproduces in production).
disableDebounce
editorClassName={editorClassName}
// Inset the message text and its placeholder by 8px so they line up
// with the role label above. Goes through editorClassName (the proper
// prop) now that the noProvider className bug is fixed. Code editors
// (JSON/tool) keep their own gutter, so they are excluded via
// `:not(.code-only)`. The role label is an antd button outside the
// editor and is aligned via the `.agenta-chat-message-editor` rule in
// globals.css. Both are skipped when alignTextWithRole is false (e.g.
// the comparison view, which applies its own editor padding).
editorClassName={cn(
alignTextWithRole &&
"[&_.editor-input:not(.code-only)]:px-2 [&_.editor-placeholder]:left-2",
editorClassName,
)}
placeholder={placeholder}
disabled={disabled}
state={disabled ? "readOnly" : state}
// `agenta-chat-message-editor` is the styling hook used in globals.css
// to align the message text with the role label (see that file). The
// padding can't go through `editorClassName` because ChatMessageEditor
// renders the Editor with `noProvider`, where `className` is dropped.
className={cn(
"agenta-chat-message-editor relative",
alignTextWithRole && "agenta-chat-message-editor",
"relative",
flexLayouts.column,
gapClasses.xs,
"rounded-md",
Expand Down
14 changes: 13 additions & 1 deletion web/packages/agenta-ui/src/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ const EditorInner = forwardRef<HTMLDivElement, EditorProps>(
disableIndentationPlugin = false,
useNativeCodeNodes = false,
diffExtensionConfig,
className,
...rest
}: EditorProps,
ref,
Expand Down Expand Up @@ -755,7 +756,17 @@ const EditorInner = forwardRef<HTMLDivElement, EditorProps>(
}, [codeOnly, editor, effectiveValue, hydrateRichTextFromControlledValue])

return (
<div className="editor-container w-full overflow-hidden relative min-h-[inherit]">
<div
className={clsx(
"editor-container w-full overflow-hidden relative min-h-[inherit]",
// In `noProvider` mode there is no EditorProvider to carry the
// consumer's `className` (it normally lands on
// `.agenta-rich-text-editor`), so apply it to the container here.
// In provider mode EditorInner receives no `className`, so this is
// a no-op and the class still lands on `.agenta-rich-text-editor`.
className,
)}
>
<div
ref={ref}
className={clsx("editor-inner border rounded-lg min-h-[inherit]", {
Expand Down Expand Up @@ -1119,6 +1130,7 @@ const Editor = ({
<EditorInner
dimensions={dimension}
id={id}
className={className}
customRender={customRender}
initialValue={initialValue}
value={value}
Expand Down
Loading