diff --git a/packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.module.css b/packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.module.css new file mode 100644 index 0000000000..69c9056313 --- /dev/null +++ b/packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.module.css @@ -0,0 +1,4 @@ +.icon { + padding-inline: var(--vkui--spacing_size_xs); + padding-block: var(--vkui--spacing_size_s); +} diff --git a/packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.tsx b/packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.tsx index c8ccad2334..51c9a11d67 100644 --- a/packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.tsx +++ b/packages/vkui-docs-theme/src/components/Sidebar/Accordion/Accordion.tsx @@ -9,23 +9,29 @@ import { Accordion as VKUIAccordion, type AccordionProps as VKUIAccordionProps, } from '@vkontakte/vkui'; +import styles from './Accordion.module.css'; export interface AccordionProps extends Omit { expanded: VKUIAccordionProps['expanded']; - onChange?: VKUIAccordionProps['onChange']; + onChange: (e?: React.MouseEvent, toggle?: boolean) => void; children?: React.ReactNode; icon?: React.ReactNode; className?: string; title: string; } +interface AccordionSummaryProps + extends Pick, + Pick {} + function AccordionSummary({ title, className, icon: Icon, + onChange, ...restProps -}: Pick) { - const { expanded, labelId, contentId, onChange } = React.useContext(AccordionContext); +}: AccordionSummaryProps) { + const { expanded, labelId, contentId } = React.useContext(AccordionContext); return ( onChange(!expanded)} + onClick={onChange} {...restProps} > {Icon} {title} - {expanded ? : } + onChange(e, true)}> + {expanded ? : } + ); } export function Accordion({ expanded = false, children, onChange, ...restProps }: AccordionProps) { return ( - - + + {children} ); diff --git a/packages/vkui-docs-theme/src/components/Sidebar/Menu/Menu.tsx b/packages/vkui-docs-theme/src/components/Sidebar/Menu/Menu.tsx index f45bfd8a39..5e0a0b613d 100644 --- a/packages/vkui-docs-theme/src/components/Sidebar/Menu/Menu.tsx +++ b/packages/vkui-docs-theme/src/components/Sidebar/Menu/Menu.tsx @@ -64,9 +64,13 @@ function Folder({ item, icon }: FolderProps) { ), icon: icon && , expanded: open, - onChange: () => { + onChange: (e, toggle) => { + if (toggle) { + e?.preventDefault(); + e?.stopPropagation(); + } if (isLink) { - if (active) { + if (active || toggle) { // eslint-disable-next-line react-compiler/react-compiler TreeState[item.route] = !open; } else { diff --git a/packages/vkui-docs-theme/src/mdx/Code/Code.module.css b/packages/vkui-docs-theme/src/mdx/Code/Code.module.css index 5c7d6a37b9..a2d74ef07d 100644 --- a/packages/vkui-docs-theme/src/mdx/Code/Code.module.css +++ b/packages/vkui-docs-theme/src/mdx/Code/Code.module.css @@ -30,3 +30,13 @@ pre .root { /* stylelint-disable-next-line csstools/value-no-unknown-custom-properties */ color: var(--shiki-dark); } + +/* stylelint-disable-next-line selector-max-type */ +.root > span[data-highlighted-line] { + background-color: rgba(125, 125, 218, 0.1); +} + +/* stylelint-disable-next-line selector-max-universal,selector-max-type */ +.root > span[data-highlighted-line]:is(html[class~='vkui--vkBase--dark'] *) { + background-color: rgba(90, 90, 197, 0.1); +} diff --git a/packages/vkui-docs-theme/src/mdx/index.module.css b/packages/vkui-docs-theme/src/mdx/index.module.css index ef5784a0db..b668182946 100644 --- a/packages/vkui-docs-theme/src/mdx/index.module.css +++ b/packages/vkui-docs-theme/src/mdx/index.module.css @@ -15,6 +15,11 @@ padding-inline: var(--vkui--spacing_size_3xl) 0; } +.ol { + padding-block: var(--vkui--spacing_size_2xl) 0; + padding-inline: var(--vkui--spacing_size_3xl) 0; +} + .li:not(:first-child) { margin-block-start: var(--vkui--spacing_size_xl); } diff --git a/packages/vkui-docs-theme/src/mdx/index.tsx b/packages/vkui-docs-theme/src/mdx/index.tsx index 91181d99e9..9c98f5529e 100644 --- a/packages/vkui-docs-theme/src/mdx/index.tsx +++ b/packages/vkui-docs-theme/src/mdx/index.tsx @@ -17,7 +17,7 @@ const DEFAULT_COMPONENTS: MDXComponents = { h5: (props) => , h6: (props) => , ul: (props) =>
    , - ol: (props) =>
      , + ol: (props) =>
        , li: (props) =>
      1. , blockquote: (props) =>
        , hr: (props) =>
        , diff --git a/packages/vkui-docs-theme/styles/global.css b/packages/vkui-docs-theme/styles/global.css index 2f58a3b9d0..7fc5ad9708 100644 --- a/packages/vkui-docs-theme/styles/global.css +++ b/packages/vkui-docs-theme/styles/global.css @@ -11,7 +11,6 @@ -webkit-tap-highlight-color: transparent; } -ol, ul, menu { list-style: none; diff --git a/website/pages/overview/about.mdx b/website/pages/overview/about.mdx index 778d60daac..bbccafb5dc 100644 --- a/website/pages/overview/about.mdx +++ b/website/pages/overview/about.mdx @@ -19,23 +19,26 @@ ## Об этой документации -### Основа +В верхнем навигационном меню вы можете найти ссылки на ключевые разделы - [Компоненты](/components) и [О системе](/overview/about), +а так же ссылки на документации иконок и токенов. -В этом разделе представлены концептуальные особенности библиотеки. [Режимы подключения](/overview/modes) позволяют узнать о возможностях использования -библиотеки в различных сценариях: автономном, "приложение внутри приложения" и частичном использовании компонентов. -[Структура экранов](/overview/structure) раскрывает принципы навигации в приложении, созданном на основе VKUI. +В разделе "О системе" представлены концептуальные особенности библиотеки. Справа располагается дополнительное подменю, пункты которого структурированы последовательно, начиная с базовых +концепций и заканчивая более сложными аспектами библиотеки. Мы рекомендуем следовать этой последовательности для лучшего понимания функционала **VKUI** и его возможностей. -### Компоненты +В разделе "Компоненты" можно найти все компоненты, доступные для использования, +на каждой странице представлена спецификация и интерактивный пример с возможностью редактирования кода. -В данном разделе представлены свойства и методы каждого компонента. -Практически на каждой странице этого раздела приведен живой пример с возможностью редактирования кода. +Мы надеемся, что эта документация поможет вам эффективно использовать **VKUI** и создавать лучшие пользовательские интерфейсы! -## Сообщить о проблеме +--- + +## Присоединяйтесь к развитию библиотеки [#contributing] + +**VKUI** - опенсор-проект, поэтому вы можете поучаствовать в его развитии, рассказав о найденных ошибках или предложив улучшения, +для этого достаточно создать [issue](https://github.com/VKCOM/VKUI/issues/new/choose) на Github. -Если вы столкнулись с какой‑либо ошибкой в нашей библиотеке или у вас есть предложения по её улучшению, пожалуйста, создайте [issue](https://github.com/VKCOM/VKUI/issues/new/choose). -А если у вас возникли вопросы или вы хотите обсудить особенности библиотеки более подробно, присоединяйтесь к обсуждению в ["Дискуссиях"](https://github.com/VKCOM/VKUI/discussions/categories/q-a). Мы стремимся сделать нашу библиотеку ещё лучше, всегда готовы выслушать вас и учесть ваши замечания. +Хотите внести изменение самостоятельно? Ознакомьтесь с [данным гайдом](https://github.com/VKCOM/VKUI/blob/master/docs/CONTRIBUTING.md), прежде чем делать [pull request](https://github.com/VKCOM/VKUI/pulls). -## Contributing +Если у вас возникли вопросы и вы хотите обсудить особенности библиотеки более подробно, присоединяйтесь к обсуждению в ["Дискуссиях"](https://github.com/VKCOM/VKUI/discussions/categories/q-a). -Мы очень радуемся, когда пользователи библиотеки работают над её улучшением. Для того, чтобы оставить след в -истории, сделайте форк проекта, внесите изменения и отправьте нам [pull request](https://github.com/VKCOM/VKUI/pulls). +Мы стремимся сделать нашу библиотеку ещё лучше, всегда готовы выслушать вас и учесть ваши замечания. diff --git a/website/pages/overview/adaptivity.mdx b/website/pages/overview/adaptivity.mdx index 7412f172c9..14ebdd3fd7 100644 --- a/website/pages/overview/adaptivity.mdx +++ b/website/pages/overview/adaptivity.mdx @@ -3,59 +3,60 @@ Одно из ключевых преимуществ VKUI - адаптивность. Библиотека предоставляет шаблоны для различных устройств, -а также позволяет большинству компонентов адаптировать под разные размеры. +а также позволяет большинству компонентов адаптироваться под разные размеры. Отображение кнопок, элементов форм и других компонентов зависит от наличия мыши, высоты и ширины экрана. В этой статье мы покажем, как сделать отзывчивый интерфейс. -## Шаг 1 +## Шаг 1. Обертка [`AdaptivityProvider`](#/AdaptivityProvider) -Для начала оберните ваше приложение в [`AdaptivityProvider`](#/AdaptivityProvider). - -```jsx static -import * as React from 'react'; -import { createRoot } from 'react-dom/client'; -import { ConfigProvider, AdaptivityProvider, AppRoot } from '@vkontakte/vkui'; -import '@vkontakte/vkui/dist/vkui.css'; +Для начала убедитесь, что ваше приложение обернуто в обязательный провайдер [`AdaptivityProvider`](#/AdaptivityProvider): +```jsx {4,6} function App() { return ( - ... + {/* ... */} ); } - -const container = document.getElementById('root'); -const root = createRoot(container); // createRoot(container!) if you use TypeScript -root.render(); ``` -## Шаг 2 +## Шаг 2. Добавление контента Добавьте [`SplitLayout`](#/SplitLayout) и хотя бы один [`SplitCol`](#/SplitCol). -- **SplitLayout** — компонент-обертка для отрисовки макета с - одной или несколькими колонками. +- **SplitLayout** — компонент-обертка для отрисовки макета с одной или несколькими колонками. - **SplitCol** — компонент для отрисовки колонки. -```jsx static -// ... - +```jsx {2-3,9-26} function App() { + const platform = usePlatform(); + const isVKCOM = platform === 'vkcom'; + return ( - - + + + {!isVKCOM && } + + Дополнительный контент + + - - + + + Panel Header + + Главный контент + + @@ -63,27 +64,15 @@ function App() { ); } - -const MainScreens = () => { - return ( - - Profile - - ); -}; - -const SideCol = () => { - return Navigation; -}; ``` -## Шаг 3 +## Шаг 3. Применение хука для адаптивности -Почти готово. Теперь необходимо уведомить приложение о том, что левая колонка нужна только на больших экранах. -Для этого мы должны использовать хук useAdaptivityConditionalRender в наших компонентах. +Теперь необходимо уведомить приложение о том, что левая колонка нужна только на больших экранах. +Для этого мы должны использовать хук `useAdaptivityConditionalRender` в наших компонентах. Ниже будет представлен пример использования этого хука, а затем будет дано объяснение его работы. -```jsx static +```jsx {4,8-17} function App() { const platform = usePlatform(); const isVKCOM = platform === 'vkcom'; @@ -93,29 +82,38 @@ function App() { }> {viewWidth.tabletPlus && ( - - Navigation + + {/* ... */} )} - - - Profile - + + {/* ... */} ; // ... } ``` -`useAdaptivityConditionalRender` возвращает параметры адаптивности (см. **Технические детали**), каждый из которых имеет +`useAdaptivityConditionalRender` возвращает параметры адаптивности (см. [Технические детали](#tech)), каждый из которых имеет дополнительную мета-информацию. В зависимости от того, что мы передали в `AdaptivityProvider`, значение у каждого отдельного параметра адаптивности может быть двух типов: - `false` – мы строго задали какой-то из параметров адаптивности в `AdaptivityProvider`. + +Например, при `` значение `viewWidth.tabletPlus` будет `false`, +т.к. мы говорим, что у нас всегда мобильный вид. + + - `{ className: string }` – CSS селектор, который на основе CSS Media Query будет переключать видимость вашего элемента. В данном случае в `AdaptivityProvider` не передавали соответствующий параметр адаптивности. + +При значение `{ className: "..." }` видимость элемента управляется через `display: none` – отсюда можно сделать вывод, +что элемент будет всегда рендерится как в **Virtual DOM**, так и в **DOM**. + + + ## Требования для адаптивности - Свойство `SplitLayout.header` нужно для создания сквозной шапки, когда интерфейс состоит из нескольких колонок (или одной центрированной) @@ -161,7 +159,7 @@ const App = () => { В нашем примере внутри `` и `` используется `useAdaptivityWithJSMediaQueries()` для переключения компонентов на мобильный или десктопный виды. -## Технические детали +## Технические детали [#tech] Адаптивность базируется на четырёх свойствах: diff --git a/website/pages/overview/advanced/_meta.tsx b/website/pages/overview/advanced/_meta.tsx new file mode 100644 index 0000000000..7153e3d7b4 --- /dev/null +++ b/website/pages/overview/advanced/_meta.tsx @@ -0,0 +1,17 @@ +export default { + 'helpers': { + title: 'Утилиты', + }, + 'unstable': { + title: 'Нестабильные компоненты', + }, + 'css-modules': { + title: 'CSS Modules', + }, + 'customize': { + title: 'Кастомизация', + }, + 'ssr': { + title: 'Серверный рендеринг', + }, +}; diff --git a/website/pages/overview/advanced/css-modules.mdx b/website/pages/overview/advanced/css-modules.mdx new file mode 100644 index 0000000000..cd8a8f0ccd --- /dev/null +++ b/website/pages/overview/advanced/css-modules.mdx @@ -0,0 +1,106 @@ + +# CSS Modules + +VKUI позволяет подключить специальную версию c [**CSS Modules**](https://github.com/css-modules/css-modules) и **ESNext**. +Сборка позволяет уменьшить размер приложения, однако для её использования необходимо дополнительно настроить сборщики. + + + +## Инструкция + +## Шаг 1. Подключение стилей + +Удалите импорт `vkui.css` и подключите дефолтные темы: + +```diff +- import "@vkontakte/vkui/dist/vkui.css"; ++ import "@vkontakte/vkui/dist/cssm/styles/themes.css"; +``` + +Если вы используете [кастомные темы](#/Customize), то необходимо просто удалить `components.css`: + +```diff +- import '@vkontakte/vkui/dist/components.css'; +import '@vkontakte/vkui-tokens/themes/vkCom/cssVars/declarations/onlyVariables.css'; +import '@vkontakte/vkui-tokens/themes/vkComDark/cssVars/declarations/onlyVariablesLocal.css'; +``` + +## Шаг 2. Конфигурация сборщиков + +Дальше необходимо трансформировать импорт, включить транспиляцию и подключить CSS modules. + +### Next.js + +```js filename="next.config.js" +module.exports = { + // ... + + // Включаем транспиляцию + transpilePackages: ['@vkontakte/vkui'], + + // Трансформируем импорты + modularizeImports: { + '@vkontakte/vkui': { + transform: '@vkontakte/vkui/dist/cssm', + skipDefaultConversion: true, + }, + }, +}; +``` + +[Пример приложения](https://codesandbox.io/p/sandbox/vkui-next-js-cssm-el0g7c) на Next.js + +### Vite + +```js filename="vite.config.js" +export default defineConfig({ + // ... + resolve: { + alias: [{ find: /^@vkontakte\/vkui$/, replacement: '@vkontakte/vkui/dist/cssm' }], + }, +}); +``` + +[Пример приложения](https://codesandbox.io/p/sandbox/vkui-vite-cssm-4iikku) на Vite + +### webpack + +```js filename="webpack.config.js" +module.exports = { + //... + + module: { + rules: [ + // Включаем транспиляцию + { + test: /\.js$/, + include: /node_modules\/@vkontakte\/vkui/, + use: ['babel-loader'], + }, + + // Обрабатываем css modules + { + test: /\.css$/, + include: /node_modules\/@vkontakte\/vkui/, + use: [ + { + loader: 'css-loader', + /* Используем следующие опции в случае использования `css-loader >= 7.0.0` (см. https://github.com/webpack-contrib/css-loader/blob/v7.1.0/CHANGELOG.md) */ + // options: { + // namedExport: false, + // exportLocalsConvention: 'as-is', + // } + }, + ], + }, + ], + }, + + // Трансформируем импорты + resolve: { + alias: { + '@vkontakte/vkui$': '@vkontakte/vkui/dist/cssm', + }, + }, +}; +``` diff --git a/website/pages/overview/advanced/customize.mdx b/website/pages/overview/advanced/customize.mdx new file mode 100644 index 0000000000..dad904fc5d --- /dev/null +++ b/website/pages/overview/advanced/customize.mdx @@ -0,0 +1,156 @@ + +# Кастомизация + +Здесь вы найдете информацию по кастомизации ваших приложений в зависимости от платформы и темы. + + + + + Прежде чем изучать этот документ, убедитесь, что вы были ознакомлены со страницей [Платформы и + темы](#/PlatformsAndThemes). + + +--- + +Чтобы переопределять цвета, размеры, отступы, типографику, скругления и тени, **VKUI** предоставляет +два API: + +1. свойства отдельных компонентов (например, `size`, `appearance`, `borderRadius` и т.п.); +2. переопределение темы — или значений CSS-переменных из [@vkontakte/vkui-tokens](https://github.com/VKCOM/vkui-tokens). + +Здесь мы рассматриваем второй способ. + + +**Дисклеймер** + +Внутренняя реализация компонентов, включая их классы — не публичное API **VKUI** и может +измениться в любой момент без предупреждения. Не привязывайтесь к ней, если хотите сохранить +возможность без проблем обновляться на новые версии библиотеки. + + + +## Использование своей темы + +В первую очередь вам нужно поправить импорт стилей: + +```diff +- import '@vkontakte/vkui/dist/vkui.css'; ++ import '@vkontakte/vkui/dist/components.css'; +``` + +Так вы отключите темы по умолчанию из [@vkontakte/vkui-tokens](https://github.com/VKCOM/vkui-tokens). + +Далее находите в [@vkontakte/vkui-tokens](https://github.com/VKCOM/vkui-tokens) нужную вам тему или +создаете свою. CSS-класс, под которым будут собраны токены, передайте в свойство `tokensClassNames` +компонента [ConfigProvider](#/ConfigProvider). Переопределить тему можно либо [глобально](#global), +либо для [конкретной платформы](#specific). + +### Глобально [#global] + +Если выбрали тему из [@vkontakte/vkui-tokens](https://github.com/VKCOM/vkui-tokens): + +```jsx {3-4,8-11} +import { ConfigProvider, AppRoot, Button } from '@vkontakte/vkui'; +import '@vkontakte/vkui/dist/components.css'; +import '@vkontakte/vkui-tokens/themes/paradigmBase/cssVars/declarations/onlyVariables.css'; +import '@vkontakte/vkui-tokens/themes/paradigmBaseDark/cssVars/declarations/onlyVariablesLocal.css'; + +ReactDOM.render( + + + + , + ), + ); +}); + +server.listen(3000); +``` diff --git a/website/pages/overview/advanced/unstable.mdx b/website/pages/overview/advanced/unstable.mdx new file mode 100644 index 0000000000..219ffa07cd --- /dev/null +++ b/website/pages/overview/advanced/unstable.mdx @@ -0,0 +1,18 @@ + +# Нестабильные компоненты + +В некоторых компонентах возникает потребность до того, как появится полноценное описание их работы. +Бывает, что дизайн не финализирован, или не до конца ясно, что может и что не может делать компонент. +Для таких случаев используется приставка `unstable_`. + + + +Нестабильные компоненты могут менять внешнее API в пределах одной мажорной версии. То есть при их использовании нужно +учитывать, что после очередного обновления минорной или патч-версии, в вашем приложении может возникнуть ошибка. +Разумеется, эти изменения будут описаны в [release notes](https://github.com/VKCOM/VKUI/releases). + +Подключаются нестабильные компоненты путем подобного импорта: + +```jsx +import { unstable_ChipsSelect as ChipsSelect } from '@vkontakte/vkui'; +``` diff --git a/website/pages/overview/integrations/_meta.tsx b/website/pages/overview/integrations/_meta.tsx new file mode 100644 index 0000000000..58e6e48fc9 --- /dev/null +++ b/website/pages/overview/integrations/_meta.tsx @@ -0,0 +1,11 @@ +export default { + 'vk-mini-apps': { + title: 'VK Mini Apps', + }, + 'icons': { + title: 'Иконки', + }, + 'design': { + title: 'Дизайн', + }, +}; diff --git a/website/pages/overview/integrations/design.mdx b/website/pages/overview/integrations/design.mdx new file mode 100644 index 0000000000..22027ea300 --- /dev/null +++ b/website/pages/overview/integrations/design.mdx @@ -0,0 +1,12 @@ + +# Figma + +Библиотека основана на [дизайн-системе ВКонтакте](https://www.figma.com/@vk) и реализует её интерфейсы для различных платформ. + + + +На странице [VK в Figma Community](https://www.figma.com/@vk) доступны четыре библиотеки: + +- VKUI Base Library — базовая библиотека, содержащая более 650 иконок и все цветовые токены для светлой и тёмной темы (в виде стилей); +- VKUI iOS Library и VKUI Android Library — библиотеки компонентов для iOS и Android, собранные на токенах из Base Library, а также шаблоны готовых экранов; +- VKUI Color Palette — палитра цветов из приложений ВКонтакте, на которых собраны цветовые токены. diff --git a/website/pages/overview/integrations/icons.mdx b/website/pages/overview/integrations/icons.mdx new file mode 100644 index 0000000000..82b02b1153 --- /dev/null +++ b/website/pages/overview/integrations/icons.mdx @@ -0,0 +1,36 @@ + +# Иконки + +Иконки хранятся отдельно в пакете `@vkontakte/icons`. У пакета есть +отдельная [документация с полным списком иконок](https://vkcom.github.io/icons). +Сама библиотека использует иконки в качестве зависимости для некоторых компонентов. + + + +## Дедупликация + +Если вы столкнулись с дублированием зависимостей, вам необходимо произвести дедупликацию: + +**npm - [npm dedupe](https://docs.npmjs.com/cli/v6/commands/npm-dedupe)** + +```sh +npm dedupe +``` + +**Yarn Classic - [yarn-deduplicate](https://www.npmjs.com/package/yarn-deduplicate)** + +```sh +npx yarn-deduplicate --packages @vkontakte/icons +``` + +**Yarn Modern - [yarn dedupe](https://yarnpkg.com/cli/dedupe)** + +```sh +yarn dedupe @vkontakte/icons +``` + +**pnpm - [pnpm dedupe](https://pnpm.io/cli/dedupe)** + +```sh +pnpm dedupe +``` diff --git a/website/pages/overview/integrations.mdx b/website/pages/overview/integrations/vk-mini-apps.mdx similarity index 82% rename from website/pages/overview/integrations.mdx rename to website/pages/overview/integrations/vk-mini-apps.mdx index 1a27de8de4..f4ffb4cbb3 100644 --- a/website/pages/overview/integrations.mdx +++ b/website/pages/overview/integrations/vk-mini-apps.mdx @@ -1,7 +1,25 @@ + +# VK Mini Apps + +[VK Mini Apps](https://vk.com/miniapps) – это кроссплатформенные мини-приложения в экосистеме социальной сети [ВКонтакте](https://vk.com/). +При создании VKUI изначально задумывался как набор компонентов для таких приложений. Несмотря на то, +что с течением времени VKUI стал использоваться не только для мини-приложений, но по-прежнему отлично подходит и для них. +Ниже приведены рекомендации по интеграции с VK Mini Apps. + + + + + Про саму разработку **VK Mini Apps** читайте [статью "Мини-приложения" на портале VK для + разработчиков](https://dev.vk.com/mini-apps/overview). + + ## Конфигурация VKUI -> Советуем использовать шаблон [`@vkontakte/create-vk-mini-app`](https://github.com/VKCOM/create-vk-mini-app). -> В нем конфигурация, описанная ниже, есть по умолчанию. + + Советуем использовать шаблон + [`@vkontakte/create-vk-mini-app`](https://github.com/VKCOM/create-vk-mini-app). В нем + конфигурация, описанная ниже, есть по умолчанию. + Для начала устанавливаем библиотеки: @@ -14,9 +32,9 @@ yarn add @vkontakte/vk-bridge @vkontakte/vk-bridge-react ``` Далее подписываемся на изменения из **VK Bridge**. Для этого используем готовые хуки из -[`@vkontakte/vk-bridge-react`](https://www.npmjs.com/package/@vkontakte/vk-bridge). +[`@vkontakte/vk-bridge-react`](https://www.npmjs.com/package/@vkontakte/vk-bridge): -```tsx static +```tsx filename="App.tsx" import * as React from 'react'; import { createRoot } from 'react-dom/client'; import vkBridge, { parseURLSearchParamsForGetLaunchParams } from '@vkontakte/vk-bridge'; @@ -29,14 +47,14 @@ import { App } from './App'; vkBridge.send('VKWebAppInit'); const Root = () => { - const vkBridgeAppearance = useAppearance() || undefined; // Вместо undefined можно задать значение по умолчанию + const vkBridgeColorScheme = useAppearance() || undefined; // Вместо undefined можно задать значение по умолчанию const vkBridgeInsets = useInsets() || undefined; // Вместо undefined можно задать значение по умолчанию const vkBridgeAdaptivityProps = transformVKBridgeAdaptivity(useAdaptivity()); // Конвертируем значения из VK Bridge в параметры AdaptivityProvider const { vk_platform } = parseURLSearchParamsForGetLaunchParams(window.location.search); // [опционально] Платформа может передаваться через URL (см. https://dev.vk.com/mini-apps/development/launch-params#vk_platform) return ( ); ``` -Файл `./transformers/transformVKBridgeAdaptivity.ts` - -```ts static +```ts filename="./transformers/transformVKBridgeAdaptivity.ts" import { type AdaptivityProps, getViewWidthByViewportWidth, @@ -104,13 +120,13 @@ export const transformVKBridgeAdaptivity = ({ [`PanelHeaderBack`](#/PanelHeaderBack)) на тех экранах, где тот требуется. -> _Правый верхний угол_ [`PanelHeader`](#/PanelHeader) зарезервирован для -> нативного бара с кнопками управления мини-приложением, поэтому не рекомендуем использовать -> параметр `after`. -> -> Чтобы автоматически скрывать `after` у [`PanelHeader`](#/PanelHeader), -> в [`ConfigProvider`](#/ConfigProvider) есть параметр -> `hasCustomPanelHeaderAfter`. + +_Правый верхний угол_ [`PanelHeader`](#/PanelHeader) зарезервирован для нативного бара с кнопками управления мини-приложением, +поэтому не рекомендуем использовать параметр `after`. + +Чтобы автоматически скрывать `after` у [`PanelHeader`](#/PanelHeader), в [`ConfigProvider`](#/ConfigProvider) есть параметр `hasCustomPanelHeaderAfter`. + + ### [`View`](#/View) @@ -126,7 +142,7 @@ export const transformVKBridgeAdaptivity = ({ первую панель и событие [`VKWebAppDisableSwipeBack`](https://dev.vk.com/bridge/VKWebAppDisableSwipeBack) при переходе на любую другую. -```tsx static +```tsx {15,17} import vkBridge from '@vkontakte/vk-bridge'; const SomeViews = () => { @@ -159,12 +175,15 @@ const SomeViews = () => { }; ``` + На устройствах с Android нажатие кнопки **Назад** вызывает в WebView событие [history.back](https://developer.mozilla.org/ru/docs/Web/API/Window/history). По нажатию этой кнопки официальное приложение сделает возврат на предыдущую страницу вашего приложения или закроет его, если вернуться невозможно. Поэтому для корректной навигации вы должны обрабатывать нажатие аппаратной клавиши в мини-приложении и реализовывать роутинг. Сделать это можно, например, при помощи библиотеки `react-router`. + + ## Виброотклик (Taptic Engine) Для улучшения пользовательского опыта при взаимодействии с вашим мини-приложением в **VK Bridge** @@ -177,7 +196,7 @@ const SomeViews = () => { Виброотликом можно воспользоваться, например, при использовании компонента [`PullToRefresh`](#/PullToRefresh) на `onRefresh`. -```tsx static +```tsx {2,13} import * as React from 'react'; import { runTapticImpactOccurred } from '@vkontakte/vk-bridge-react'; diff --git a/website/pages/overview/platforms-and-themes.mdx b/website/pages/overview/platforms-and-themes.mdx index 0e16ee674e..13347a9ad8 100644 --- a/website/pages/overview/platforms-and-themes.mdx +++ b/website/pages/overview/platforms-and-themes.mdx @@ -2,7 +2,7 @@ # Платформы и темы Одна из особенностей VKUI — это способность мимикрировать под дизайны и поведение разных платформ. -Она позволяет создавать интерфейсы, которые неотличимы от нативных. +Благодаря ей вы можете расширять функционал интерфейсами, которые неотличимы от нативных. @@ -14,10 +14,10 @@ Передавать платформу в `ConfigProvider` необязательно, т.к. она по умолчанию определяется автоматически. -Для ручного определения вы можете передать в компонент [`ConfigProvider`](#/ConfigProvider) свойство -`platform` с нужной платформой. Пример: +Для ручного определения или форсирования платформы вы можете передать в компонент [`ConfigProvider`](#/ConfigProvider) свойство +`platform` с нужным значением: -```jsx +```jsx {1} @@ -30,13 +30,13 @@ Или, если вам необходимо переопределить платформу точечно для отдельных компонентов приложения, то вы можете сделать это с помощью `PlatformProvider`. -```jsx static +```jsx {1,3} Поделиться ``` -Чтобы получить значение текущей платформы, используйте хук `usePlatform` или HOC `withPlatform`. +Чтобы получить значение текущей платформы, используйте хук `usePlatform`. Подробнее об этих инструментах можно прочитать на странице [Утилиты](#/Utils). ### О `vkcom` [#vkcom] @@ -62,17 +62,17 @@ ### Режимы [#modes] Каждая тема обычно поддерживает как светлый (англ. `light`), так и тёмный (англ. `dark`) режим. -За его определение отвечает свойство `appearance`, и также как `platform`, по умолчанию, определяется +За его определение отвечает свойство `colorScheme`, и также как `platform`, по умолчанию, определяется автоматически за счёт CSS медиа выражения [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme). Ручное определение будет выглядеть так: -```jsx static +```jsx {5} import { ConfigProvider, AdaptivityProvider, AppRoot, SimpleCell } from '@vkontakte/vkui'; import '@vkontakte/vkui/dist/vkui.css'; ReactDOM.render( - + Темным-темно @@ -84,22 +84,55 @@ ReactDOM.render( ``` Если вы хотите переопределить режим для отдельных компонентов приложения, воспользуйтесь -`AppearanceProvider`. +`ColorSchemeProvider`. Убедитесь, что потомок `AppearanceProvider` принимает свойство `className`, +иначе переопределить тему не получится. -```jsx static - +```jsx {1} + Поделиться - + ``` -Чтобы получить значение текущего режима, используйте хук `useAppearance`. Может пригодиться для -замены изображений на инвертированную версию в темных темах. Пример: +Чтобы получить значение текущего режима, используйте хук `useColorScheme`. +Это может пригодиться для замены изображений на инвертированную версию в темных темах. Пример: -```jsx static -const appearance = useAppearance(); -
        {appearance === 'light' ? 'Out of the blue' : 'And into the black'}
        ; +```jsx +const colorScheme = useColorScheme(); +
        {colorScheme === 'light' ? 'Out of the blue' : 'And into the black'}
        ; ``` + + +Стоит иметь ввиду, что некоторые компоненты делегируют цвет фона родителю выше. +Например, это компонент [Cell](#/Cell) и его производные. + +На примере [SimpleCell](#/SimpleCell) рассмотрим решение проблемы через допустимое определение +фона посредством `className` или `style`: + +```jsx +Настройка тем}> + }>Системная тема + + } + style={{ backgroundColor: 'var(--vkui--color_background_content)' }} + > + Тёмная тема + + + + } + style={{ backgroundColor: 'var(--vkui--color_background_content)' }} + > + Светлая тема + + + +``` + + + ### [@vkontakte/vkui-tokens](https://github.com/VKCOM/vkui-tokens) **VKUI** использует пакет `@vkontakte/vkui-tokens`, который предоставляет готовые наборы **дизайн-токенов**. @@ -123,4 +156,4 @@ const appearance = useAppearance(); ### Переопределение темы -См. страницу [Кастомизация](#/Customize). +См. страницу [Кастомизация](/overview/advanced/customize). diff --git a/website/pages/overview/quick-start.mdx b/website/pages/overview/quick-start.mdx index f5d17e9e61..08e6d786d2 100644 --- a/website/pages/overview/quick-start.mdx +++ b/website/pages/overview/quick-start.mdx @@ -5,15 +5,19 @@ -## Шаг 1 + + Если вы разработчик мини-приложений Вконтакте, используйте [библиотеку + `create-vk-mini-app`](https://www.npmjs.com/package/@vkontakte/create-vk-mini-app) и переходите + сразу к [шагу 3](#step3). + -Подготовьте [SPA React приложение](https://ru.reactjs.org/docs/create-a-new-react-app.html). Вы можете использовать любые шаблоны и сборщики, в том числе и Create React App. -Обратите внимание, что VKUI поддерживает Typescript. +## Шаг 1. Подготовьте [SPA React приложение](https://ru.reactjs.org/docs/create-a-new-react-app.html) [#step1] -## Шаг 2 +Вы можете использовать любые шаблоны и сборщики, в том числе [Next.js](https://nextjs.org/) или [Vite](https://vite.dev/). Обратите внимание, что **VKUI** поддерживает Typescript. -Если вы используете [библиотеку `create-vk-mini-app`](https://www.npmjs.com/package/@vkontakte/create-vk-mini-app), отдельно подключать VKUI не нужно. Переходите сразу к шагу 3. -Если нет, то установите необходимые пакеты. Для этого воспользуйтесь одной из команд: +## Шаг 2. Подключите @vkontakte/vkui [#step2] + +Установите библиотеку, воспользовавшись нужной командой в соответствии с вашим пакетным менеджером: ```sh # npm @@ -24,9 +28,10 @@ yarn add @vkontakte/vkui pnpm add @vkontakte/vkui ``` -## Шаг 3 +## Шаг 3. Настройте meta-тэг [#step3] -Добавьте тег viewport для корректного отображения интерфейса на безрамочных смартфонах (подробнее см. в статье ["The Notch" and CSS](https://css-tricks.com/the-notch-and-css/)). +Для корректного отображения интерфейса на безрамочных смартфонах (подробнее см. в статье ["The Notch" and CSS](https://css-tricks.com/the-notch-and-css/)), +необходимо добавить [meta-тэг](https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag) в корневой `html`: ```html ``` -## Шаг 4 +- если вы используете Create React App, то инструкцию, как это можно сделать, ищите на [данной странице](https://create-react-app.dev/docs/title-and-meta-tags/). +- если вы используете Vite, воспользуйтесь [этой инструкцией](https://vite.dev/guide/#index-html-and-project-root) +- если вы используете Next.js, то ориентируйтесь на [эту страницу](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) -Соберите базовый app shell для VKUI. +## Шаг 4. Соберите базовое приложение [#step4] -```js copy -import * as React from 'react'; -import { createRoot } from 'react-dom/client'; +Найдите корневой файл, в котором инициализируется ваше приложение. Обычно это `App.tsx` (`pages/_app.tsx` для Next.js), +ориентируйтесь на выбранный шаблон или сборщик. +Вставьте следующий программный код в найденный файл: + +```js import { AdaptivityProvider, ConfigProvider, @@ -54,42 +63,59 @@ import { Header, Group, SimpleCell, + usePlatform, } from '@vkontakte/vkui'; import '@vkontakte/vkui/dist/vkui.css'; -const App = () => { +export default function App() { const platform = usePlatform(); return ( - - }> - - - - VKUI - Items}> - Hello - World - - - - - - + + + + }> + + + + VKUI + Items}> + Hello + World + + + + + + + + ); -}; +} +``` + +Если вы собираете приложение без использования каких-нибудь шаблонов или сборщиков, не забудьте +отрендерить ваш компонент, добавив следующие строки: +```js +// добавить в блок с импортами +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; + +// добавить в конце файла const container = document.getElementById('root'); const root = createRoot(container); // createRoot(container!) if you use TypeScript -root.render( - - - - - , -); +root.render(); ``` + +**Обратите внимание** + +Обертки `ConfigProvider`, `AdaptivityProvider` и `AppRoot` обязательны для приложения, +остальная структура остается на ваше усмотрение. + + + ## Ваше приложение готово! -Теперь можно добавлять более сложные компоненты, новые экраны и настроить переходы между ними. +Теперь можно добавлять более сложные компоненты, новые экраны и настраивать переходы между ними. diff --git a/website/pages/overview/structure.mdx b/website/pages/overview/structure.mdx index a126c1972f..ea106ae6bb 100644 --- a/website/pages/overview/structure.mdx +++ b/website/pages/overview/structure.mdx @@ -1,3 +1,20 @@ + +# Структура экранов + +Каждое VKUI-приложение – это набор экранов и есть два типа переходов между ними. + + + + +**Важно** + +Структура экранов должна быть постоянной и не должна меняться в рантайме. То есть нельзя на лету добавлять и +удалять `Panel` или `View`. Нельзя так же менять `id` у `Panel` или `View`. Структура – это _декларация_ приложения. +Единственный способ для перехода между `Panel` в пределах `View` и `View` в пределах `Root` – это обновление свойств `activePanel` +и `activeView` соответственно. + + + ## Переход между панелями `Panel` – это компонент, в который передается `children`, видимый пользователю. Компонент `View` – это набор таких панелей. Пример: @@ -76,3 +93,19 @@ import { View, Panel } from '@vkontakte/vkui'; ; ``` + + +**Авторы [мини-приложений ВКонтакте](https://dev.vk.com/mini-apps/overview), обратите внимание!** + +Вашему приложению доступна почти вся площадь экрана, поэтому для корректной работы навигации: + +- Используйте компонент [`PanelHeader`](#/PanelHeader) на каждом экране приложения. + Он должен содержать название приложения и значок "Назад" на тех экранах, где тот требуется. +- Не занимайте правый верхний угол [`PanelHeader`](#/PanelHeader) — это место зарезервировано для нативного бара с кнопками "Меню" и "Закрыть", + который отображается всегда (для этого передавайте `hasCustomPanelHeaderAfter` в `ConfigProvider`). +- Используйте стилизованный под платформу значок "Назад". Для этого применяйте компонент [`PanelHeaderBack`](#/PanelHeaderBack). + +На устройствах с Android нажатие аппаратной кнопки "Назад" вызывает в `WebView` событие `history.back`. +По нажатию этой кнопки официальное приложение ВКонтакте сделает возврат на предыдущую страницу вашего приложения или закроет его, если вернуться невозможно. Поэтому для корректной навигации необходимо обрабатывать нажатие в мини-приложении и реализовывать роутинг. Например, при помощи библиотеки `react-router`. + +