diff --git a/assets/javascripts/discourse/components/ai-indicator-wave.gjs b/assets/javascripts/discourse/components/ai-indicator-wave.gjs
new file mode 100644
index 00000000..92ec6370
--- /dev/null
+++ b/assets/javascripts/discourse/components/ai-indicator-wave.gjs
@@ -0,0 +1,12 @@
+const indicatorDots = [".", ".", "."];
+const AiIndicatorWave =
+ {{#if @loading}}
+
+ {{#each indicatorDots as |dot|}}
+ {{dot}}
+ {{/each}}
+
+ {{/if}}
+;
+
+export default AiIndicatorWave;
diff --git a/assets/javascripts/discourse/components/ai-summary-skeleton.gjs b/assets/javascripts/discourse/components/ai-summary-skeleton.gjs
index a09daa6f..07c9e26b 100644
--- a/assets/javascripts/discourse/components/ai-summary-skeleton.gjs
+++ b/assets/javascripts/discourse/components/ai-summary-skeleton.gjs
@@ -9,6 +9,7 @@ import { cancel } from "@ember/runloop";
import concatClass from "discourse/helpers/concat-class";
import i18n from "discourse-common/helpers/i18n";
import discourseLater from "discourse-common/lib/later";
+import AiIndicatorWave from "./ai-indicator-wave";
class Block {
@tracked show = false;
@@ -118,11 +119,7 @@ export default class AiSummarySkeleton extends Component {
{{i18n "summary.in_progress"}}
-
- .
- .
- .
-
+
diff --git a/assets/javascripts/discourse/components/modal/diff-modal.gjs b/assets/javascripts/discourse/components/modal/diff-modal.gjs
index aea982db..34be825f 100644
--- a/assets/javascripts/discourse/components/modal/diff-modal.gjs
+++ b/assets/javascripts/discourse/components/modal/diff-modal.gjs
@@ -3,13 +3,13 @@ import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import { htmlSafe } from "@ember/template";
-import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import CookText from "discourse/components/cook-text";
import DButton from "discourse/components/d-button";
import DModal from "discourse/components/d-modal";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import i18n from "discourse-common/helpers/i18n";
+import AiIndicatorWave from "../ai-indicator-wave";
export default class ModalDiffModal extends Component {
@service currentUser;
@@ -65,25 +65,23 @@ export default class ModalDiffModal extends Component {
@closeModal={{@closeModal}}
>
<:body>
-
- {{#if this.loading}}
-
-
-
+ {{#if this.loading}}
+
+
+
+ {{else}}
+ {{#if this.diff}}
+ {{htmlSafe this.diff}}
{{else}}
- {{#if this.diff}}
- {{htmlSafe this.diff}}
- {{else}}
-
- {{@model.selectedText}}
-
+
+ {{@model.selectedText}}
+
-
- {{this.suggestion}}
-
- {{/if}}
+
+ {{this.suggestion}}
+
{{/if}}
-
+ {{/if}}
@@ -93,7 +91,9 @@ export default class ModalDiffModal extends Component {
class="btn-primary"
@label="discourse_ai.ai_helper.context_menu.loading"
@disabled={{true}}
- />
+ >
+
+
{{else}}
- {{#if this.searching}}
-
- .
- .
- .
-
- {{/if}}
+
diff --git a/assets/stylesheets/common/streaming.scss b/assets/stylesheets/common/streaming.scss
index 9608749a..3c9c08d3 100644
--- a/assets/stylesheets/common/streaming.scss
+++ b/assets/stylesheets/common/streaming.scss
@@ -29,3 +29,32 @@ article.streaming .cooked {
animation: flashing 1.5s infinite;
}
}
+
+@keyframes ai-indicator-wave {
+ 0%,
+ 60%,
+ 100% {
+ transform: initial;
+ }
+ 30% {
+ transform: translateY(-0.2em);
+ }
+}
+
+.ai-indicator-wave {
+ flex: 0 0 auto;
+ display: inline-flex;
+
+ &__dot {
+ display: inline-block;
+ @media (prefers-reduced-motion: no-preference) {
+ animation: ai-indicator-wave 1.8s linear infinite;
+ }
+ &:nth-child(2) {
+ animation-delay: -1.6s;
+ }
+ &:nth-child(3) {
+ animation-delay: -1.4s;
+ }
+ }
+}
diff --git a/assets/stylesheets/modules/embeddings/common/semantic-search.scss b/assets/stylesheets/modules/embeddings/common/semantic-search.scss
index c41c9ca8..c6e67aa9 100644
--- a/assets/stylesheets/modules/embeddings/common/semantic-search.scss
+++ b/assets/stylesheets/modules/embeddings/common/semantic-search.scss
@@ -7,6 +7,10 @@
flex-direction: column;
align-items: baseline;
+ .ai-indicator-wave {
+ color: var(--primary-medium);
+ }
+
.semantic-search {
&__searching {
display: flex;
@@ -23,22 +27,6 @@
display: inline-block;
margin-left: 3px;
}
-
- &__indicator-wave {
- flex: 0 0 auto;
- display: inline-flex;
- color: var(--primary-medium);
- }
- &__indicator-dot {
- display: inline-block;
- animation: ai-summary__indicator-wave 1.8s linear infinite;
- &:nth-child(2) {
- animation-delay: -1.6s;
- }
- &:nth-child(3) {
- animation-delay: -1.4s;
- }
- }
}
.semantic-search__entries {
diff --git a/assets/stylesheets/modules/summarization/common/ai-summary.scss b/assets/stylesheets/modules/summarization/common/ai-summary.scss
index 2c469bf3..3bd13803 100644
--- a/assets/stylesheets/modules/summarization/common/ai-summary.scss
+++ b/assets/stylesheets/modules/summarization/common/ai-summary.scss
@@ -157,22 +157,6 @@
display: inline-block;
margin-left: 3px;
}
- &__indicator-wave {
- flex: 0 0 auto;
- display: inline-flex;
- }
- &__indicator-dot {
- display: inline-block;
- @media (prefers-reduced-motion: no-preference) {
- animation: ai-summary__indicator-wave 1.8s linear infinite;
- }
- &:nth-child(2) {
- animation-delay: -1.6s;
- }
- &:nth-child(3) {
- animation-delay: -1.4s;
- }
- }
}
.placeholder-summary {
@@ -211,17 +195,6 @@
}
}
-@keyframes ai-summary__indicator-wave {
- 0%,
- 60%,
- 100% {
- transform: initial;
- }
- 30% {
- transform: translateY(-0.2em);
- }
-}
-
@keyframes appear {
0% {
opacity: 0;
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 3d7cad56..faae0e05 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -294,7 +294,7 @@ en:
missing_content: "Please enter some content to generate suggestions."
context_menu:
trigger: "Ask AI"
- loading: "AI is generating..."
+ loading: "AI is generating"
cancel: "Cancel"
regen: "Try Again"
confirm: "Confirm"
diff --git a/test/javascripts/integration/components/ai-indicator-wave-test.gjs b/test/javascripts/integration/components/ai-indicator-wave-test.gjs
new file mode 100644
index 00000000..54038a25
--- /dev/null
+++ b/test/javascripts/integration/components/ai-indicator-wave-test.gjs
@@ -0,0 +1,18 @@
+import { render } from "@ember/test-helpers";
+import { module, test } from "qunit";
+import { setupRenderingTest } from "discourse/tests/helpers/component-test";
+import AiIndicatorWave from "discourse/plugins/discourse-ai/discourse/components/ai-indicator-wave";
+
+module("Integration | Component | ai-indicator-wave", function (hooks) {
+ setupRenderingTest(hooks);
+
+ test("it renders an indicator wave", async function (assert) {
+ await render();
+ assert.dom(".ai-indicator-wave").exists();
+ });
+
+ test("it does not render the indicator wave when loading is false", async function (assert) {
+ await render();
+ assert.dom(".ai-indicator-wave").doesNotExist();
+ });
+});