Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1242aac
wip
stuartromanek Aug 26, 2024
4e3ff1e
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Aug 26, 2024
182f0c6
wip
stuartromanek Aug 28, 2024
a7426f4
retry
stuartromanek Aug 28, 2024
d1ac09f
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Aug 28, 2024
bec4eec
switch promise timeout for nexttick
stuartromanek Aug 28, 2024
00b6bf2
focus considerations for media uploader
stuartromanek Aug 28, 2024
84618f1
remove logs
stuartromanek Aug 28, 2024
689304a
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 3, 2024
c4a8a64
merge
stuartromanek Sep 3, 2024
1655d34
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 4, 2024
e9df8db
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 12, 2024
e0ed87e
restore focus to last selected item after prop change
stuartromanek Sep 12, 2024
60ac86c
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 12, 2024
31d7bc1
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 18, 2024
6efc895
merge
stuartromanek Sep 19, 2024
5b0b16a
make sure we have modal
stuartromanek Sep 19, 2024
30ee6ea
split button focus, widget priority button
stuartromanek Sep 19, 2024
90c1175
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 20, 2024
2f3388e
wip
stuartromanek Sep 23, 2024
f0ff6a7
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 23, 2024
ee12fd7
fix line
stuartromanek Sep 23, 2024
6fb3c09
lint
stuartromanek Sep 23, 2024
493416f
remove conditional rendering
stuartromanek Sep 23, 2024
fbb1042
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Sep 24, 2024
37b67ad
flex media manager containers
stuartromanek Oct 3, 2024
6d7eb2a
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Oct 3, 2024
78fef12
Merge branch 'main' into PRO-4505/modal-priority
myovchev Oct 3, 2024
c342c08
Fix media manager not handling search results properly (sometimes)
myovchev Oct 3, 2024
2b0e31f
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Oct 4, 2024
0e8addf
Merge branch 'main' into PRO-4505/modal-priority
stuartromanek Oct 7, 2024
40e5be1
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Oct 7, 2024
06448a4
Merge branch 'PRO-4505/modal-priority' of github.com:apostrophecms/ap…
stuartromanek Oct 7, 2024
8ed8037
cleanup
stuartromanek Oct 9, 2024
f8624b1
merge
stuartromanek Oct 9, 2024
4f793e7
changelog fix
stuartromanek Oct 9, 2024
d36676a
Merge branch 'main' of github.com:apostrophecms/apostrophe into PRO-4…
stuartromanek Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

### Adds

* Elements inside modals can have a `data-apos-focus-priority` attribute that prioritizes them inside the focusable elements list.
* Modals will continute trying to find focusable elements until an element marked `data-apos-focus-priority` appears or the max retry threshold is reached.
* Takes care of an edge case where Media Manager would duplicate search results.
* Modules can now have a `before: "module-name"` property in their configuration to run (initialization) before another module.

### Fixes

* Modifies the `AposAreaMenu.vue` component to set the `disabled` attribute to `true` if the max number of widgets have been added in an area with `expanded: true`.
* `pnpm: true` option in `app.js` is no longer breaking the application.
* Remove unused `vue-template-compiler` dependency.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<button
v-for="(item, itemIndex) in group.widgets"
:key="itemIndex"
:data-apos-focus-priority="itemIndex === 0 ? true : null"
class="apos-widget"
@click="add(item)"
>
Expand Down Expand Up @@ -259,6 +260,7 @@ export default {
& {
padding: 0;
border: none;
border-radius: var(--a-border-radius);
background: none;
text-align: inherit;
}
Expand Down Expand Up @@ -294,6 +296,12 @@ export default {
}
}

&:focus,
&:active {
outline: 2px solid var(--a-primary-light-40);
outline-offset: 4px;
}

&:hover {
cursor: pointer;
// stylelint-disable max-nesting-depth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<header class="apos-modal__header">
<div class="apos-modal__header__main">
<AposButton
:attrs="{'data-apos-focus-priority': true}"
type="default"
:title="$t('apostrophe:commandMenuEsc')"
:icon-only="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<AposButton
type="default"
label="apostrophe:cancel"
:attrs="{'data-apos-focus-priority': isPriorityButton('cancel')}"
@click="confirmAndCancel"
/>
</template>
Expand Down Expand Up @@ -42,6 +43,7 @@
:label="saveLabel"
:disabled="saveDisabled"
:tooltip="errorTooltip"
:attrs="{'data-apos-focus-priority': isPriorityButton('save')}"
@click="onRestore"
/>
<AposButtonSplit
Expand All @@ -51,6 +53,7 @@
:disabled="saveDisabled"
:tooltip="errorTooltip"
:selected="savePreference"
:attrs="{'data-apos-focus-priority': isPriorityButton('splitSave')}"
@click="saveHandler($event)"
/>
</template>
Expand Down Expand Up @@ -883,6 +886,12 @@ export default {
}

return body;
},
isPriorityButton(name) {
const priority = this.restoreOnly ? 'save'
: this.saveMenu ? 'splitSave'
: this.saveDisabled ? 'cancel' : null;
return name === priority || null;
Comment on lines +891 to +894
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤯

}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,15 @@
<template #footer>
<AposButton
v-if="isLastStep()"
:attrs="{'data-apos-focus-priority': true}"
type="primary"
label="apostrophe:localizeContent"
:disabled="!complete() || wizard.busy"
@click="submit"
/>
<AposButton
v-else
:attrs="{'data-apos-focus-priority': true}"
type="primary"
icon="arrow-right-icon"
:modifiers="['icon-right']"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
type="primary"
label="apostrophe:update"
:disabled="docFields.hasErrors"
:attrs="{'data-apos-focus-priority': true}"
@click="submit"
/>
</template>
Expand Down Expand Up @@ -94,7 +95,6 @@
<template #main>
<div ref="cropperContainer" class="apos-image-cropper__container">
<AposImageCropper
v-if="containerHeight"
:attachment="item.attachment"
:doc-fields="docFields"
:aspect-ratio="aspectRatio"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
type="primary"
:label="saveRelationshipLabel"
:disabled="!!relationshipErrors"
:attrs="{'data-apos-focus-priority': true}"
@click="saveRelationship"
/>
</template>
Expand Down Expand Up @@ -373,6 +374,7 @@ export default {
if (Array.isArray(tagList)) {
this.tagList = tagList;
}
this.items = [];
this.currentPage = currentPage;
this.totalPages = totalPages;
for (const item of items) {
Expand Down Expand Up @@ -610,7 +612,8 @@ export default {
}

:deep(.apos-modal__body-inner) {
overflow: hidden;
display: flex;
flex-direction: column;
height: 100%;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
/>
</div>
<button
:id="`btn-${item._id}`"
:id="`btn-${item._id.replaceAll(':', '-')}`"
:disabled="
item._id === 'placeholder' || canSelect(item._id) === false
"
Expand Down Expand Up @@ -168,6 +168,13 @@ export default {
async isLastPage(val) {
await this.$nextTick();
this.$emit('set-load-ref', this.$refs.scrollLoad);
},
async checked(newVal) {
if (newVal.length) {
await this.$nextTick();
const target = newVal[newVal.length - 1];
this.$el.querySelector(`#btn-${target.replaceAll(':', '-')}`).focus();
}
}
},
mounted() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<label
class="apos-media-manager-display__cell apos-media-uploader"
:class="{'apos-media-uploader--enabled': !disabled}"
:disabled="disabled"
:disabled="disabled ? disabled : null"
@drop.prevent="uploadMedia"
@dragover.prevent=""
@dragenter="incrementDragover"
Expand All @@ -12,6 +12,7 @@
class="apos-media-uploader__inner"
:class="{'apos-is-dragging': dragover}"
tabindex="0"
data-apos-focus-priority
@keydown="onUploadDragAndDropKeyDown"
>
<AposCloudUploadIcon
Expand Down Expand Up @@ -231,6 +232,10 @@ export default {
const isEnterPressed = e.key === 'Enter' || e.code === 'Enter' || e.code === 'NumpadEnter';
const isSpaceBarPressed = e.keyCode === 32 || e.code === 'Space';

if (isSpaceBarPressed) {
e.preventDefault();
}

if (isEnterPressed || isSpaceBarPressed) {
this.create();
}
Expand Down
92 changes: 64 additions & 28 deletions modules/@apostrophecms/modal/ui/apos/components/AposModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@leave="onLeave"
>
<section
v-if="modal.active"
v-show="modal.active"
ref="modalEl"
:class="classes"
role="dialog"
Expand Down Expand Up @@ -39,7 +39,11 @@
<AposSpinner :weight="'heavy'" class="apos-busy__spinner" />
</div>
</template>
<template v-else>
<div
v-show="!renderingElements && !modal.busy"
class="apos-modal__content"
data-apos-test="modal-content"
>
<header v-if="!modal.disableHeader" class="apos-modal__header">
<div class="apos-modal__header__main">
<div v-if="hasSlot('secondaryControls')" class="apos-modal__controls--secondary">
Expand Down Expand Up @@ -72,17 +76,23 @@
<slot class="apos-modal__breadcrumbs" name="breadcrumbs" />
</div>
</header>
<div class="apos-modal__main" :class="gridModifier">
<div
class="apos-modal__main"
:class="gridModifier"
>
<slot name="leftRail" />
<slot name="main" />
<slot name="rightRail" />
</div>
<footer v-if="hasSlot('footer')" class="apos-modal__footer">
<footer
v-if="hasSlot('footer')"
class="apos-modal__footer"
>
<div class="apos-modal__footer__inner">
<slot name="footer" />
</div>
</footer>
</template>
</div>
</div>
</transition>
</section>
Expand Down Expand Up @@ -110,8 +120,8 @@ const {
cycleElementsToFocus,
focusElement,
focusLastModalFocusedElement,
isElementVisible,
storeFocusedElement
storeFocusedElement,
findPriorityElementOrFirst
} = useAposFocus();

const props = defineProps({
Expand All @@ -134,6 +144,9 @@ const store = useModalStore();
const slots = useSlots();
const emit = defineEmits([ 'inactive', 'esc', 'show-modal', 'no-modal', 'ready' ]);
const modalEl = ref(null);
const findPriorityFocusElementRetryMax = ref(3);
const currentPriorityFocusElementRetry = ref(0);
const renderingElements = ref(true);
const currentLocale = ref(store.activeModal?.locale || apos.i18n.locale);

const transitionType = computed(() => {
Expand Down Expand Up @@ -216,6 +229,8 @@ onMounted(async () => {
await nextTick();
if (shouldTrapFocus.value) {
trapFocus();
} else {
renderingElements.value = false;
}
store.updateModalData(props.modalData.id, { modalEl: modalEl.value });
window.addEventListener('keydown', onKeydown);
Expand Down Expand Up @@ -249,29 +264,44 @@ function onLeave() {
emit('no-modal');
}

function trapFocus() {
const elementSelectors = [
'[tabindex]',
'[href]',
'input',
'select',
'textarea',
'button'
];

const selector = elementSelectors
.map(addExcludingAttributes)
.join(', ');

const elementsToFocus = [ ...modalEl.value.querySelectorAll(selector) ]
.filter(isElementVisible);

store.updateModalData(props.modalData.id, { elementsToFocus });

focusElement(props.modalData.focusedElement, props.modalData.elementsToFocus[0]);
async function trapFocus() {
if (modalEl?.value) {
const elementSelectors = [
'[tabindex]',
'[href]',
'input',
'select',
'textarea',
'button',
'[data-apos-focus-priority]'
];

const selector = elementSelectors
.map(addExcludingAttributes)
.join(', ');

const elementsToFocus = [ ...modalEl.value.querySelectorAll(selector) ];

store.updateModalData(props.modalData.id, { elementsToFocus });

const firstElementToFocus = findPriorityElementOrFirst(elementsToFocus);
const foundPriorityElement = firstElementToFocus?.hasAttribute('data-apos-focus-priority');

// // Components render at various times and can't be counted on to be available on modal's mount
// // Update the trap focus list until a data-apos-focus-priority element is found or the retry limit is reached
if (!foundPriorityElement && findPriorityFocusElementRetryMax.value > currentPriorityFocusElementRetry.value) {
await new Promise(resolve => setTimeout(resolve, 50));
currentPriorityFocusElementRetry.value++;
trapFocus();
return;
}
renderingElements.value = false;
await nextTick();
focusElement(props.modalData.focusedElement, firstElementToFocus);
}

function addExcludingAttributes(element) {
return `${element}:not([tabindex="-1"]):not([disabled]):not([type="hidden"]):not([aria-hidden])`;
return `${element}:not([tabindex="-1"]):not([disabled]):not([type="hidden"]):not([aria-hidden]):not(.apos-sr-only)`;
}
}

Expand Down Expand Up @@ -372,6 +402,12 @@ function close() {
height: 100%;
}

.apos-modal__content {
display: flex;
flex-direction: column;
height: 100%;
}

.apos-modal__main {
display: grid;
flex-grow: 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
</div>
<div
class="apos-modal__body-main"
:style="{ height: `calc(100% - ${headerHeight}px)`}"
>
<slot name="bodyMain" />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@
<div class="apos-confirm__btns">
<AposButton
v-if="mode !== 'alert'"
:attrs="{'data-apos-focus-priority': mode !== 'alert' ? true : null}"
class="apos-confirm__btn"
:label="content.negativeLabel || 'apostrophe:cancel'"
@click="cancel"
/>
<AposButton
ref="confirm"
:attrs="{'data-apos-focus-priority': mode === 'alert' ? true : null}"
class="apos-confirm__btn"
:label="affirmativeLabel"
:type="content.theme || 'primary'"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<AposToggle
v-model="disabled"
class="apos-share-draft__toggle"
data-apos-focus-priority
@toggle="toggle"
/>
<p class="apos-share-draft__toggle-label" @click="toggle">
Expand Down
Loading
Loading