Skip to content

Commit

Permalink
Hovering over message highlights TOC item (#598)
Browse files Browse the repository at this point in the history
  • Loading branch information
edemaine committed Apr 11, 2022
1 parent 122adee commit d385b8c
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 36 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ To see every change with descriptions aimed at developers, see
As a continuously updated web app, Coauthor uses dates
instead of version numbers.

## 2022-04-11

* Hovering over a message highlights the corresponding item
of the table of contents, or if that item is out of visual range,
the relevant border.
[[#598](https://github.com/edemaine/coauthor/issues/598)]

## 2022-03-22

* Messages can now be pinned to highlight them as "important"
Expand Down
98 changes: 66 additions & 32 deletions client/message.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,28 @@ export TableOfContents = React.memo ({message, parent, index}) ->
</ErrorBoundary>
TableOfContents.displayName = 'TableOfContents'

tocItemTop = (item) ->
itemTop = 0
ancestor = item.parentNode
while ancestor? and not /sticky/.test ancestor.className
itemTop += ancestor.offsetTop
ancestor = ancestor.offsetParent
itemTop

tocHoverIndicator = _.debounce ->
toc = document.querySelector 'nav.contents'
return unless toc? # not in a view with table of contents
toc.previousSibling?.classList.remove 'active'
toc.nextSibling?.classList.remove 'active'
item = toc.querySelector '.hover'
return unless item? # no hovered item
top = tocItemTop item
if top < toc.scrollTop
toc.previousSibling?.classList.add 'active'
else if top > toc.scrollTop + toc.clientHeight
toc.nextSibling?.classList.add 'active'
, 100

export WrappedTableOfContents = React.memo ({message, parent, index}) ->
isRoot = not parent? # should not differ between calls (for hook properties)
formattedTitle = useTracker ->
Expand Down Expand Up @@ -1739,14 +1761,18 @@ export WrappedTableOfContents = React.memo ({message, parent, index}) ->
</ul>

if isRoot
<nav className="contents">
<ul className="nav contents">
<li className="btn-group-xs #{if folded then 'folded' else ''}">
{inner}
</li>
</ul>
{children}
</nav>
<>
<div className="top indicator"/>
<nav className="contents" onScroll={tocHoverIndicator}>
<ul className="nav contents">
<li className="btn-group-xs #{if folded then 'folded' else ''}">
{inner}
</li>
</ul>
{children}
</nav>
<div className="bottom indicator"/>
</>
else
<li className="btn-group-xs #{if folded then 'folded' else ''}">
{inner}
Expand Down Expand Up @@ -2367,36 +2393,44 @@ export WrappedSubmessage = React.memo ({message, read}) ->
## Scroll the table of contents (if visible) to align with this message (if
## possible), and pulse the table of contents item (for when not possible).
showTOC = (e) ->
## Ignore propagated events e.g. from Action dropdown button.
return unless e.target.className.startsWith 'panel-heading'
e.preventDefault()
## Find corresponding table of contents entry
toc = document.querySelector 'nav.contents'
return unless toc?
return unless toc? # not in a view with table of contents
item = toc.querySelector "a[data-id='#{message._id}']"
return unless item?
return unless item? # this message is hidden in table of contents
msgTop = e.currentTarget.getBoundingClientRect().top
itemTop = 0
ancestor = item.parentNode
while ancestor? and not /sticky/.test ancestor.className
itemTop += ancestor.offsetTop
ancestor = ancestor.offsetParent
toc.scroll
top: itemTop - msgTop - 9 # fudge factor to align heading with toc item
behavior: scrollBehavior()
## Pulse item
item.animate [
transform: 'scale(1)'
,
transform: if prefersReducedMotion() then 'scale(1)' else 'scale(0.95)'
backgroundColor: '#888'
,
transform: 'scale(1)'
],
duration: 500
iterations: 3
itemTop = tocItemTop item
switch e.type
when 'mouseenter'
item.classList.add 'hover'
tocHoverIndicator()
when 'mouseleave'
item.classList.remove 'hover'
tocHoverIndicator()
when 'click'
## Ignore propagated click events e.g. from Action dropdown button.
return unless e.target.className.startsWith 'panel-heading'
## Scroll to align TOC item with message header
toc.scroll
top: itemTop - msgTop - 9 # fudge factor
behavior: scrollBehavior()
## Pulse TOC item
item.animate [
transform: 'scale(1)'
,
transform:
if prefersReducedMotion() then 'scale(1)' else 'scale(0.95)'
backgroundColor: '#888'
,
transform: 'scale(1)'
],
duration: 500
iterations: 3

<div className="panel message #{messagePanelClass message, editing}" data-message={message._id} id={message._id} ref={setRef}>
<div className="panel-heading clearfix" onClick={showTOC}>
<div className="panel-heading clearfix" onClick={showTOC}
onMouseEnter={showTOC} onMouseLeave={showTOC}>
{if editing and not history?
<input className="push-down form-control title" type="text" placeholder="Title" value={editTitle} onChange={onChangeTitle} tabIndex={tabindex0+18}/>
else
Expand Down
26 changes: 22 additions & 4 deletions client/message.styl
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,22 @@ bootstrap-3-button(bg-color) // based on mixins/buttons.less
.toc-toggle
margin-top: -19.39px // rendered height, putting exactly into margin

.indicator
position: absolute
left: 0
width: calc(100% - 15px) // 15px from right padding of .col-xs-3 parent
height: 8px
border: 4px solid transparent
z-index: 2000 // above 1020 from .sticky-top
&.top
top: 0
&.active
border-top-color: #f0f
&.bottom
bottom: 0
&.active
border-bottom-color: #f0f

nav.contents
padding-bottom: 5px
height: 100% // match parent height set in JavaScript
Expand Down Expand Up @@ -254,6 +270,12 @@ nav.contents
background: #ebe2f8
/.dark &
background: #241835
// Hovering over corresponding message overrides color from visibility
// to a hue of 300
a.hover
background: #f8bff8 !important
/.dark &
background: #5c1d5c !important

.subcontents
border-left: solid 2px #8465b3
Expand Down Expand Up @@ -292,10 +314,6 @@ nav.contents

// Message heading

.message
> .panel-heading:hover
border-color: red

// Message body

.message-body
Expand Down

0 comments on commit d385b8c

Please sign in to comment.