From 9307ac9862416609b2bd302350b94664ab072656 Mon Sep 17 00:00:00 2001 From: Philippe Caron Date: Tue, 18 Aug 2026 15:01:06 +0000 Subject: [PATCH 1/6] Add new feature banner prototype --- .../javascripts/attachments/AttachmentsWidget.js | 2 +- .../stylesheets/tailwind/components/buttons.css | 6 ++++++ .../stylesheets/tailwind/components/layout.css | 13 +++++++++++++ app/templates/views/templates/template.html | 9 ++++++++- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/attachments/AttachmentsWidget.js b/app/assets/javascripts/attachments/AttachmentsWidget.js index d6b359163d..fd77762e02 100644 --- a/app/assets/javascripts/attachments/AttachmentsWidget.js +++ b/app/assets/javascripts/attachments/AttachmentsWidget.js @@ -252,7 +252,7 @@ export const AttachmentsWidget = ({ + + {% else %}

{{ _('Attached files') }}

{% if current_user.has_permissions('manage_service') %} From 12e7510a680762cfb062759eb7039525f7970c41 Mon Sep 17 00:00:00 2001 From: Philippe Caron Date: Tue, 18 Aug 2026 15:01:28 +0000 Subject: [PATCH 2/6] format --- app/assets/stylesheets/tailwind/components/layout.css | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/stylesheets/tailwind/components/layout.css b/app/assets/stylesheets/tailwind/components/layout.css index a460e74148..3ff9b7a61d 100644 --- a/app/assets/stylesheets/tailwind/components/layout.css +++ b/app/assets/stylesheets/tailwind/components/layout.css @@ -102,7 +102,6 @@ left: anchor(var(--anchored-to) center); top: anchor(--new-feature-container top); @apply w-10 h-10 -translate-x-1/2 -translate-y-1/2 rotate-45 bg-brand-100; - } /*! purgecss end ignore */ From ca613276d26e9c6df0945ec2875cf574d041a6e3 Mon Sep 17 00:00:00 2001 From: Philippe Caron Date: Tue, 18 Aug 2026 15:32:24 +0000 Subject: [PATCH 3/6] Add translations --- app/templates/views/templates/template.html | 4 ++-- app/translations/csv/fr.csv | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/templates/views/templates/template.html b/app/templates/views/templates/template.html index 77fbbafdbf..feb07c618f 100644 --- a/app/templates/views/templates/template.html +++ b/app/templates/views/templates/template.html @@ -103,9 +103,9 @@ url_for('main.download_template_attachment', service_id=current_service.id, template_id=template.id) ) }}
- Upload attachments without the API + {{ _('Upload attachments without the API') }}
diff --git a/app/translations/csv/fr.csv b/app/translations/csv/fr.csv index a4fa73c05d..11c27a9b5a 100644 --- a/app/translations/csv/fr.csv +++ b/app/translations/csv/fr.csv @@ -2506,3 +2506,6 @@ "Attachment","Pièce jointe" "files attached","fichiers joints" "Files attached to this template","Fichiers joints à ce gabarit" +"Upload attachments without the API","Téléverser des pièces jointes sans l’API" +"About file attachments","À propos des pièces jointes" +"Dismiss","Ignorer" \ No newline at end of file From 2baefacd4734efbb88831c49c4beeee961b93998 Mon Sep 17 00:00:00 2001 From: Philippe Caron Date: Tue, 18 Aug 2026 18:02:19 +0000 Subject: [PATCH 4/6] make a component macro, doc in storybook --- app/templates/components/new-feature.html | 9 +++++ app/templates/views/storybook/indicator.html | 38 ++++++++++++++++--- .../views/storybook/storybook-menu.html | 2 +- app/templates/views/templates/template.html | 14 +++---- app/translations/csv/fr.csv | 2 +- 5 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 app/templates/components/new-feature.html diff --git a/app/templates/components/new-feature.html b/app/templates/components/new-feature.html new file mode 100644 index 0000000000..da1eae2a2b --- /dev/null +++ b/app/templates/components/new-feature.html @@ -0,0 +1,9 @@ +{% macro new_feature(title, cta="", cta_link="", anchored_to="") %} +
+ {{ title }} +
+ {{ cta }} + +
+
+{% endmacro %} diff --git a/app/templates/views/storybook/indicator.html b/app/templates/views/storybook/indicator.html index a4b63971c2..1469c31d55 100644 --- a/app/templates/views/storybook/indicator.html +++ b/app/templates/views/storybook/indicator.html @@ -2,18 +2,19 @@ {% from "components/badge.html" import badge %} {% from "components/task-shortcut.html" import task_shortcut %} {% from 'components/remaining-messages.html' import remaining_messages with context %} +{% from 'components/new-feature.html' import new_feature %} {% block maincolumn_content %} -
Indicator component examples
+
Indicator and new feature banner

The indicator component wraps any element and displays a badge in the corner.

Button with "New" Badge

-
+
{{ indicator('', badge('New', variant='blue')) }}

Code

-
+
{% raw %}
 {{ indicator(
     '<button type="button" class="button">Inbox</button>',
@@ -24,7 +25,7 @@ 

Code

Task Shortcut with Badge

-
+
{{ indicator( task_shortcut( description=_("Start here to write a new message."), @@ -35,7 +36,7 @@

Task Shortcut with Badge

badge('New', variant='blue') ) }}

Code

-
+
{% raw %}
 {{ indicator(
     task_shortcut(
@@ -49,4 +50,31 @@ 

Code

{% endraw %}
+ +

New Feature Banner

+

The feature banner sits within the page flow. This keeps content visible and accessible.

+

You can optionally anchor the banner to an element using CSS. A caret points to the anchor, creating a visual connection..

+
+
+ + {{ new_feature( + title=_("You can do something with this new thing"), + cta=_("About this new thing"), + cta_link="/new-features", + anchored_to="new-feature-example" + ) }} +
+

Code

+
+
{% raw %}
+<button type="button" class="button [anchor-name:--new-feature-example]" id="new-feature-example">Anchoring element</button>
+{{ new_feature(
+    title=_("You can do something with this new thing"),
+    cta=_("About this new thing"),
+    cta_link="/new-features",
+    anchored_to="new-feature-example"
+) }}
+{% endraw %}
+
+
{% endblock %} diff --git a/app/templates/views/storybook/storybook-menu.html b/app/templates/views/storybook/storybook-menu.html index 53cbb11709..365176d8ac 100644 --- a/app/templates/views/storybook/storybook-menu.html +++ b/app/templates/views/storybook/storybook-menu.html @@ -47,7 +47,7 @@ 'path': 'focus_management/full-form' }, { - 'name': 'Indicator', + 'name': 'Indicator and new feature banner', 'path': 'indicator' }, { diff --git a/app/templates/views/templates/template.html b/app/templates/views/templates/template.html index feb07c618f..98ef59ec13 100644 --- a/app/templates/views/templates/template.html +++ b/app/templates/views/templates/template.html @@ -7,6 +7,7 @@ {% from "components/textbox.html" import textbox %} {% from "components/api-key.html" import api_key %} {% from "components/page-header.html" import page_header %} +{% from "components/new-feature.html" import new_feature %} {% block service_page_title %} {{ page_title_folder_path(current_service.get_template_path(template._template)) }} @@ -102,13 +103,12 @@ url_for('main.template_attachment_status', service_id=current_service.id, template_id=template.id), url_for('main.download_template_attachment', service_id=current_service.id, template_id=template.id) ) }} -
- {{ _('Upload attachments without the API') }} -
- {{ _('About file attachments') }} - -
-
+ {{ new_feature( + title=_("Upload attachments without the API"), + cta=_("About file attachments"), + cta_link="/new-features", + anchored_to="new-feature-attachments" + ) }} {% else %}

{{ _('Attached files') }}

{% if current_user.has_permissions('manage_service') %} diff --git a/app/translations/csv/fr.csv b/app/translations/csv/fr.csv index 11c27a9b5a..157847b7d2 100644 --- a/app/translations/csv/fr.csv +++ b/app/translations/csv/fr.csv @@ -2508,4 +2508,4 @@ "Files attached to this template","Fichiers joints à ce gabarit" "Upload attachments without the API","Téléverser des pièces jointes sans l’API" "About file attachments","À propos des pièces jointes" -"Dismiss","Ignorer" \ No newline at end of file +"Hide","Ignorer" \ No newline at end of file From f51b54510580a81bc05b13e901bf30089b2691a9 Mon Sep 17 00:00:00 2001 From: Philippe Caron Date: Wed, 19 Aug 2026 14:37:37 +0000 Subject: [PATCH 5/6] Hook up the HIDE button to a cookie --- app/assets/javascripts/main.js | 26 +++++++++++++++++++++++ app/templates/components/new-feature.html | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 8f60cc5d64..70f4d6be36 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -158,6 +158,32 @@ $(() => GOVUK.modules.start()); return null; }; }).call(this); + +document.querySelectorAll("[data-new-feature]").forEach(function (banner) { + var featureId = banner.dataset.newFeature; + if (featureId && GOVUK.cookie("new-feature-" + featureId)) { + banner.remove(); + } else { + banner.classList.remove("hidden"); + } +}); + +document.addEventListener("click", function (event) { + var hideButton = event.target.closest("[data-dismiss-notice]"); + if (!hideButton) { + return; + } + + var banner = hideButton.closest("[data-new-feature]"); + var featureId = banner && banner.dataset.newFeature; + if (!featureId) { + return; + } + + GOVUK.cookie("new-feature-" + featureId, "hidden", { days: 365 }); + banner.remove(); +}); + (function () { "use strict"; var root = this || window; diff --git a/app/templates/components/new-feature.html b/app/templates/components/new-feature.html index da1eae2a2b..e7901cbf53 100644 --- a/app/templates/components/new-feature.html +++ b/app/templates/components/new-feature.html @@ -1,5 +1,5 @@ {% macro new_feature(title, cta="", cta_link="", anchored_to="") %} -
+