Skip to content

Commit

Permalink
rehypeAutoHeading from depth to nesting, add scroll-up, fix top tit…
Browse files Browse the repository at this point in the history
…le select, add headlines to main page
  • Loading branch information
MarkMelior committed Jul 18, 2024
1 parent d9a1226 commit 3b98cb5
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 60 deletions.
2 changes: 2 additions & 0 deletions app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ClientProviders } from '@/app/providers/client-providers';
import '@/app/styles/index.scss';
import { ScrollUp } from '@/features';
import { i18n, Locale } from '@/shared/config/i18n';
import { FontDefault } from '@/shared/const/fonts';
import { GlowingLine, Light, PageLoader } from '@/shared/ui';
Expand Down Expand Up @@ -38,6 +39,7 @@ export default async function RootLayout({
}
>
<Light />
<ScrollUp />
<GlowingLine className='fixed z-50 top-0' />
<Navbar />
<div className='max-w-7xl mx-auto px-4 sm:px-6 md:px-8 z-20 grid lg:grid-cols-[17.5rem,1fr] gap-10'>
Expand Down
7 changes: 3 additions & 4 deletions app/[lang]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getLang } from '@/shared/config/i18n';
import { getMdx, MDXRemote } from '@/shared/config/mdx';
import { StackButtons } from '@/shared/ui';
import { Header } from '@/widgets';
import { Header, Headlines } from '@/widgets';
import { MDXComponents } from 'mdx/types';
import dynamic from 'next/dynamic';
import path from 'path';
Expand All @@ -10,9 +10,7 @@ export default async function Home() {
const lang = await getLang();

const dir = path.join(process.cwd(), 'app', `home-${lang}.mdx`);
const mdx = await getMdx(dir);
const metadata = mdx.metadata;
const content = mdx.content;
const { metadata, content, headlines } = await getMdx(dir);

const components: MDXComponents = {
StackButtons: dynamic(() =>
Expand All @@ -33,6 +31,7 @@ export default async function Home() {
classNames={{ description: 'mt-4 text-[1.075rem] md:w-[75%] mx-auto' }}
/>
<MDXRemote source={content} components={components} />
<Headlines headlines={headlines} />
<StackButtons
tags={[
'TypeScript',
Expand Down
13 changes: 5 additions & 8 deletions src/app/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,19 @@
}

html {
min-height: 100vh;
font-size: 16px;

@media (max-width: theme('screens.sm')) {
font-size: 14px;
}
}

body {
background: linear-gradient(90deg, theme('colors.default-50') 15px, transparent 1%) 50%, linear-gradient(theme('colors.default-50') 15px, theme('colors.default-200') 1%) 0, hsla(0deg, 0%, 100%, 16%);
background-size: 16px 16px;
min-height: 100vh;

[class="light"] & {
background: linear-gradient(90deg, theme('colors.default-100') 15px, transparent 1%) 50%, linear-gradient(theme('colors.default-100') 15px, theme('colors.default-300') 1%) 0, hsla(0deg, 0%, 100%, 16%);
background-size: 16px 16px;
}

@media (max-width: theme('screens.sm')) {
font-size: 14px;
}
}

::-webkit-scrollbar {
Expand Down
2 changes: 2 additions & 0 deletions src/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { FormSignup } from './auth/ui/form-signup/form-signup';
import { LogoutButton } from './auth/ui/logout-button/logout-button';
import { Burger } from './burger/burger';
import { LocaleSwitcher } from './locale-switcher/locale-switcher';
import { ScrollUp } from './scroll-up/scroll-up';
import { ThemeSwitcher } from './theme-switcher/theme-switcher';

export {
Expand All @@ -17,6 +18,7 @@ export {
LocaleSwitcher,
logout,
LogoutButton,
ScrollUp,
ThemeSwitcher,
verifySession,
};
49 changes: 49 additions & 0 deletions src/features/scroll-up/scroll-up.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use client';

import { Button, cn } from '@nextui-org/react';
import { useEffect, useState } from 'react';
import { GoArrowUp } from 'react-icons/go';

export const ScrollUp = () => {
const [isScrolled, setIsScrolled] = useState(false);

useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 30) {
setIsScrolled(true);
} else {
setIsScrolled(false);
}
};

window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);

const scrollToTop = () => {
if (!isScrolled) return;

window.scrollTo({
top: 0,
behavior: 'smooth',
});
};

return (
<Button
className={cn(
'bg-default-100 hover:bg-primary-500 fixed bottom-4 right-4 text-default-500 hover:text-default-900',
{
'opacity-0': !isScrolled,
},
)}
onClick={scrollToTop}
radius='lg'
isIconOnly
>
<GoArrowUp size={22} />
</Button>
);
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
'use client';

import { Dictionary, i18n, Link, Locale } from '@/shared/config/i18n';
import { cn } from '@/shared/lib';
import { usePathname } from 'next/navigation';
import { FC } from 'react';

interface FooterGithubLinkProps {
dict: Dictionary['ui'];
interface GithubEditLinkProps {
dict?: Dictionary['ui'];
lang: Locale;
className?: string;
}

export const FooterGithubLink: FC<FooterGithubLinkProps> = ({ dict, lang }) => {
export const GithubEditLink: FC<GithubEditLinkProps> = ({
dict,
lang,
className,
}) => {
const pathname = usePathname();

if (
pathname === '/' ||
i18n.locales.includes(pathname.split('/')[1] as Locale)
i18n.locales.includes(pathname.split('/')[1] as Locale) ||
!dict
)
return null;

Expand All @@ -26,7 +33,7 @@ export const FooterGithubLink: FC<FooterGithubLinkProps> = ({ dict, lang }) => {
<Link
target='_blank'
href={hrefGithub}
className='hover:text-default-600 transition'
className={cn('hover:text-default-600 transition', className)}
>
{dict['footer-edit']}
</Link>
Expand Down
3 changes: 2 additions & 1 deletion src/shared/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GithubEditLink } from './github-edit-link/github-edit-link';
import { Portal } from './portal/portal';
import { PortalEnum } from './portal/portal-enum';

export { Portal, PortalEnum };
export { GithubEditLink, Portal, PortalEnum };
1 change: 1 addition & 0 deletions src/shared/config/i18n/dictionaries/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"footer-nav-home": "Home",
"navbar-title": "Simple App",
"navbar-desc": "Small and modern pet-projects",
"headlines-title": "On this page",
"change-lang": "Change language",
"lang-rus": "Russian",
"lang-eng": "English",
Expand Down
1 change: 1 addition & 0 deletions src/shared/config/i18n/dictionaries/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"footer-nav-home": "Главная",
"navbar-title": "Simple App",
"navbar-desc": "Небольшие и современные пет-проекты",
"headlines-title": "Навигация по странице",
"change-lang": "Сменить язык",
"lang-rus": "Русский",
"lang-eng": "English",
Expand Down
8 changes: 6 additions & 2 deletions src/shared/config/mdx/mdx-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,21 +117,25 @@ function Heading({
children,
className,
Tag,
id,
...props
}: {
children: React.ReactNode;
className?: string;
Tag: keyof JSX.IntrinsicElements;
id?: string;
}) {
return (
<Tag
className={cn(
'whitespace-pre-wrap relative text-default-900 pt-[var(--height-navbar)] -mt-[var(--height-navbar)]',
'pt-[var(--height-navbar)] -mt-[var(--height-navbar)] text-default-900',
className,
)}
id={id}
data-headline-id={id}
{...props}
>
{children}
<span className='whitespace-pre-wrap relative'>{children}</span>
</Tag>
);
}
34 changes: 27 additions & 7 deletions src/shared/config/mdx/plugins/rehype-auto-heading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,41 @@ import { MdxHeadline } from '../types/get-mdx.type';

export function rehypeAutoHeading(headlines?: MdxHeadline[]) {
return (tree: any) => {
const stack: { depth: number; headline: MdxHeadline }[] = [];

visit(tree, 'element', (node) => {
if (/h[1-6]/.test(node.tagName)) {
const text = toString(node);

const id = slug(text);
const depth = parseInt(node.tagName.slice(1), 10);
const headline = {
title: text.endsWith(':') ? text.slice(0, -1) : text,
href: `#${id}`,
};

if (!node.properties) node.properties = {};
node.properties.id = id;

headlines &&
headlines.push({
depth: parseInt(node.tagName.slice(1), 10),
title: text.endsWith(':') ? text.slice(0, -1) : text,
href: `#${id}`,
});
// Ensure that the headline is pushed to the correct nesting level
while (stack.length && stack[stack.length - 1].depth >= depth) {
stack.pop();
}

if (headlines) {
if (depth === 1 || stack.length === 0) {
headlines.push(headline);
stack.push({ depth, headline });
} else {
const parent = stack[stack.length - 1].headline;
if (!parent.nested) {
parent.nested = [];
}
parent.nested.push(headline);
if (depth === 2) {
stack.push({ depth, headline });
}
}
}

node.children = [
{
Expand Down
2 changes: 1 addition & 1 deletion src/shared/config/mdx/types/get-mdx.type.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { StackVariants } from '@/shared/ui';

export interface MdxHeadline {
depth: number;
title: string;
href: string;
nested?: MdxHeadline[];
}

export interface ProjectMetadata {
Expand Down
4 changes: 2 additions & 2 deletions src/widgets/footer/footer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getProjects } from '@/entity/project';
import { GithubEditLink } from '@/shared/components';
import { getDictionary, getLang, Link } from '@/shared/config/i18n';
import { FooterGithubLink } from './footer-github-link';
import { FooterNavigation } from './footer-navigation';
import cls from './footer.module.scss';

Expand All @@ -24,7 +24,7 @@ export const Footer = async () => {
</Link>
</p>
</div>
<FooterGithubLink dict={dict} lang={lang} />
<GithubEditLink dict={dict} lang={lang} />
</div>
</footer>
);
Expand Down
18 changes: 18 additions & 0 deletions src/widgets/headlines/headlines.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.content {
@apply mb-8 flex flex-col mt-auto;
}

// .content {
// @apply bg-default-50/80 border-default-900/5 hover:border-default-900/10 rounded-lg border px-4 py-3 transition-colors mb-8 flex flex-col relative;

// &::before {
// content: "";
// display: block;
// left: 0;
// width: 100%;
// background: linear-gradient(90deg, rgba(56, 189, 248, 0) 20%, rgba(144, 163, 187, 0.2) 50%, rgba(236, 72, 153, 0) 80%);
// height: 1px;
// position: absolute;
// top: -1px;
// }
// }
Loading

0 comments on commit 3b98cb5

Please sign in to comment.