« get me outta code hell

content: generateAlbumSidebar + misc fixes - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content/dependencies/generatePageLayout.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-04-15 12:22:48 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-04-15 12:24:22 -0300
commit6b35077eb1542eaf9a89534d6920c35fee86cc04 (patch)
tree3ff4e6bb1860b67b9b2a4f2e39cdcd76cbeaa4b9 /src/content/dependencies/generatePageLayout.js
parent3a5b49cf3a10702c0dae1190c9baabd8a2c2ef3b (diff)
content: generateAlbumSidebar + misc fixes
This restores the CSS for sticky sidebars, but removes the
specific lines applying that effect (for the album sidebar).
There's also an experimental new splitter for the joined
group info box but we might go back on that or do something
different.

No tests for the new stuff here yet!
Diffstat (limited to 'src/content/dependencies/generatePageLayout.js')
-rw-r--r--src/content/dependencies/generatePageLayout.js128
1 files changed, 113 insertions, 15 deletions
diff --git a/src/content/dependencies/generatePageLayout.js b/src/content/dependencies/generatePageLayout.js
index 98b2d350..1ea5ce24 100644
--- a/src/content/dependencies/generatePageLayout.js
+++ b/src/content/dependencies/generatePageLayout.js
@@ -29,6 +29,47 @@ export default {
     transformMultiline,
     wikiInfo,
   }) {
+    const sidebarSlots = side => ({
+      // Content is a flat HTML array. It'll generate one sidebar section
+      // if specified.
+      [side + 'Content']: {type: 'html'},
+
+      // Multiple is an array of {content: (HTML)} objects. Each of these
+      // will generate one sidebar section.
+      [side + 'Multiple']: {
+        validate: v =>
+          v.arrayOf(
+            v.validateProperties({
+              content: v.isHTML,
+            })),
+      },
+
+      // Sticky mode controls which sidebar section(s), if any, follow the
+      // scroll position, "sticking" to the top of the browser viewport.
+      //
+      // 'last' - last or only sidebar box is sticky
+      // 'column' - entire column, incl. multiple boxes from top, is sticky
+      // 'none' - sidebar not sticky at all, stays at top of page
+      //
+      // Note: This doesn't affect the content of any sidebar section, only
+      // the whole section's containing box (or the sidebar column as a whole).
+      [side + 'StickyMode']: {
+        validate: v => v.is('last', 'column', 'static'),
+      },
+
+      // Collapsing sidebars disappear when the viewport is sufficiently
+      // thin. (This is the default.) Override as false to make the sidebar
+      // stay visible in thinner viewports, where the page layout will be
+      // reflowed so the sidebar is as wide as the screen and appears below
+      // nav, above the main content.
+      [side + 'Collapse']: {type: 'boolean', default: true},
+
+      // Wide sidebars generally take up more horizontal space in the normal
+      // page layout, and should be used if the content of the sidebar has
+      // a greater than typical focus compared to main content.
+      [side + 'Wide']: {type: 'boolean', defualt: false},
+    });
+
     return html.template({
       annotation: 'generatePageLayout',
 
@@ -36,15 +77,8 @@ export default {
         title: {type: 'html'},
         cover: {type: 'html'},
 
-        mainContent: {type: 'html'},
-        footerContent: {type: 'html'},
         socialEmbed: {type: 'html'},
 
-        headingMode: {
-          validate: v => v.is('sticky', 'static'),
-          default: 'static',
-        },
-
         styleRules: {
           validate: v => v.arrayOf(v.isString),
           default: [],
@@ -54,6 +88,24 @@ export default {
           validate: v => v.arrayOf(v.isString),
           default: [],
         },
+
+        // Main
+
+        mainContent: {type: 'html'},
+
+        headingMode: {
+          validate: v => v.is('sticky', 'static'),
+          default: 'static',
+        },
+
+        // Sidebars
+
+        ...sidebarSlots('leftSidebar'),
+        ...sidebarSlots('rightSidebar'),
+
+        // Nav & Footer
+
+        footerContent: {type: 'html'},
       },
 
       content(slots) {
@@ -114,6 +166,52 @@ export default {
               relations.footerLocalizationLinks,
             ]);
 
+        const generateSidebarHTML = (side, id) => {
+          const content = slots[side + 'Content'];
+          const multiple = slots[side + 'Multiple'];
+          const stickyMode = slots[side + 'StickyMode'];
+          const wide = slots[side + 'Wide'];
+          const collapse = slots[side + 'Collapse'];
+
+          let sidebarClasses = [];
+          let sidebarContent = html.blank();
+
+          if (!html.isBlank(content)) {
+            sidebarClasses = ['sidebar'];
+            sidebarContent = content;
+          } else if (multiple) {
+            sidebarClasses = ['sidebar-multiple'];
+            sidebarContent =
+              multiple
+                .filter(Boolean)
+                .map(({content}) =>
+                  html.tag('div',
+                    {
+                      [html.onlyIfContent]: true,
+                      class: 'sidebar',
+                    },
+                    content));
+          }
+
+          return html.tag('div',
+            {
+              [html.onlyIfContent]: true,
+              id,
+              class: [
+                'sidebar-column',
+                wide && 'wide',
+                !collapse && 'no-hide',
+                stickyMode !== 'static' && `sticky-${stickyMode}`,
+                ...sidebarClasses,
+              ],
+            },
+            sidebarContent);
+        }
+
+        const sidebarLeftHTML = generateSidebarHTML('leftSidebar', 'sidebar-left');
+        const sidebarRightHTML = generateSidebarHTML('rightSidebar', 'sidebar-right');
+        const collapseSidebars = slots.leftSidebarCollapse && slots.rightSidebarCollapse;
+
         const layoutHTML = [
           // navHTML,
           // banner.position === 'top' && bannerHTML,
@@ -122,18 +220,18 @@ export default {
             {
               class: [
                 'layout-columns',
-                // !collapseSidebars && 'vertical-when-thin',
-                // (sidebarLeftHTML || sidebarRightHTML) && 'has-one-sidebar',
-                // (sidebarLeftHTML && sidebarRightHTML) && 'has-two-sidebars',
-                // !(sidebarLeftHTML || sidebarRightHTML) && 'has-zero-sidebars',
-                // sidebarLeftHTML && 'has-sidebar-left',
-                // sidebarRightHTML && 'has-sidebar-right',
+                !collapseSidebars && 'vertical-when-thin',
+                (sidebarLeftHTML || sidebarRightHTML) && 'has-one-sidebar',
+                (sidebarLeftHTML && sidebarRightHTML) && 'has-two-sidebars',
+                !(sidebarLeftHTML || sidebarRightHTML) && 'has-zero-sidebars',
+                sidebarLeftHTML && 'has-sidebar-left',
+                sidebarRightHTML && 'has-sidebar-right',
               ],
             },
             [
-              // sidebarLeftHTML,
+              sidebarLeftHTML,
               mainHTML,
-              // sidebarRightHTML,
+              sidebarRightHTML,
             ]),
           // banner.position === 'bottom' && bannerHTML,
           footerHTML,