From 0721cad96740045d92bbca8eead3427e038c798f Mon Sep 17 00:00:00 2001 From: Victoria Zhizhonkova Date: Wed, 18 Dec 2024 22:58:19 +0700 Subject: [PATCH 1/4] feat(docs): add vkui-docs-theme component + minimal doc --- package.json | 2 +- packages/vkui-docs-theme/index.ts | 5 + packages/vkui-docs-theme/package.json | 4 +- .../scripts/generateCSSCustomMedias.mjs | 57 +++++ packages/vkui-docs-theme/src/breakpoints.ts | 10 + .../vkui-docs-theme/src/components/Anchor.tsx | 28 +++ .../Breadcrumbs/Breadcrumbs.module.css | 25 ++ .../components/Breadcrumbs/Breadcrumbs.tsx | 26 +++ .../src/components/ColorSchemeSwitch.tsx | 33 +++ .../vkui-docs-theme/src/components/Head.tsx | 29 +++ .../components/NavLinks/NavLinks.module.css | 38 +++ .../src/components/NavLinks/NavLinks.tsx | 69 ++++++ .../src/components/Navbar/Navbar.module.css | 102 ++++++++ .../src/components/Navbar/Navbar.tsx | 129 +++++++++++ .../src/components/ProjectButton.tsx | 16 ++ .../Sidebar/Accordion/Accordion.tsx | 57 +++++ .../components/Sidebar/Menu/Menu.module.css | 71 ++++++ .../src/components/Sidebar/Menu/Menu.tsx | 156 +++++++++++++ .../MobileSidebar/MobileSidebar.module.css | 141 +++++++++++ .../Sidebar/MobileSidebar/MobileSidebar.tsx | 98 ++++++++ .../src/components/Sidebar/Sidebar.module.css | 59 +++++ .../src/components/Sidebar/Sidebar.tsx | 42 ++++ .../vkui-docs-theme/src/components/index.ts | 7 + packages/vkui-docs-theme/src/constants.tsx | 39 ++++ .../src/contexts/color-scheme/helpers.ts | 42 ++++ .../src/contexts/color-scheme/index.tsx | 109 +++++++++ .../src/contexts/color-scheme/script.tsx | 43 ++++ .../src/contexts/color-scheme/types.ts | 14 ++ .../vkui-docs-theme/src/contexts/config.tsx | 64 +++++ .../vkui-docs-theme/src/contexts/index.ts | 4 + .../vkui-docs-theme/src/contexts/menu.tsx | 22 ++ .../vkui-docs-theme/src/contexts/theme.tsx | 32 +++ .../vkui-docs-theme/src/helpers/render.tsx | 13 ++ .../vkui-docs-theme/src/hooks/useFetch.ts | 78 +++++++ .../vkui-docs-theme/src/icons/FigmaIcon.tsx | 16 ++ .../vkui-docs-theme/src/icons/GithubIcon.tsx | 14 ++ .../vkui-docs-theme/src/icons/LogoIcon.tsx | 22 ++ .../src/icons/StorybookIcon.tsx | 14 ++ .../src/icons/SvgIcon.module.css | 15 ++ .../vkui-docs-theme/src/icons/SvgIcon.tsx | 41 ++++ packages/vkui-docs-theme/src/icons/index.ts | 4 + packages/vkui-docs-theme/src/index.tsx | 48 +++- .../src/mdx/Callout/Callout.module.css | 24 ++ .../src/mdx/Callout/Callout.tsx | 18 ++ .../src/mdx/Code/Code.module.css | 26 +++ .../vkui-docs-theme/src/mdx/Code/Code.tsx | 31 +++ .../mdx/HeadingLink/HeadingLink.module.css | 35 +++ .../src/mdx/HeadingLink/HeadingLink.tsx | 37 +++ .../src/mdx/Layout/Layout.module.css | 31 +++ .../vkui-docs-theme/src/mdx/Layout/Layout.tsx | 70 ++++++ .../src/mdx/Overview/Overview.module.css | 46 ++++ .../src/mdx/Overview/Overview.tsx | 57 +++++ .../src/mdx/Overview/background.png | Bin 0 -> 2734 bytes .../CopyToClipboard.module.css | 58 +++++ .../Pre/CopyToClipboard/CopyToClipboard.tsx | 45 ++++ .../src/mdx/Pre/Pre.module.css | 34 +++ packages/vkui-docs-theme/src/mdx/Pre/Pre.tsx | 37 +++ .../vkui-docs-theme/src/mdx/index.module.css | 39 ++++ packages/vkui-docs-theme/src/mdx/index.tsx | 39 ++++ packages/vkui-docs-theme/src/types.ts | 84 +++++++ .../vkui-docs-theme/src/wrappers/index.ts | 1 + .../src/wrappers/vkui/index.module.css | 10 + .../src/wrappers/vkui/index.tsx | 20 ++ packages/vkui-docs-theme/styles.css | 13 ++ packages/vkui-docs-theme/styles/colors.css | 31 +++ packages/vkui-docs-theme/styles/constants.css | 11 + .../styles/customMedias.generated.css | 10 + packages/vkui-docs-theme/styles/global.css | 30 +++ stylelint.config.mjs | 21 ++ website/pages/_meta.tsx | 29 +++ website/pages/components/index.mdx | 1 + website/pages/overview/_meta.tsx | 40 ++++ website/pages/overview/about.mdx | 41 ++++ website/pages/overview/adaptivity.mdx | 172 ++++++++++++++ website/pages/overview/integrations.mdx | 218 ++++++++++++++++++ website/pages/overview/modes.mdx | 38 +++ .../pages/overview/platforms-and-themes.mdx | 126 ++++++++++ website/pages/overview/quick-start.mdx | 95 ++++++++ website/pages/overview/structure.mdx | 78 +++++++ website/postcss.config.js | 7 +- website/src/components/Versions/Versions.tsx | 29 +++ .../src/components/Versions/VersionsModal.tsx | 71 ++++++ website/src/components/index.ts | 1 + website/theme.config.tsx | 32 ++- 84 files changed, 3664 insertions(+), 10 deletions(-) create mode 100644 packages/vkui-docs-theme/scripts/generateCSSCustomMedias.mjs create mode 100644 packages/vkui-docs-theme/src/breakpoints.ts create mode 100644 packages/vkui-docs-theme/src/components/Anchor.tsx create mode 100644 packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.module.css create mode 100644 packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.tsx create mode 100644 packages/vkui-docs-theme/src/components/ColorSchemeSwitch.tsx create mode 100644 packages/vkui-docs-theme/src/components/Head.tsx create mode 100644 packages/vkui-docs-theme/src/components/NavLinks/NavLinks.module.css create mode 100644 packages/vkui-docs-theme/src/components/NavLinks/NavLinks.tsx create mode 100644 packages/vkui-docs-theme/src/components/Navbar/Navbar.module.css create mode 100644 packages/vkui-docs-theme/src/components/Navbar/Navbar.tsx create mode 100644 packages/vkui-docs-theme/src/components/ProjectButton.tsx create mode 100644 packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.tsx create mode 100644 packages/vkui-docs-theme/src/components/Sidebar/Menu/Menu.module.css create mode 100644 packages/vkui-docs-theme/src/components/Sidebar/Menu/Menu.tsx create mode 100644 packages/vkui-docs-theme/src/components/Sidebar/MobileSidebar/MobileSidebar.module.css create mode 100644 packages/vkui-docs-theme/src/components/Sidebar/MobileSidebar/MobileSidebar.tsx create mode 100644 packages/vkui-docs-theme/src/components/Sidebar/Sidebar.module.css create mode 100644 packages/vkui-docs-theme/src/components/Sidebar/Sidebar.tsx create mode 100644 packages/vkui-docs-theme/src/components/index.ts create mode 100644 packages/vkui-docs-theme/src/constants.tsx create mode 100644 packages/vkui-docs-theme/src/contexts/color-scheme/helpers.ts create mode 100644 packages/vkui-docs-theme/src/contexts/color-scheme/index.tsx create mode 100644 packages/vkui-docs-theme/src/contexts/color-scheme/script.tsx create mode 100644 packages/vkui-docs-theme/src/contexts/color-scheme/types.ts create mode 100644 packages/vkui-docs-theme/src/contexts/config.tsx create mode 100644 packages/vkui-docs-theme/src/contexts/index.ts create mode 100644 packages/vkui-docs-theme/src/contexts/menu.tsx create mode 100644 packages/vkui-docs-theme/src/contexts/theme.tsx create mode 100644 packages/vkui-docs-theme/src/helpers/render.tsx create mode 100644 packages/vkui-docs-theme/src/hooks/useFetch.ts create mode 100644 packages/vkui-docs-theme/src/icons/FigmaIcon.tsx create mode 100644 packages/vkui-docs-theme/src/icons/GithubIcon.tsx create mode 100644 packages/vkui-docs-theme/src/icons/LogoIcon.tsx create mode 100644 packages/vkui-docs-theme/src/icons/StorybookIcon.tsx create mode 100644 packages/vkui-docs-theme/src/icons/SvgIcon.module.css create mode 100644 packages/vkui-docs-theme/src/icons/SvgIcon.tsx create mode 100644 packages/vkui-docs-theme/src/icons/index.ts create mode 100644 packages/vkui-docs-theme/src/mdx/Callout/Callout.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/Callout/Callout.tsx create mode 100644 packages/vkui-docs-theme/src/mdx/Code/Code.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/Code/Code.tsx create mode 100644 packages/vkui-docs-theme/src/mdx/HeadingLink/HeadingLink.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/HeadingLink/HeadingLink.tsx create mode 100644 packages/vkui-docs-theme/src/mdx/Layout/Layout.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/Layout/Layout.tsx create mode 100644 packages/vkui-docs-theme/src/mdx/Overview/Overview.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/Overview/Overview.tsx create mode 100644 packages/vkui-docs-theme/src/mdx/Overview/background.png create mode 100644 packages/vkui-docs-theme/src/mdx/Pre/CopyToClipboard/CopyToClipboard.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/Pre/CopyToClipboard/CopyToClipboard.tsx create mode 100644 packages/vkui-docs-theme/src/mdx/Pre/Pre.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/Pre/Pre.tsx create mode 100644 packages/vkui-docs-theme/src/mdx/index.module.css create mode 100644 packages/vkui-docs-theme/src/mdx/index.tsx create mode 100644 packages/vkui-docs-theme/src/types.ts create mode 100644 packages/vkui-docs-theme/src/wrappers/index.ts create mode 100644 packages/vkui-docs-theme/src/wrappers/vkui/index.module.css create mode 100644 packages/vkui-docs-theme/src/wrappers/vkui/index.tsx create mode 100644 packages/vkui-docs-theme/styles/colors.css create mode 100644 packages/vkui-docs-theme/styles/constants.css create mode 100644 packages/vkui-docs-theme/styles/customMedias.generated.css create mode 100644 packages/vkui-docs-theme/styles/global.css create mode 100644 website/pages/_meta.tsx create mode 100644 website/pages/components/index.mdx create mode 100644 website/pages/overview/_meta.tsx create mode 100644 website/pages/overview/about.mdx create mode 100644 website/pages/overview/adaptivity.mdx create mode 100644 website/pages/overview/integrations.mdx create mode 100644 website/pages/overview/modes.mdx create mode 100644 website/pages/overview/platforms-and-themes.mdx create mode 100644 website/pages/overview/quick-start.mdx create mode 100644 website/pages/overview/structure.mdx create mode 100644 website/src/components/Versions/Versions.tsx create mode 100644 website/src/components/Versions/VersionsModal.tsx create mode 100644 website/src/components/index.ts diff --git a/package.json b/package.json index 01c07e27b6a..7dd19689088 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "lint:style": "cross-env LINT_PRECOMMIT_RUN=1 stylelint '**/*.css' --cache --cache-location .cache/.stylelintcache", "lint:prettier": "prettier --check --ignore-unknown --cache --cache-location .cache/.prettiercache .", "lint:types": "tsc --incremental --emitDeclarationOnly --declaration --tsBuildInfoFile .cache/.tsbuildinfo", - "lint:generated-files": "yarn workspace @vkontakte/vkui run lint:generated-files", + "lint:generated-files": "concurrently 'yarn workspace @vkontakte/vkui run lint:generated-files' 'yarn workspace @vkontakte/vkui-docs-theme run lint:generated-files'", "prepare": "husky", "playwright:install": "playwright install --with-deps", "playwright:cmd:merge-reports": "playwright merge-reports", diff --git a/packages/vkui-docs-theme/index.ts b/packages/vkui-docs-theme/index.ts index 52c46650194..933afae8660 100644 --- a/packages/vkui-docs-theme/index.ts +++ b/packages/vkui-docs-theme/index.ts @@ -1,2 +1,7 @@ import Layout from './src/index'; +import type { PartialDocsThemeConfig as DocsThemeConfig } from './src/types'; + +export { useFetch } from './src/hooks/useFetch'; +export { StorybookIcon, GithubIcon, FigmaIcon } from './src/icons'; +export { type DocsThemeConfig }; export default Layout; diff --git a/packages/vkui-docs-theme/package.json b/packages/vkui-docs-theme/package.json index f24946b5d05..2323144fc6e 100644 --- a/packages/vkui-docs-theme/package.json +++ b/packages/vkui-docs-theme/package.json @@ -44,6 +44,8 @@ "react-dom": "^18.3.1" }, "scripts": { - "test": "jest" + "test": "jest", + "lint:generated-files": "yarn run generate:css-custom-medias && git diff --exit-code styles/customMedias.generated.css", + "generate:css-custom-medias": "node scripts/generateCSSCustomMedias.mjs" } } diff --git a/packages/vkui-docs-theme/scripts/generateCSSCustomMedias.mjs b/packages/vkui-docs-theme/scripts/generateCSSCustomMedias.mjs new file mode 100644 index 00000000000..ce98b2b4bb9 --- /dev/null +++ b/packages/vkui-docs-theme/scripts/generateCSSCustomMedias.mjs @@ -0,0 +1,57 @@ +/* eslint no-console: 0 */ +import fs from 'node:fs'; +import path from 'node:path'; +import ts from 'typescript'; + +const inputSourceFilePath = path.resolve(import.meta.dirname, '../src/breakpoints.ts'); +const outputSourceFilePath = path.resolve( + import.meta.dirname, + '../styles/customMedias.generated.css', +); + +/** + * Возвращает медиа выражения необходимые по дизайн-системе. У ключей синтаксис должен быть как у CSS Custom Properties. + * + * > ❗️IMPORTANT❗️ + * > При изменении функции следует вызвать команду `yarn workspace @vkontakte/vkui-docs-theme run generate:css-custom-medias`, + * > для обновления CSS файла, и закоммитить изменения. + * + * @link https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-media + * @link https://github.com/Microsoft/TypeScript-wiki/blob/main/Using-the-Compiler-API.md#a-simple-transform-function + * @link https://2ality.com/2019/10/eval-via-import.html#evaluating-simple-code-via-import() + * + */ +async function main() { + console.log('🔄 Processing...'); + + const sourceTS = fs.readFileSync(inputSourceFilePath, 'utf-8').toString(); + const { outputText: sourceJS } = ts.transpileModule(sourceTS, { + compilerOptions: { module: ts.ModuleKind.ESNext }, + }); + const { MEDIA_QUERIES } = await import( + `data:text/javascript;charset=utf-8,${encodeURIComponent(sourceJS)}` + ); + + const dataRaw = []; + + dataRaw.push('/* ⚠️ Документ сгенерирован автоматически */'); + dataRaw.push('/* 📝 Если требуются изменения, то запустите команду `yarn workspace @vkontakte/vkui-docs-theme run generate:css-custom-medias` */'); // prettier-ignore + dataRaw.push(''); + dataRaw.push('/* stylelint-disable */'); + dataRaw.push( + Object.entries(MEDIA_QUERIES) + .map(([key, value]) => { + return ['/* prettier-ignore */', `@custom-media ${key} ${value};`].join('\n'); + }) + .join('\n'), + ); + dataRaw.push(''); + + const data = dataRaw.join('\n'); + + fs.writeFileSync(outputSourceFilePath, data, 'utf-8'); + + console.log(`✅ ${outputSourceFilePath}`); +} + +void main(); diff --git a/packages/vkui-docs-theme/src/breakpoints.ts b/packages/vkui-docs-theme/src/breakpoints.ts new file mode 100644 index 00000000000..7df34b0cbd5 --- /dev/null +++ b/packages/vkui-docs-theme/src/breakpoints.ts @@ -0,0 +1,10 @@ +export const BREAKPOINTS = { + DESKTOP: 1250, + TABLET: 500, +}; + +export const MEDIA_QUERIES = { + '--view-mobile': `(max-width: ${BREAKPOINTS.TABLET - 0.1}px)`, + '--view-tablet': `(min-width: ${BREAKPOINTS.TABLET}px) and (max-width: ${BREAKPOINTS.DESKTOP - 0.1}px)`, + '--view-desktop': `(min-width: ${BREAKPOINTS.DESKTOP}px)`, +}; diff --git a/packages/vkui-docs-theme/src/components/Anchor.tsx b/packages/vkui-docs-theme/src/components/Anchor.tsx new file mode 100644 index 00000000000..77581dac34c --- /dev/null +++ b/packages/vkui-docs-theme/src/components/Anchor.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { type LinkProps, Link as VKUILink } from '@vkontakte/vkui'; +import NextLink from 'next/link'; + +const EXTERNAL_HREF_REGEX = /https?:\/\//; + +const Link = React.forwardRef((props, ref) => ( + +)); +Link.displayName = 'VKUILinkWithRef'; + +export function Anchor({ href = '', children, ...props }: LinkProps) { + const newWindow = EXTERNAL_HREF_REGEX.test(href); + + if (newWindow) { + return ( + + {children} + + ); + } + + return ( + + {children} + + ); +} diff --git a/packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.module.css b/packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.module.css new file mode 100644 index 00000000000..2f919d9ad4e --- /dev/null +++ b/packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.module.css @@ -0,0 +1,25 @@ +.root { + display: flex; + align-items: center; + justify-content: flex-start; +} + +/* stylelint-disable-next-line selector-max-universal */ +.root > .item:not(:last-child), +.root > .icon { + margin-inline-end: 4px; +} + +.item { + color: var(--vkui--color_text_secondary); + + --vkui--color_text_link: var(--vkui--color_text_secondary); +} + +.icon { + color: var(--vkui--color_icon_secondary); +} + +.activeItem { + color: var(--vkui--color_text_primary); +} diff --git a/packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.tsx b/packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.tsx new file mode 100644 index 00000000000..6fc07ae3eda --- /dev/null +++ b/packages/vkui-docs-theme/src/components/Breadcrumbs/Breadcrumbs.tsx @@ -0,0 +1,26 @@ +import { Fragment } from 'react'; +import { Icon12ChevronOutline } from '@vkontakte/icons'; +import { classNames, Footnote } from '@vkontakte/vkui'; +import type { Item } from 'nextra/normalize-pages'; +import { Anchor } from '../Anchor'; +import styles from './Breadcrumbs.module.css'; + +export function Breadcrumbs({ activePath }: { activePath: Item[] }) { + return ( +
+ {activePath.map((item, index) => { + const isLink = !item.children || item.withIndexPage; + const isActive = index === activePath.length - 1; + + return ( + + {index > 0 && } + + {isLink && !isActive ? {item.title} : item.title} + + + ); + })} +
+ ); +} diff --git a/packages/vkui-docs-theme/src/components/ColorSchemeSwitch.tsx b/packages/vkui-docs-theme/src/components/ColorSchemeSwitch.tsx new file mode 100644 index 00000000000..982a167c7c4 --- /dev/null +++ b/packages/vkui-docs-theme/src/components/ColorSchemeSwitch.tsx @@ -0,0 +1,33 @@ +import { Icon20MoonOutline, Icon20SunOutline } from '@vkontakte/icons'; +import { AdaptivityProvider, SegmentedControl, Skeleton } from '@vkontakte/vkui'; +import { useMounted } from 'nextra/hooks'; +import { useColorScheme } from '../contexts'; + +const options = [ + { 'value': 'light', 'label': , 'aria-label': 'Переключить на светлую тему' }, + { 'value': 'dark', 'label': , 'aria-label': 'Переключить на тёмную тему' }, +]; + +const SWITCH_WIDTH = 94; + +export function ColorSchemeSwitch() { + const { setColorScheme, resolvedColorScheme } = useColorScheme(); + const mounted = useMounted(); + + if (!mounted) { + return ; + } + + return ( + + + + ); +} diff --git a/packages/vkui-docs-theme/src/components/Head.tsx b/packages/vkui-docs-theme/src/components/Head.tsx new file mode 100644 index 00000000000..c2ec36f0709 --- /dev/null +++ b/packages/vkui-docs-theme/src/components/Head.tsx @@ -0,0 +1,29 @@ +import NextHead from 'next/head'; +import { useMounted } from 'nextra/hooks'; +import { useColorScheme, useThemeConfig } from '../contexts'; + +export function Head() { + const themeConfig = useThemeConfig(); + const { resolvedColorScheme } = useColorScheme(); + const mounted = useMounted(); + + const head = typeof themeConfig.head === 'function' ? themeConfig.head({}) : themeConfig.head; + + return ( + + {mounted ? ( + + ) : ( + <> + + + + )} + + {head} + + ); +} diff --git a/packages/vkui-docs-theme/src/components/NavLinks/NavLinks.module.css b/packages/vkui-docs-theme/src/components/NavLinks/NavLinks.module.css new file mode 100644 index 00000000000..5a140d8f969 --- /dev/null +++ b/packages/vkui-docs-theme/src/components/NavLinks/NavLinks.module.css @@ -0,0 +1,38 @@ +.root { + display: flex; + align-items: center; + padding-block-start: var(--vkui--spacing_size_4xl); + border-block-start: 1px solid var(--vkui_docs--color_stroke_separator_secondary); + margin-block-start: 56px; +} + +.navLinkItem { + display: flex; + flex-direction: column; + color: var(--vkui--color_text_subhead); + align-items: flex-end; + padding-block: var(--vkui--spacing_size_m); + padding-inline: var(--vkui--spacing_size_xl); + text-decoration: none; +} + +.navLink { + margin-block-start: var(--vkui--spacing_size_s); + display: flex; + align-items: center; + justify-content: flex-end; + color: var(--vkui--color_text_primary); +} + +.navLinkItemNext { + margin-inline-start: auto; + align-items: flex-start; +} + +.navLinkPrevIcon { + margin-inline-end: var(--vkui--spacing_size_m); +} + +.navLinkNextIcon { + margin-inline-start: var(--vkui--spacing_size_m); +} diff --git a/packages/vkui-docs-theme/src/components/NavLinks/NavLinks.tsx b/packages/vkui-docs-theme/src/components/NavLinks/NavLinks.tsx new file mode 100644 index 00000000000..2212cbc7358 --- /dev/null +++ b/packages/vkui-docs-theme/src/components/NavLinks/NavLinks.tsx @@ -0,0 +1,69 @@ +import * as React from 'react'; +import { Icon16ChevronLeft, Icon16ChevronOutline } from '@vkontakte/icons'; +import { classNames } from '@vkontakte/vkjs'; +import { Footnote, Headline, Tappable } from '@vkontakte/vkui'; +import NextLink from 'next/link'; +import type { Item } from 'nextra/normalize-pages'; +import { useThemeConfig } from '../../contexts'; +import styles from './NavLinks.module.css'; + +interface NavLinkProps { + currentIndex: number; + flatDirectories: Item[]; +} + +interface NavLinkItemProps { + route: string; + children: React.ReactNode; + className?: string; + type?: 'prev' | 'next'; +} + +function NavLinkItem({ type = 'prev', route, children, className }: NavLinkItemProps) { + return ( + + {type === 'next' ? 'Следующая' : 'Предыдущая'} +
{children}
+
+ ); +} + +export function NavLinks({ flatDirectories, currentIndex }: NavLinkProps) { + const themeConfig = useThemeConfig(); + const nav = themeConfig.navigation; + const navigation = typeof nav === 'boolean' ? { prev: nav, next: nav } : nav; + let prev = navigation.prev && flatDirectories[currentIndex - 1]; + let next = navigation.next && flatDirectories[currentIndex + 1]; + + if (prev && !prev.isUnderCurrentDocsTree) { + prev = false; + } + if (next && !next.isUnderCurrentDocsTree) { + next = false; + } + + if (!prev && !next) { + return null; + } + + return ( +
+ {prev && ( + + + {prev.title} + + )} + {next && ( + + {next.title} + + + )} +
+ ); +} diff --git a/packages/vkui-docs-theme/src/components/Navbar/Navbar.module.css b/packages/vkui-docs-theme/src/components/Navbar/Navbar.module.css new file mode 100644 index 00000000000..cbcef8d4fc6 --- /dev/null +++ b/packages/vkui-docs-theme/src/components/Navbar/Navbar.module.css @@ -0,0 +1,102 @@ +.root { + position: sticky; + inset-block-start: 0; + z-index: 20; + inline-size: 100%; + background-color: transparent; + color: var(--vkui--color_text_primary); + border-block-end: var(--vkui--size_border--regular) solid + var(--vkui_docs--color_stroke_separator_secondary); + box-shadow: 0 8px 30px 0 rgba(0, 0, 0, 0.04); +} + +.navbar { + display: flex; + margin-inline: auto; + align-items: center; + block-size: var(--vkui_docs--navbar-height); + max-inline-size: var(--vkui_docs--max-width); + justify-content: space-between; + padding-block: var(--vkui--spacing_size_xl); + padding-inline: var(--vkui--spacing_size_2xl); + background-color: var(--vkui--color_background_content); +} + +@media (--view-desktop) { + .navbar { + padding-inline: 40px; + padding-block: var(--vkui--spacing_size_4xl); + } +} + +.extraContent { + display: none; +} + +@media (--view-desktop) { + .extraContent { + display: flex; + align-items: center; + } +} + +/* stylelint-disable-next-line selector-max-universal */ +.extraContent > *:not(:first-child) { + margin-inline-start: var(--vkui--spacing_size_m); +} + +.navbarLink { + color: var(--vkui--color_text_primary); + padding-block: 8px; + padding-inline: 16px; + text-decoration: none; +} + +.navbarLink:not(:last-child) { + margin-inline-end: var(--vkui--spacing_size_m); +} + +.navbarLinkActive { + background-color: var(--vkui--color_field_background); +} + +.links { + display: none; +} + +@media (--view-desktop) { + .links { + display: flex; + block-size: 36px; + align-items: stretch; + } +} + +.separator.separator { + color: var(--vkui_docs--color_stroke_separator_secondary); + margin-inline-end: var(--vkui--spacing_size_m); +} + +.logoLink { + color: var(--vkui--color_text_primary); +} + +@media (--view-desktop) { + .menuButton { + display: none; + } +} + +.menuIcon { + box-sizing: initial; +} + +.search { + inline-size: 200px; +} + +@media (--view-mobile) { + .search { + display: none; + } +} diff --git a/packages/vkui-docs-theme/src/components/Navbar/Navbar.tsx b/packages/vkui-docs-theme/src/components/Navbar/Navbar.tsx new file mode 100644 index 00000000000..1caf51d7b2c --- /dev/null +++ b/packages/vkui-docs-theme/src/components/Navbar/Navbar.tsx @@ -0,0 +1,129 @@ +import * as React from 'react'; +import { Icon24MenuOutline } from '@vkontakte/icons'; +import { classNames } from '@vkontakte/vkjs'; +import { + ButtonGroup, + Flex, + Headline, + IconButton, + Tappable, + type TappableProps, + Separator as VKUISeparator, +} from '@vkontakte/vkui'; +import NextLink from 'next/link'; +import { useFSRoute } from 'nextra/hooks'; +import type { PageItem } from 'nextra/normalize-pages'; +import { useMenu, useThemeConfig } from '../../contexts'; +import { renderComponent } from '../../helpers/render'; +import { type DocsThemeConfig } from '../../types'; +import { ColorSchemeSwitch } from '../ColorSchemeSwitch'; +import { ProjectButton } from '../ProjectButton'; +import styles from './Navbar.module.css'; + +export type NavbarProps = { + items: PageItem[]; +}; + +export function Navbar({ items }: NavbarProps): React.ReactElement { + const themeConfig = useThemeConfig(); + const activeRoute = useFSRoute(); + const { setMenu } = useMenu(); + + return ( +
+ +
+ ); +} + +function NavBarLink({ + title, + newWindow, + ...restProps +}: TappableProps & { title: PageItem['title']; newWindow?: boolean }) { + return ( + + {title} + + ); +} + +function Logo({ logo, logoLink }: Pick) { + return ( + + {renderComponent(logo)} + + ); +} + +function Separator() { + return ; +} diff --git a/packages/vkui-docs-theme/src/components/ProjectButton.tsx b/packages/vkui-docs-theme/src/components/ProjectButton.tsx new file mode 100644 index 00000000000..0d837ac5585 --- /dev/null +++ b/packages/vkui-docs-theme/src/components/ProjectButton.tsx @@ -0,0 +1,16 @@ +import { Button } from '@vkontakte/vkui'; +import { type DocsThemeConfig } from '../types'; + +export function ProjectButton({ icon, link }: Pick['project']) { + return ( +