diff --git a/client/scss/components/_breadcrumbs.scss b/client/scss/components/_breadcrumbs.scss
index e43710f962..cb5e9edee7 100644
--- a/client/scss/components/_breadcrumbs.scss
+++ b/client/scss/components/_breadcrumbs.scss
@@ -11,5 +11,9 @@
font-size: theme('fontSize.22');
}
}
+
+ .w-breadcrumbs__sublabel {
+ display: inline-block;
+ }
}
}
diff --git a/wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html b/wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html
index fb81c902b3..096f27564a 100644
--- a/wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html
+++ b/wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html
@@ -3,7 +3,7 @@
The breadcrumb component is reused across most of Wagtail's headers.
Variables this template accepts:
- `items` - A list of {"url": Union[str, None], "label": str} dicts
+ `items` - A list of {"url": Union[str, None], "label": str, "sublabel": Union[str, None]} dicts
`classname` - Modifier classes
`is_expanded` - Whether the breadcrumbs are always expanded or not, if True the breadcrumbs will not be collapsible
{% endcomment %}
@@ -48,13 +48,23 @@
data-w-breadcrumbs-target="content"
{% endif %}
>
+ {% fragment as sublabel %}
+ {% if item.sublabel %}
+ :
+
+ {{ item.sublabel }}
+
+ {% endif %}
+ {% endfragment %}
{% if item.url is not None %}
{{ item.label }}
+ {{ sublabel }}
{% else %}
{{ item.label }}
+ {{ sublabel }}
{% endif %}
{% if not forloop.last %}
diff --git a/wagtail/admin/tests/viewsets/test_model_viewset.py b/wagtail/admin/tests/viewsets/test_model_viewset.py
index 2bf66aa9d8..02239d4197 100644
--- a/wagtail/admin/tests/viewsets/test_model_viewset.py
+++ b/wagtail/admin/tests/viewsets/test_model_viewset.py
@@ -773,6 +773,7 @@ class TestBreadcrumbs(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
{
"url": "",
"label": "History",
+ "sublabel": str(self.object),
},
]
self.assertBreadcrumbsItemsRendered(items, response.content)
@@ -797,6 +798,7 @@ class TestBreadcrumbs(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
{
"url": "",
"label": "Usage",
+ "sublabel": str(self.object),
},
]
self.assertBreadcrumbsItemsRendered(items, response.content)
@@ -821,6 +823,7 @@ class TestBreadcrumbs(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
{
"url": "",
"label": "Inspect",
+ "sublabel": str(self.object),
},
]
self.assertBreadcrumbsItemsRendered(items, response.content)
diff --git a/wagtail/snippets/tests/test_viewset.py b/wagtail/snippets/tests/test_viewset.py
index 80664520f2..53a526472c 100644
--- a/wagtail/snippets/tests/test_viewset.py
+++ b/wagtail/snippets/tests/test_viewset.py
@@ -1472,7 +1472,7 @@ class TestBreadcrumbs(AdminTemplateTestUtils, BaseSnippetViewSetTests):
"url": self.get_url("edit", args=(self.object.pk,)),
"label": str(self.object),
},
- {"url": "", "label": "History"},
+ {"url": "", "label": "History", "sublabel": str(self.object)},
]
self.assertBreadcrumbsItemsRendered(items, response.content)
@@ -1487,7 +1487,7 @@ class TestBreadcrumbs(AdminTemplateTestUtils, BaseSnippetViewSetTests):
"url": self.get_url("edit", args=(self.object.pk,)),
"label": str(self.object),
},
- {"url": "", "label": "Usage"},
+ {"url": "", "label": "Usage", "sublabel": str(self.object)},
]
self.assertBreadcrumbsItemsRendered(items, response.content)
@@ -1502,7 +1502,7 @@ class TestBreadcrumbs(AdminTemplateTestUtils, BaseSnippetViewSetTests):
"url": self.get_url("edit", args=(self.object.pk,)),
"label": str(self.object),
},
- {"url": "", "label": "Inspect"},
+ {"url": "", "label": "Inspect", "sublabel": str(self.object)},
]
self.assertBreadcrumbsItemsRendered(items, response.content)
diff --git a/wagtail/test/utils/template_tests.py b/wagtail/test/utils/template_tests.py
index c89ef1bb7a..e6f5e69f9b 100644
--- a/wagtail/test/utils/template_tests.py
+++ b/wagtail/test/utils/template_tests.py
@@ -58,13 +58,26 @@ class AdminTemplateTestUtils:
element,
f"Expected '{item['label']}' breadcrumbs item to be a div",
)
- label = element.text.strip()
+
+ # Sublabel is optional and the : separator is invisible
+ label = element.get_text(strip=True)
+ sublabel = None
+ if item.get("sublabel"):
+ label, sublabel = label.split(":", maxsplit=1)
+
self.assertEqual(
label,
item["label"],
f"Expected '{item['label']}' breadcrumbs item label, found '{label}'",
)
+ if sublabel:
+ self.assertEqual(
+ sublabel,
+ item["sublabel"],
+ f"Expected '{item['sublabel']}' breadcrumbs item sublabel, found '{sublabel}'",
+ )
+
def assertBreadcrumbsNotRendered(
self: Union[WagtailTestUtils, SimpleTestCase],
html: Union[str, bytes],