Skip to content

Commit a9ce05a

Browse files
committed
docs: translate UI from Ukrainian to English and add language switching support
1 parent 828bb99 commit a9ce05a

File tree

15 files changed

+1270
-564
lines changed

15 files changed

+1270
-564
lines changed

README.md

Lines changed: 171 additions & 180 deletions
Large diffs are not rendered by default.

README.uk.md

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
# JavaScript Event Loop Візуалізатор 🔄
2+
3+
Інтерактивний інструмент для візуалізації та навчання принципів роботи JavaScript Event Loop. Сучасний веб-додаток на React з красивим UI, що допомагає розробникам зрозуміти асинхронність JavaScript, порядок виконання операцій та взаємодію між Call Stack, Web APIs, та чергами Microtask і Task (Callback).
4+
5+
![JavaScript Event Loop Візуалізатор](./screenshot.png)
6+
7+
[![Live Demo](https://img.shields.io/badge/demo-online-brightgreen.svg)](https://vitalii4reva.com/visual-js-event-loop/)
8+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
9+
[![React](https://img.shields.io/badge/React-19-61DAFB?logo=react)](https://react.dev/)
10+
[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript)](https://www.typescriptlang.org/)
11+
12+
## ✨ Можливості
13+
14+
### 🎨 UI/UX
15+
- **Сучасний дизайн** з shadcn/ui компонентами та responsive сайдбаром
16+
- **Темна та світла тема** з автоматичним перемиканням
17+
- **Повністю адаптивний** дизайн для мобільних, планшетів та десктопів
18+
- **Інтелектуальний сайдбар**:
19+
- Автоматично згортається на вузьких екранах (тільки іконки)
20+
- Розгортається на широких екранах з повним текстом
21+
- Перемикається клавішею `B`
22+
- **Плавні анімації** та переходи між станами
23+
- **Інтуїтивний інтерфейс** з tooltips та підказками
24+
- **Чистий UI** - порожні секції автоматично ховаються
25+
26+
### 📚 Функціонал
27+
- **Візуалізація** Call Stack, Web APIs, Microtask Queue, Task Queue, Stack та Heap пам'яті
28+
- **Покрокове виконання** з детальними поясненнями кожної дії
29+
- **5 вбудованих прикладів**:
30+
- 🗄️ **Пам'ять та Змінні** - демонстрація Stack та Heap (примітиви, об'єкти, функції)
31+
- ⏱️ **setTimeout** - базова робота з асинхронним кодом
32+
-**Promise vs setTimeout** - різниця між microtask та macrotask
33+
- 🔄 **Складний приклад** - вкладені Promise та setTimeout
34+
- 🌐 **Fetch API** - мережеві запити та їх обробка
35+
- **Два режими роботи**: автоматичний та ручний
36+
- **Історія дій** для відстеження всіх кроків виконання
37+
- **Відображення коду** з підсвічуванням активного рядка
38+
- **Інтерактивний сайдбар** з:
39+
- Швидким запуском прикладів
40+
- Кнопками очищення (повне та вибіркове)
41+
- Довідкою по роботі Event Loop
42+
- **Keyboard shortcuts**: Space, 0-4, A, B, C, Esc для швидкої роботи
43+
44+
### 🌍 Локалізація
45+
- Повна підтримка **української мови**
46+
- Готовність до додавання інших мов
47+
48+
## 🚀 Швидкий Старт
49+
50+
### Передумови
51+
52+
- [Node.js](https://nodejs.org/) 18.0.0+ (рекомендовано 20+)
53+
- [pnpm](https://pnpm.io/) (рекомендовано) або npm
54+
55+
### Встановлення
56+
57+
```bash
58+
# Клонуйте репозиторій
59+
git clone https://github.com/vitalii4reva/visual-js-event-loop.git
60+
cd visual-js-event-loop
61+
62+
# Встановіть залежності
63+
pnpm install
64+
65+
# Запустіть dev сервер
66+
pnpm dev
67+
```
68+
69+
Відкрийте [http://localhost:3000](http://localhost:3000) в браузері.
70+
71+
### Збірка для Production
72+
73+
```bash
74+
# Створіть production build
75+
pnpm build
76+
77+
# Перегляньте production версію локально
78+
pnpm preview
79+
```
80+
81+
Build результат буде в теці `dist/`
82+
83+
## 🏗️ Технології
84+
85+
- ⚛️ **React 19** - UI framework
86+
- 📘 **TypeScript 5.9** - Type safety
87+
- 🎨 **Tailwind CSS 3.4** - Styling
88+
- 🧩 **shadcn/ui** - UI компоненти
89+
-**Vite 6** - Build tool
90+
- 🎭 **Lucide React** - Іконки
91+
- 🌓 **next-themes** - Theme management
92+
93+
## 📂 Структура Проекту
94+
95+
```
96+
src/
97+
├── components/ # React компоненти
98+
│ ├── ui/ # shadcn/ui компоненти (sidebar, button, card...)
99+
│ ├── layout/ # Header, ExamplesSidebar, KeyboardShortcuts
100+
│ ├── event-loop/ # Візуалізація Event Loop
101+
│ │ ├── CallStack.tsx
102+
│ │ ├── WebAPIs.tsx
103+
│ │ ├── MicrotaskQueue.tsx
104+
│ │ ├── TaskQueue.tsx
105+
│ │ ├── Memory.tsx # Heap пам'ять
106+
│ │ └── StackVariables.tsx # Stack frames
107+
│ ├── controls/ # StepControls
108+
│ └── panels/ # HistoryPanel
109+
├── hooks/ # Custom React hooks
110+
│ ├── useEventLoop.ts
111+
│ ├── useStepExecution.ts
112+
│ ├── useKeyboardShortcuts.ts
113+
│ └── use-mobile.tsx
114+
├── context/ # React Context (ThemeProvider)
115+
├── lib/ # Утиліти та приклади
116+
│ ├── examples.ts # 5 вбудованих прикладів
117+
│ └── utils.ts
118+
├── types/ # TypeScript типи
119+
│ ├── eventLoop.ts
120+
│ └── memory.ts
121+
├── i18n/ # Переклади
122+
├── App.tsx # Головний компонент
123+
└── main.tsx # Entry point
124+
```
125+
126+
## 🔧 Як це працює
127+
128+
Візуалізатор демонструє роботу JavaScript Event Loop та управління пам'яттю:
129+
130+
1. **Call Stack**: Відображає функції, які зараз виконуються.
131+
2. **Web APIs**: Показує асинхронні операції, що виконуються у фоні.
132+
3. **Microtask Queue**: Черга високопріоритетних завдань (Promise).
133+
4. **Task Queue**: Черга регулярних завдань (setTimeout, setInterval).
134+
5. **Stack Variables**: Відображає локальні змінні у Stack Frames.
135+
6. **Memory (Heap)**: Показує об'єкти, функції та інші складні типи даних.
136+
7. **Event Loop**: Постійно перевіряє стан стеку та черг, дотримуючись пріоритетів.
137+
138+
### Порядок виконання в Event Loop:
139+
140+
1. Виконати весь синхронний код у Call Stack
141+
2. Перевірити чи Call Stack порожній
142+
3. Обробити ВСІ мікрозавдання з Microtask Queue
143+
4. Взяти ОДНЕ завдання з Task Queue
144+
5. Повторити з кроку 1
145+
146+
## 🎯 Як Використовувати
147+
148+
1. **Виберіть приклад** в сайдбарі зліва (або клавіші **0-4**):
149+
- **0** - Пам'ять та Змінні (Stack & Heap)
150+
- **1** - setTimeout демонстрація
151+
- **2** - Promise vs setTimeout
152+
- **3** - Складний приклад
153+
- **4** - Fetch API
154+
2. **Режим виконання**:
155+
- **Ручний режим**: Натискайте "Наступний крок" або **Space/Enter**
156+
- **Авто режим**: Автоматичне виконання з затримкою 1.5 сек (клавіша **A**)
157+
3. **Спостерігайте**:
158+
- Call Stack - активні функції
159+
- Web APIs - асинхронні операції
160+
- Microtask Queue - високопріоритетні завдання (Promise)
161+
- Task Queue - звичайні завдання (setTimeout)
162+
- Stack Variables - локальні змінні (з'являються в прикладі 0)
163+
- Memory (Heap) - об'єкти та функції (з'являються в прикладі 0)
164+
4. **Відстежуйте** історію дій у правій панелі
165+
5. **Керуйте сайдбаром** - клавіша **B** або кнопка у header
166+
6. **Keyboard shortcuts** - Натисніть іконку клавіатури у header для переліку всіх скорочень
167+
168+
## 👥 Як Зробити Внесок
169+
170+
Ми заохочуємо внески в розвиток проекту!
171+
172+
### Способи Допомоги
173+
174+
- 🐛 Повідомте про баг через [Issues](https://github.com/vitalii4reva/visual-js-event-loop/issues)
175+
- ✨ Запропонуйте нову функцію
176+
- 📝 Покращіть документацію
177+
- 🌍 Додайте переклад на іншу мову
178+
- 💻 Відправте Pull Request
179+
180+
### Процес
181+
182+
1. Fork репозиторію
183+
2. Створіть гілку: `git checkout -b feature/amazing-feature`
184+
3. Внесіть зміни та commit: `git commit -m 'Add amazing feature'`
185+
4. Push до гілки: `git push origin feature/amazing-feature`
186+
5. Відкрийте Pull Request
187+
188+
## 💡 Ідеї для Покращення
189+
190+
- [x] ~~Додати Examples 3 та 4 (складний приклад, Fetch API)~~
191+
- [x] ~~Keyboard shortcuts (Space, числа, A, C)~~
192+
- [x] ~~Responsive сайдбар з shadcn/ui~~
193+
- [x] ~~Візуалізація Stack та Heap пам'яті~~
194+
- [x] ~~Приклад роботи з пам'яттю~~
195+
- [ ] Інтерактивний режим для створення власних прикладів
196+
- [ ] Експорт історії виконання
197+
- [ ] Додаткові мови інтерфейсу (EN, PL)
198+
- [ ] Анімації з Framer Motion
199+
- [ ] Touch gestures для мобільних
200+
201+
## 📈 SEO та Performance
202+
203+
Проект оптимізований для пошукових систем:
204+
- ✅ Structured Data (JSON-LD) з інформацією про автора
205+
- ✅ Open Graph та Twitter Cards
206+
- ✅ robots.txt та sitemap.xml
207+
- ✅ Оптимізовані meta теги
208+
- ✅ humans.txt з інформацією про команду
209+
- ✅ Bundle size: ~112 KB (gzipped)
210+
211+
## 📸 Screenshots
212+
213+
### Світла Тема
214+
![Light Theme](./screenshot.png)
215+
216+
### Темна Тема
217+
Підтримка темної теми з автоматичним визначенням системних налаштувань
218+
219+
### Мобільна Версія
220+
Повністю адаптивний дизайн для всіх пристроїв
221+
222+
## 📄 Ліцензія
223+
224+
Цей проект поширюється під ліцензією MIT. Див. файл [LICENSE](./LICENSE) для деталей.
225+
226+
## 👨‍💻 Автор
227+
228+
**Vitalii Reva**
229+
- Email: [vitalii4reva@gmail.com](mailto:vitalii4reva@gmail.com)
230+
- GitHub: [@vitalii4reva](https://github.com/vitalii4reva)
231+
- Website: [vitalii4reva.com](https://vitalii4reva.com)
232+
233+
## 🙏 Подяки
234+
235+
- Натхнення від освітніх матеріалів по JavaScript
236+
- Спільнота React та TypeScript
237+
- [shadcn/ui](https://ui.shadcn.com/) за чудові компоненти
238+
239+
## 📊 Статус Проекту
240+
241+
![Build](https://img.shields.io/github/actions/workflow/status/vitalii4reva/visual-js-event-loop/deploy.yml?branch=main)
242+
![Last Commit](https://img.shields.io/github/last-commit/vitalii4reva/visual-js-event-loop)
243+
![Contributors](https://img.shields.io/github/contributors/vitalii4reva/visual-js-event-loop)
244+
245+
---
246+
247+
<div align="center">
248+
249+
**Зроблено з ❤️ в Україні 🇺🇦**
250+
251+
[⭐ Star на GitHub](https://github.com/vitalii4reva/visual-js-event-loop)[🐛 Повідомити про баг](https://github.com/vitalii4reva/visual-js-event-loop/issues)[💡 Запропонувати функцію](https://github.com/vitalii4reva/visual-js-event-loop/issues)
252+
253+
</div>

dist/index.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
<meta name="theme-color" content="#1e293b" media="(prefers-color-scheme: dark)">
5353

5454
<!-- Favicon -->
55-
<link rel="icon" type="image/x-icon" href="/favicon.ico">
55+
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
56+
<link rel="alternate icon" type="image/x-icon" href="/favicon.ico">
57+
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
5658

5759
<!-- Structured Data JSON-LD -->
5860
<script type="application/ld+json">
@@ -149,8 +151,8 @@
149151
}
150152
</script>
151153
<!-- End Google Tag Manager -->
152-
<script type="module" crossorigin src="/visual-js-event-loop/assets/index-BfAq5QEV.js"></script>
153-
<link rel="stylesheet" crossorigin href="/visual-js-event-loop/assets/index-D67uQN3c.css">
154+
<script type="module" crossorigin src="/visual-js-event-loop/assets/index-CJx2MF7c.js"></script>
155+
<link rel="stylesheet" crossorigin href="/visual-js-event-loop/assets/index-DeaXlI7w.css">
154156
</head>
155157
<body>
156158
<!-- Google Tag Manager (noscript) -->

src/App.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ThemeProvider } from '@/context/ThemeProvider'
2+
import { LanguageProvider } from '@/context/LanguageProvider'
23
import { Header } from '@/components/layout/Header'
34
import { CallStack } from '@/components/event-loop/CallStack'
45
import { WebAPIs } from '@/components/event-loop/WebAPIs'
@@ -16,12 +17,14 @@ import { useEventLoop } from '@/hooks/useEventLoop'
1617
import { useStepExecution } from '@/hooks/useStepExecution'
1718
import { useKeyboardShortcuts } from '@/hooks/useKeyboardShortcuts'
1819
import { useIsMobile } from '@/hooks/use-mobile'
19-
import { examples } from '@/lib/examples'
20-
import { translations } from '@/i18n/translations'
20+
import { getExamples } from '@/lib/examples'
21+
import { useLanguage } from '@/context/LanguageProvider'
2122
import { Separator } from '@/components/ui/separator'
2223
import { SidebarProvider, SidebarTrigger, SidebarInset, useSidebar } from '@/components/ui/sidebar'
2324

2425
function AppContent() {
26+
const { t } = useLanguage()
27+
const examples = getExamples(t)
2528
const { state, actions } = useEventLoop()
2629
const { toggleSidebar, open, isMobile } = useSidebar()
2730
const {
@@ -107,7 +110,7 @@ function AppContent() {
107110
stepCount={state.stepCount}
108111
stepInfo={state.history.length > 0
109112
? state.history[state.history.length - 1].message
110-
: translations.select_example}
113+
: t.select_example}
111114
canProceed={canProceed}
112115
showManualHint={showManualHint}
113116
/>
@@ -162,13 +165,15 @@ function App() {
162165
const isMobile = useIsMobile()
163166

164167
return (
165-
<ThemeProvider defaultTheme="system" storageKey="event-loop-theme">
166-
<SidebarProvider defaultOpen={!isMobile}>
167-
<div className="flex min-h-screen w-full bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-slate-900 dark:to-slate-800 transition-colors duration-300">
168-
<AppContent />
169-
</div>
170-
</SidebarProvider>
171-
</ThemeProvider>
168+
<LanguageProvider>
169+
<ThemeProvider defaultTheme="system" storageKey="event-loop-theme">
170+
<SidebarProvider defaultOpen={!isMobile}>
171+
<div className="flex min-h-screen w-full bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-slate-900 dark:to-slate-800 transition-colors duration-300">
172+
<AppContent />
173+
</div>
174+
</SidebarProvider>
175+
</ThemeProvider>
176+
</LanguageProvider>
172177
)
173178
}
174179

src/components/layout/EmptyState.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { FileCode, ArrowLeft, Smartphone } from 'lucide-react'
22
import { Button } from '@/components/ui/button'
33
import { useSidebar } from '@/components/ui/sidebar'
44
import { useIsMobile } from '@/hooks/use-mobile'
5+
import { useLanguage } from '@/context/LanguageProvider'
56

67
export function EmptyState() {
78
const { toggleSidebar, open } = useSidebar()
89
const isMobile = useIsMobile()
10+
const { t } = useLanguage()
911

1012
return (
1113
<div className="flex items-center justify-center min-h-[60vh]">
@@ -29,12 +31,12 @@ export function EmptyState() {
2931
{/* Title */}
3032
<div className="space-y-2">
3133
<h2 className="text-2xl font-bold text-foreground">
32-
Виберіть приклад для початку
34+
{t.empty_state_title}
3335
</h2>
3436
<p className="text-muted-foreground">
3537
{isMobile
36-
? "Натисніть кнопку меню зліва вгорі та оберіть один з прикладів коду"
37-
: "Оберіть один з прикладів у лівій панелі або натисніть клавіші 0-4"
38+
? t.empty_state_description_mobile
39+
: t.empty_state_description_desktop
3840
}
3941
</p>
4042
</div>
@@ -47,7 +49,7 @@ export function EmptyState() {
4749
className="gap-2 shadow-lg"
4850
>
4951
<Smartphone className="w-5 h-5" />
50-
Відкрити меню з прикладами
52+
{t.empty_state_open_menu}
5153
</Button>
5254
)}
5355

@@ -57,19 +59,19 @@ export function EmptyState() {
5759
<span className="inline-flex items-center justify-center w-6 h-6 rounded bg-primary/10 text-primary font-mono text-xs">
5860
0
5961
</span>
60-
Пам'ять та Змінні
62+
{t.empty_state_memory_example}
6163
</p>
6264
<p className="flex items-center justify-center gap-2">
6365
<span className="inline-flex items-center justify-center w-6 h-6 rounded bg-primary/10 text-primary font-mono text-xs">
6466
1
6567
</span>
66-
setTimeout
68+
{t.empty_state_setTimeout_example}
6769
</p>
6870
<p className="flex items-center justify-center gap-2">
6971
<span className="inline-flex items-center justify-center w-6 h-6 rounded bg-primary/10 text-primary font-mono text-xs">
7072
2
7173
</span>
72-
Promise vs setTimeout
74+
{t.empty_state_promise_example}
7375
</p>
7476
</div>
7577
</div>

0 commit comments

Comments
 (0)