initial commit, lesson 1
8
.eslintrc.cjs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['@it-incubator/eslint-config'],
|
||||||
|
rules: {
|
||||||
|
'no-console': ['warn', {
|
||||||
|
allow: ['warn', 'error', 'info']
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
5
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
58
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<HTMLCodeStyleSettings>
|
||||||
|
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||||
|
<option name="HTML_ENFORCE_QUOTES" value="true" />
|
||||||
|
</HTMLCodeStyleSettings>
|
||||||
|
<JSCodeStyleSettings version="0">
|
||||||
|
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||||
|
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||||
|
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
||||||
|
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||||
|
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||||
|
</JSCodeStyleSettings>
|
||||||
|
<TypeScriptCodeStyleSettings version="0">
|
||||||
|
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||||
|
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||||
|
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
||||||
|
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||||
|
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||||
|
</TypeScriptCodeStyleSettings>
|
||||||
|
<VueCodeStyleSettings>
|
||||||
|
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
||||||
|
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
||||||
|
</VueCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="HTML">
|
||||||
|
<option name="SOFT_MARGINS" value="80" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="JavaScript">
|
||||||
|
<option name="SOFT_MARGINS" value="80" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="TypeScript">
|
||||||
|
<option name="SOFT_MARGINS" value="80" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="Vue">
|
||||||
|
<option name="SOFT_MARGINS" value="80" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
12
.idea/flashcards-docs.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
6
.idea/jsLinters/eslint.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="EslintConfiguration">
|
||||||
|
<option name="fix-on-save" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/flashcards-docs.iml" filepath="$PROJECT_DIR$/.idea/flashcards-docs.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
.idea/prettier.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PrettierConfiguration">
|
||||||
|
<option name="myConfigurationMode" value="AUTOMATIC" />
|
||||||
|
<option name="myRunOnSave" value="true" />
|
||||||
|
<option name="myFilesPattern" value="{**/*,*}.{js,ts,jsx,tsx,vue,astro,css,scss,mdx,md}" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
4
.prettierrc.cjs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
...require('@it-incubator/prettier-config'),
|
||||||
|
//override settings here
|
||||||
|
}
|
||||||
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"gotoSymbolStack.currentStackPosition": 0,
|
||||||
|
"gotoSymbolStack.maxStackPosition": 0,
|
||||||
|
"gotoSymbolStack.filePositionInfo": []
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
.counter {
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 2px 6px;
|
|
||||||
margin: 12px 0 0;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Example from https://beta.reactjs.org/learn
|
|
||||||
|
|
||||||
import { useState } from 'react'
|
|
||||||
import styles from './counters.module.css'
|
|
||||||
|
|
||||||
function MyButton() {
|
|
||||||
const [count, setCount] = useState(0)
|
|
||||||
|
|
||||||
function handleClick() {
|
|
||||||
setCount(count + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<button onClick={handleClick} className={styles.counter}>
|
|
||||||
Clicked {count} times
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MyApp() {
|
|
||||||
return <MyButton />
|
|
||||||
}
|
|
||||||
10
components/download-link/index.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export const DownloadLink = ({ href }: { href: string }) => {
|
||||||
|
return (
|
||||||
|
<p style={{ marginTop: 24 }}>
|
||||||
|
<a id="raw-url" download href={href} style={{ fontWeight: 700, color: 'blue' }}>
|
||||||
|
Скачайте файл watchers.xml
|
||||||
|
</a>{' '}
|
||||||
|
и импортируйте его в Settings | Tools | File Watchers
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
1
components/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './download-link'
|
||||||
1
middleware.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { locales as middleware } from 'nextra/locales'
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
const withNextra = require('nextra')({
|
const withNextra = require('nextra')({
|
||||||
|
defaultShowCopyCode: true,
|
||||||
theme: 'nextra-theme-docs',
|
theme: 'nextra-theme-docs',
|
||||||
themeConfig: './theme.config.tsx',
|
themeConfig: './theme.config.tsx',
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = withNextra()
|
module.exports = withNextra({
|
||||||
|
i18n: {
|
||||||
|
locales: ['en', 'ru'],
|
||||||
|
defaultLocale: 'en',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@it-incubator/eslint-config": "^0.1.2",
|
||||||
|
"@it-incubator/prettier-config": "^0.1.1",
|
||||||
"@types/node": "18.11.10",
|
"@types/node": "18.11.10",
|
||||||
"typescript": "^4.9.3"
|
"typescript": "^4.9.3"
|
||||||
}
|
}
|
||||||
|
|||||||
10
pages/_meta.en.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"index": "Introduction",
|
||||||
|
"figma": {
|
||||||
|
"title": "Figma ↗",
|
||||||
|
"type": "page",
|
||||||
|
"href": "https://www.figma.com/file/PwHkQjA62wyw8BSEyW4gIk/%D0%9E%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-%D0%BA%D0%B0%D1%80%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC?node-id=0%3A1&mode=dev",
|
||||||
|
"newWindow": true
|
||||||
|
},
|
||||||
|
"lesson-1": "Lesson 1: Hello World!"
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"index": "Introduction",
|
|
||||||
"another": "Another Page",
|
|
||||||
"advanced": "Advanced (A Folder)",
|
|
||||||
"about": {
|
|
||||||
"title": "About",
|
|
||||||
"type": "page"
|
|
||||||
},
|
|
||||||
"contact": {
|
|
||||||
"title": "Contact ↗",
|
|
||||||
"type": "page",
|
|
||||||
"href": "https://twitter.com/shuding_",
|
|
||||||
"newWindow": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
10
pages/_meta.ru.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"index": "Введение",
|
||||||
|
"figma": {
|
||||||
|
"title": "Figma ↗",
|
||||||
|
"type": "page",
|
||||||
|
"href": "https://www.figma.com/file/PwHkQjA62wyw8BSEyW4gIk/%D0%9E%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-%D0%BA%D0%B0%D1%80%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC?node-id=0%3A1&mode=dev",
|
||||||
|
"newWindow": true
|
||||||
|
},
|
||||||
|
"lesson-1": "Урок 1"
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# About
|
|
||||||
|
|
||||||
This is the about page! This page is shown on the navbar.
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# Advanced
|
|
||||||
|
|
||||||
This is the index page for the Advanced folder!
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# Satori
|
|
||||||
|
|
||||||
Satori (悟り) is a Japanese Buddhist term for awakening, "comprehension; understanding".
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Another Page
|
|
||||||
|
|
||||||
```js filename="demo.js" {3} copy
|
|
||||||
let a = 1;
|
|
||||||
|
|
||||||
console.log(a);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Component
|
|
||||||
|
|
||||||
import { useState } from 'react'
|
|
||||||
|
|
||||||
{/* Import CSS modules */}
|
|
||||||
import styles from '../components/counters.module.css'
|
|
||||||
|
|
||||||
export const Counter = () => {
|
|
||||||
const [count, setCount] = useState(0);
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<button onClick={() => setCount(count + 1)} className={styles.counter}>Clicked {count} times</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
<Counter/>
|
|
||||||
|
|
||||||
## External Component
|
|
||||||
|
|
||||||
import Counters from '../components/counters'
|
|
||||||
|
|
||||||
<Counters />
|
|
||||||
5
pages/index.en.mdx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { Callout } from 'nextra/components'
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
<Callout type="warning">This page is under construction. Check back later!</Callout>
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Introduction
|
|
||||||
|
|
||||||
Welcome to Nextra! This is a basic docs template. You can use it as a starting point for your own project :)
|
|
||||||
|
|
||||||
## What is Nextra?
|
|
||||||
|
|
||||||
A **simple**, **powerful** and **flexible** site generation framework with everything you love from Next.js.
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
The documentation is available at [https://nextra.site](https://nextra.site).
|
|
||||||
5
pages/index.ru.mdx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { Callout } from 'nextra/components'
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
<Callout type="warning">Страница в разработке, возвращайтесь попозже!</Callout>
|
||||||
4
pages/lesson-1/_meta.en.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"chapter-1": "Chapter 1",
|
||||||
|
"chapter-2": "Chapter 2"
|
||||||
|
}
|
||||||
4
pages/lesson-1/_meta.ru.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"chapter-1": "1. Создание и настройка проекта",
|
||||||
|
"chapter-2": "Chapter 2"
|
||||||
|
}
|
||||||
1
pages/lesson-1/chapter-1.en.mdx
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Under construction
|
||||||
181
pages/lesson-1/chapter-1.ru.mdx
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
import { Callout } from 'nextra/components'
|
||||||
|
import { DownloadLink } from '../../components'
|
||||||
|
|
||||||
|
# 1. Создание и настройка проекта
|
||||||
|
|
||||||
|
## Vite
|
||||||
|
|
||||||
|
Мы будем использовать [Vite](https://vitejs.dev/) в качестве сборщика.
|
||||||
|
|
||||||
|
```bash filename="Terminal"
|
||||||
|
pnpm create vite
|
||||||
|
```
|
||||||
|
|
||||||
|
- Выберите название для проекта на ваш вкус
|
||||||
|
- Фреймворк - React
|
||||||
|
- Тип приложения - TypeScript
|
||||||
|
|
||||||
|
<Callout type={'warning'}>
|
||||||
|
После создания проекта не забудьте установить зависимости, используя <code>pnpm i</code>
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
## Инициализация git
|
||||||
|
|
||||||
|
В отличие от create-react-app, vite не инициализирует git репозиторий автоматически, поэтому нам нужно сделать это вручную:
|
||||||
|
|
||||||
|
```bash filename="Terminal"
|
||||||
|
git init
|
||||||
|
```
|
||||||
|
|
||||||
|
## Установка зависимостей
|
||||||
|
|
||||||
|
### Linters
|
||||||
|
|
||||||
|
Мы будем использовать линтеры от команды IT-Incubator:
|
||||||
|
|
||||||
|
```bash filename="Terminal"
|
||||||
|
pnpm i @it-incubator/eslint-config @it-incubator/prettier-config @it-incubator/stylelint-config stylelint -D
|
||||||
|
```
|
||||||
|
|
||||||
|
### SASS
|
||||||
|
|
||||||
|
Мы будем использовать SASS в качестве препроцессора стилей:
|
||||||
|
|
||||||
|
```bash filename="Terminal"
|
||||||
|
pnpm i sass -D
|
||||||
|
```
|
||||||
|
|
||||||
|
## Конфигурация линтеров
|
||||||
|
|
||||||
|
### Prettier
|
||||||
|
|
||||||
|
Создайте файл .prettierrc.cjs в корне проекта и скопируйте туда следующее содержимое:
|
||||||
|
|
||||||
|
```js filename=".prettierrc.cjs"
|
||||||
|
module.exports = {
|
||||||
|
...require('@it-incubator/prettier-config'),
|
||||||
|
//override settings here
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ESLint
|
||||||
|
|
||||||
|
Замените содержимое файла .eslintrc.cjs на следующее:
|
||||||
|
|
||||||
|
```js filename=".eslintrc.cjs"
|
||||||
|
module.exports = {
|
||||||
|
extends: '@it-incubator/eslint-config',
|
||||||
|
rules: { 'no-console': ['warn', { allow: ['warn', 'error'] }] },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stylelint
|
||||||
|
|
||||||
|
Создайте файл .stylelintrc.cjs в корне проекта и скопируйте туда следующее содержимое:
|
||||||
|
|
||||||
|
```js filename=".stylelintrc.cjs"
|
||||||
|
module.exports = {
|
||||||
|
extends: '@it-incubator/stylelint-config',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Конфигурация WebStorm
|
||||||
|
|
||||||
|
### Включить ESLint
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Включить Prettier
|
||||||
|
|
||||||
|
```bash
|
||||||
|
{**/*,*}.{js,ts,jsx,tsx,vue,astro,cjs,mjs,css,scss}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Включить stylelint
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Включить автоматическое исправление ошибок при сохранении .css/.scss файлов
|
||||||
|
|
||||||
|
<DownloadLink href="./watchers.xml" />
|
||||||
|
|
||||||
|
После импорта получим следующее: 
|
||||||
|
|
||||||
|
### Добавить скрипты в package.json, перезаписывая значения по умолчанию при необходимости
|
||||||
|
|
||||||
|
```json lines filename="package.json"
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"format": "prettier --write src",
|
||||||
|
"lint": "eslint --fix src/**/*.{tsx,ts,jsx,js} --no-error-on-unmatched-pattern && stylelint --fix src/{,*/}*.{scss,css} --allow-empty-input"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Убрать boilerplate
|
||||||
|
|
||||||
|
- Удалить файл App.css
|
||||||
|
- Удалить папку assets
|
||||||
|
- Заменить содержимое файла App.tsx на следующее:
|
||||||
|
|
||||||
|
```tsx filename="App.tsx"
|
||||||
|
export function App() {
|
||||||
|
return <div>Hello</div>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Запустить линтеры
|
||||||
|
|
||||||
|
- Prettier
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm run format
|
||||||
|
```
|
||||||
|
|
||||||
|
- Eslint и Stylelint
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
Некоторые ошибки eslint не исправляются автоматически, поэтому вам придется сделать это самостоятельно, например:
|
||||||
|

|
||||||
|
|
||||||
|
Постарайтесь разобраться сами, если не получится - замените содержимое файла main.tsx на следующее:
|
||||||
|
|
||||||
|
```tsx filename="main.tsx"
|
||||||
|
import './index.css'
|
||||||
|
import { StrictMode } from 'react'
|
||||||
|
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
|
||||||
|
import { App } from './App.tsx'
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
<Callout type={'warning'}>
|
||||||
|
Наш eslint конфиг использует плагин import\/order, который требует, чтобы ваши файлы **css/scss
|
||||||
|
были размещены либо первыми, либо последними в импортах** (см. пример выше), иначе вы получите
|
||||||
|
неразрешимые ошибки.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
## Итоговая структура папок
|
||||||
|
|
||||||
|
Так должна выглядеть структура папок к концу этой главы:
|
||||||
|

|
||||||
|
|
||||||
|
## Коммитим изменения
|
||||||
|
|
||||||
|
Не забудьте закоммитить изменения:
|
||||||
|
|
||||||
|
```bash filename="Terminal"
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial commit"
|
||||||
|
```
|
||||||
207
pages/lesson-1/chapter-2.md
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
# Chapter 2
|
||||||
|
|
||||||
|
## Deploy to Vercel
|
||||||
|
|
||||||
|
You should already know how to do it.
|
||||||
|
|
||||||
|
If you're using the Redux-vite template make sure to change the output directory to 'build' in project settings on
|
||||||
|
Vercel:
|
||||||
|

|
||||||
|
|
||||||
|
Make sure it is deployed successfully.
|
||||||
|
|
||||||
|
## Storybook
|
||||||
|
|
||||||
|
- Install:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dlx storybook@latest init
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Accept eslint config**
|
||||||
|
|
||||||
|
- Try it out:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm run storybook
|
||||||
|
```
|
||||||
|
|
||||||
|
## Install fonts
|
||||||
|
|
||||||
|
[Fontsource/montserrat](https://fontsource.org/fonts/montserrat)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install @fontsource-variable/montserrat
|
||||||
|
```
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// main.tsx
|
||||||
|
|
||||||
|
import '@fontsource-variable/montserrat'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Set up css variables
|
||||||
|
|
||||||
|
- Create an _src/styles_ directory in your project
|
||||||
|
containing the following files:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
src
|
||||||
|
└── styles
|
||||||
|
└── \_boilerplate.scss
|
||||||
|
└── \_colors.scss
|
||||||
|
└── \_typography.scss
|
||||||
|
└── index.scss
|
||||||
|
```
|
||||||
|
|
||||||
|
- Add the following to _index.scss_:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
@forward 'colors';
|
||||||
|
@forward 'typography';
|
||||||
|
@forward 'boilerplate';
|
||||||
|
```
|
||||||
|
|
||||||
|
- Add the following to \__colors.scss_:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
:root {
|
||||||
|
// text
|
||||||
|
--color-text-primary: #000;
|
||||||
|
--color-text-secondary: #fff;
|
||||||
|
|
||||||
|
// backgrounds
|
||||||
|
--color-bg-primary: #3d3d3d;
|
||||||
|
--color-bg-secondary: #fcfcfc;
|
||||||
|
--color-bg-tertiary: #efefef;
|
||||||
|
|
||||||
|
// palette
|
||||||
|
--color-primary: #366eff;
|
||||||
|
--color-secondary: #ffc700;
|
||||||
|
--color-danger: #ff3636;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Add any extra colors you need yourself
|
||||||
|
|
||||||
|
- Add the following to \__typography.scss_:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
:root {
|
||||||
|
--font-family-primary: 'Montserrat Variable', sans-serif;
|
||||||
|
|
||||||
|
// line heights
|
||||||
|
--line-height-xs: 0.991rem;
|
||||||
|
--line-height-s: 1.219rem;
|
||||||
|
--line-height-m: 1.5rem;
|
||||||
|
--line-height-l: 1.75rem;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Add font sizes and font weights yourself
|
||||||
|
|
||||||
|
> Transform font sizes to rem: <https://nekocalc.com/px-to-rem-converter>
|
||||||
|
|
||||||
|
- Add the following to \__boilerplate.scss_:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
html {
|
||||||
|
font-size: 100%;
|
||||||
|
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
select,
|
||||||
|
textarea,
|
||||||
|
optgroup,
|
||||||
|
option {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: inherit;
|
||||||
|
font-style: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
font-family: var(--font-family-primary);
|
||||||
|
line-height: var(--line-height-m);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
|
background-color: var(--color-bg-primary);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Import _index.scss_ in _main.tsx_:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// main.tsx
|
||||||
|
|
||||||
|
import './styles/index.scss'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Import fonts and styles in storybook:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// .storybook/preview.tsx
|
||||||
|
import '@fontsource-variable/montserrat'
|
||||||
|
import '../src/styles/index.scss'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
- Create an _src/components/ui_ directory in your project
|
||||||
|
|
||||||
|
### Button
|
||||||
|
|
||||||
|
- Create a _button_ directory in _src/components/ui_ with the following files:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
src
|
||||||
|
└── components
|
||||||
|
└── ui
|
||||||
|
└── button
|
||||||
|
└── button.tsx
|
||||||
|
└── button.module.scss
|
||||||
|
└── button.stories.ts
|
||||||
|
└── index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Try to create the component yourself first**
|
||||||
|
|
||||||
|
Essentially, we are going to have 5 variants of our button:
|
||||||
|
|
||||||
|
- Primary (blue)
|
||||||
|
- Secondary (white)
|
||||||
|
- Danger (orange)
|
||||||
|
- Full width
|
||||||
|
- A link that looks like a button
|
||||||
|
|
||||||
|
What it means is that we are going to need these props:
|
||||||
|
<https://www.tints.dev>
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ComponentPropsWithoutRef } from 'react'
|
||||||
|
|
||||||
|
type ButtonProps = {
|
||||||
|
variant?: 'primary' | 'secondary' | 'danger'
|
||||||
|
fullWidth?: boolean
|
||||||
|
} & ComponentPropsWithoutRef<'button'>
|
||||||
|
```
|
||||||
|
|
||||||
|
The problem here is that we are getting button props, but we will also need it to be a link, and, potentially, a react-router-dom Link, so we want to make our component polymorphic:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
|
||||||
|
```
|
||||||
BIN
pages/lesson-1/images/eslint-error-main.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
pages/lesson-1/images/eslint-settings.png
Normal file
|
After Width: | Height: | Size: 569 KiB |
BIN
pages/lesson-1/images/file-watchers-settings.png
Normal file
|
After Width: | Height: | Size: 563 KiB |
BIN
pages/lesson-1/images/final-folder-structure.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
pages/lesson-1/images/prettier-settings.png
Normal file
|
After Width: | Height: | Size: 554 KiB |
BIN
pages/lesson-1/images/stylelint-settings.png
Normal file
|
After Width: | Height: | Size: 633 KiB |
BIN
pages/lesson-1/images/vercel-output-directory.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
42
pages/lesson-1/watchers.xml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<TaskOptions>
|
||||||
|
<TaskOptions>
|
||||||
|
<option name="arguments" value="$FilePath$ --fix" />
|
||||||
|
<option name="checkSyntaxErrors" value="true" />
|
||||||
|
<option name="description" />
|
||||||
|
<option name="exitCodeBehavior" value="ERROR" />
|
||||||
|
<option name="fileExtension" value="css" />
|
||||||
|
<option name="immediateSync" value="false" />
|
||||||
|
<option name="name" value="Stylelint" />
|
||||||
|
<option name="output" value="$FilePath$" />
|
||||||
|
<option name="outputFilters">
|
||||||
|
<array />
|
||||||
|
</option>
|
||||||
|
<option name="outputFromStdout" value="false" />
|
||||||
|
<option name="program" value="$ProjectFileDir$/node_modules/.bin/stylelint" />
|
||||||
|
<option name="runOnExternalChanges" value="false" />
|
||||||
|
<option name="scopeName" value="Current File" />
|
||||||
|
<option name="trackOnlyRoot" value="false" />
|
||||||
|
<option name="workingDir" value="" />
|
||||||
|
<envs />
|
||||||
|
</TaskOptions>
|
||||||
|
<TaskOptions>
|
||||||
|
<option name="arguments" value="$FilePath$ --fix" />
|
||||||
|
<option name="checkSyntaxErrors" value="true" />
|
||||||
|
<option name="description" />
|
||||||
|
<option name="exitCodeBehavior" value="ERROR" />
|
||||||
|
<option name="fileExtension" value="scss" />
|
||||||
|
<option name="immediateSync" value="false" />
|
||||||
|
<option name="name" value="Stylelint scss" />
|
||||||
|
<option name="output" value="$FilePath$" />
|
||||||
|
<option name="outputFilters">
|
||||||
|
<array />
|
||||||
|
</option>
|
||||||
|
<option name="outputFromStdout" value="false" />
|
||||||
|
<option name="program" value="$ProjectFileDir$/node_modules/.bin/stylelint" />
|
||||||
|
<option name="runOnExternalChanges" value="false" />
|
||||||
|
<option name="scopeName" value="Current File" />
|
||||||
|
<option name="trackOnlyRoot" value="false" />
|
||||||
|
<option name="workingDir" value="" />
|
||||||
|
<envs />
|
||||||
|
</TaskOptions>
|
||||||
|
</TaskOptions>
|
||||||
3141
pnpm-lock.yaml
generated
@@ -1,17 +1,66 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
import { DocsThemeConfig } from 'nextra-theme-docs'
|
import { DocsThemeConfig } from 'nextra-theme-docs'
|
||||||
|
|
||||||
const config: DocsThemeConfig = {
|
const config: DocsThemeConfig = {
|
||||||
logo: <span>My Project</span>,
|
logo: <span>Flashcards docs</span>,
|
||||||
project: {
|
project: {
|
||||||
link: 'https://github.com/shuding/nextra-docs-template',
|
link: 'https://github.com/ershisan99/cards-front-new/tree/master',
|
||||||
},
|
},
|
||||||
chat: {
|
i18n: [
|
||||||
link: 'https://discord.com',
|
{ locale: 'en', text: 'English' },
|
||||||
},
|
{ locale: 'ru', text: 'Русский' },
|
||||||
docsRepositoryBase: 'https://github.com/shuding/nextra-docs-template',
|
],
|
||||||
|
docsRepositoryBase: 'https://github.com/ershisan99/flashcards-docs',
|
||||||
footer: {
|
footer: {
|
||||||
text: 'Nextra Docs Template',
|
text: 'Powered by Nextra',
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
placeholder: () => {
|
||||||
|
const { locale } = useRouter()
|
||||||
|
|
||||||
|
if (locale === 'ru') {
|
||||||
|
return 'Поиск...'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Search...'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
toc: {
|
||||||
|
title: () => {
|
||||||
|
const { locale } = useRouter()
|
||||||
|
|
||||||
|
if (locale === 'ru') {
|
||||||
|
return <>Cодержание</>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>On This Page</>
|
||||||
|
},
|
||||||
|
},
|
||||||
|
editLink: {
|
||||||
|
// @ts-ignore
|
||||||
|
text: () => {
|
||||||
|
const { locale } = useRouter()
|
||||||
|
|
||||||
|
if (locale === 'ru') {
|
||||||
|
return 'Редактировать эту страницу'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Edit this page'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
feedback: {
|
||||||
|
// @ts-ignore
|
||||||
|
content: () => {
|
||||||
|
const { locale } = useRouter()
|
||||||
|
|
||||||
|
if (locale === 'ru') {
|
||||||
|
return 'Отправить отзыв'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Send feedback'
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||