Skip to content
Closed
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,13 @@ 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 pad the editor body via
// editorClassName; 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 +202,11 @@ 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; 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,11 @@ 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`) applied to the container below. It
// must NOT be forwarded as `editorClassName` — on the editor body
// it strips the editor's own border and gutter (see the matching
// note on the code-editor branch above).
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,24 @@ 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. 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, aligned by the
// `.agenta-chat-message-editor` rule in globals.css. Both insets 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
13 changes: 12 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,16 @@ 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]",
// `noProvider` mode has no EditorProvider to carry the consumer's
// `className`, so it lands here. In provider mode EditorInner
// receives no `className` (the provider applies it on
// `.agenta-rich-text-editor`), so it is never applied twice.
className,
)}
>
<div
ref={ref}
className={clsx("editor-inner border rounded-lg min-h-[inherit]", {
Expand Down Expand Up @@ -1119,6 +1129,7 @@ const Editor = ({
<EditorInner
dimensions={dimension}
id={id}
className={className}
customRender={customRender}
initialValue={initialValue}
value={value}
Expand Down
9 changes: 9 additions & 0 deletions web/packages/agenta-ui/src/Editor/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ export interface EditorProviderProps extends React.HTMLProps<HTMLDivElement> {
}

export interface EditorProps extends React.HTMLProps<HTMLDivElement> {
/**
* Lands on a different node per mode: in provider mode on the
* `.agenta-rich-text-editor` wrapper (an ancestor of the editor
* container), with `noProvider` on the `.editor-container` div itself.
* Descendant selectors (`[&_...]`) behave the same in both modes, but
* box-level utilities (padding, width, border) style a different element
* depending on the mode.
*/
className?: string
disabled?: boolean
id?: string
initialEditorState?: LexicalEditor["_editorState"]
Expand Down
Loading