-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(docs): add vkui-docs-theme component + minimal doc * fix: review notes * fix: use breakpoints from vkui * feat(blog): add blog pages * fix review notes
- Loading branch information
1 parent
44b3c5d
commit 83d64a6
Showing
41 changed files
with
795 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { SimpleGrid } from '@vkontakte/vkui'; | ||
import { useRouter } from 'next/router'; | ||
import { useConfig } from '../contexts'; | ||
import { Post } from './components/Post'; | ||
import { findPosts } from './helpers'; | ||
import { getTags } from './tags'; | ||
|
||
export function PostsLayout() { | ||
const config = useConfig(); | ||
const { pageMap, frontMatter } = config; | ||
const posts = findPosts(pageMap); | ||
const router = useRouter(); | ||
const { type } = frontMatter; | ||
const tagName = type === 'tag' ? router.query.tag : null; | ||
|
||
return ( | ||
<SimpleGrid columns={3} gap="xl"> | ||
{posts.map((post) => { | ||
const tags = getTags(post.frontMatter); | ||
if (tagName) { | ||
if (!Array.isArray(tagName) && !tags.includes(tagName)) { | ||
return null; | ||
} | ||
} else if (type === 'tag') { | ||
return null; | ||
} | ||
|
||
const postTitle = post.frontMatter?.title || post.name; | ||
const date: Date | null = post.frontMatter?.date ? new Date(post.frontMatter.date) : null; | ||
|
||
return ( | ||
<Post | ||
key={post.route} | ||
title={postTitle} | ||
description={post.frontMatter?.description} | ||
publishDate={date} | ||
tags={tags} | ||
route={post.route} | ||
image={post.frontMatter?.image} | ||
/> | ||
); | ||
})} | ||
</SimpleGrid> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import * as React from 'react'; | ||
import { Title } from '@vkontakte/vkui'; | ||
|
||
export interface HeadingProps extends React.ComponentProps<'h2'> { | ||
Tag?: `h${1 | 2 | 3}`; | ||
} | ||
|
||
export function Heading({ Tag = 'h2', children, ...props }: HeadingProps) { | ||
return ( | ||
<Title Component={Tag} {...props}> | ||
{children} | ||
</Title> | ||
); | ||
} |
40 changes: 40 additions & 0 deletions
40
packages/vkui-docs-theme/src/blog/components/Post/Post.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
.root { | ||
display: flex; | ||
flex-direction: column; | ||
overflow: hidden; | ||
} | ||
|
||
.heading { | ||
--vkui--color_text_link: var(--vkui--color_text_primary); | ||
|
||
color: var(--vkui--color_text_primary); | ||
} | ||
|
||
.headingPrimary { | ||
font-size: 40px; | ||
line-height: 46px; | ||
} | ||
|
||
.date:not(:only-child)::after { | ||
content: '•'; | ||
padding-inline: var(--vkui--spacing_size_s); | ||
} | ||
|
||
.content { | ||
padding-block: var(--vkui--size_base_padding_vertical--regular); | ||
padding-inline: var(--vkui--size_base_padding_horizontal--regular); | ||
display: flex; | ||
flex-direction: column; | ||
flex-grow: 1; | ||
|
||
--vkui--color_text_link: var(--vkui--color_text_primary); | ||
} | ||
|
||
.description { | ||
margin-block-start: var(--vkui--spacing_size_s); | ||
} | ||
|
||
.meta { | ||
margin-block-start: auto; | ||
padding-block-start: var(--vkui--spacing_size_s); | ||
} |
40 changes: 40 additions & 0 deletions
40
packages/vkui-docs-theme/src/blog/components/Post/Post.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import * as React from 'react'; | ||
import { Card, Link, Text } from '@vkontakte/vkui'; | ||
import NextLink from 'next/link'; | ||
import { useRouter } from 'next/router'; | ||
import { PostHeading } from './PostHeading'; | ||
import { PostMeta, type PostMetaProps } from './PostMeta'; | ||
import styles from './Post.module.css'; | ||
|
||
interface PostProps extends PostMetaProps { | ||
title: React.ReactNode; | ||
description?: React.ReactNode; | ||
route?: string; | ||
image?: string; | ||
} | ||
|
||
export function Post({ title, description, tags, publishDate, route, image }: PostProps) { | ||
const router = useRouter(); | ||
|
||
return ( | ||
<Card className={styles.root} mode="outline-tint" Component="article"> | ||
<img src={`${router.basePath}${image}`} alt={`Лого для карточки ${title}`} width="100%" /> | ||
<div className={styles.content}> | ||
<PostHeading> | ||
<Link href={route} Component={NextLink}> | ||
{title} | ||
</Link> | ||
</PostHeading> | ||
{description && ( | ||
<Text className={styles.description}> | ||
{description}{' '} | ||
<Link href={route} Component={NextLink}> | ||
Читать далее... | ||
</Link> | ||
</Text> | ||
)} | ||
<PostMeta className={styles.meta} publishDate={publishDate} tags={tags} /> | ||
</div> | ||
</Card> | ||
); | ||
} |
20 changes: 20 additions & 0 deletions
20
packages/vkui-docs-theme/src/blog/components/Post/PostHeading.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import * as React from 'react'; | ||
import { classNames } from '@vkontakte/vkjs'; | ||
import { Heading, type HeadingProps } from '../Heading'; | ||
import styles from './Post.module.css'; | ||
|
||
export interface PostHeadingProps extends HeadingProps { | ||
children?: React.ReactNode; | ||
} | ||
|
||
export function PostHeading({ children, Tag }: PostHeadingProps) { | ||
if (Tag === 'h1') { | ||
return <h1 className={classNames(styles.heading, styles.headingPrimary)}>{children}</h1>; | ||
} | ||
|
||
return ( | ||
<Heading className={styles.heading} Tag={Tag}> | ||
{children} | ||
</Heading> | ||
); | ||
} |
27 changes: 27 additions & 0 deletions
27
packages/vkui-docs-theme/src/blog/components/Post/PostMeta.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { ContentBadge, Footnote } from '@vkontakte/vkui'; | ||
import NextLink from 'next/link'; | ||
import { DateFormatter } from '../../../helpers/date'; | ||
import styles from './Post.module.css'; | ||
|
||
export interface PostMetaProps { | ||
publishDate?: Date | null; | ||
tags?: string[]; | ||
className?: string; | ||
} | ||
|
||
export function PostMeta({ publishDate, tags = [], className }: PostMetaProps) { | ||
return ( | ||
<div className={className}> | ||
{publishDate && ( | ||
<Footnote className={styles.date} inline> | ||
<time dateTime={publishDate.toISOString()}>{DateFormatter.format(publishDate)}</time> | ||
</Footnote> | ||
)} | ||
{tags.map((tag) => ( | ||
<NextLink href={`/blog/tags/${tag}`} key={tag}> | ||
<ContentBadge appearance="neutral"># {tag}</ContentBadge> | ||
</NextLink> | ||
))} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { Post } from './Post'; | ||
export { PostMeta } from './PostMeta'; | ||
export { PostHeading } from './PostHeading'; |
29 changes: 29 additions & 0 deletions
29
packages/vkui-docs-theme/src/blog/components/PostHeader.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Icon12ChevronLeft } from '@vkontakte/icons'; | ||
import { Button } from '@vkontakte/vkui'; | ||
import { useRouter } from 'next/router'; | ||
import { useConfig } from '../../contexts'; | ||
import { getTags } from '../tags'; | ||
import { PostHeading, PostMeta } from './Post'; | ||
|
||
export function PostHeader() { | ||
const config = useConfig(); | ||
const { frontMatter } = config; | ||
const router = useRouter(); | ||
const tags = getTags(frontMatter); | ||
|
||
const back = () => { | ||
void router.push('/blog'); | ||
}; | ||
|
||
const date: Date | null = frontMatter.date ? new Date(frontMatter.date) : null; | ||
|
||
return ( | ||
<div> | ||
<Button onClick={back} mode="link" before={<Icon12ChevronLeft />} size="s"> | ||
Назад | ||
</Button> | ||
<PostMeta publishDate={date} tags={tags} /> | ||
<PostHeading Tag="h1">{frontMatter.title}</PostHeading> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import type { MdxFile, PageMapItem, PageOpts } from 'nextra'; | ||
|
||
const sortPosts = (a: MdxFile, b: MdxFile): number => { | ||
if (!a.frontMatter?.date || !b.frontMatter?.date) { | ||
return -1; | ||
} | ||
|
||
return new Date(b.frontMatter.date).getTime() - new Date(a.frontMatter.date).getTime(); | ||
}; | ||
|
||
export const isPost = (page: PageMapItem): page is MdxFile => { | ||
if ('frontMatter' in page) { | ||
const { draft, type } = page.frontMatter || {}; | ||
return !draft && type === 'post'; | ||
} | ||
return false; | ||
}; | ||
|
||
export function findPosts(pageMap: PageOpts['pageMap']) { | ||
const posts: MdxFile[] = []; | ||
|
||
for (const item of pageMap) { | ||
if ('children' in item && item.name === 'blog') { | ||
for (const pageMapItem of item.children) { | ||
if (isPost(pageMapItem)) { | ||
posts.push(pageMapItem); | ||
} | ||
} | ||
} | ||
} | ||
posts.sort(sortPosts); | ||
return posts; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { PostsLayout } from './PostsLayout'; | ||
export { PostHeader } from './components/PostHeader'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import type { GetStaticPaths } from 'next'; | ||
import Head from 'next/head'; | ||
import type { FrontMatter, PageMapItem } from 'nextra'; | ||
import { useData } from 'nextra/hooks'; | ||
import { isPost } from './helpers'; | ||
|
||
const NEXTRA_INTERNAL = Symbol.for('__nextra_internal__'); | ||
|
||
export const TagTitle = () => { | ||
const { tag } = useData(); | ||
const title = `Посты по теме ${tag}`; | ||
return ( | ||
<Head> | ||
<title>{title}</title> | ||
</Head> | ||
); | ||
}; | ||
|
||
export const TagName = () => { | ||
const { tag } = useData(); | ||
return tag || null; | ||
}; | ||
|
||
export function getTags(frontMatter: FrontMatter | undefined) { | ||
if (!frontMatter) { | ||
return []; | ||
} | ||
const tags: string | string[] = frontMatter.tag || []; | ||
return (Array.isArray(tags) ? tags : tags.split(',')).map((s) => s.trim()); | ||
} | ||
|
||
const getStaticTags = (pageMap: PageMapItem[]) => { | ||
const tags = []; | ||
|
||
for (const item of pageMap) { | ||
if ('children' in item && item.name === 'blog') { | ||
for (const pageMapItem of item.children) { | ||
if (isPost(pageMapItem)) { | ||
tags.push(...getTags(pageMapItem.frontMatter)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return [...new Set(tags)]; | ||
}; | ||
|
||
export const getStaticPathsTags: GetStaticPaths = () => { | ||
const tags = getStaticTags((globalThis as any)[NEXTRA_INTERNAL].pageMap); | ||
return { | ||
paths: tags.map((v: any) => ({ params: { tag: v } })), | ||
fallback: false, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.