Skip to content

Commit

Permalink
Make showcase expandable
Browse files Browse the repository at this point in the history
Previously, the showcase would drop cards as the width decreases. This
is presumably to prevent the showcase from taking up too much height.
Instead of hiding the unused cards, allow them to be accessed by making
the showcase expandable.
  • Loading branch information
victorlin committed May 24, 2024
1 parent f2e4113 commit f5cf6b0
Showing 1 changed file with 79 additions and 9 deletions.
88 changes: 79 additions & 9 deletions static-site/src/components/ListResources/Showcase.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable react/prop-types */
import React, { useCallback, useEffect, useState } from 'react';
import { FaChevronDown, FaChevronUp } from 'react-icons/fa';
import styled from 'styled-components';
import {CardInner, CardImg, CardTitle} from "../Cards/styles";
import { theme } from "../../layouts/theme";
Expand All @@ -9,26 +10,67 @@ import { LIST_ANCHOR } from "./index";
import { Card, FilterOption, Group } from './types';

const cardWidthHeight = 160; // pixels
const expandPreviewHeight = 50 //pixels

type ShowcaseProps = {
cards: Card[]
setSelectedFilterOptions: React.Dispatch<React.SetStateAction<readonly FilterOption[]>>
}

export const Showcase = ({cards, setSelectedFilterOptions}: ShowcaseProps) => {
if (!cards.length) return null;

const [numRows, setNumRows] = useState<number>(0);
const [isExpanded, setIsExpanded] = useState<boolean>(false);

const toggleExpand = () => {
setIsExpanded(!isExpanded);
};


/**
* Function that runs on changes to the container.
* Used to compute the number of rows of cards upon resize.
*/
function containerRef(container: HTMLDivElement) {
if (!container) return;

const cards = container.children;

if (cards && cards.length > 0) {
const leftBorder = (cards[0] as HTMLElement).offsetLeft;

let newNumRows = 0;
for (let i = 0; i < cards.length; i++) {
if ((cards[i] as HTMLElement).offsetLeft == leftBorder) {
newNumRows++;
}
}
if (numRows != newNumRows) {
setNumRows(newNumRows);
}
}
}

const isExpandable = numRows > 1;

return (
<div>
<Byline>
Showcase resources: click to filter the resources to a pathogen
</Byline>
<SingleRow>
<ShowcaseContainer>
<ShowcaseContainer $isExpanded={isExpanded} $isExpandable={isExpandable}>
<CardsContainer ref={containerRef}>
{cards.map((el) => (
<ShowcaseTile card={el} key={el.name} setSelectedFilterOptions={setSelectedFilterOptions}/>
))}
</ShowcaseContainer>
</SingleRow>
</CardsContainer>
{isExpandable && !isExpanded && <PreviewOverlay onClick={toggleExpand} />}
</ShowcaseContainer>
{isExpandable && <>
<ArrowButton onClick={toggleExpand}>
{isExpanded ? <FaChevronUp/> : <FaChevronDown/>}
</ArrowButton>
</>}
<Spacer/>
</div>
)
Expand Down Expand Up @@ -70,12 +112,40 @@ const ShowcaseTile = ({card, setSelectedFilterOptions}: ShowcaseTileProps) => {
element we can leverage the intelligent wrapping of the flexbox to decide how
many tiles to show in a single row. The downside is that showcase tiles are
still in the DOM, and the images are still fetched etc */
const SingleRow = styled.div`
max-height: ${cardWidthHeight}px;
overflow-y: clip;
const ShowcaseContainer = styled.div<{$isExpanded: boolean, $isExpandable: boolean}>`
position: relative;
height: ${(props) =>
props.$isExpandable ?
props.$isExpanded ?
"" : `${cardWidthHeight + expandPreviewHeight}px`
: `${cardWidthHeight}px`
};
overflow-y: hidden;
`

const ArrowButton = styled.div`
text-align: center;
width: 100%;
height: 1em;
cursor: pointer;
`

const ShowcaseContainer = styled.div`
const PreviewOverlay = styled.div`
position: absolute;
z-index: 1;
bottom: 0;
left: 0;
background-image: linear-gradient(
to bottom,
rgba(255, 255, 255, 0) -100%,
rgba(255, 255, 255, 1) 100%);
width: 100%;
height: ${expandPreviewHeight}px;
cursor: pointer;
`;

const CardsContainer = styled.div`
/* background-color: #ffeab0; */
display: flex;
flex-direction: row;
Expand Down

0 comments on commit f5cf6b0

Please sign in to comment.