diff --git a/libs/client-shared/src/providers/Notifications/ui/notifications-provider.tsx b/libs/client-shared/src/providers/notifications/ui/notifications-provider.tsx
similarity index 100%
rename from libs/client-shared/src/providers/Notifications/ui/notifications-provider.tsx
rename to libs/client-shared/src/providers/notifications/ui/notifications-provider.tsx
diff --git a/libs/editor/src/components/settings/hooks/use-color-callback.ts b/libs/editor/src/components/settings/hooks/use-color-callback.ts
new file mode 100644
index 00000000..73eb6ebd
--- /dev/null
+++ b/libs/editor/src/components/settings/hooks/use-color-callback.ts
@@ -0,0 +1,17 @@
+import { CUSTOM_THEME } from '@/shared/consts'
+import { useActions, useStore } from '@/shared/hooks'
+
+import { Hex, useDebounce } from '$/client-shared'
+
+export const useColorCallback = (cb: (hex: Hex) => void) => {
+ const { theme } = useStore()
+ const actions = useActions()
+
+ return useDebounce((_: unknown, hex: Hex) => {
+ if (theme !== CUSTOM_THEME) {
+ actions.changeTheme(CUSTOM_THEME)
+ }
+
+ return cb(hex)
+ }, 300)
+}
diff --git a/libs/editor/src/components/settings/ui/key-buildings/key-buildings.tsx b/libs/editor/src/components/settings/ui/key-buildings/key-buildings.tsx
new file mode 100644
index 00000000..0c476e84
--- /dev/null
+++ b/libs/editor/src/components/settings/ui/key-buildings/key-buildings.tsx
@@ -0,0 +1,45 @@
+import { Typography } from 'antd'
+
+import { KeyBuildings as Keys } from '@/shared/consts'
+
+import { KeyBuildingStyles, SettingsText } from '../settings/settings.styles'
+
+import { WithChildren } from '$/client-shared'
+
+type KeyBuildingProps = WithChildren<{
+ keyCode: string
+ experimental?: boolean
+}>
+
+const KeyBuilding = ({ keyCode, children, experimental }: KeyBuildingProps) => {
+ return (
+
+
+ {experimental ? '🧪' : '✌️'} Alt + {keyCode}
+
+
+ {children}
+
+
+ )
+}
+
+const KeyBuildings = () => {
+ return (
+ <>
+
+ Open a file on your OS
+
+
+ Save a file on your OS
+
+ Open new tab
+ Close current tab
+ Open/close terminal
+ Open/close test cases
+ Open/close settings
+ >
+ )
+}
+
+export default KeyBuildings
diff --git a/libs/editor/src/components/tabs/hooks/use-confirm.ts b/libs/editor/src/components/tabs/hooks/use-confirm.ts
new file mode 100644
index 00000000..54c69901
--- /dev/null
+++ b/libs/editor/src/components/tabs/hooks/use-confirm.ts
@@ -0,0 +1,25 @@
+import { useState } from 'react'
+
+import { AnyFunction, Nullable } from '$/client-shared'
+
+export const useConfirm = () => {
+ const [confirmKey, setConfirmKey] = useState>(null)
+
+ return {
+ protect(callback: AnyFunction) {
+ return (...args: any[]) => {
+ if (confirmKey) {
+ return
+ }
+ callback(...args)
+ }
+ },
+ off() {
+ setConfirmKey(null)
+ },
+ on(key: string) {
+ setConfirmKey(key)
+ },
+ val: confirmKey
+ }
+}
diff --git a/libs/editor/src/components/tabs/hooks/use-mapped-tabs.ts b/libs/editor/src/components/tabs/hooks/use-mapped-tabs.ts
new file mode 100644
index 00000000..7f9f3b1e
--- /dev/null
+++ b/libs/editor/src/components/tabs/hooks/use-mapped-tabs.ts
@@ -0,0 +1,8 @@
+import { ContentTab } from '@/components/tabs'
+
+export const useMappedTabs = (content: ContentTab[]) => {
+ return content.map((tab) => ({
+ label: tab.getLabel(),
+ key: tab.getKeyId()
+ }))
+}
diff --git a/libs/editor/src/components/tabs/lib/helpers/is-max-tabs-length.ts b/libs/editor/src/components/tabs/lib/helpers/is-max-tabs-length.ts
new file mode 100644
index 00000000..6d492eba
--- /dev/null
+++ b/libs/editor/src/components/tabs/lib/helpers/is-max-tabs-length.ts
@@ -0,0 +1,6 @@
+import { ContentTab } from '@/components/tabs'
+import { maxTabsLength } from '@/shared/consts'
+
+export const isMaxTabsLength = (content: ContentTab[]) => {
+ return content.length >= maxTabsLength
+}
diff --git a/libs/editor/src/components/tabs/store/content-tab.ts b/libs/editor/src/components/tabs/store/content-tab.ts
new file mode 100644
index 00000000..328f50b8
--- /dev/null
+++ b/libs/editor/src/components/tabs/store/content-tab.ts
@@ -0,0 +1,107 @@
+import { makeAutoObservable } from 'mobx'
+import { v4 as generateId } from 'uuid'
+
+import { FileHandlerData } from '@/modules/editor-content/types'
+import { LanguagesValues } from '@/shared/consts'
+
+import { ContentTabInstance } from '../types'
+
+import { Nullable } from '$/client-shared'
+
+type ContentTabArgs = Partial<{
+ lastNumber: number
+ fileData: FileHandlerData
+ instance: ContentTabInstance
+}>
+
+export class ContentTab {
+ private _key = generateId()
+ private _fileHandle: Nullable = null
+ private _label = 'Untitled'
+ private _content = ''
+ public idx = 0
+ public lang: LanguagesValues = 'text'
+ public wasChanged = false
+
+ constructor({ lastNumber, fileData, instance }: ContentTabArgs) {
+ makeAutoObservable(this)
+
+ if (instance) {
+ this.initUsingInstance(instance)
+ } else if (fileData) {
+ this.initUsingFileData(fileData)
+ }
+
+ if (lastNumber) {
+ this.idx = lastNumber + 1
+ }
+ }
+
+ public setFileHandle(fileHandle: FileSystemFileHandle) {
+ this._fileHandle = fileHandle
+ this.wasChanged = false
+ this.setLabel(fileHandle.name)
+ }
+
+ public getFileHandle() {
+ return this._fileHandle
+ }
+
+ public setLabel(newLabel: string) {
+ this._label = newLabel
+ }
+
+ public getLabel() {
+ return this._label
+ }
+
+ private updateLabel() {
+ // TODO: refactor
+
+ if (this._fileHandle) {
+ if (!this.wasChanged) {
+ this.setLabel(`${this.getLabel()} •`)
+ }
+ this.wasChanged = true
+
+ return
+ }
+ const firstLine = this._content.split('\n')[0].slice(0, 10)
+ const cropped = firstLine.replace(' ', '').replace('\n', '')
+ const newLabel = `${cropped.length > 1 ? firstLine : 'Untitled'} •`
+ this.wasChanged = true
+
+ this.setLabel(newLabel)
+ }
+
+ public setTabContent(content: string) {
+ this._content = content
+
+ this.updateLabel()
+ }
+
+ public getContent() {
+ return this._content
+ }
+
+ public getKeyId() {
+ return this._key
+ }
+
+ private initUsingFileData(fileData: FileHandlerData) {
+ this._fileHandle = fileData.fileHandle
+ this.lang = fileData.language
+ this._content = fileData.content
+ this._label = fileData.name
+ }
+
+ private initUsingInstance(instance: ContentTabInstance) {
+ this._key = instance._key
+ this._label = instance._label
+ this.idx = instance.idx
+ this._content = instance._content
+ this._fileHandle = instance._fileHandle
+ this.wasChanged = instance.wasChanged
+ this.lang = instance.lang
+ }
+}
diff --git a/libs/editor/src/components/terminal/hooks/use-terminal-tabs.ts b/libs/editor/src/components/terminal/hooks/use-terminal-tabs.ts
new file mode 100644
index 00000000..bde7fc14
--- /dev/null
+++ b/libs/editor/src/components/terminal/hooks/use-terminal-tabs.ts
@@ -0,0 +1,32 @@
+import { useCallback } from 'react'
+
+import { useModalsContext } from '@/shared/hooks'
+
+export type TerminalTabKeys = 'terminal' | 'test_cases'
+
+interface TerminalTab {
+ label: string
+ key: TerminalTabKeys
+}
+
+const terminalTabs: TerminalTab[] = [
+ { label: 'Terminal', key: 'terminal' },
+ { label: 'Test cases', key: 'test_cases' }
+]
+
+export const useTerminalTabs = () => {
+ const modalsContext = useModalsContext()
+ const activeKey = modalsContext.state.selectedTerminalTab
+
+ const setActiveKey = useCallback((key: TerminalTabKeys) => {
+ modalsContext.update({
+ selectedTerminalTab: key
+ })
+ }, [])
+
+ return {
+ key: activeKey,
+ set: setActiveKey,
+ val: terminalTabs
+ }
+}
diff --git a/libs/editor/src/modules/Aside/hooks/use-aside-animation.ts b/libs/editor/src/modules/aside/hooks/use-aside-animation.ts
similarity index 100%
rename from libs/editor/src/modules/Aside/hooks/use-aside-animation.ts
rename to libs/editor/src/modules/aside/hooks/use-aside-animation.ts
diff --git a/libs/editor/src/modules/Aside/hooks/use-editor-actions.ts b/libs/editor/src/modules/aside/hooks/use-editor-actions.ts
similarity index 100%
rename from libs/editor/src/modules/Aside/hooks/use-editor-actions.ts
rename to libs/editor/src/modules/aside/hooks/use-editor-actions.ts
diff --git a/libs/editor/src/modules/Header/hooks/use-code-runner.ts b/libs/editor/src/modules/header/hooks/use-code-runner.ts
similarity index 100%
rename from libs/editor/src/modules/Header/hooks/use-code-runner.ts
rename to libs/editor/src/modules/header/hooks/use-code-runner.ts
diff --git a/libs/editor/src/modules/Header/hooks/use-header-animation.ts b/libs/editor/src/modules/header/hooks/use-header-animation.ts
similarity index 100%
rename from libs/editor/src/modules/Header/hooks/use-header-animation.ts
rename to libs/editor/src/modules/header/hooks/use-header-animation.ts
diff --git a/libs/editor/src/modules/Header/ui/header-options/header-options.styles.ts b/libs/editor/src/modules/header/ui/header-options/header-options.styles.ts
similarity index 100%
rename from libs/editor/src/modules/Header/ui/header-options/header-options.styles.ts
rename to libs/editor/src/modules/header/ui/header-options/header-options.styles.ts
diff --git a/libs/editor/src/modules/Header/ui/header-options/header-options.tsx b/libs/editor/src/modules/header/ui/header-options/header-options.tsx
similarity index 100%
rename from libs/editor/src/modules/Header/ui/header-options/header-options.tsx
rename to libs/editor/src/modules/header/ui/header-options/header-options.tsx
diff --git a/libs/editor/src/modules/Header/ui/header-right-section/header-right-section.styles.ts b/libs/editor/src/modules/header/ui/header-right-section/header-right-section.styles.ts
similarity index 100%
rename from libs/editor/src/modules/Header/ui/header-right-section/header-right-section.styles.ts
rename to libs/editor/src/modules/header/ui/header-right-section/header-right-section.styles.ts
diff --git a/libs/editor/src/modules/Header/ui/header-right-section/header-right-section.tsx b/libs/editor/src/modules/header/ui/header-right-section/header-right-section.tsx
similarity index 100%
rename from libs/editor/src/modules/Header/ui/header-right-section/header-right-section.tsx
rename to libs/editor/src/modules/header/ui/header-right-section/header-right-section.tsx