Skip to content

Commit

Permalink
Revert "Revert "feat: Added ArticleNavigation component, which provid…
Browse files Browse the repository at this point in the history
…es next/prev navigation between articles (#159)" (#168)"

This reverts commit 1c118e5.
  • Loading branch information
Aleksei committed Feb 2, 2024
1 parent 1c118e5 commit a8504f8
Show file tree
Hide file tree
Showing 11 changed files with 324 additions and 47 deletions.
66 changes: 66 additions & 0 deletions src/components/ArticleNavigation/ArticleNavigation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
@use '~@gravity-ui/page-constructor/styles/variables.scss' as pcVariables;
@use '../../variables.scss';

$block: '.#{variables.$ns}article-navigation';

#{$block} {
display: flex;
gap: var(--g-spacing-6);
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'md') - 1) {
gap: var(--g-spacing-5);
}
&__content {
padding: var(--g-spacing-2) 0;
overflow: hidden;
width: 100%;
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'md') - 1) {
padding: var(--g-spacing-3) 0;
}
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'sm') - 1) {
display: none;
}
&-title {
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'md') - 1) {
display: none;
}
}
}
&__button {
cursor: pointer;
text-decoration: none;
display: flex;
gap: var(--g-spacing-3);
width: 50%;
border-radius: 16px;
border: 1px solid var(--g-color-sfx-fade);
padding: var(--g-spacing-1);
justify-content: space-between;
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'sm') - 1) {
width: unset;
}
&_reverse {
flex-direction: row-reverse;
margin-left: auto;
padding-left: var(--g-spacing-5);
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'sm') - 1) {
padding-left: var(--g-spacing-1);
}
}
&-icon {
flex: none;
border-radius: 12px;
background: var(--g-color-base-generic);
display: flex;
align-items: center;
justify-content: center;
color: var(--g-color-text-primary);
padding: 0 var(--g-spacing-5);
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'md') - 1) {
padding: 0 var(--g-spacing-3);
}
@media (max-width: map-get(pcVariables.$gridBreakpoints, 'sm') - 1) {
padding: var(--g-spacing-3);
}
}
}
}
82 changes: 82 additions & 0 deletions src/components/ArticleNavigation/ArticleNavigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {ArrowLeft, ArrowRight} from '@gravity-ui/icons';
import {Flex, Icon, Text} from '@gravity-ui/uikit';
import Link from 'next/link';
import {useCallback} from 'react';
import {CONTENT_WRAPPER_ID} from 'src/constants';
import {block} from 'src/utils';

import {SubSection} from '../NavigationLayout/types';

const b = block('article-navigation');

import './ArticleNavigation.scss';

interface ArticleNavigationProps {
prevSection: SubSection | null;
nextSection: SubSection | null;
}

export const ArticleNavigation = ({prevSection, nextSection}: ArticleNavigationProps) => {
const scrollTop = useCallback(() => {
const content = document.getElementById(CONTENT_WRAPPER_ID);
if (content) {
content.scrollTo({
top: 0,
behavior: 'smooth',
});
}
}, []);

const linkClickHandler = () => {
scrollTop();
};

return (
<div className={b()}>
{prevSection && (
<Link href={prevSection.url}>
<a className={b('button')} onClick={linkClickHandler}>
<div className={b('button-icon')}>
<Icon data={ArrowLeft} size={16} />
</div>
<Flex direction="column" gap="1" className={b('content')}>
<Text variant="body-short" color="light-complementary">
Previous
</Text>
<Text
className={b('content-title')}
ellipsis={true}
variant="body-2"
color="primary"
>
{prevSection.title}
</Text>
</Flex>
</a>
</Link>
)}
{nextSection && (
<Link href={nextSection.url}>
<a className={b('button', {reverse: true})} onClick={linkClickHandler}>
<div className={b('button-icon')}>
<Icon data={ArrowRight} size={16} />
</div>
<Flex direction="column" gap="1" className={b('content')}>
<Text variant="body-short" color="light-complementary">
Next
</Text>
<Text
className={b('content-title')}
ellipsis={true}
variant="body-2"
color="primary"
>
{nextSection.title}
</Text>
</Flex>
</a>
</Link>
)}
</div>
);
};
1 change: 1 addition & 0 deletions src/components/ArticleNavigation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {ArticleNavigation} from './ArticleNavigation';
4 changes: 4 additions & 0 deletions src/components/Component/Component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ $block: '.#{variables.$ns}component';
border-radius: 10px;
}

&__navigation {
margin-top: var(--g-spacing-10);
}

&__header {
display: flex;
align-items: center;
Expand Down
59 changes: 58 additions & 1 deletion src/components/Component/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import githubIcon from '../../assets/icons/github.svg';
import {MDXRenderer} from '../../components/MDXRenderer/MDXRenderer';
import {Component as ComponentType} from '../../content/components/types';
import {block, getRouteFromReadmeUrl} from '../../utils';
import {ArticleNavigation} from '../ArticleNavigation/ArticleNavigation';
import {Section} from '../NavigationLayout/types';
import {SandboxBlock} from '../SandboxBlock';

import './Component.scss';
Expand All @@ -34,15 +36,64 @@ export type ComponentProps = {
libId: string;
component: ComponentType;
readmeContent: string;
sections: Section[];
};

export const Component: React.FC<ComponentProps> = ({libId, component, readmeContent}) => {
export const Component: React.FC<ComponentProps> = ({
libId,
component,
readmeContent,
sections,
}) => {
const router = useRouter();
const {tabId} = router.query;

const [activeTab, setActiveTab] = React.useState(
tabId === Tab.Design ? Tab.Design : Tab.Overview,
);

const currentSection = React.useMemo(
() => sections.find((item) => item.id === libId),
[libId, sections],
);

const currentIndex = React.useMemo(() => {
if (!currentSection || !currentSection.subSections) {
return null;
}
return currentSection.subSections.findIndex((item) => item.id === component.id);
}, [currentSection, component.id]);

const nextSection = React.useMemo(() => {
if (
!currentSection ||
!currentSection.subSections ||
(!currentIndex && currentIndex !== 0)
) {
return null;
}
const nextIndex = currentIndex + 1;
if (nextIndex >= currentSection.subSections.length) {
return null;
}
return currentSection.subSections[nextIndex];
}, [currentIndex, currentSection]);

const prevSection = React.useMemo(() => {
if (
!currentSection ||
!currentSection.subSections ||
(!currentIndex && currentIndex !== 0)
) {
return null;
}
const prevIndex = currentIndex - 1;
if (prevIndex < 0) {
return null;
}
return currentSection.subSections[prevIndex];
}, [currentIndex, currentSection]);

React.useEffect(() => {
setActiveTab(tabId === Tab.Design ? Tab.Design : Tab.Overview);
}, [tabId]);
Expand Down Expand Up @@ -140,6 +191,12 @@ export const Component: React.FC<ComponentProps> = ({libId, component, readmeCon
rewriteLinks={rewriteLinks}
withComponents
/>
<div className={b('navigation')}>
<ArticleNavigation
prevSection={prevSection}
nextSection={nextSection}
/>
</div>
</>
)}
</div>
Expand Down
20 changes: 3 additions & 17 deletions src/components/ComponentsLayout/ComponentsLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
import React, {useMemo} from 'react';
import React from 'react';

import {libs} from '../../content/components';
import {NavigationLayout, Section} from '../NavigationLayout/NavigationLayout';

export type ComponentsLayoutProps = {
libId: string;
componentId?: string;
children?: React.ReactNode;
sections: Section[];
};

export const ComponentsLayout: React.FC<ComponentsLayoutProps> = ({
libId,
componentId,
children,
sections,
}) => {
const sections = useMemo<Section[]>(() => {
return libs.map((lib) => ({
id: lib.id,
title: lib.title,
// url: `/components/${lib.id}`, // "Overview" link
subSections: lib.components.map((component) => ({
id: component.id,
title: component.title,
url:
component.isComingSoon === true ? '#' : `/components/${lib.id}/${component.id}`,
isComingSoon: component.isComingSoon,
})),
}));
}, []);

return (
<NavigationLayout
sections={sections}
Expand Down
3 changes: 3 additions & 0 deletions src/components/DesignArticle/DesignArticle.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ $block: '.#{variables.$ns}design-article';
line-height: 48px;
font-weight: 600;
}
&__navigation {
margin-top: var(--g-spacing-10);
}
}
55 changes: 51 additions & 4 deletions src/components/DesignArticle/DesignArticle.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,70 @@
import React from 'react';
import React, {useMemo} from 'react';

import {Article} from '../../content/design/types';
import {block} from '../../utils';
import {ArticleNavigation} from '../ArticleNavigation/ArticleNavigation';
import {MDXRenderer} from '../MDXRenderer/MDXRenderer';
import {Section} from '../NavigationLayout/types';

import './DesignArticle.scss';

const b = block('design-article');

export type DesignArticleProps = {
article: Article;
sectionId?: string;
sections: Section[];
};

export const DesignArticle: React.FC<DesignArticleProps> = ({article}) => {
export const DesignArticle: React.FC<DesignArticleProps> = ({article, sectionId, sections}) => {
const currentSection = useMemo(
() => sections.find((item) => item.id === sectionId),
[sectionId, sections],
);

const currentIndex = useMemo(() => {
if (!currentSection || !currentSection.subSections) {
return null;
}
return currentSection.subSections.findIndex((item) => item.id === article.id);
}, [currentSection, article.id]);

const nextSection = useMemo(() => {
if (
!currentSection ||
!currentSection.subSections ||
(!currentIndex && currentIndex !== 0)
) {
return null;
}
const nextIndex = currentIndex + 1;
if (nextIndex >= currentSection.subSections.length) {
return null;
}
return currentSection.subSections[nextIndex];
}, [currentIndex, currentSection]);

const prevSection = useMemo(() => {
if (
!currentSection ||
!currentSection.subSections ||
(!currentIndex && currentIndex !== 0)
) {
return null;
}
const prevIndex = currentIndex - 1;
if (prevIndex < 0) {
return null;
}
return currentSection.subSections[prevIndex];
}, [currentIndex, currentSection]);

return (
<div className={b()}>
<h1 className={b('title')}>{article.title}</h1>
<div className={b('content')}>
<MDXRenderer text={article.content} />
<MDXRenderer text={article.content} />
<div className={b('navigation')}>
<ArticleNavigation prevSection={prevSection} nextSection={nextSection} />
</div>
</div>
);
Expand Down
Loading

0 comments on commit a8504f8

Please sign in to comment.