diff --git a/resources/js/components/book-sort.js b/resources/js/components/book-sort.js index 3c849c5c6..e8ecd49a4 100644 --- a/resources/js/components/book-sort.js +++ b/resources/js/components/book-sort.js @@ -162,7 +162,7 @@ export class BookSort extends Component { } /** - * Setup the handlers for the item-level move buttons. + * Set up the handlers for the item-level move buttons. */ setupMoveActions() { // Handle move button click @@ -173,20 +173,12 @@ export class BookSort extends Component { this.runSortAction(sortItem, action); } }); - // TODO - Probably can remove this - // // Handle action updating on likely use - // this.container.addEventListener('focusin', event => { - // const sortItem = event.target.closest('[data-type="chapter"],[data-type="page"]'); - // if (sortItem) { - // this.updateMoveActionState(sortItem); - // } - // }); this.updateMoveActionStateForAll(); } /** - * Setup the handlers for the preset sort type buttons. + * Set up the handlers for the preset sort type buttons. */ setupSortPresets() { let lastSort = ''; @@ -235,6 +227,9 @@ export class BookSort extends Component { this.sortContainer.append(newBookContainer); this.setupBookSortable(newBookContainer); this.updateMoveActionStateForAll(); + + const summary = newBookContainer.querySelector('summary'); + summary.focus(); }); } @@ -243,8 +238,7 @@ export class BookSort extends Component { * @param {Element} bookContainer */ setupBookSortable(bookContainer) { - const sortElems = [bookContainer.querySelector('.sort-list')]; - sortElems.push(...bookContainer.querySelectorAll('.entity-list-item + ul')); + const sortElems = Array.from(bookContainer.querySelectorAll('.sort-list, .sortable-page-sublist')); const bookGroupConfig = { name: 'book', diff --git a/resources/js/services/keyboard-navigation.js b/resources/js/services/keyboard-navigation.js index 0e1dcf1a7..0f866ceaa 100644 --- a/resources/js/services/keyboard-navigation.js +++ b/resources/js/services/keyboard-navigation.js @@ -86,7 +86,7 @@ export class KeyboardNavigationHandler { */ #getFocusable() { const focusable = []; - const selector = '[tabindex]:not([tabindex="-1"]),[href],button:not([tabindex="-1"]),input:not([type=hidden])'; + const selector = '[tabindex]:not([tabindex="-1"]),[href],button:not([tabindex="-1"],[disabled]),input:not([type=hidden])'; for (const container of this.containers) { focusable.push(...container.querySelectorAll(selector)) } diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 834cfacba..8bf805774 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -149,17 +149,18 @@ return [ 'books_sort_chapters_first' => 'Chapters First', 'books_sort_chapters_last' => 'Chapters Last', 'books_sort_show_other' => 'Show Other Books', + 'books_sort_save' => 'Save New Order', 'books_sort_show_other_desc' => 'Add other books here to include them in the sort operation, and allow easy cross-book reorganisation.', 'books_sort_move_up' => 'Move Up', 'books_sort_move_down' => 'Move Down', - 'books_sort_move_prev_book' => 'Move To Previous Book', - 'books_sort_move_next_book' => 'Move To Next Book', + 'books_sort_move_prev_book' => 'Move to Previous Book', + 'books_sort_move_next_book' => 'Move to Next Book', 'books_sort_move_prev_chapter' => 'Move Into Previous Chapter', 'books_sort_move_next_chapter' => 'Move Into Next Chapter', - 'books_sort_move_book_start' => 'Move To Start of Book', - 'books_sort_move_book_end' => 'Move To End of Book', - 'books_sort_move_before_chapter' => 'Move To Before Chapter', - 'books_sort_move_after_chapter' => 'Move To After Chapter', + 'books_sort_move_book_start' => 'Move to Start of Book', + 'books_sort_move_book_end' => 'Move to End of Book', + 'books_sort_move_before_chapter' => 'Move to Before Chapter', + 'books_sort_move_after_chapter' => 'Move to After Chapter', 'books_copy' => 'Copy Book', 'books_copy_success' => 'Book successfully copied', diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 39b2afee6..33e500d6a 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -267,7 +267,7 @@ .entity-list-item > span:first-child { align-self: flex-start; } - .sortable-selected .entity-list-item, .sortable-selected .entity-list-item:hover { + .sortable-selected, .sortable-selected:hover { outline: 1px dotted var(--color-primary); background-color: var(--color-primary-light) !important; } @@ -284,6 +284,7 @@ padding-inline-start: $-m; } li { + @include lightDark(background-color, #FFF, #222); border: 1px solid; @include lightDark(border-color, #DDD, #666); margin-top: -1px; @@ -316,6 +317,22 @@ details.sort-box summary .caret-container svg { details.sort-box[open] summary .caret-container svg { transform: rotate(90deg); } +.sort-box-actions .icon-button { + opacity: .6; +} +.sort-box .flex-container-row:hover .sort-box-actions .icon-button, +.sort-box .flex-container-row:focus-within .sort-box-actions .icon-button { + opacity: 1; +} +.sort-box-actions .icon-button[disabled] { + visibility: hidden; +} +.sort-box-actions .dropdown-menu button[disabled] { + display: none; +} +.sort-list-handle { + cursor: grab; +} .activity-list-item { padding: $-s 0; diff --git a/resources/views/books/parts/sort-box-actions.blade.php b/resources/views/books/parts/sort-box-actions.blade.php index c9a1d323e..cd5a59e15 100644 --- a/resources/views/books/parts/sort-box-actions.blade.php +++ b/resources/views/books/parts/sort-box-actions.blade.php @@ -1,10 +1,12 @@ -<div class="sort-box-actions"> - <button type="button" data-move="up" title="{{ trans('entities.books_sort_move_up') }}">@icon('chevron-up')</button> - <button type="button" data-move="down" +<div class="sort-box-actions flex-container-row items-center px-s gap-xxs"> + <button type="button" data-move="up" class="icon-button p-xs text-bigger" + title="{{ trans('entities.books_sort_move_up') }}">@icon('chevron-up')</button> + <button type="button" data-move="down" class="icon-button p-xs text-bigger" title="{{ trans('entities.books_sort_move_down') }}">@icon('chevron-down')</button> <div class="dropdown-container" component="dropdown"> <button refs="dropdown@toggle" title="{{ trans('common.more') }}" + class="icon-button p-xs text-bigger" aria-haspopup="true" aria-expanded="false"> @icon('more') diff --git a/resources/views/books/parts/sort-box.blade.php b/resources/views/books/parts/sort-box.blade.php index 33448f483..ca034a880 100644 --- a/resources/views/books/parts/sort-box.blade.php +++ b/resources/views/books/parts/sort-box.blade.php @@ -21,30 +21,35 @@ @foreach($bookChildren as $bookChild) <li class="text-{{ $bookChild->getType() }}" - data-id="{{$bookChild->id}}" data-type="{{ $bookChild->getType() }}" - data-name="{{ $bookChild->name }}" data-created="{{ $bookChild->created_at->timestamp }}" - data-updated="{{ $bookChild->updated_at->timestamp }}" tabindex="0"> - <div class="text-muted sort-list-handle">@icon('grip')</div> - <div class="entity-list-item"> - <span>@icon($bookChild->getType()) </span> - <div> - {{ $bookChild->name }} + data-id="{{$bookChild->id}}" + data-type="{{ $bookChild->getType() }}" + data-name="{{ $bookChild->name }}" + data-created="{{ $bookChild->created_at->timestamp }}" + data-updated="{{ $bookChild->updated_at->timestamp }}" + tabindex="0"> + <div class="flex-container-row items-center"> + <div class="text-muted sort-list-handle px-s py-m">@icon('grip')</div> + <div class="entity-list-item px-none no-hover"> + <span>@icon($bookChild->getType()) </span> <div> + {{ $bookChild->name }} + <div> + </div> </div> </div> + @include('books.parts.sort-box-actions') </div> - @include('books.parts.sort-box-actions') @if($bookChild->isA('chapter')) <ul class="sortable-page-sublist"> @foreach($bookChild->visible_pages as $page) - <li class="text-page" + <li class="text-page flex-container-row items-center" data-id="{{$page->id}}" data-type="page" data-name="{{ $page->name }}" data-created="{{ $page->created_at->timestamp }}" data-updated="{{ $page->updated_at->timestamp }}" tabindex="0"> - <div class="text-muted sort-list-handle">@icon('grip')</div> - <div class="entity-list-item"> + <div class="text-muted sort-list-handle px-s py-m">@icon('grip')</div> + <div class="entity-list-item px-none no-hover"> <span>@icon('page')</span> <span>{{ $page->name }}</span> </div>