From 5b37493800793d5604b40c94fc91cc7c781c0f88 Mon Sep 17 00:00:00 2001 From: lqdev Date: Tue, 6 Feb 2024 21:37:26 +0100 Subject: [PATCH] treehouse on flexbox --- crates/treehouse/src/html/tree.rs | 10 +- static/css/tree.css | 237 ++++++++++++++++-------------- 2 files changed, 130 insertions(+), 117 deletions(-) diff --git a/crates/treehouse/src/html/tree.rs b/crates/treehouse/src/html/tree.rs index caa1406..82154bc 100644 --- a/crates/treehouse/src/html/tree.rs +++ b/crates/treehouse/src/html/tree.rs @@ -61,6 +61,8 @@ pub fn branch_to_html( s.push_str("
"); } + s.push_str(""); + let raw_block_content = &source.input()[branch.content.clone()]; let mut unindented_block_content = String::with_capacity(raw_block_content.len()); for line in raw_block_content.lines() { @@ -115,13 +117,9 @@ pub fn branch_to_html( }, Some(broken_link_callback), ); - if has_children { - s.push_str("") - } + s.push_str(""); markdown::push_html(s, treehouse, config, markdown_parser); - if has_children { - s.push_str("") - } + s.push_str(""); if let Content::Link(link) = &branch.attributes.content { write!( diff --git a/static/css/tree.css b/static/css/tree.css index a268d6c..5b0f8e6 100644 --- a/static/css/tree.css +++ b/static/css/tree.css @@ -44,9 +44,7 @@ content: ''; display: inline-block; - background-image: - /* breadcrumb */ - var(--icon-breadcrumb); + background-image: var(--icon-breadcrumb); background-repeat: no-repeat; background-position: 50% 50%; opacity: 70%; @@ -71,118 +69,74 @@ /*** Tree ***/ +/* Compute an indent level appropriate for the viewport. */ .tree ul { padding-left: clamp(12px, 2vw, 24px); } +/* Top level should not have an indent. */ .tree>ul { padding-left: 0; } -.tree { - --tree-icon-position: 8px 50%; - --tree-icon-space: 28px; +.tree details { - /* I have no clue why this works, deal with it */ - --tree-hover-expansion: 6px; + /* Disable the rightwards chevron in
elements */ + &>summary { + list-style: none; + cursor: pointer; - position: relative; -} - -.tree details>summary { - list-style: none; - cursor: pointer; -} - -/* Can webkit not be a dick for once? */ -.tree details>summary::-webkit-details-marker { - display: none; + &::-webkit-details-marker { + display: none; + } + } } +/* Child branches */ .tree li { + /*
  • elements should not have any bullet points or whatever */ list-style: none; - display: flex; - flex-direction: row; + /* Stretch branch content to the full width of the page */ + &>div, + &>details { + width: 100%; + } + + /* Add an underline for leaf branches */ + &>div { + box-sizing: border-box; + + &:hover { + border-bottom: 1px solid var(--border-1); + margin-bottom: -1px; + } + } + + &>div, + &>details>summary { + /* Child elements are laid out horizontally in a flexbox. */ + display: flex; + align-items: center; + } - position: relative; -} - -.tree li>*:first-child { - width: 100%; -} - -.tree li>div:first-child { - box-sizing: border-box; -} - -.tree li>div:first-child, -.tree li>details>summary:first-child { - padding-right: 32px; -} - -.tree li[is="th-linked-branch"]>details>summary:first-child { - padding-right: 56px; -} - -.tree li>div:first-child:hover { - border-bottom: 1px solid var(--border-1); - margin-bottom: -1px; } +/* is used for the visual content of branches with children. It's the large horizontal bar + and notably *excludes* children. */ .tree details>summary { - background-image: var(--icon-expand); - background-repeat: no-repeat; - background-position: var(--tree-icon-position); - padding-left: var(--tree-icon-space); - margin-left: calc(- var(--tree-icon-space)); - - padding-top: var(--tree-hover-expansion); - padding-bottom: var(--tree-hover-expansion); + /* Slightly round for elegance */ border-radius: 8px; + /* Give it a shaded background on hover */ background-color: transparent; + + &:hover { + background-color: var(--shaded-background); + } } -.tree details>summary:hover { - background-color: var(--shaded-background); -} - -.tree li>div { - background-image: var(--icon-leaf); - background-repeat: no-repeat; - background-position: var(--tree-icon-position); - padding-left: var(--tree-icon-space); - margin-left: calc(- var(--tree-icon-space)); - padding-top: var(--tree-hover-expansion); - padding-bottom: var(--tree-hover-expansion); -} - -.tree details[open]>summary { - background-image: var(--icon-collapse); -} - -.tree details:not([open])>summary>.branch-summary>:last-child::after { - content: '\00A0'; - display: inline-block; - - background-image: var(--icon-more); - background-repeat: no-repeat; - background-position: 50% 50%; - - width: 16px; - height: 1.2em; - - vertical-align: text-bottom; - margin-left: 0.5em; - - margin-right: -32px; -} - -.tree details:not([open])>summary>.branch-summary>:last-child { - padding-right: 32px; -} - +/* For media without hover functionality, draw a bottom border everywhere as a visual anchor for where to tap */ @media (hover: none) { .tree li>div:first-child, @@ -191,53 +145,114 @@ } .tree details>summary { + /* In that case summaries shall not be rounded. */ border-radius: 0px; } } +/* The following three elements - bp, bc, and bb - are there in all branches, regardless of their parent. */ -.tree th-bb { +/* bp - bullet point */ +th-bp { + display: block; + width: 28px; height: 24px; + + background-image: var(--icon-leaf); + background-repeat: no-repeat; + background-position: 50% 50%; + + /* Prevent shrinkage when viewport is too low */ + flex-shrink: 0; +} + +/* Change image of th-bp if it has children and/or is collapsible */ +.tree details[open]>summary>th-bp { + background-image: var(--icon-collapse); +} + +.tree details:not([open])>summary>th-bp { + background-image: var(--icon-expand); +} + +/* bc - branch content */ +th-bc { + display: block; + padding-top: 6px; + padding-bottom: 6px; + + /* Grow to fill the entire available space. This pushes out th-bb to the far right. */ + flex-grow: 1; +} + +/* Display a chevron hinting that the collapsed branch has more content in its children. */ +.tree details:not([open])>summary>th-bc>:last-child { + /* Add some padding such that text wraps together with this element. */ + padding-right: 32px; + + &::after { + content: '\00A0'; + display: inline-block; + + background-image: var(--icon-more); + background-repeat: no-repeat; + background-position: 50% 50%; + + width: 16px; + height: 1.2em; + + vertical-align: text-bottom; + margin-left: 0.5em; + + margin-right: -32px; + } +} + +/* bb - button bar */ +th-bb { + height: 100%; margin: 4px; - position: absolute; - top: 0; - right: 0; + /* Should be displayed on the top of the branch rather than in the middle. */ + align-self: start; display: flex; flex-direction: row; + /* Keep the button bar invisible by default. */ opacity: 0%; } - -.tree li>details>summary:hover>th-bb, -.tree li>div:hover>th-bb { +/* When the parent is hovered over, display the button bar. */ +.tree *:hover>th-bb { opacity: 100%; } +/* For media without hover functionality, th-bb should always be visible */ @media (hover: none) { .tree th-bb { opacity: 100%; } } -.tree .icon { - background-repeat: no-repeat; - background-position: 50% 50%; - opacity: 35%; +/* Icons (used in the button bar) */ +.tree { + & .icon { + background-repeat: no-repeat; + background-position: 50% 50%; + opacity: 35%; - width: 24px; - height: 24px; -} + width: 24px; + height: 24px; + } + & .icon-permalink { + background-image: var(--icon-permalink); + } -.tree .icon-permalink { - background-image: var(--icon-permalink); -} - -.tree .icon-go { - background-image: var(--icon-go); + & .icon-go { + background-image: var(--icon-go); + } } .tree a.navigate {