From cb10ad804f046d652950dbafb3d549875b4f898f Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Wed, 18 May 2022 14:06:40 +0100
Subject: [PATCH] Made chapter toggle in book sidebar nav more consistent

- Now has a hover state to match other items.
- Now spans the full sidebar with like other items.
- Also updated chapter-toggle to a chapter-contents component, following
  the newer component system.
---
 resources/js/components/chapter-contents.js   | 37 +++++++++++++++++++
 resources/js/components/chapter-toggle.js     | 33 -----------------
 resources/js/components/index.js              |  4 +-
 resources/sass/_components.scss               |  4 +-
 resources/sass/_lists.scss                    | 37 +++++++++++--------
 .../views/chapters/parts/child-menu.blade.php | 13 +++++--
 .../views/chapters/parts/list-item.blade.php  |  9 +++--
 7 files changed, 76 insertions(+), 61 deletions(-)
 create mode 100644 resources/js/components/chapter-contents.js
 delete mode 100644 resources/js/components/chapter-toggle.js

diff --git a/resources/js/components/chapter-contents.js b/resources/js/components/chapter-contents.js
new file mode 100644
index 000000000..c824d0f78
--- /dev/null
+++ b/resources/js/components/chapter-contents.js
@@ -0,0 +1,37 @@
+import {slideUp, slideDown} from "../services/animations";
+
+/**
+ * @extends {Component}
+ */
+class ChapterContents {
+
+    setup() {
+        this.list = this.$refs.list;
+        this.toggle = this.$refs.toggle;
+
+        this.isOpen = this.toggle.classList.contains('open');
+        this.toggle.addEventListener('click', this.click.bind(this));
+    }
+
+    open() {
+        this.toggle.classList.add('open');
+        this.toggle.setAttribute('aria-expanded', 'true');
+        slideDown(this.list, 180);
+        this.isOpen = true;
+    }
+
+    close() {
+        this.toggle.classList.remove('open');
+        this.toggle.setAttribute('aria-expanded', 'false');
+        slideUp(this.list, 180);
+        this.isOpen = false;
+    }
+
+    click(event) {
+        event.preventDefault();
+        this.isOpen ?  this.close() : this.open();
+    }
+
+}
+
+export default ChapterContents;
diff --git a/resources/js/components/chapter-toggle.js b/resources/js/components/chapter-toggle.js
deleted file mode 100644
index 2fb3f3f1e..000000000
--- a/resources/js/components/chapter-toggle.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import {slideUp, slideDown} from "../services/animations";
-
-class ChapterToggle {
-
-    constructor(elem) {
-        this.elem = elem;
-        this.isOpen = elem.classList.contains('open');
-        elem.addEventListener('click', this.click.bind(this));
-    }
-
-    open() {
-        const list = this.elem.parentNode.querySelector('.inset-list');
-        this.elem.classList.add('open');
-        this.elem.setAttribute('aria-expanded', 'true');
-        slideDown(list, 180);
-    }
-
-    close() {
-        const list = this.elem.parentNode.querySelector('.inset-list');
-        this.elem.classList.remove('open');
-        this.elem.setAttribute('aria-expanded', 'false');
-        slideUp(list, 180);
-    }
-
-    click(event) {
-        event.preventDefault();
-        this.isOpen ?  this.close() : this.open();
-        this.isOpen = !this.isOpen;
-    }
-
-}
-
-export default ChapterToggle;
diff --git a/resources/js/components/index.js b/resources/js/components/index.js
index 1bbca864c..f360e2b0c 100644
--- a/resources/js/components/index.js
+++ b/resources/js/components/index.js
@@ -6,7 +6,7 @@ import attachmentsList from "./attachments-list.js"
 import autoSuggest from "./auto-suggest.js"
 import backToTop from "./back-to-top.js"
 import bookSort from "./book-sort.js"
-import chapterToggle from "./chapter-toggle.js"
+import chapterContents from "./chapter-contents.js"
 import codeEditor from "./code-editor.js"
 import codeHighlighter from "./code-highlighter.js"
 import codeTextarea from "./code-textarea.js"
@@ -63,7 +63,7 @@ const componentMapping = {
     "auto-suggest": autoSuggest,
     "back-to-top": backToTop,
     "book-sort": bookSort,
-    "chapter-toggle": chapterToggle,
+    "chapter-contents": chapterContents,
     "code-editor": codeEditor,
     "code-highlighter": codeHighlighter,
     "code-textarea": codeTextarea,
diff --git a/resources/sass/_components.scss b/resources/sass/_components.scss
index e30492b6b..e3c9d5eea 100644
--- a/resources/sass/_components.scss
+++ b/resources/sass/_components.scss
@@ -61,7 +61,7 @@
   }
 }
 
-[chapter-toggle] {
+.chapter-contents-toggle {
   cursor: pointer;
   margin: 0;
   transition: all ease-in-out 180ms;
@@ -77,7 +77,7 @@
     transform: rotate(90deg);
   }
   svg[data-icon="caret-right"] + * {
-    margin-inline-start: $-xs;
+    margin-inline-start: $-xxs;
   }
 }
 
diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss
index 4521e7fd4..8ca811c5c 100644
--- a/resources/sass/_lists.scss
+++ b/resources/sass/_lists.scss
@@ -56,13 +56,13 @@
   > .content {
     flex: 1;
   }
-  .chapter-expansion-toggle {
+  .chapter-contents-toggle {
     border-radius: 0 4px 4px 0;
     padding: $-xs ($-m + $-xxs);
     width: 100%;
     text-align: start;
   }
-  .chapter-expansion-toggle:hover {
+  .chapter-contents-toggle:hover {
     background-color: rgba(0, 0, 0, 0.06);
   }
 }
@@ -171,6 +171,7 @@
     border-radius: 0 3px 3px 0;
     padding-inline-end: 0;
     .content {
+      width: 100%;
       padding-top: $-xs;
       padding-bottom: $-xs;
       max-width: calc(100% - 20px);
@@ -193,9 +194,18 @@
     margin-top: -.2rem;
     margin-inline-start: -1rem;
   }
-  [chapter-toggle] {
-    padding-inline-start: .7rem;
-    padding-bottom: .2rem;
+  .chapter-contents-toggle {
+    display: block;
+    width: 100%;
+    text-align: left;
+    padding: $-xxs $-s ($-xxs * 2) $-s;
+    border-radius: 0 3px 3px 0;
+    line-height: 1;
+    margin-top: -$-xxs;
+    margin-bottom: -$-xxs;
+    &:hover {
+      @include lightDark(background-color, rgba(0, 0, 0, 0.06), rgba(255, 255, 255, 0.06));
+    }
   }
   .entity-list-item .icon {
     z-index: 2;
@@ -214,16 +224,11 @@
   }
 }
 
-.chapter-child-menu {
-  ul.sub-menu {
-    display: none;
-    padding-inline-start: 0;
-    position: relative;
-    margin-bottom: 0;
-  }
-  [chapter-toggle].open + .sub-menu {
-    display: block;
-  }
+.chapter-child-menu ul.sub-menu {
+  display: none;
+  padding-inline-start: 0;
+  position: relative;
+  margin-bottom: 0;
 }
 
 // Sortable Lists
@@ -457,7 +462,7 @@ ul.pagination {
 }
 
 .entity-list-item-children {
-  padding: $-m;
+  padding: $-m $-l;
   > div {
     overflow: hidden;
     padding: 0 0 $-xs 0;
diff --git a/resources/views/chapters/parts/child-menu.blade.php b/resources/views/chapters/parts/child-menu.blade.php
index a00f0f7e1..8fdd09143 100644
--- a/resources/views/chapters/parts/child-menu.blade.php
+++ b/resources/views/chapters/parts/child-menu.blade.php
@@ -1,9 +1,14 @@
-<div class="chapter-child-menu">
-    <button chapter-toggle type="button" aria-expanded="{{ $isOpen ? 'true' : 'false' }}"
-            class="text-muted @if($isOpen) open @endif">
+<div component="chapter-contents" class="chapter-child-menu">
+    <button type="button"
+            refs="chapter-contents@toggle"
+            aria-expanded="{{ $isOpen ? 'true' : 'false' }}"
+            class="text-muted chapter-contents-toggle @if($isOpen) open @endif">
         @icon('caret-right') @icon('page') <span>{{ trans_choice('entities.x_pages', $bookChild->visible_pages->count()) }}</span>
     </button>
-    <ul class="sub-menu inset-list @if($isOpen) open @endif" @if($isOpen) style="display: block;" @endif role="menu">
+    <ul refs="chapter-contents@list"
+        class="chapter-contents-list sub-menu inset-list @if($isOpen) open @endif" @if($isOpen)
+        style="display: block;" @endif
+        role="menu">
         @foreach($bookChild->visible_pages as $childPage)
             <li class="list-item-page {{ $childPage->isA('page') && $childPage->draft ? 'draft' : '' }}" role="presentation">
                 @include('entities.list-item-basic', ['entity' => $childPage, 'classes' => $current->matches($childPage)? 'selected' : '' ])
diff --git a/resources/views/chapters/parts/list-item.blade.php b/resources/views/chapters/parts/list-item.blade.php
index 5aa9864b2..c3e735e2b 100644
--- a/resources/views/chapters/parts/list-item.blade.php
+++ b/resources/views/chapters/parts/list-item.blade.php
@@ -12,11 +12,12 @@
 @if ($chapter->visible_pages->count() > 0)
     <div class="chapter chapter-expansion">
         <span class="icon text-chapter">@icon('page')</span>
-        <div class="content">
-            <button type="button" chapter-toggle
+        <div component="chapter-contents" class="content">
+            <button type="button"
+                    refs="chapter-contents@toggle"
                     aria-expanded="false"
-                    class="text-muted chapter-expansion-toggle">@icon('caret-right') <span>{{ trans_choice('entities.x_pages', $chapter->visible_pages->count()) }}</span></button>
-            <div class="inset-list">
+                    class="text-muted chapter-contents-toggle">@icon('caret-right') <span>{{ trans_choice('entities.x_pages', $chapter->visible_pages->count()) }}</span></button>
+            <div refs="chapter-contents@list" class="inset-list chapter-contents-list">
                 <div class="entity-list-item-children">
                     @include('entities.list', ['entities' => $chapter->visible_pages])
                 </div>