Skip to content

Commit

Permalink
Merge pull request #348 from samvera-labs/scroll-indicator
Browse files Browse the repository at this point in the history
Add fade out and message to indicate scrolling of structured nav
  • Loading branch information
masaball authored Jan 24, 2024
2 parents 17c8359 + 67d21a1 commit 0d5ab15
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 26 deletions.
92 changes: 69 additions & 23 deletions src/components/StructuredNavigation/StructuredNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const StructuredNavigation = () => {
let canvasIsEmptyRef = React.useRef(canvasIsEmpty);

const structureContainerRef = React.useRef();
const scrollableStructure = React.useRef();

React.useEffect(() => {
// Update currentTime and canvasIndex in state if a
Expand All @@ -48,7 +49,7 @@ const StructuredNavigation = () => {
}
}, [manifest]);

// Set currentNavItem when current Canvas is an inaccessible/empty item
// Set currentNavItem when current Canvas is an inaccessible/empty item
React.useEffect(() => {
if (canvasIsEmpty && playlist.isPlaylist) {
manifestDispatch({
Expand Down Expand Up @@ -124,33 +125,78 @@ const StructuredNavigation = () => {
}
}, [isClicked, player]);

// Structured nav is populated by the time the player hook fires so we listen for
// that to run the check on whether the structured nav is scrollable.
React.useEffect(() => {
if (structureContainerRef.current) {
const elem = structureContainerRef.current;
const structureEnd = Math.abs(elem.scrollHeight - (elem.scrollTop + elem.clientHeight)) <= 1;
scrollableStructure.current = !structureEnd;
}
}, [player]);

// Update scrolling indicators when end of scrolling has been reached
const handleScroll = (e) => {
const elem = e.target;
const sibling = elem.nextSibling;
const structureEnd = Math.abs(elem.scrollHeight - (elem.scrollTop + elem.clientHeight)) <= 1;

if (structureEnd && elem.classList.contains('scrollable')) {
elem.classList.remove('scrollable');
} else if (!structureEnd && !elem.classList.contains('scrollable')) {
elem.classList.add('scrollable');
}

if (structureEnd && sibling.classList.contains('scrollable')) {
sibling.classList.remove('scrollable');
} else if (!structureEnd && !sibling.classList.contains('scrollable')) {
sibling.classList.add('scrollable');
}
}

if (!manifest) {
return <p>No manifest - Please provide a valid manifest.</p>;
}

// Check for scrolling on initial render and build appropriate element class
let divClass = ''
let spanClass = ''
if (scrollableStructure.current) {
divClass = "ramp--structured-nav scrollable";
spanClass = "scrollable";
} else {
divClass = "ramp--structured-nav";
}

return (
<div
data-testid="structured-nav"
className="ramp--structured-nav"
key={Math.random()}
ref={structureContainerRef}
role="list"
aria-label="Structural content"
>
{structureItemsRef.current?.length > 0 ? (
structureItemsRef.current.map((item, index) => (
<List
items={[item]}
sectionRef={React.createRef()}
key={index}
structureContainerRef={structureContainerRef}
/>
))
) : (
<p className="ramp--no-structure">
There are no structures in the manifest
</p>
)}
<div className="ramp--structured-nav__border">
<div
data-testid="structured-nav"
className={divClass}
key={Math.random()}
ref={structureContainerRef}
role="list"
aria-label="Structural content"
onScroll={handleScroll}
>
{structureItemsRef.current?.length > 0 ? (
structureItemsRef.current.map((item, index) => (
<List
items={[item]}
sectionRef={React.createRef()}
key={index}
structureContainerRef={structureContainerRef}
/>
))
) : (
<p className="ramp--no-structure">
There are no structures in the manifest
</p>
)}
</div>
<span className={spanClass}>
Scroll to see more
</span>
</div>
);
};
Expand Down
51 changes: 48 additions & 3 deletions src/components/StructuredNavigation/StructuredNavigation.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@import '../../styles/_vars.scss';

.ramp--structured-nav {
margin-top: 20px;
margin-top: 0;
max-height: 40vh;
max-width: 50vw;
overflow-y: auto;
Expand All @@ -22,15 +22,60 @@
}
}

// Mask for scrollable area fadeout
.ramp--structured-nav.scrollable {
mask-image: linear-gradient(to bottom, black 80%, transparent 100%);
-webkit-mask-image: linear-gradient(to bottom, black 80%, transparent 100%)
}

// Border box
.ramp--structured-nav__border {
margin-top: 20px;
box-sizing: border-box;
border: 1px solid #ddd;
border-radius: 0.25rem;
}

.ramp--structured-nav__border > span {
display: none;
}

// Scroll to see more message
.ramp--structured-nav__border > span.scrollable {
background: $primary;
text-align: center;
display: block;
position: relative;
color: black;
font-size: 13px;
width: 15%;
left: 40%;
border: 1px solid #ddd;
border-radius: 0.25rem 0.25rem 0 0;
border-bottom: none;
}

// CSS for accordion style UI in structure
ul.ramp--structured-nav__list {
list-style: none;
padding: 0 0 0 10px;
padding: 0 0 0 0;
margin: 0px;

li:last-child {
padding: 0 0 0 0;
}

li {
display: block;
padding: 0.25rem 0.5rem;
padding: 0 0 0.5rem 0px;

ul > li {
padding: 0 0 0.5rem 1rem;
}

ul > li:last-child {
padding: 0 0 0 1rem;
}
}

li.active>a {
Expand Down

0 comments on commit 0d5ab15

Please sign in to comment.