diff --git a/.changelog/19452.txt b/.changelog/19452.txt
new file mode 100644
index 00000000000..3be80b92bb2
--- /dev/null
+++ b/.changelog/19452.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: when an Action has long output, anchor to the latest messages
+```
diff --git a/ui/app/components/action-card.hbs b/ui/app/components/action-card.hbs
index ba4d797fb56..7bd8db9ad8e 100644
--- a/ui/app/components/action-card.hbs
+++ b/ui/app/components/action-card.hbs
@@ -71,7 +71,12 @@
{{/if}}
{{#if this.instance.messages.length}}
- Error: {{this.instance.error}}
+ {{this.instance.messages}}
+
{{else}}
{{#if (eq this.instance.state "complete")}}
+ {{this.instance.messages}}
+
+
+
block parent.
+ * A trick here is that, if the user scrolls up from the bottom of the block,
+ * we don't want to force them down to the bottom again on update, but we do
+ * want to keep them there by default (so they have the latest output).
+ * The hasBeenAnchored flag is used to track this state, and we do a little
+ * trick when the messages get long enough to cause a scroll to start the
+ * anchoring process here.
+ *
+ * @param {HTMLElement} element
+ */
+ @action anchorToBottom(element) {
+ if (this.hasBeenAnchored) return;
+ const parentHeight = element.parentElement.clientHeight;
+ const elementHeight = element.clientHeight;
+ if (elementHeight > parentHeight) {
+ this.hasBeenAnchored = true;
+ element.parentElement.scroll(0, elementHeight);
+ }
+ }
}
diff --git a/ui/app/styles/components/actions.scss b/ui/app/styles/components/actions.scss
index cca1e695c3c..017650121f5 100644
--- a/ui/app/styles/components/actions.scss
+++ b/ui/app/styles/components/actions.scss
@@ -117,14 +117,30 @@
}
.messages {
+ width: 100%;
overflow: hidden;
- code > pre {
- height: 200px;
+ code {
background-color: #0a0a0a;
color: whitesmoke;
+ display: block;
+ overflow: auto;
+ height: 200px;
border-radius: 6px;
resize: vertical;
+ pre {
+ background-color: transparent;
+ color: unset;
+ overflow-anchor: none;
+ min-height: 100%;
+ white-space: pre-wrap;
+ }
+ .anchor {
+ overflow-anchor: auto;
+ height: 1px;
+ margin-top: -1px;
+ visibility: hidden;
+ }
}
}