Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PoC]: Docs Beta #6315

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
**/src/**/__image_snapshots__/*.png filter=lfs diff=lfs merge=lfs -text
**/static/img/**/*.png filter=lfs diff=lfs merge=lfs -text

# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
/.yarn/releases/** binary
Expand Down
4 changes: 4 additions & 0 deletions .github/file-filters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ docs_storybook:
- 'packages/vkui/src/**/*.stories.*'
- 'packages/vkui/src/**/*.mdx'
- 'tools/storybook-*/**'

docs_beta:
- *package_vkui
- 'docs-beta/**'
37 changes: 36 additions & 1 deletion .github/workflows/pull_request_packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
package_vkui: ${{ steps.changes.outputs.package_vkui }}
docs_styleguide: ${{ steps.changes.outputs.docs_styleguide }}
docs_storybook: ${{ steps.changes.outputs.docs_storybook }}
docs_beta: ${{ steps.changes.outputs.docs_beta }}
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -225,9 +226,43 @@ jobs:
name: storybook-dist
path: packages/vkui/storybook-static

docs_beta_upload:
if: ${{ needs.changed_files.outputs.docs_beta == 'true' }}
needs: changed_files
runs-on: ubuntu-latest
name: Upload docs dist artifact (beta)
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup NodeJS
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'yarn'

- name: Install dependencies
run: YARN_ENABLE_SCRIPTS=false yarn install --immutable

- name: Build
run: yarn docs:beta:build

- name: Upload dist
uses: actions/upload-artifact@v4
with:
name: docs-beta-dist
path: docs-beta/build

upload_pr_workflow_payload:
# Дожидаемся выгрузки артефактов, на случай если вокрфлоу будет отменён или перезапушен
needs: [test, test_e2e_prepare_and_upload_report, docs_styleguide_upload, docs_storybook_upload]
needs:
[
test,
test_e2e_prepare_and_upload_report,
docs_styleguide_upload,
docs_storybook_upload,
docs_beta_upload,
]
# Не используем always(), т.к. он не учитывает отмену воркфлоу
# см. https://github.com/orgs/community/discussions/26303
if: ${{ !cancelled() }}
Expand Down
37 changes: 36 additions & 1 deletion .github/workflows/pull_request_packages_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,46 @@ jobs:
id: url
run: echo "value=${{ env.AWS_S3_URL }}/pull/${{ needs.pr_workflow_payload.outputs.pr_number }}/${{ env.PR_HEAD_SHA }}/storybook/index.html" >> $GITHUB_OUTPUT

deploy_docs_beta:
needs: pr_workflow_payload
if: ${{ needs.pr_workflow_payload.outputs.status == 'success' }}
runs-on: ubuntu-latest
name: Deploy docs (beta)
outputs:
url: ${{ steps.url.outputs.value }}
steps:
- name: Download dist artifact
id: artifact
uses: VKCOM/gh-actions/shared/download-workflow-artifact@main
with:
name: docs-beta-dist
path: docs-beta-dist/

- name: Upload
if: ${{ steps.artifact.outputs.found_artifact == 'true' }}
id: deploy
uses: VKCOM/gh-actions/VKUI/s3@main
with:
awsAccessKeyId: ${{ secrets.AWS_ACCESS_KEY_ID }}
awsSecretAccessKey: ${{ secrets.AWS_SECRET_KEY }}
awsBucket: ${{ vars.AWS_BUCKET }}
awsEndpoint: https://${{ vars.AWS_ENDPOINT }}
command: upload
commandUploadSrc: docs-beta-dist/
commandUploadDist: pull/${{ needs.pr_workflow_payload.outputs.pr_number }}/${{ env.PR_HEAD_SHA }}/docs-beta

- name: Create doc url
if: ${{ steps.deploy.outcome == 'success' }}
id: url
run: echo "value=${{ env.AWS_S3_URL }}/pull/${{ needs.pr_workflow_payload.outputs.pr_number }}/${{ env.PR_HEAD_SHA }}/docs-beta/index.html" >> $GITHUB_OUTPUT

docs_comment:
needs:
- deploy_storybook
- deploy_styleguide
- deploy_docs_beta
- pr_workflow_payload
if: ${{ needs.deploy_styleguide.outputs.url != '' || needs.deploy_storybook.outputs.url != '' }}
if: ${{ needs.deploy_styleguide.outputs.url != '' || needs.deploy_storybook.outputs.url != '' || needs.deploy_docs_beta.outputs.url != '' }}
runs-on: ubuntu-latest
name: Docs comment
steps:
Expand All @@ -181,6 +215,7 @@ jobs:

- ${{ (needs.deploy_styleguide.outputs.url != '' && '✅') || '❌' }} [Styleguide](${{ needs.deploy_styleguide.outputs.url }})
- ${{ (needs.deploy_storybook.outputs.url != '' && '✅') || '❌' }} [Storybook](${{ needs.deploy_storybook.outputs.url }})
- ${{ (needs.deploy_docs_beta.outputs.url != '' && '✅') || '❌' }} [Docs (beta)](${{ needs.deploy_docs_beta.outputs.url }})

Commit ${{ env.PR_HEAD_SHA }}
edit-mode: replace
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
dist
build
coverage
.idea
.vscode/*
Expand All @@ -21,6 +22,7 @@ storybook-static/
playwright-report/
blob-report/
all-blob-reports/
.docusaurus

packages/vkui-floating-ui/**/*.d.ts
packages/vkui-floating-ui/**/*.d.mts
Expand Down
1 change: 1 addition & 0 deletions .stylelintignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules/
dist/
styleguide/
docs-beta/
coverage/
!packages/vkui
tmp/
Expand Down
20 changes: 20 additions & 0 deletions docs-beta/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
41 changes: 41 additions & 0 deletions docs-beta/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Website

This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.

### Installation

```
$ yarn
```

### Local Development

```
$ yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

```
$ yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

### Deployment

Using SSH:

```
$ USE_SSH=true yarn deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> yarn deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
3 changes: 3 additions & 0 deletions docs-beta/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};
186 changes: 186 additions & 0 deletions docs-beta/docs/basics/adaptivity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
---
sidebar_label: Адаптивность
---

# Адаптивность

Одно из основных преимуществ VKUI — это адаптивность. Библиотека не только реализует разные шаблоны для разных устройств:
под габариты адаптируются практически все компоненты.
От наличия мышки, высоты и ширины экрана зависит отображение кнопок, элементов форм и так далее.
В этой статье мы разберём, как сделать ваш интерфейс отзывчивым.

Для начала, нужно обернуть ваше приложение в [`AdaptivityProvider`](https://vkcom.github.io/VKUI/#/AdaptivityProvider).

:::info[Важно]

Учтите порядок подключения компонентов для конфигурации. `ConfigProvider` -> `AdaptivityProvider` -> `AppRoot`
:::

```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';

function App() {
return (
<ConfigProvider>
<AdaptivityProvider>
<AppRoot>...</AppRoot>
</AdaptivityProvider>
</ConfigProvider>
);
}

const container = document.getElementById('root');
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(<App />);
```

Далее, нужно добавить [`SplitLayout`](https://vkcom.github.io/VKUI/#/SplitLayout) и хотя бы один [`SplitCol`](https://vkcom.github.io/VKUI/#/SplitCol).

- `SplitLayout` — компонент-обертка для отрисовки макета с одной или несколькими колонками.
- `SplitCol` — компонент для отрисовки колонки.

```jsx static
// ...

function App() {
return (
<ConfigProvider>
<AdaptivityProvider>
<AppRoot>
<SplitLayout>
<SplitCol width={280}>
<SideCol />
</SplitCol>
<SplitCol>
<MainScreens />
</SplitCol>
</SplitLayout>
</AppRoot>
</AdaptivityProvider>
</ConfigProvider>
);
}

const MainScreens = () => {
return (
<View activePanel="profile">
<Panel id="profile">Profile</Panel>
</View>
);
};

const SideCol = () => {
return <Panel id="nav">Navigation</Panel>;
};
```

Почти готово. Теперь мы должны сообщить приложению, что левая колонка нужна только на больших экранах. Для этого нам
нужно использовать хук `useAdaptivityConditionalRender` в своих компонентах. Далее будет пример, а следом объяснение,
что делает хук.

```jsx static
function App() {
const platform = usePlatform();
const isVKCOM = platform === 'vkcom';
const { viewWidth } = useAdaptivityConditionalRender();

// ...

<SplitLayout header={!isVKCOM && <PanelHeader separator={false} />}>
{viewWidth.tabletPlus && (
<SplitCol width={280} className={viewWidth.tabletPlus.className}>
<Panel id="nav">Navigation</Panel>
</SplitCol>
)}
<SplitCol autoSpaced>
<View activePanel="profile">
<Panel id="profile">Profile</Panel>
</View>
</SplitCol>
</SplitLayout>;
// ...
}
```

`useAdaptivityConditionalRender` возвращает параметры адаптивности (см. **Технические детали**), каждый из которых имеет
дополнительную мета-информацию.

В зависимости от того, что мы передали в `AdaptivityProvider`, значение у каждого отдельного параметра адаптивности
может быть двух типов:

- `false` – мы строго задали какой-то из параметров адаптивности в
`AdaptivityProvider`.

> Например, при `<AdaptivityProvider viewWidth={ViewWidth.MOBILE}>` значение `viewWidth.tabletPlus` будет `false`,
> т.к. мы говорим, что у нас всегда мобильный вид.

- `{ className: string }` – CSS селектор, который на основе CSS Media Query будет переключать видимость вашего
элемента. В данном случае в `AdaptivityProvider` не передавали соответствующий параметр адаптивности.

> Например, при `<AdaptivityProvider sizeX="compact">` значение `viewWidth.tabletPlus` будет
> `{ className: "..." }`.
>
> ⚠️ Видимость элемента управляется через `display: none` – отсюда можно сделать вывод, что элемент будет всегда
> рендерится как в **Virtual DOM**, так и в **DOM**.

## Требования для адаптивности

- Свойство `SplitLayout.header` нужно для создания сквозной шапки, когда интерфейс состоит из нескольких колонок (или одной центрированной)
- Анимация перехода между панелями должна быть отключена при размерах `ViewWidth.TABLET` и более (`SplitCol.animate`)
- Если интерфейс состоит из нескольких колонок, то у центральных колонок должны быть отступы (в трёх-колоночном режиме это одна центральная колонка) (`SplitCol.autoSpaced`)

## Адаптивность через JS

Если вы:

- **не поддерживаете SSR** или
- **у вас есть компонент, который не показывается при первом рендере**,

то вы можете смело использовать хук `useAdaptivityWithJSMediaQueries()`.

Мы используем этот хук для _всплывающих окон_. Как раз из-за того, что они удовлетворяют условию показа только после
первого рендера.

Вот небольшой и наглядный пример:

```jsx static
// ❌ bad for SSR
const App = () => {
return (
<ModalRoot activeModal="main">
<ModalPage id="main">Hello World!</ModalPage>
</ModalRoot>
);
};

// ✅ good for SSR
const App = () => {
const [mounted, setMounted] = React.useState(false);

React.useEffect(() => {
setMounted(true);
}, []);

return mounted ? (
<ModalRoot activeModal="main">
<ModalPage id="main">Hello World!</ModalPage>
</ModalRoot>
) : null;
};
```

В нашем примере внутри `<ModalRoot />` и `<ModalPage />` используется `useAdaptivityWithJSMediaQueries()` для
переключения компонентов на мобильный или десктопный виды.

## Технические детали

Адаптивность базируется на четырёх свойствах:

- `sizeX` и `sizeY` принимают значения `'regular' | 'compact'`
- `viewWidth` — `ViewWidth.SMALL_MOBILE | ViewWidth.MOBILE | ViewWidth.SMALL_TABLET | ViewWidth.TABLET | ViewWidth.DESKTOP`
- `viewHeight` — `ViewHeight.SMALL | ViewHeight.MEDIUM`

Эти свойства задаются в `AdaptivityProvider`.
Loading
Loading