From 6ef73f900c78309c92f3f05125509297c609d860 Mon Sep 17 00:00:00 2001 From: Olympe Lespagnon Date: Mon, 19 Jan 2026 15:57:11 +0100 Subject: [PATCH 1/4] Add feedback message parameter to banner component --- addon/components/o-s-s/banner.hbs | 60 +++++++++++-------- addon/components/o-s-s/banner.stories.js | 10 ++++ addon/components/o-s-s/banner.ts | 8 ++- app/styles/banner.less | 4 ++ tests/dummy/app/templates/index.hbs | 18 ++++++ .../components/o-s-s/banner-test.ts | 27 +++++++++ 6 files changed, 100 insertions(+), 27 deletions(-) diff --git a/addon/components/o-s-s/banner.hbs b/addon/components/o-s-s/banner.hbs index 63a77dd20..d612e8919 100644 --- a/addon/components/o-s-s/banner.hbs +++ b/addon/components/o-s-s/banner.hbs @@ -1,30 +1,38 @@ -
- {{#if (has-block "custom-icon")}} -
{{yield to="custom-icon"}}
- {{else if @icon}} - - {{else if @image}} - banner - {{/if}} -
- {{#if @title}} -
- {{@title}} - {{#if (has-block "title-suffix")}} - {{yield to="title-suffix"}} - {{/if}} -
- {{/if}} - {{#if @subtitle}} - {{@subtitle}} +
+
+ {{#if (has-block "custom-icon")}} +
{{yield to="custom-icon"}}
+ {{else if @icon}} + + {{else if @image}} + banner {{/if}} - {{#if (has-block "secondary-actions")}} - {{yield to="secondary-actions"}} +
+ {{#if @title}} +
+ {{@title}} + {{#if (has-block "title-suffix")}} + {{yield to="title-suffix"}} + {{/if}} +
+ {{/if}} + {{#if @subtitle}} + {{@subtitle}} + {{/if}} + {{#if (has-block "secondary-actions")}} + {{yield to="secondary-actions"}} + {{/if}} +
+ {{#if (has-block "actions")}} +
{{yield to="actions"}}
{{/if}}
- {{#if (has-block "actions")}} -
{{yield to="actions"}}
+ + {{#if @feedbackMessage.value}} + {{@feedbackMessage.value}} {{/if}} -
+
\ No newline at end of file diff --git a/addon/components/o-s-s/banner.stories.js b/addon/components/o-s-s/banner.stories.js index e56161f60..bb9bf76fb 100644 --- a/addon/components/o-s-s/banner.stories.js +++ b/addon/components/o-s-s/banner.stories.js @@ -77,6 +77,16 @@ export default { type: 'boolean' } }, + feedbackMessage: { + description: 'An error message that will be displayed below the banner.', + table: { + type: { + summary: '{ type: string, value: string }' + }, + defaultValue: { summary: 'undefined' } + }, + control: { type: 'object' } + }, size: { description: 'Allows to adjust the size of the component. Currently available options are `sm`, `md` and `lg`. Defaults to `md`.', diff --git a/addon/components/o-s-s/banner.ts b/addon/components/o-s-s/banner.ts index 97623b832..5bf9cf305 100644 --- a/addon/components/o-s-s/banner.ts +++ b/addon/components/o-s-s/banner.ts @@ -1,5 +1,6 @@ import { isBlank } from '@ember/utils'; import Component from '@glimmer/component'; +import type { FeedbackMessage } from './input-container'; type SizeType = 'sm' | 'md' | 'lg'; @@ -8,6 +9,7 @@ interface OSSBannerArgs { plain?: boolean; selected?: boolean; disabled?: boolean; + feedbackMessage?: FeedbackMessage; } const SIZE_CLASSES: Record = { @@ -24,6 +26,10 @@ export default class OSSBanner extends Component { return this.args.selected ? 'upf-banner--selected' : ''; } + get erroredClass(): string { + return this.args.feedbackMessage ? 'upf-banner--errored' : ''; + } + get plainClass(): string { return this.args.plain ? 'background-color-gray-50' : 'background-color-white'; } @@ -33,7 +39,7 @@ export default class OSSBanner extends Component { } get modifierClasses(): string { - return [this.disabledClass, this.selectedClass, this.plainClass, this.sizeClass] + return [this.disabledClass, this.selectedClass, this.plainClass, this.sizeClass, this.erroredClass] .filter((mc) => !isBlank(mc)) .join(' '); } diff --git a/app/styles/banner.less b/app/styles/banner.less index 62e2d904d..f14082876 100644 --- a/app/styles/banner.less +++ b/app/styles/banner.less @@ -9,6 +9,10 @@ transition: ease-in-out 0.25s; } + &--errored { + border: 1px solid var(--color-error-500); + } + &--disabled { background-color: var(--color-gray-100); border: 1px solid var(--color-border-default); diff --git a/tests/dummy/app/templates/index.hbs b/tests/dummy/app/templates/index.hbs index 3d7e413b5..7bc5dc8b4 100644 --- a/tests/dummy/app/templates/index.hbs +++ b/tests/dummy/app/templates/index.hbs @@ -296,6 +296,24 @@
+
+ + + <:actions> + + + +
diff --git a/tests/integration/components/o-s-s/banner-test.ts b/tests/integration/components/o-s-s/banner-test.ts index 878ca38b3..71e6c9da7 100644 --- a/tests/integration/components/o-s-s/banner-test.ts +++ b/tests/integration/components/o-s-s/banner-test.ts @@ -156,4 +156,31 @@ module('Integration | Component | o-s-s/banner', function (hooks) { assert.dom('.upf-banner.upf-banner--size-lg').doesNotExist(); }); }); + + module('@feedbackMessage parameter', function () { + hooks.beforeEach(function () { + this.feedbackMessage = { + type: 'error', + value: 'This is a feedback message' + }; + }); + + test('When parameter is passed, it adds upf-banner--errored class', async function (assert) { + await render(hbs``); + + assert.dom('.upf-banner.upf-banner--errored').exists(); + }); + + test('When parameter is passed, the feedback message is swhown', async function (assert) { + await render(hbs``); + + assert.dom('.font-color-error-500').hasText('This is a feedback message'); + }); + + test('When parameter is not passed, it does not add upf-banner--errored class', async function (assert) { + await render(hbs``); + + assert.dom('.upf-banner.upf-banner--errored').doesNotExist(); + }); + }); }); From c006d4eab7c1157a87ce18cbf28bee95e2f81b21 Mon Sep 17 00:00:00 2001 From: Olympe Lespagnon Date: Mon, 19 Jan 2026 16:38:10 +0100 Subject: [PATCH 2/4] Fix test --- tests/integration/components/o-s-s/banner-test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/integration/components/o-s-s/banner-test.ts b/tests/integration/components/o-s-s/banner-test.ts index 71e6c9da7..a45be7160 100644 --- a/tests/integration/components/o-s-s/banner-test.ts +++ b/tests/integration/components/o-s-s/banner-test.ts @@ -152,6 +152,7 @@ module('Integration | Component | o-s-s/banner', function (hooks) { test("when the value is undefined, it doesn't add the size class", async function (assert) { await render(hbs``); + assert.dom('.upf-banner.upf-banner--size-sm').doesNotExist(); assert.dom('.upf-banner.upf-banner--size-lg').doesNotExist(); }); @@ -172,13 +173,13 @@ module('Integration | Component | o-s-s/banner', function (hooks) { }); test('When parameter is passed, the feedback message is swhown', async function (assert) { - await render(hbs``); + await render(hbs``); assert.dom('.font-color-error-500').hasText('This is a feedback message'); }); test('When parameter is not passed, it does not add upf-banner--errored class', async function (assert) { - await render(hbs``); + await render(hbs``); assert.dom('.upf-banner.upf-banner--errored').doesNotExist(); }); From a2f5de793c2a74b39051f4f7efcad3b9fc1eeb3c Mon Sep 17 00:00:00 2001 From: Olympe Lespagnon Date: Mon, 19 Jan 2026 17:22:44 +0100 Subject: [PATCH 3/4] Review --- addon/components/o-s-s/banner.hbs | 4 ++-- addon/components/o-s-s/banner.ts | 12 ++++++++--- app/styles/banner.less | 2 +- .../components/o-s-s/banner-test.ts | 20 +++++++++++++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/addon/components/o-s-s/banner.hbs b/addon/components/o-s-s/banner.hbs index d612e8919..7fb0e0e65 100644 --- a/addon/components/o-s-s/banner.hbs +++ b/addon/components/o-s-s/banner.hbs @@ -32,7 +32,7 @@ {{/if}} - {{#if @feedbackMessage.value}} - {{@feedbackMessage.value}} + {{#if this.feedbackMessage}} + {{this.feedbackMessage}} {{/if}} \ No newline at end of file diff --git a/addon/components/o-s-s/banner.ts b/addon/components/o-s-s/banner.ts index 5bf9cf305..c3c9b0613 100644 --- a/addon/components/o-s-s/banner.ts +++ b/addon/components/o-s-s/banner.ts @@ -26,8 +26,8 @@ export default class OSSBanner extends Component { return this.args.selected ? 'upf-banner--selected' : ''; } - get erroredClass(): string { - return this.args.feedbackMessage ? 'upf-banner--errored' : ''; + get errorClass(): string { + return this.args.feedbackMessage ? 'upf-banner--error' : ''; } get plainClass(): string { @@ -38,8 +38,14 @@ export default class OSSBanner extends Component { return SIZE_CLASSES[this.args.size ?? 'md'] ?? ''; } + get feedbackMessage(): string | undefined { + return this.args.feedbackMessage && !isBlank(this.args.feedbackMessage.value) + ? this.args.feedbackMessage.value + : undefined; + } + get modifierClasses(): string { - return [this.disabledClass, this.selectedClass, this.plainClass, this.sizeClass, this.erroredClass] + return [this.disabledClass, this.selectedClass, this.plainClass, this.sizeClass, this.errorClass] .filter((mc) => !isBlank(mc)) .join(' '); } diff --git a/app/styles/banner.less b/app/styles/banner.less index f14082876..498a86c73 100644 --- a/app/styles/banner.less +++ b/app/styles/banner.less @@ -9,7 +9,7 @@ transition: ease-in-out 0.25s; } - &--errored { + &--error { border: 1px solid var(--color-error-500); } diff --git a/tests/integration/components/o-s-s/banner-test.ts b/tests/integration/components/o-s-s/banner-test.ts index a45be7160..9933dfda0 100644 --- a/tests/integration/components/o-s-s/banner-test.ts +++ b/tests/integration/components/o-s-s/banner-test.ts @@ -166,10 +166,10 @@ module('Integration | Component | o-s-s/banner', function (hooks) { }; }); - test('When parameter is passed, it adds upf-banner--errored class', async function (assert) { + test('When parameter is passed, it adds upf-banner--error class', async function (assert) { await render(hbs``); - assert.dom('.upf-banner.upf-banner--errored').exists(); + assert.dom('.upf-banner.upf-banner--error').exists(); }); test('When parameter is passed, the feedback message is swhown', async function (assert) { @@ -178,10 +178,22 @@ module('Integration | Component | o-s-s/banner', function (hooks) { assert.dom('.font-color-error-500').hasText('This is a feedback message'); }); - test('When parameter is not passed, it does not add upf-banner--errored class', async function (assert) { + test('When parameter is not passed, it does not add upf-banner--error class', async function (assert) { await render(hbs``); - assert.dom('.upf-banner.upf-banner--errored').doesNotExist(); + assert.dom('.upf-banner.upf-banner--error').doesNotExist(); + }); + + test('When parameter is passed with empty value, upf-banner--error class is added but no error message is displayed', async function (assert) { + this.feedbackMessage = { + type: 'error', + value: '' + }; + + await render(hbs``); + + assert.dom('.upf-banner.upf-banner--error').exists(); + assert.dom('.font-color-error-500').doesNotExist(); }); }); }); From ce5f0e3299819f892c485de1ca2dfc2d44a78031 Mon Sep 17 00:00:00 2001 From: Olympe Lespagnon Date: Mon, 19 Jan 2026 18:23:35 +0100 Subject: [PATCH 4/4] Facultative feedbackMessage.value --- addon/components/o-s-s/banner.hbs | 4 ++-- addon/components/o-s-s/banner.ts | 6 ------ tests/integration/components/o-s-s/banner-test.ts | 12 ------------ 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/addon/components/o-s-s/banner.hbs b/addon/components/o-s-s/banner.hbs index 7fb0e0e65..d612e8919 100644 --- a/addon/components/o-s-s/banner.hbs +++ b/addon/components/o-s-s/banner.hbs @@ -32,7 +32,7 @@ {{/if}} - {{#if this.feedbackMessage}} - {{this.feedbackMessage}} + {{#if @feedbackMessage.value}} + {{@feedbackMessage.value}} {{/if}} \ No newline at end of file diff --git a/addon/components/o-s-s/banner.ts b/addon/components/o-s-s/banner.ts index c3c9b0613..f745963e5 100644 --- a/addon/components/o-s-s/banner.ts +++ b/addon/components/o-s-s/banner.ts @@ -38,12 +38,6 @@ export default class OSSBanner extends Component { return SIZE_CLASSES[this.args.size ?? 'md'] ?? ''; } - get feedbackMessage(): string | undefined { - return this.args.feedbackMessage && !isBlank(this.args.feedbackMessage.value) - ? this.args.feedbackMessage.value - : undefined; - } - get modifierClasses(): string { return [this.disabledClass, this.selectedClass, this.plainClass, this.sizeClass, this.errorClass] .filter((mc) => !isBlank(mc)) diff --git a/tests/integration/components/o-s-s/banner-test.ts b/tests/integration/components/o-s-s/banner-test.ts index 9933dfda0..3d80eafa3 100644 --- a/tests/integration/components/o-s-s/banner-test.ts +++ b/tests/integration/components/o-s-s/banner-test.ts @@ -183,17 +183,5 @@ module('Integration | Component | o-s-s/banner', function (hooks) { assert.dom('.upf-banner.upf-banner--error').doesNotExist(); }); - - test('When parameter is passed with empty value, upf-banner--error class is added but no error message is displayed', async function (assert) { - this.feedbackMessage = { - type: 'error', - value: '' - }; - - await render(hbs``); - - assert.dom('.upf-banner.upf-banner--error').exists(); - assert.dom('.font-color-error-500').doesNotExist(); - }); }); });