kopia lustrzana https://github.com/wagtail/wagtail
Co-authored-by: Thibaud Colas <thibaudcolas@gmail.com>pull/7291/head
rodzic
297fb10597
commit
3ee060ffd7
|
@ -12,6 +12,7 @@ Changelog
|
|||
* Added `WAGTAIL_WORKFLOW_ENABLED` setting for enabling / disabling moderation workflows globally (Matt Westcott)
|
||||
* Allow specifying `max_width` and `max_height` on EmbedBlock (Petr Dlouhý)
|
||||
* Add warning when StreamField is used without a StreamFieldPanel (Naomi Morduch Toubman)
|
||||
* Added keyboard and screen reader support to Wagtail user bar (LB Johnston, Storm Heg)
|
||||
* Fix: Invalid filter values for foreign key fields in the API now give an error instead of crashing (Tidjani Dia)
|
||||
* Fix: Ordering specified in `construct_explorer_page_queryset` hook is now taken into account again by the page explorer API (Andre Fonseca)
|
||||
* Fix: Deleting a page from its listing view no longer results in a 404 error (Tidjani Dia)
|
||||
|
|
|
@ -2,57 +2,206 @@
|
|||
// Please stick to old JS APIs and avoid importing anything that might require a vendored module
|
||||
// More background can be found in webpack.config.js
|
||||
|
||||
document.addEventListener('DOMContentLoaded', (e) => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const userbar = document.querySelector('[data-wagtail-userbar]');
|
||||
const trigger = userbar.querySelector('[data-wagtail-userbar-trigger]');
|
||||
const list = userbar.querySelector('.wagtail-userbar-items');
|
||||
const className = 'is-active';
|
||||
const hasTouch = 'ontouchstart' in window;
|
||||
const clickEvent = 'click';
|
||||
const list = userbar.querySelector('[role=menu]');
|
||||
const listItems = list.querySelectorAll('li');
|
||||
const isActiveClass = 'is-active';
|
||||
|
||||
if (hasTouch) {
|
||||
userbar.classList.add('touch');
|
||||
|
||||
// Bind to touchend event, preventDefault to prevent DELAY and CLICK
|
||||
// in accordance with: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how/
|
||||
trigger.addEventListener('touchend', (e2) => {
|
||||
e.preventDefault();
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
toggleUserbar(e2);
|
||||
});
|
||||
} else {
|
||||
userbar.classList.add('no-touch');
|
||||
}
|
||||
// querySelector for all items that can be focused.
|
||||
// source: https://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
|
||||
const focusableItemSelector = `a[href]:not([tabindex='-1']),
|
||||
button:not([disabled]):not([tabindex='-1']),
|
||||
input:not([disabled]):not([tabindex='-1']),
|
||||
[tabindex]:not([tabindex='-1'])`;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
trigger.addEventListener(clickEvent, toggleUserbar, false);
|
||||
trigger.addEventListener('click', toggleUserbar, false);
|
||||
|
||||
// make sure userbar is hidden when navigating back
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
window.addEventListener('pageshow', hideUserbar, false);
|
||||
|
||||
function showUserbar() {
|
||||
userbar.classList.add(className);
|
||||
// Handle keyboard events on the trigger
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
userbar.addEventListener('keydown', handleTriggerKeyDown);
|
||||
|
||||
|
||||
function showUserbar(shouldFocus) {
|
||||
userbar.classList.add(isActiveClass);
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
list.addEventListener(clickEvent, sandboxClick, false);
|
||||
list.addEventListener('click', sandboxClick, false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
window.addEventListener(clickEvent, clickOutside, false);
|
||||
window.addEventListener('click', clickOutside, false);
|
||||
|
||||
// Start handling keyboard input now that the userbar is open.
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
userbar.addEventListener('keydown', handleUserbarItemsKeyDown, false);
|
||||
|
||||
// The userbar has role=menu which means that the first link should be focused on popup
|
||||
// For weird reasons shifting focus only works after some amount of delay
|
||||
// Which is why we are forced to use setTimeout
|
||||
if (shouldFocus) {
|
||||
// Find the first focusable element (if any) and focus it
|
||||
if (list.querySelector(focusableItemSelector)) {
|
||||
setTimeout(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
setFocusToFirstItem();
|
||||
}, 300); // Less than 300ms doesn't seem to work
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hideUserbar() {
|
||||
userbar.classList.remove(className);
|
||||
userbar.classList.remove(isActiveClass);
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
list.addEventListener(clickEvent, sandboxClick, false);
|
||||
list.addEventListener('click', sandboxClick, false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
window.removeEventListener(clickEvent, clickOutside, false);
|
||||
window.removeEventListener('click', clickOutside, false);
|
||||
|
||||
// Cease handling keyboard input now that the userbar is closed.
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
userbar.removeEventListener('keydown', handleUserbarItemsKeyDown, false);
|
||||
}
|
||||
|
||||
function toggleUserbar(e2) {
|
||||
e2.stopPropagation();
|
||||
if (userbar.classList.contains(className)) {
|
||||
if (userbar.classList.contains(isActiveClass)) {
|
||||
hideUserbar();
|
||||
} else {
|
||||
showUserbar();
|
||||
showUserbar(true);
|
||||
}
|
||||
}
|
||||
|
||||
function setFocusToTrigger() {
|
||||
setTimeout(() => trigger.focus(), 300);
|
||||
}
|
||||
|
||||
function isFocusOnItems() {
|
||||
return document.activeElement && !!document.activeElement.closest('.wagtail-userbar-items');
|
||||
}
|
||||
|
||||
function setFocusToFirstItem() {
|
||||
if (listItems.length > 0) {
|
||||
setTimeout(() => {
|
||||
listItems[0].firstElementChild.focus();
|
||||
}, 100); // Workaround for focus bug
|
||||
}
|
||||
}
|
||||
|
||||
function setFocusToLastItem() {
|
||||
if (listItems.length > 0) {
|
||||
setTimeout(() => {
|
||||
listItems[listItems.length - 1].firstElementChild.focus();
|
||||
}, 100); // Workaround for focus bug
|
||||
}
|
||||
}
|
||||
|
||||
function setFocusToNextItem() {
|
||||
listItems.forEach((element, idx) => {
|
||||
// Check which item is currently focused
|
||||
if (element.firstElementChild === document.activeElement) {
|
||||
setTimeout(() => {
|
||||
if (idx + 1 < listItems.length) {
|
||||
// Focus the next item
|
||||
listItems[idx + 1].firstElementChild.focus();
|
||||
} else {
|
||||
setFocusToFirstItem();
|
||||
}
|
||||
}, 100); // Workaround for focus bug
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setFocusToPreviousItem() {
|
||||
// Check which item is currently focused
|
||||
listItems.forEach((element, idx) => {
|
||||
if (element.firstElementChild === document.activeElement) {
|
||||
setTimeout(() => {
|
||||
if (idx > 0) {
|
||||
// Focus the previous item
|
||||
listItems[idx - 1].firstElementChild.focus();
|
||||
} else {
|
||||
setFocusToLastItem();
|
||||
}
|
||||
}, 100); // Workaround for focus bug
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
This handler is responsible for keyboard input when items inside the userbar are focused.
|
||||
It should only listen when the userbar is open.
|
||||
|
||||
It is responsible for:
|
||||
- Shifting focus using the arrow / home / end keys.
|
||||
- Closing the menu when 'Escape' is pressed.
|
||||
*/
|
||||
function handleUserbarItemsKeyDown(event) {
|
||||
// Only handle keyboard input if the userbar is open
|
||||
if (trigger.getAttribute('aria-expanded') === 'true') {
|
||||
if (event.key === 'Escape') {
|
||||
hideUserbar();
|
||||
setFocusToTrigger();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFocusOnItems()) {
|
||||
switch (event.key) {
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
setFocusToNextItem();
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
event.preventDefault();
|
||||
setFocusToPreviousItem();
|
||||
break;
|
||||
case 'Home':
|
||||
event.preventDefault();
|
||||
setFocusToFirstItem();
|
||||
break;
|
||||
case 'End':
|
||||
event.preventDefault();
|
||||
setFocusToLastItem();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This handler is responsible for opening the userbar with the arrow keys
|
||||
if it's focused and not open yet. It should always be listening.
|
||||
*/
|
||||
function handleTriggerKeyDown(event) {
|
||||
// Check if the userbar is focused (but not open yet) and should be opened by keyboard input
|
||||
if (trigger === document.activeElement && trigger.getAttribute('aria-expanded') === 'false') {
|
||||
switch (event.key) {
|
||||
case 'ArrowUp':
|
||||
event.preventDefault();
|
||||
showUserbar(false);
|
||||
|
||||
// Workaround for focus bug
|
||||
// Needs extra delay to account for the userbar open animation. Otherwise won't focus properly.
|
||||
setTimeout(() => setFocusToLastItem(), 300);
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
showUserbar(false);
|
||||
|
||||
// Workaround for focus bug
|
||||
// Needs extra delay to account for the userbar open animation. Otherwise won't focus properly.
|
||||
setTimeout(() => setFocusToFirstItem(), 300);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -817,7 +817,7 @@ Hooks for customising the way users are directed through the process of creating
|
|||
class UserbarPuppyLinkItem:
|
||||
def render(self, request):
|
||||
return '<li><a href="http://cuteoverload.com/tag/puppehs/" ' \
|
||||
+ 'target="_parent" class="action icon icon-wagtail">Puppies!</a></li>'
|
||||
+ 'target="_parent" role="menuitem" class="action icon icon-wagtail">Puppies!</a></li>'
|
||||
|
||||
@hooks.register('construct_wagtail_userbar')
|
||||
def add_puppy_link_item(request, items):
|
||||
|
|
|
@ -20,6 +20,7 @@ Other features
|
|||
* Added ``WAGTAIL_WORKFLOW_ENABLED`` setting for enabling / disabling moderation workflows globally (Matt Westcott)
|
||||
* Allow specifying ``max_width`` and ``max_height`` on EmbedBlock (Petr Dlouhý)
|
||||
* Add warning when StreamField is used without a StreamFieldPanel (Naomi Morduch Toubman)
|
||||
* Added keyboard and screen reader support to Wagtail user bar (LB Johnston, Storm Heg)
|
||||
|
||||
Bug fixes
|
||||
~~~~~~~~~
|
||||
|
@ -44,3 +45,10 @@ Removed support for Django 2.2
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Django 2.2 is no longer supported as of this release; please upgrade to Django 3.0 or above before upgrading Wagtail.
|
||||
|
||||
User bar with keyboard and screen reader support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Wagtail user bar (“edit bird”) widget now supports keyboard and screen reader navigation. To make the most of this, we now recommend placing the widget near the top of the page ``<body>``, so users can reach it without having to go through the whole page. See :ref:`wagtailuserbar_tag` for more information.
|
||||
|
||||
For implementers of custom user bar menu items, we also now require the addition of ``role="menuitem"`` on the ``a`` element to provide the correct semantics. See :ref:`construct_wagtail_userbar` for more information.
|
||||
|
|
|
@ -246,11 +246,22 @@ This tag provides a contextual flyout menu for logged-in users. The menu gives e
|
|||
|
||||
This tag may be used on regular Django views, without page object. The user bar will contain one item pointing to the admin.
|
||||
|
||||
We recommend putting the tag near the top of the ``<body>`` element so keyboard users can reach it. You should consider putting the tag after any `skip links <https://webaim.org/techniques/skipnav/>`_ but before the navigation and main content of your page.
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% load wagtailuserbar %}
|
||||
...
|
||||
{% wagtailuserbar %}
|
||||
<body>
|
||||
<a id="#content">Skip to content</a>
|
||||
{% wagtailuserbar %} {# This is a good place for the userbar #}
|
||||
<nav>
|
||||
...
|
||||
</nav>
|
||||
<main id="content">
|
||||
...
|
||||
</main>
|
||||
</body>
|
||||
|
||||
By default the User Bar appears in the bottom right of the browser window, inset from the edge. If this conflicts with your design it can be moved by passing a parameter to the template tag. These examples show you how to position the userbar in each corner of the screen:
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ $positions: (
|
|||
|
||||
// stylelint-disable declaration-no-important
|
||||
.#{$namespace}-userbar-trigger {
|
||||
all: initial;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -124,6 +125,7 @@ $positions: (
|
|||
margin: 0 !important;
|
||||
overflow: hidden;
|
||||
background-color: $color-white;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 50%;
|
||||
color: $color-black;
|
||||
padding: 0 !important;
|
||||
|
@ -134,15 +136,15 @@ $positions: (
|
|||
text-decoration: none !important;
|
||||
position: relative;
|
||||
|
||||
.#{$namespace}-userbar.touch.is-active &,
|
||||
.#{$namespace}-userbar.no-touch &:hover {
|
||||
box-shadow: $box-shadow-props, 0 3px 15px 0 rgba(107, 214, 230, 0.95);
|
||||
}
|
||||
|
||||
.#{$namespace}-userbar-help-text {
|
||||
// Visually hide the help text
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.#{$namespace}-icon:before {
|
||||
|
@ -151,9 +153,14 @@ $positions: (
|
|||
width: auto;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: $color-focus-outline solid 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.#{$namespace}-userbar-items {
|
||||
all: revert;
|
||||
display: block;
|
||||
list-style: none;
|
||||
position: absolute;
|
||||
|
@ -182,6 +189,11 @@ $positions: (
|
|||
transition-duration: 0.15s;
|
||||
transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1);
|
||||
|
||||
// stylelint-disable-next-line scss/media-feature-value-dollar-variable
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.#{$namespace}-userbar.is-active & {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
|
@ -205,6 +217,7 @@ $positions: (
|
|||
|
||||
|
||||
.#{$namespace}-userbar__item {
|
||||
all: revert;
|
||||
margin: 0;
|
||||
background-color: $color-grey-1;
|
||||
opacity: 0;
|
||||
|
@ -215,6 +228,14 @@ $positions: (
|
|||
font-size: 16px !important;
|
||||
text-decoration: none !important;
|
||||
|
||||
// stylelint-disable-next-line scss/media-feature-value-dollar-variable
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition: none !important;
|
||||
|
||||
// Force disable transitions for all items
|
||||
transition-delay: 0s !important;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: $userbar-radius;
|
||||
border-top-right-radius: $userbar-radius;
|
||||
|
@ -242,11 +263,14 @@ $positions: (
|
|||
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: none;
|
||||
color: $color-white;
|
||||
background-color: rgba(100, 100, 100, 0.15);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: $color-focus-outline solid 3px;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
@include svg-icon(1.1em, middle);
|
||||
margin-right: 0.5em;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<div class="wagtail-userbar wagtail-userbar--{{ position|default:'bottom-right' }}" data-wagtail-userbar>
|
||||
<link rel="stylesheet" href="{% versioned_static 'wagtailadmin/css/userbar.css' %}" type="text/css" />
|
||||
<div class="wagtail-userbar-nav">
|
||||
<div class="wagtail-userbar-trigger" data-wagtail-userbar-trigger>
|
||||
<button aria-controls="wagtail-userbar-items" aria-haspopup="true" class="wagtail-userbar-trigger" id="wagtail-userbar-trigger" data-wagtail-userbar-trigger>
|
||||
{% block branding_logo %}
|
||||
<div style="display: none">
|
||||
<svg>
|
||||
|
@ -22,13 +22,13 @@
|
|||
<use href="#icon-wagtail-icon"></use>
|
||||
</svg>
|
||||
{% endblock %}
|
||||
<span class="wagtail-userbar-help-text">{% trans 'Go to Wagtail admin interface' %}</span>
|
||||
</div>
|
||||
<div class='wagtail-userbar-items'>
|
||||
<span class="wagtail-userbar-help-text">{% trans 'View Wagtail quick actions' %}</span>
|
||||
</button>
|
||||
<ul aria-labelledby="wagtail-userbar-trigger" class="wagtail-userbar-items" id="wagtail-userbar-items" role="menu">
|
||||
{% for item in items %}
|
||||
{{ item|safe }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
<script src="{% versioned_static 'wagtailadmin/js/userbar.js' %}"></script>
|
||||
</div>
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% block item_content %}
|
||||
<div class="wagtail-action">
|
||||
<a href="{% url 'wagtailadmin_home' %}" target="_parent">
|
||||
{% icon name="wagtail-icon" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Go to Wagtail admin' %}
|
||||
</a>
|
||||
</div>
|
||||
<a href="{% url 'wagtailadmin_home' %}" target="_parent" class="wagtail-userbar-link" role="menuitem">
|
||||
{% icon name="wagtail-icon" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Go to Wagtail admin' %}
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
<div class="wagtail-userbar__item {% block item_classes %}{% endblock %}">{% block item_content %}{% endblock %}</div>
|
||||
<li class="wagtail-userbar__item {% block item_classes %}{% endblock %}" role="presentation">
|
||||
{% block item_content %}{% endblock %}
|
||||
</li>
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% block item_content %}
|
||||
<div class="wagtail-action">
|
||||
<a href="{% url 'wagtailadmin_pages:add_subpage' self.page.id %}" target="_parent">
|
||||
{% icon name="plus" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Add a child page' %}
|
||||
</a>
|
||||
</div>
|
||||
<a href="{% url 'wagtailadmin_pages:add_subpage' self.page.id %}" target="_parent" role="menuitem">
|
||||
{% icon name="plus" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Add a child page' %}
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
{% block item_content %}
|
||||
<form action="{% url 'wagtailadmin_pages:approve_moderation' self.revision.id %}" target="_parent" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="wagtail-action">
|
||||
<button type="submit" value="{% trans 'Approve' %}" class="button">
|
||||
{% icon name="tick" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Approve' %}
|
||||
</button>
|
||||
</div>
|
||||
<button type="submit" value="{% trans 'Approve' %}" class="button" role="menuitem">
|
||||
{% icon name="tick" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Approve' %}
|
||||
</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% block item_content %}
|
||||
<div class="wagtail-action">
|
||||
<a href="{% url 'wagtailadmin_pages:edit' self.page.id %}" target="_parent">
|
||||
{% icon name="edit" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Edit this page' %}
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
<a href="{% url 'wagtailadmin_pages:edit' self.page.id %}" target="_parent" role="menuitem">
|
||||
{% icon name="edit" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Edit this page' %}
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% block item_content %}
|
||||
<div class="wagtail-action">
|
||||
<a href="{% url 'wagtailadmin_explore' self.parent_page.id %}" target="_parent">
|
||||
{% icon name="folder-open-inverse" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Show in Explorer' %}
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
<a href="{% url 'wagtailadmin_explore' self.parent_page.id %}" target="_parent" role="menuitem">
|
||||
{% icon name="folder-open-inverse" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Show in Explorer' %}
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
{% block item_content %}
|
||||
<form action="{% url 'wagtailadmin_pages:reject_moderation' self.revision.id %}" target="_parent" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="wagtail-action">
|
||||
<button type="submit" value="{% trans 'Reject' %}" class="button">
|
||||
{% icon name="cross" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Reject' %}
|
||||
</button>
|
||||
</div>
|
||||
<button type="submit" value="{% trans 'Reject' %}" class="button" role="menuitem">
|
||||
{% icon name="cross" class_name="wagtail-action-icon" %}
|
||||
{% trans 'Reject' %}
|
||||
</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -111,7 +111,7 @@ class TestUserbarAddLink(TestCase, WagtailTestUtils):
|
|||
# page allows subpages, so the 'add page' button should show
|
||||
expected_url = reverse('wagtailadmin_pages:add_subpage', args=(self.event_index.id, ))
|
||||
needle = f"""
|
||||
<a href="{expected_url}" target="_parent">
|
||||
<a href="{expected_url}" target="_parent" role="menuitem">
|
||||
<svg class="icon icon-plus wagtail-action-icon" aria-hidden="true" focusable="false">
|
||||
<use href="#icon-plus"></use>
|
||||
</svg>
|
||||
|
|
Ładowanie…
Reference in New Issue