Refactor the old table.icon-and-text to col.col-(iconN|text) for responsiveness
authorNick Downing <nick@ndcode.org>
Fri, 11 Feb 2022 05:35:48 +0000 (16:35 +1100)
committerNick Downing <nick@ndcode.org>
Sat, 12 Feb 2022 01:56:15 +0000 (12:56 +1100)
blog/index.html.jst
css/bootstrap/_custom.scss
css/bootstrap/_nav.scss
my_account/index.html.jst

index 62e1d5b..fb8996a 100644 (file)
@@ -16,7 +16,7 @@ return async env => {
         let children = await p.get('children')
         let menu = await p.get_json('menu')
 
-        ul.nav.flex-column {
+        nav {
           for (let i = 0; i < menu.length; ++i) {
             let name = menu[i]
             let q = await children.get(name)
@@ -26,24 +26,21 @@ return async env => {
             while (images.length < 3)
               images.push(images[images.length - 1])
 
-            li.nav-item {
-              a.nav-link.grid-gutter-background(href=`${name}/index.html`) {
-                table.icon-and-text {
-                  tr {
-                    td {
-                      img(
-                        src=`${name}/${images[2]}`
-                      ) {}
-                    }
-                    td {
-                      span.h2{
-                        `${await q.get_json('title')}`
-                      }
-                      br {}
-                      span.h4{
-                        `${await q.get_json('description')}—by ${await q.get_json('author')}`
-                      }
-                    }
+            // note: make the row a link to show hover background at edges
+            // (similar to the grid-gutter-background class I use elsewhere)
+            // note: position: relative sets the target for stretched link
+            div.row.flex-nowrap.align-items-center.nav-link-outer.position-relative {
+              div.col.col-icon256 {
+                img.img-fluid.py-3(src=`${name}/${images[2]}`) {}
+              }
+              div.col.col-text {
+                a.nav-link-inner.stretched-link(href=`${name}/index.html`) {
+                  span.h2{
+                    `${await q.get_json('title')}`
+                  }
+                  br {}
+                  span.h4{
+                    `${await q.get_json('description')}—by ${await q.get_json('author')}`
                   }
                 }
               }
index 8b345d7..87c97a2 100644 (file)
@@ -35,7 +35,21 @@ $footer-link-hover-color: darken($footer-link-color, 10%);
   padding-right: .5 * $grid-gutter-width;
 }
 
+// similar to bootstrap's navbar class, but appears to the side
+// responsive in a fairly sophisticated way, with 5 different modes:
+// >= xs: appears above content, toggleable, animates vertically
+// >= md: appears to left of content, toggleable, animates horizontally
+// >= xl: appears to left of content, always visible
+// >= 2xl: same as xl but has a right margin half the width of the sidebar
+// >= 3xl: same as xl but has a right margin the same width as the sidebar
+// (the last way gives a balanced look, as the content is along the middle)
+// note: flex item cannot be smaller than its contents with overflow visible,
+// so to be safe (when screen so small that a word cannot fit) make it hidden
 .sidebar-outer {
+  // note: the following properties are set via javascript using inline style:
+  // height: 0px if hidden and animation is vertical, otherwise content height
+  // flex-basis: 0px if hidden and animation is horizontal, otherwise 350px
+  // transition-property: flex-basis / height during animation, otherwise none
   flex-grow: 0;
   flex-shrink: 0;
   padding-left: 0;
@@ -48,7 +62,7 @@ $footer-link-hover-color: darken($footer-link-color, 10%);
     max-height: 100vh;
     overflow-y: auto;
   }
-  transition: none .35s ease; // transition property is set via inline style
+  transition: none .35s ease;
   background-color: $gray-200;
 }
 .sidebar-inner {
@@ -63,13 +77,18 @@ $footer-link-hover-color: darken($footer-link-color, 10%);
     display: none;
   }
 }
-//.sidebar-content {
-//  max-width: 1280px;
-//}
+.sidebar-content {
+  overflow: hidden;
+  // the following gives an effect more like .container, as the text wrap
+  // becomes predictable after a certain screen size, but text is biased
+  // to the left on larger screens, I prefer to have it wider and centred
+  //max-width: 1280px;
+}
 .sidebar-dummy {
   flex: 0 0 0px;
   padding-left: 0px;
   padding-right: 0px;
+  overflow: hidden;
   @include media-breakpoint-up(2xl) {
     flex-basis: 175px;
   }
@@ -161,12 +180,26 @@ $icon-sizes: (
   font-family: $font-family-serif;
 }
 
-// apply this to table to get an icon with vertically centred text next to it
-.icon-and-text {
-  vertical-align: middle;
-  td {
-    padding: .25em .5em;
-  }
+// use this with bootstrap's grid system to make an icon with text beside it
+// the icon can take up to 1/2 of the width, but not more than its N-px width
+// note: flex item cannot be smaller than its contents with overflow visible,
+// so to be safe (when screen so small that a word cannot fit) make it hidden
+// note: col has position: relative, and I believe this is so that stretched
+// links will fill the column, but we want them to fill the row in this case
+.col-icon128 {
+  flex: 0 1 calc(128px + $grid-gutter-width);
+  overflow: hidden;
+  position: static;
+}
+.col-icon256 {
+  flex: 0 1 calc(256px + $grid-gutter-width);
+  overflow: hidden;
+  position: static;
+}
+.col-text {
+  flex: 1 0 50%;
+  overflow: hidden;
+  position: static;
 }
 
 .search-results li {
index 102bf7a..187bd88 100644 (file)
   }
 }
 
+// Nick (for stretched links)
+.nav-link-inner {
+  display: block;
+  padding: $nav-link-padding-y $nav-link-padding-x;
+  text-decoration: if($link-decoration == none, null, none);
+}
+.nav-link-outer {
+  @include hover-focus() {
+    text-decoration: none;
+    background: $nav-link-hover-bg; // Nick
+  }
+
+  // Disabled state lightens text
+  &.disabled {
+    color: $nav-link-disabled-color;
+    pointer-events: none;
+    cursor: default;
+  }
+}
+
 //
 // Tabs
 //
index 3bc9a12..6176b3f 100644 (file)
@@ -234,25 +234,26 @@ return async env => {
           let children = await p.get('children')
           let menu = await p.get_json('menu')
   
-          ul.nav.flex-column {
+          nav {
             for (let i = 0; i < menu.length; ++i) {
               let name = menu[i]
               let q = await children.get(name)
-  
-              li.nav-item {
-                a.nav-link.grid-gutter-background(href=`${name}/index.html`) {
-                  table.icon-and-text {
-                    tr {
-                      td {
-                        _out.push(
-                          await env.site.get_min_svg(await q.get_json('icon'))
-                        )
-                      }
-                      td {
-                        span.h2{
-                          `${await q.get_json('title')}`
-                        }
-                      }
+
+              // note: make the row a link to show hover background at edges
+              // (similar to the grid-gutter-background class I use elsewhere)
+              // note: position: relative sets the target for stretched link
+              div.row.flex-nowrap.align-items-center.nav-link-outer.position-relative {
+                div.col.col-icon128 {
+                  div.img-fluid.py-3 {
+                    _out.push(
+                      await env.site.get_min_svg(await q.get_json('icon'))
+                    )
+                  }
+                }
+                div.col.col-text {
+                  a.nav-link-inner.stretched-link(href=`${name}/index.html`) {
+                    span.h2{
+                      `${await q.get_json('title')}`
                     }
                   }
                 }