Skip to content

Commit

Permalink
refactor: project details page (thenewboston-blockchain#2017)
Browse files Browse the repository at this point in the history
* feat: project details page

* style: fix styles based on feedback

* refactor: project details page

* Add handling of project details page in breadcrumb

Co-authored-by: jamessspanggg <[email protected]>
  • Loading branch information
thesanjeevsharma and jamessspanggg authored Aug 14, 2021
1 parent 4fcacad commit 632ed85
Show file tree
Hide file tree
Showing 23 changed files with 588 additions and 83 deletions.
6 changes: 5 additions & 1 deletion src/containers/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ const App: FC = () => {
<Route exact path="/developer" component={withSuspense(DeveloperPortal)} />
<Route exact path="/developer/projects" component={DeveloperPortalProjects} />
<Route exact path="/developer/projects/rules" component={DeveloperPortalProjectRulesAndGuidelines} />
<Route exact path="/developer/projects/approved-projects" component={DeveloperPortalApprovedProjects} />
<Route
exact
path="/developer/projects/approved-projects/:projectId?"
component={DeveloperPortalApprovedProjects}
/>
<Route exact path="/developer/whitepaper" component={LivingWhitepaper} />
<Route exact path="/developer/whitepaper/principal-entities/:chapter?" component={PrincipalEntities} />
<Route
Expand Down
20 changes: 20 additions & 0 deletions src/containers/DeveloperPortalProjects/_shared.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
$top-nav-height: 60px;
$top-links-height: 72px;
$breadcrumbs-height: 56px;

$details-header-height: 180px;
$details-header-height-768: 260px;
$top-content-height: calc(#{$top-nav-height} + #{$details-header-height});
$top-content-height-576: calc(#{$top-nav-height} + #{$details-header-height-768});

// cards
$card-width-original: 384px;
$card-min-width-original: 300px;
$card-height-original: 324px;

$card-width-992: 432px;
$card-min-width-992: 330px;

$card-width-768: 320px;
$card-min-width-768: 220px;
$card-height-768: 262px;

$card-height-480: 324px;
$card-width-480: 376px;
164 changes: 124 additions & 40 deletions src/containers/DeveloperPortalProjects/components/Breadcrumb/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {Link as ReactRouterLink} from 'react-router-dom';
import {Link} from 'react-scroll';
import {useWindowDimensions} from 'hooks';
import {PATHNAME_TO_TITLE_MAPPING, PATHNAME_TO_DROPDOWN_SELECTIONS} from '../../constants';
import {orderedProjectDetailsTopic} from '../../containers/ProjectDetails/constants';

import './Breadcrumb.scss';

Expand All @@ -21,16 +22,21 @@ type Props = {
url: string;
}[]
| null;
projectName?: string;
};

const TOP_LINK_HEIGHT = 72;
const PROJECT_DETAILS_HEADER_HEIGHT = 180;
const PROJECT_DETAILS_HEADER_HEIGHT_768 = 260;

const Breadcrumb: FC<Props> = ({approvedProjectUrls, breadcrumbHeight, className}) => {
const Breadcrumb: FC<Props> = ({approvedProjectUrls, breadcrumbHeight, className, projectName}) => {
const location = useLocation();
const {width} = useWindowDimensions();
const [projectsDropdownEl, setProjectsDropdownEl] = useState<HTMLButtonElement | null>(null);
const [sectionDropdownEl, setSectionDropdownEl] = useState<HTMLButtonElement | null>(null);
const [projectDetailsDropdownEl, setProjectDetailsDropdownEl] = useState<HTMLButtonElement | null>(null);
const pathnames = location.pathname.slice(1).split('/');
const projectDetailsHeaderHeight = width > 768 ? PROJECT_DETAILS_HEADER_HEIGHT : PROJECT_DETAILS_HEADER_HEIGHT_768;

const toggleWhitepaperDropdown = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
if (!e) return;
Expand All @@ -52,6 +58,16 @@ const Breadcrumb: FC<Props> = ({approvedProjectUrls, breadcrumbHeight, className
}
};

const toggleProjectDetailsDropdown = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
if (!e) return;

if (projectDetailsDropdownEl) {
setProjectDetailsDropdownEl(null);
} else {
setProjectDetailsDropdownEl(e.currentTarget);
}
};

return (
<div className={clsx('Breadcrumb', className)}>
{pathnames.map((pathname, index) => {
Expand All @@ -62,12 +78,10 @@ const Breadcrumb: FC<Props> = ({approvedProjectUrls, breadcrumbHeight, className
<ReactRouterLink className="Breadcrumb__link" to={`/${pathname}`}>
{PATHNAME_TO_TITLE_MAPPING[pathname]}
</ReactRouterLink>
<Icon className="Breadcrumb__icon" icon={IconType.chevronRight} size={16} totalSize={16} />
</div>
) : (
<ReactRouterLink className="Breadcrumb__link-container" key={pathname} to={`/${pathname}`}>
<span className="Breadcrumb__link">{PATHNAME_TO_TITLE_MAPPING[pathname]}</span>
<Icon className="Breadcrumb__icon" icon={IconType.chevronRight} size={16} totalSize={16} />
</ReactRouterLink>
);
}
Expand All @@ -79,16 +93,17 @@ const Breadcrumb: FC<Props> = ({approvedProjectUrls, breadcrumbHeight, className
<div className="Breadcrumb__link-container" key={pathname}>
{width > 992 ? (
<>
<Icon className="Breadcrumb__icon" icon={IconType.chevronRight} size={16} totalSize={16} />
<ReactRouterLink
className={clsx('Breadcrumb__link', isLastIndex && 'Breadcrumb__link--active')}
to={`/developer/${pathname}`}
>
{PATHNAME_TO_TITLE_MAPPING[pathname]}
</ReactRouterLink>
<Icon className="Breadcrumb__icon" icon={IconType.chevronRight} size={16} totalSize={16} />
</>
) : (
<>
<Icon className="Breadcrumb__icon" icon={IconType.chevronRight} size={16} totalSize={16} />
<button className="Breadcrumb__button" onClick={toggleWhitepaperDropdown}>
<span className={clsx('Breadcrumb__link', isLastIndex && 'Breadcrumb__link--active')}>
{PATHNAME_TO_TITLE_MAPPING[pathname]}
Expand Down Expand Up @@ -126,64 +141,133 @@ const Breadcrumb: FC<Props> = ({approvedProjectUrls, breadcrumbHeight, className
}

// rules or approved projects
return (
if (index === 2) {
return (
<div className="Breadcrumb__link-container" key={pathname}>
{width > 992 ? (
<>
<Icon className="Breadcrumb__icon" icon={IconType.chevronRight} size={16} totalSize={16} />
<ReactRouterLink
className={clsx('Breadcrumb__link', isLastIndex && 'Breadcrumb__link--active')}
to={`/developer/projects/${pathname}`}
>
{PATHNAME_TO_TITLE_MAPPING[pathname]}
</ReactRouterLink>
</>
) : (
<>
<button className="Breadcrumb__button" onClick={toggleSectionDropdown}>
<span className={clsx('Breadcrumb__link', isLastIndex && 'Breadcrumb__link--active')}>
{PATHNAME_TO_TITLE_MAPPING[pathname]}
</span>
<Icon
className="Breadcrumb__icon"
id={pathname}
icon={sectionDropdownEl ? IconType.chevronUp : IconType.chevronDown}
size={16}
totalSize={16}
/>
</button>
<Popover
anchorEl={sectionDropdownEl}
anchorOrigin={{horizontal: 'center', vertical: 'bottom'}}
className="Breadcrumb__Popover"
closePopover={() => setSectionDropdownEl(null)}
id={pathname}
open={!!sectionDropdownEl}
transformOrigin={{horizontal: 'center', vertical: 'top'}}
transformOffset={{horizontal: 50, vertical: 12}}
>
{pathname === 'approved-projects'
? approvedProjectUrls &&
approvedProjectUrls.map((selection) => {
return (
<ReactRouterLink
className="Breadcrumb__Popover-link"
key={selection.url}
to={selection.url}
>
{selection.title}
</ReactRouterLink>
);
})
: PATHNAME_TO_DROPDOWN_SELECTIONS[pathname]?.map((selection) => {
const selectionHash = selection.url.slice(selection.url.indexOf('#') + 1);
return (
<Link
activeClass="SideMenu__link--active"
className="Breadcrumb__Popover-link"
hashSpy
ignoreCancelEvents
key={selection.url}
offset={-(NAVBAR_HEIGHT + TOP_LINK_HEIGHT + breadcrumbHeight)}
smooth
spy
to={selectionHash}
>
{selection.title}
</Link>
);
})}
</Popover>
</>
)}
</div>
);
}

// individual project details
return projectName ? (
<div className="Breadcrumb__link-container" key={pathname}>
{width > 992 ? (
<span className="Breadcrumb__link--active">{PATHNAME_TO_TITLE_MAPPING[pathname]}</span>
<>
<Icon className="Breadcrumb__icon" icon={IconType.chevronRight} size={16} totalSize={16} />
<span className="Breadcrumb__link--active">{projectName}</span>
</>
) : (
<>
<button className="Breadcrumb__button" onClick={toggleSectionDropdown}>
<span className="Breadcrumb__link--active">{PATHNAME_TO_TITLE_MAPPING[pathname]}</span>
<button className="Breadcrumb__button" onClick={toggleProjectDetailsDropdown}>
<span className="Breadcrumb__link--active">{projectName}</span>
<Icon
className="Breadcrumb__icon"
id={pathname}
icon={sectionDropdownEl ? IconType.chevronUp : IconType.chevronDown}
icon={projectDetailsDropdownEl ? IconType.chevronUp : IconType.chevronDown}
size={16}
totalSize={16}
/>
</button>
<Popover
anchorEl={sectionDropdownEl}
anchorEl={projectDetailsDropdownEl}
anchorOrigin={{horizontal: 'center', vertical: 'bottom'}}
className="Breadcrumb__Popover"
closePopover={() => setSectionDropdownEl(null)}
closePopover={() => setProjectDetailsDropdownEl(null)}
id={pathname}
open={!!sectionDropdownEl}
open={!!projectDetailsDropdownEl}
transformOrigin={{horizontal: 'center', vertical: 'top'}}
transformOffset={{horizontal: 50, vertical: 12}}
>
{pathname === 'approved-projects'
? approvedProjectUrls &&
approvedProjectUrls.map((selection) => {
return (
<ReactRouterLink className="Breadcrumb__Popover-link" key={selection.url} to={selection.url}>
{selection.title}
</ReactRouterLink>
);
})
: PATHNAME_TO_DROPDOWN_SELECTIONS[pathname].map((selection) => {
const selectionHash = selection.url.slice(selection.url.indexOf('#') + 1);
return (
<Link
activeClass="SideMenu__link--active"
className="Breadcrumb__Popover-link"
hashSpy
ignoreCancelEvents
key={selection.url}
offset={-(NAVBAR_HEIGHT + TOP_LINK_HEIGHT + breadcrumbHeight)}
smooth
spy
to={selectionHash}
>
{selection.title}
</Link>
);
})}
{orderedProjectDetailsTopic.map((topic) => {
return (
<Link
activeClass="SideMenu__link--active"
className="Breadcrumb__Popover-link"
hashSpy
ignoreCancelEvents
key={topic.anchor}
offset={-(NAVBAR_HEIGHT + TOP_LINK_HEIGHT + breadcrumbHeight + projectDetailsHeaderHeight)}
smooth
spy
to={topic.anchor}
>
{topic.title}
</Link>
);
})}
</Popover>
</>
)}
</div>
);
) : null;
})}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
&__breadcrumb {
position: sticky;
top: $top-nav-height + $top-links-height;
z-index: $z-index-whitepaper-breadcrumb;
z-index: $z-index-dev-portal-breadcrumb;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ type Props = {
url: string;
}[]
| null;
projectName?: string;
};

const TIMEOUT_DELAY = 200;

const DeveloperPortalLayout: FC<Props> = ({approvedProjectUrls, children, pageName}) => {
const DeveloperPortalLayout: FC<Props> = ({approvedProjectUrls, children, pageName, projectName}) => {
const [breadcrumbHeight, setBreadcrumbHeight] = useState(56);
const {hash} = useLocation();
const TOTAL_OFFSET = NAVBAR_HEIGHT + LIVING_WHITEPAPER_TOP_LINKS_HEIGHT + breadcrumbHeight;
Expand All @@ -49,7 +50,11 @@ const DeveloperPortalLayout: FC<Props> = ({approvedProjectUrls, children, pageNa
{({measureRef}) => (
<div className="DeveloperPortalLayout__breadcrumb" ref={measureRef}>
<Container>
<Breadcrumb approvedProjectUrls={approvedProjectUrls} breadcrumbHeight={breadcrumbHeight} />
<Breadcrumb
approvedProjectUrls={approvedProjectUrls}
breadcrumbHeight={breadcrumbHeight}
projectName={projectName}
/>
</Container>
<Divider />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
position: sticky;
top: $top-nav-height + $top-links-height + $breadcrumbs-height;
width: 256px;
z-index: $z-index-whitepaper-sidemenu;
z-index: $z-index-dev-portal-sidemenu;

@media (max-width: 1366px) {
padding: 32px 48px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {A} from 'components';
import {NAVBAR_HEIGHT, LIVING_WHITEPAPER_TOP_LINKS_HEIGHT} from 'constants/offsets';
import {Link} from 'react-scroll';
import {useLocation, useHistory} from 'react-router';
import {Link as ReactRouterLink} from 'react-router-dom';
import {PATHNAME_TO_DROPDOWN_SELECTIONS, approvedProjectsPath, projectRulesPath} from '../../constants';

import './SideMenu.scss';
Expand Down Expand Up @@ -56,14 +57,13 @@ const SideMenu: FC<Props> = ({approvedProjectUrls, breadcrumbHeight}) => {
approvedProjectUrls &&
approvedProjectUrls.map((selection) => {
return (
<A
<ReactRouterLink
className={clsx('SideMenu__link', 'SideMenu__approved-projects-link')}
href={selection.url}
to={selection.url}
key={selection.url}
newWindow={false}
>
{selection.title}
</A>
</ReactRouterLink>
);
})}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
justify-content: center;
position: sticky;
top: $top-nav-height;
z-index: $z-index-whitepaper-top-links;
z-index: $z-index-dev-portal-top-links;

&__link {
@extend %body1;
Expand Down
Loading

0 comments on commit 632ed85

Please sign in to comment.