From 2ef8da6da56da6f39462de60d1fa1bbaeb5be221 Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Mon, 29 May 2023 07:40:17 +0300 Subject: [PATCH] Feature/85 side panel (#104) * Add shortcuts list to the side panel * Night mode style --- package-lock.json | 147 +++++++++++++++ package.json | 1 + public/icons/night-theme.svg | 4 + public/locales/en/translation.json | 19 +- public/locales/ru/translation.json | 19 +- public/logo.svg | 3 +- src/components/Article/FullArticle.tsx | 12 +- src/components/Discours/Footer.module.scss | 9 +- src/components/Editor/Panel/Panel.module.scss | 45 ++++- src/components/Editor/Panel/Panel.tsx | 177 +++++++++++++----- .../TextBubbleMenu/TextBubbleMenu.module.scss | 10 +- src/components/Nav/Header.module.scss | 59 +++--- src/components/Nav/HeaderAuth.tsx | 2 +- src/components/Nav/Snackbar.module.scss | 2 +- .../_shared/Button/Button.module.scss | 10 +- .../DarkModeToggle/DarkModeToggle.module.scss | 57 ++++++ .../_shared/DarkModeToggle/DarkModeToggle.tsx | 64 +++++++ .../_shared/DarkModeToggle/index.ts | 1 + .../GrowingTextarea.module.scss | 5 +- .../GrowingTextarea/GrowingTextarea.tsx | 2 +- src/components/_shared/Popover/Popover.tsx | 2 +- .../_shared/Popup/Popup.module.scss | 4 +- src/styles/app.scss | 40 +++- 23 files changed, 582 insertions(+), 112 deletions(-) create mode 100644 public/icons/night-theme.svg create mode 100644 src/components/_shared/DarkModeToggle/DarkModeToggle.module.scss create mode 100644 src/components/_shared/DarkModeToggle/DarkModeToggle.tsx create mode 100644 src/components/_shared/DarkModeToggle/index.ts diff --git a/package-lock.json b/package-lock.json index 90f794ce..726c46b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@aws-sdk/client-s3": "3.303.0", "@aws-sdk/lib-storage": "3.303.0", "@hocuspocus/provider": "2.0.6", + "@solid-primitives/media": "2.2.3", "form-data": "4.0.0", "formidable": "2.1.1", "i18next": "22.4.15", @@ -5634,6 +5635,47 @@ "@sinonjs/commons": "^2.0.0" } }, + "node_modules/@solid-primitives/event-listener": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/@solid-primitives/event-listener/-/event-listener-2.2.13.tgz", + "integrity": "sha512-8GtVEq0ECZoa5Klo1jjfGPfwg0zVJ8TNnNkWu8FqRkh0CkhbhCVJAKwjleem9K/qL6zUDfJihLjhqGBTBbb+8w==", + "dependencies": { + "@solid-primitives/utils": "^6.2.0" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/event-listener/node_modules/@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/media": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@solid-primitives/media/-/media-2.2.3.tgz", + "integrity": "sha512-xhKaTJjH6e65OL706/hA38WWitafbJCm/Zpv7qAn4cy/cgxZ39Cl0bPdYzZhUlkJvTt8YVT0IBcOBLKlJVaPRg==", + "dependencies": { + "@solid-primitives/event-listener": "^2.2.13", + "@solid-primitives/rootless": "^1.4.1", + "@solid-primitives/static-store": "^0.0.4", + "@solid-primitives/utils": "^6.2.0" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/media/node_modules/@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, "node_modules/@solid-primitives/memo": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@solid-primitives/memo/-/memo-1.2.4.tgz", @@ -5668,6 +5710,25 @@ "solid-js": "^1.6.12" } }, + "node_modules/@solid-primitives/rootless": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@solid-primitives/rootless/-/rootless-1.4.1.tgz", + "integrity": "sha512-h7VBUk8usD76Eh1a4wT17PcGtIRxGPlLuJ4Mf7roCNu46W5cc9DAoz8M6XebuZWVKeUkML/JuPMZQSV0mLo2Fw==", + "dependencies": { + "@solid-primitives/utils": "^6.2.0" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/rootless/node_modules/@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, "node_modules/@solid-primitives/scheduled": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@solid-primitives/scheduled/-/scheduled-1.3.2.tgz", @@ -5686,6 +5747,25 @@ "solid-js": "^1.6.12" } }, + "node_modules/@solid-primitives/static-store": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@solid-primitives/static-store/-/static-store-0.0.4.tgz", + "integrity": "sha512-NcLtDNA6H+Z9LmqaUe4SKfMx0YbszIMXEqfV15cB34t5XyEeOM5TihYwsVJ/dpkmpHYzflm0SwAL+P9uwyzvWQ==", + "dependencies": { + "@solid-primitives/utils": "^6.2.0" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/static-store/node_modules/@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, "node_modules/@solid-primitives/storage": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/@solid-primitives/storage/-/storage-1.3.9.tgz", @@ -24755,6 +24835,41 @@ "@sinonjs/commons": "^2.0.0" } }, + "@solid-primitives/event-listener": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/@solid-primitives/event-listener/-/event-listener-2.2.13.tgz", + "integrity": "sha512-8GtVEq0ECZoa5Klo1jjfGPfwg0zVJ8TNnNkWu8FqRkh0CkhbhCVJAKwjleem9K/qL6zUDfJihLjhqGBTBbb+8w==", + "requires": { + "@solid-primitives/utils": "^6.2.0" + }, + "dependencies": { + "@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "requires": {} + } + } + }, + "@solid-primitives/media": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@solid-primitives/media/-/media-2.2.3.tgz", + "integrity": "sha512-xhKaTJjH6e65OL706/hA38WWitafbJCm/Zpv7qAn4cy/cgxZ39Cl0bPdYzZhUlkJvTt8YVT0IBcOBLKlJVaPRg==", + "requires": { + "@solid-primitives/event-listener": "^2.2.13", + "@solid-primitives/rootless": "^1.4.1", + "@solid-primitives/static-store": "^0.0.4", + "@solid-primitives/utils": "^6.2.0" + }, + "dependencies": { + "@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "requires": {} + } + } + }, "@solid-primitives/memo": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@solid-primitives/memo/-/memo-1.2.4.tgz", @@ -24783,6 +24898,22 @@ "@solid-primitives/utils": "^5.5.1" } }, + "@solid-primitives/rootless": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@solid-primitives/rootless/-/rootless-1.4.1.tgz", + "integrity": "sha512-h7VBUk8usD76Eh1a4wT17PcGtIRxGPlLuJ4Mf7roCNu46W5cc9DAoz8M6XebuZWVKeUkML/JuPMZQSV0mLo2Fw==", + "requires": { + "@solid-primitives/utils": "^6.2.0" + }, + "dependencies": { + "@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "requires": {} + } + } + }, "@solid-primitives/scheduled": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@solid-primitives/scheduled/-/scheduled-1.3.2.tgz", @@ -24797,6 +24928,22 @@ "dev": true, "requires": {} }, + "@solid-primitives/static-store": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@solid-primitives/static-store/-/static-store-0.0.4.tgz", + "integrity": "sha512-NcLtDNA6H+Z9LmqaUe4SKfMx0YbszIMXEqfV15cB34t5XyEeOM5TihYwsVJ/dpkmpHYzflm0SwAL+P9uwyzvWQ==", + "requires": { + "@solid-primitives/utils": "^6.2.0" + }, + "dependencies": { + "@solid-primitives/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==", + "requires": {} + } + } + }, "@solid-primitives/storage": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/@solid-primitives/storage/-/storage-1.3.9.tgz", diff --git a/package.json b/package.json index 0bc6985f..b94cd67c 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@aws-sdk/client-s3": "3.303.0", "@aws-sdk/lib-storage": "3.303.0", "@hocuspocus/provider": "2.0.6", + "@solid-primitives/media": "2.2.3", "form-data": "4.0.0", "formidable": "2.1.1", "i18next": "22.4.15", diff --git a/public/icons/night-theme.svg b/public/icons/night-theme.svg new file mode 100644 index 00000000..91aa910e --- /dev/null +++ b/public/icons/night-theme.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 453916b7..711e6c01 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -15,6 +15,7 @@ "Audio": "Audio", "Author": "Author", "Authors": "Authors", + "Autotypograph": "Autotypograph", "Back to main page": "Back to main page", "Become an author": "Become an author", "Bookmarked": "Saved", @@ -73,7 +74,7 @@ "Feed settings": "Feed settings", "Feedback": "Feedback", "Fill email": "Fill email", - "Fix typography": "Fix typography", + "Fixed": "Fixed", "Follow": "Follow", "Follow the topic": "Follow the topic", "Followers": "Followers", @@ -132,6 +133,7 @@ "New only": "New only", "New password": "New password", "New stories every day and even more!": "New stories and more are waiting for you every day!", + "Night mode": "Night mode", "No such account, please try to register": "No such account found, please try to register", "Nothing here yet": "There's nothing here yet", "Nothing is here": "There is nothing here", @@ -204,6 +206,7 @@ "Suggest an idea": "Suggest an idea", "Support us": "Help the magazine", "Terms of use": "Site rules", + "Text checking": "Text checking", "Thank you": "Thank you", "This comment has not yet been rated": "This comment has not yet been rated", "This email is already taken. If it's you": "This email is already taken. If it's you", @@ -280,5 +283,17 @@ "topics": "topics", "user already exist": "user already exists", "view": "view", - "zine": "zine" + "zine": "zine", + "back to menu": "back to menu", + "bold": "bold", + "italic": "italic", + "add link": "add link", + "header 1": "header 1", + "header 2": "header 2", + "header 3": "header 3", + "marker list": "marker list", + "number list": "number list", + "delimiter": "delimiter", + "cancel_low_caps": "cancel", + "repeat": "repeat" } diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 644b415f..72a75569 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -17,6 +17,7 @@ "Audio": "Аудио", "Author": "Автор", "Authors": "Авторы", + "Autotypograph": "Автотипограф", "Back to main page": "Вернуться на главную", "Become an author": "Стать автором", "Bookmarked": "Сохранено", @@ -76,7 +77,7 @@ "Feed settings": "Настройки ленты", "Feedback": "Обратная связь", "Fill email": "Введите почту", - "Fix typography": "Исправить типографику", + "Fixed": "Все поправлено", "Follow": "Подписаться", "Follow the topic": "Подписаться на тему", "Followers": "Подписчики", @@ -139,6 +140,7 @@ "New only": "Только новые", "New password": "Новый пароль", "New stories every day and even more!": "Каждый день вас ждут новые истории и ещё много всего интересного!", + "Night mode": "Ночная тема", "No such account, please try to register": "Такой адрес не найден, попробуйте зарегистрироваться", "Nothing here yet": "Здесь пока ничего нет", "Nothing is here": "Здесь ничего нет", @@ -217,6 +219,7 @@ "Suggest an idea": "Предложить идею", "Support us": "Помочь журналу", "Terms of use": "Правила сайта", + "Text checking": "Проверка текста", "Thank you": "Благодарности", "This comment has not yet been rated": "Этот комментарий еще пока никто не оценил", "This email is already taken. If it's you": "Такой email уже зарегистрирован. Если это вы", @@ -301,5 +304,17 @@ "topics": "темы", "user already exist": "пользователь уже существует", "view": "просмотр", - "zine": "журнал" + "zine": "журнал", + "back to menu": "назад в меню", + "bold": "жирный", + "italic": "курсив", + "add link": "добавить ссылку", + "header 1": "заголовок 1", + "header 2": "заголовок 2", + "header 3": "заголовок 3", + "marker list": "маркир. список", + "number list": "нумер. список", + "delimiter": "разделитель", + "cancel_low_caps": "отменить", + "repeat": "повторить" } diff --git a/public/logo.svg b/public/logo.svg index bf7f6de3..6863a4bd 100644 --- a/public/logo.svg +++ b/public/logo.svg @@ -1,3 +1,4 @@ - + diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 08105677..ad14135a 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -1,17 +1,7 @@ import { capitalize, formatDate } from '../../utils' import { Icon } from '../_shared/Icon' import { AuthorCard } from '../Author/AuthorCard' -import { - createEffect, - createMemo, - createSignal, - For, - Match, - onCleanup, - onMount, - Show, - Switch -} from 'solid-js' +import { createEffect, createMemo, createSignal, For, Match, onMount, Show, Switch } from 'solid-js' import type { Author, Shout } from '../../graphql/types.gen' import MD from './MD' import { SharePopup } from './SharePopup' diff --git a/src/components/Discours/Footer.module.scss b/src/components/Discours/Footer.module.scss index 129668e8..bb82ad84 100644 --- a/src/components/Discours/Footer.module.scss +++ b/src/components/Discours/Footer.module.scss @@ -1,6 +1,5 @@ .discoursFooter { @include font-size(1.7rem); - background: #000; color: rgb(255 255 255 / 64%); padding: 2.4rem 0 4.2rem; @@ -22,10 +21,11 @@ a { color: rgb(255 255 255 / 64%); - transition: color 0.3s; + transition: color 0.3s, background-color 0.3s; &:hover { - color: #fff; + background: #fff; + color: #000; } } } @@ -58,7 +58,8 @@ color: rgb(255 255 255 / 70%); &:hover { - color: #fff; + background: #fff; + color: #000; } } } diff --git a/src/components/Editor/Panel/Panel.module.scss b/src/components/Editor/Panel/Panel.module.scss index 539ff8ad..2f8b590f 100644 --- a/src/components/Editor/Panel/Panel.module.scss +++ b/src/components/Editor/Panel/Panel.module.scss @@ -1,10 +1,7 @@ .Panel { background: #1f1f1f; color: rgb(255 255 255 / 35%); - display: flex; - flex-direction: column; font-size: 1.7rem; - justify-content: flex-start; height: 100%; line-height: 1.4; padding: $grid-gutter-width calc($grid-gutter-width / 2); @@ -20,7 +17,9 @@ } .actionsHolder { - padding: 0 calc($grid-gutter-width / 2); + height: 100%; + display: flex; + flex-direction: column; &.scrolled { overflow-y: auto; @@ -61,6 +60,7 @@ text-decoration: none; border-bottom: none; color: rgb(255 255 255 / 35%); + font-size: inherit; font-weight: normal !important; &:hover { @@ -95,4 +95,41 @@ vertical-align: bottom; } } + + .typograph { + align-items: baseline; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + } + + .typographStatus { + @include font-size(1.2rem); + } + + .typographStatusSuccess { + color: #28d353; + } + + .backToMenuControl { + color: rgb(255 255 255 / 0.7); + } + + .shortcutList { + color: #fff; + } + + .shortcut { + margin-left: 1em; + } + + .shortcutButton { + border: 1px solid; + border-bottom-width: 2px; + border-radius: 2px; + display: inline-block; + font-style: italic; + margin-right: 0.5em; + padding: 0.1em 0.4em; + } } diff --git a/src/components/Editor/Panel/Panel.tsx b/src/components/Editor/Panel/Panel.tsx index 2313c50c..c9a7cca7 100644 --- a/src/components/Editor/Panel/Panel.tsx +++ b/src/components/Editor/Panel/Panel.tsx @@ -10,6 +10,8 @@ import { getPagePath } from '@nanostores/router' import { router } from '../../../stores/router' import { useEditorHTML } from 'solid-tiptap' import Typograf from 'typograf' +import { createSignal, Show } from 'solid-js' +import { DarkModeToggle } from '../../_shared/DarkModeToggle' const typograf = new Typograf({ locale: ['ru', 'en-US'] }) @@ -30,6 +32,9 @@ export const Panel = (props: Props) => { current: null } + const [isShortcutsVisible, setIsShortcutsVisible] = createSignal(false) + const [isTypographyFixed, setIsTypographyFixed] = createSignal(false) + useOutsideClickHandler({ containerRef, predicate: () => isEditorPanelVisible(), @@ -53,6 +58,7 @@ export const Panel = (props: Props) => { const handleFixTypographyClick = () => { const html = useEditorHTML(() => editorRef.current()) editorRef.current().commands.setContent(typograf.execute(html())) + setIsTypographyFixed(true) } return ( @@ -60,15 +66,13 @@ export const Panel = (props: Props) => { ref={(el) => (containerRef.current = el)} class={clsx('col-md-6', styles.Panel, { [styles.hidden]: !isEditorPanelVisible() })} > -
-
-
+

@@ -160,6 +152,107 @@ export const Panel = (props: Props) => { {/*

*/} + +
+

+ +

+ +
+

+ {t('bold')} + + Ctrl + B + +

+

+ {t('italic')} + + Ctrl + I + +

+

+ {t('add link')} + + Ctrl + K + +

+
+ +
+

+ {t('header 1')} + + Ctrl + Alt + 1 + +

+

+ {t('header 2')} + + Ctrl + Alt + 2 + +

+

+ {t('header 3')} + + Ctrl + Alt + 3 + +

+
+ +
+

+ {t('marker list')} + + * + Space + +

+

+ {t('number list')} + + 1 + Space + +

+

+ {t('delimiter')} + + *** + Enter + +

+
+ +
+

+ {t('cancel_low_caps')} + + Ctrl + Z + +

+

+ {t('repeat')} + + Ctrl + Shift + Z + +

+
+
) } diff --git a/src/components/Editor/TextBubbleMenu/TextBubbleMenu.module.scss b/src/components/Editor/TextBubbleMenu/TextBubbleMenu.module.scss index d82cd864..f9f613e5 100644 --- a/src/components/Editor/TextBubbleMenu/TextBubbleMenu.module.scss +++ b/src/components/Editor/TextBubbleMenu/TextBubbleMenu.module.scss @@ -1,5 +1,5 @@ .TextBubbleMenu { - background: #fff; + background: var(--editor-bubble-menu-background); box-shadow: 0 4px 10px rgba(#000, 0.25); .bubbleMenuButton { @@ -21,6 +21,10 @@ border-radius: 50%; background: #f6e3a1; } + + img { + filter: var(--icon-filter); + } } .bubbleMenuButtonActive { @@ -50,8 +54,8 @@ left: 50%; transform: translateX(-50%); box-shadow: 0 4px 10px rgb(0 0 0 / 25%); - background: #fff; - color: #898c94; + background: var(--editor-bubble-menu-background); + color: var(--default-color); & > header { font-size: 10px; diff --git a/src/components/Nav/Header.module.scss b/src/components/Nav/Header.module.scss index e383b4c7..d475f070 100644 --- a/src/components/Nav/Header.module.scss +++ b/src/components/Nav/Header.module.scss @@ -1,5 +1,6 @@ .mainHeader { - background: #fff; + background: var(--background-color); + color: var(--default-color); font-size: 1.4rem; margin-bottom: 2.2rem; position: absolute; @@ -42,7 +43,8 @@ .headerInner { align-items: center; - background: #fff; + background: var(--background-color); + color: var(--default-color); flex-wrap: nowrap !important; justify-content: flex-start; margin: 0; @@ -63,6 +65,7 @@ .mainLogo { align-items: center; + color: var(--default-color); display: inline-flex; height: 56px; padding: 0; @@ -81,20 +84,20 @@ transition: height 0.2s; vertical-align: middle; width: 100px; + + [data-editor-dark-mode='true'] & { + filter: invert(1); + } } a, a:link, a:visited { border-bottom: none; - color: #000; + color: var(--link-color); &:hover { background: none; - - img { - filter: none; - } } } } @@ -142,13 +145,13 @@ } @include media-breakpoint-down(md) { - background: #fff; + background: var(--background-color); bottom: 0; display: none; font-size: 2.6rem; font-weight: bold; left: 0; - padding: $container-padding-x; + padding: $container-padding-x !important; position: fixed; top: 74px; width: 100%; @@ -160,14 +163,17 @@ } @include media-breakpoint-down(sm) { - padding: divide($container-padding-x, 2); + padding: divide($container-padding-x, 2) !important; } - .fixed & { - display: inline-flex; + @include media-breakpoint-down(md) { + :global(.fixed) & { + font-size: 2.2rem !important; - @include media-breakpoint-down(lg) { - display: block !important; + &, + li { + display: block !important; + } } } } @@ -196,7 +202,6 @@ } .burger { - background: #fff; cursor: pointer; height: 1.8rem; display: inline-block; @@ -207,7 +212,7 @@ > div, &::after, &::before { - background: #000; + background: var(--link-color); content: ''; display: block; height: 2px; @@ -412,21 +417,21 @@ background: none; &::before { - background-color: #000; + background-color: var(--default-color); } img { - filter: invert(1); + filter: var(--icon-filter-hover); } } img { - filter: invert(0); + filter: var(--icon-filter); transition: filter 0.3s; } &::before { - background-color: #fff; + background-color: var(--background-color); border-radius: 100%; content: ''; height: 100%; @@ -459,7 +464,7 @@ } .userControlItemVerbose { - margin-left: 0.5em; + margin-left: 1.2em !important; &:global(.loginbtn) { .icon { @@ -475,6 +480,7 @@ } @include media-breakpoint-up(lg) { + margin-left: 0.5em !important; margin-right: 0; width: auto; @@ -483,7 +489,8 @@ } .textLabel { - padding: 0 1.2rem; + color: var(--link-color); + padding: 0; display: inline; position: relative; z-index: 1; @@ -495,9 +502,17 @@ border-radius: 1.2em !important; } + button:hover, a:hover { + background-color: var(--link-hover-background); + color: var(--link-hover-color); + .icon { filter: invert(0); } + + .textLabel { + color: var(--link-hover-color); + } } } diff --git a/src/components/Nav/HeaderAuth.tsx b/src/components/Nav/HeaderAuth.tsx index 62c212e5..46c1ea19 100644 --- a/src/components/Nav/HeaderAuth.tsx +++ b/src/components/Nav/HeaderAuth.tsx @@ -2,7 +2,7 @@ import styles from './Header.module.scss' import { clsx } from 'clsx' import { router, useRouter } from '../../stores/router' import { Icon } from '../_shared/Icon' -import { createEffect, createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' +import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' import Notifications from './Notifications' import { ProfilePopup } from './ProfilePopup' import Userpic from '../Author/Userpic' diff --git a/src/components/Nav/Snackbar.module.scss b/src/components/Nav/Snackbar.module.scss index 7d2c56ae..ade8289a 100644 --- a/src/components/Nav/Snackbar.module.scss +++ b/src/components/Nav/Snackbar.module.scss @@ -1,6 +1,6 @@ .snackbar { min-height: 2px; - background-color: #141414; + background-color: var(--default-color); color: #fff; transition: background-color 0.3s; diff --git a/src/components/_shared/Button/Button.module.scss b/src/components/_shared/Button/Button.module.scss index f6149439..6b7c32e4 100644 --- a/src/components/_shared/Button/Button.module.scss +++ b/src/components/_shared/Button/Button.module.scss @@ -61,18 +61,18 @@ &:hover, &:active { - background: #000; - border-color: #000; - color: #fff; + background: var(--link-color); + border-color: var(--link-color); + color: var(--link-hover-color); :global(.icon) { - filter: invert(1); + filter: var(--icon-filter-hover); } } :global(.icon) { margin: 0 -0.5em; - filter: invert(0); + filter: var(--icon-filter); transition: filter 0.3s; } } diff --git a/src/components/_shared/DarkModeToggle/DarkModeToggle.module.scss b/src/components/_shared/DarkModeToggle/DarkModeToggle.module.scss new file mode 100644 index 00000000..e5a48870 --- /dev/null +++ b/src/components/_shared/DarkModeToggle/DarkModeToggle.module.scss @@ -0,0 +1,57 @@ +.DarkModeToggle { + .switcher { + background: #000; + border-radius: 2em; + height: 2.8rem; + position: relative; + width: 4.6rem; + + &:before { + background: #fff; + border-radius: 100%; + content: ''; + height: 1.6rem; + left: 0.6rem; + position: absolute; + top: 0.6rem; + transition: left 0.3s; + width: 1.6rem; + z-index: 1; + } + + .icon { + filter: none; + height: 1rem; + position: absolute; + right: 0.5rem; + top: 0.9rem; + width: auto; + } + } + + input { + opacity: 0; + position: absolute; + z-index: -1; + + & + label { + cursor: pointer; + display: flex; + justify-content: space-between; + padding: 0; + position: relative; + + &:before { + display: none; + } + } + + &:checked + label { + .switcher { + &:before { + left: 2.4rem; + } + } + } + } +} diff --git a/src/components/_shared/DarkModeToggle/DarkModeToggle.tsx b/src/components/_shared/DarkModeToggle/DarkModeToggle.tsx new file mode 100644 index 00000000..06ef580e --- /dev/null +++ b/src/components/_shared/DarkModeToggle/DarkModeToggle.tsx @@ -0,0 +1,64 @@ +import { clsx } from 'clsx' +import styles from './DarkModeToggle.module.scss' +import { Icon } from '../Icon' +import { useLocalize } from '../../../context/localize' +import { createEffect, createSignal, onCleanup, onMount } from 'solid-js' +import { createPrefersDark } from '@solid-primitives/media' + +type Props = { + class?: string +} + +const editorDarkModeSelected = localStorage.getItem('editorDarkMode') +const editorDarkModeAttr = document.documentElement.getAttribute('editorDarkMode') + +export const DarkModeToggle = (props: Props) => { + const { t } = useLocalize() + const prefersDark = createPrefersDark() + const [editorDarkMode, setEditorDarkMode] = createSignal(false) + + onMount(() => { + if (editorDarkModeSelected === 'true') { + setEditorDarkMode(true) + document.documentElement.dataset.editorDarkMode = 'true' + } else if (editorDarkModeSelected === 'false') { + setEditorDarkMode(false) + document.documentElement.dataset.editorDarkMode = 'false' + } + + if (!editorDarkModeAttr && !editorDarkModeSelected) { + setEditorDarkMode(prefersDark()) + localStorage.setItem('editorDarkMode', prefersDark() ? 'true' : 'false') + document.documentElement.dataset.editorDarkMode = prefersDark() ? 'true' : 'false' + } + + onCleanup(() => { + setEditorDarkMode(false) + delete document.documentElement.dataset.editorDarkMode + }) + }) + + const handleSwitchTheme = () => { + setEditorDarkMode(!editorDarkMode()) + localStorage.setItem('editorDarkMode', editorDarkMode() ? 'true' : 'false') + document.documentElement.dataset.editorDarkMode = editorDarkMode() ? 'true' : 'false' + } + + return ( +
+ + +
+ ) +} diff --git a/src/components/_shared/DarkModeToggle/index.ts b/src/components/_shared/DarkModeToggle/index.ts new file mode 100644 index 00000000..7e5abe18 --- /dev/null +++ b/src/components/_shared/DarkModeToggle/index.ts @@ -0,0 +1 @@ +export { DarkModeToggle } from './DarkModeToggle' diff --git a/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss b/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss index bb642ee9..272dc522 100644 --- a/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss +++ b/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss @@ -14,8 +14,10 @@ } .textInput { - margin-bottom: 0; + background: var(--background-color); border: none; + color: var(--default-color); + margin-bottom: 0; resize: none; overflow: hidden; @@ -45,6 +47,7 @@ } .maxLength { + color: #000; opacity: 1; position: absolute; right: 0.6rem; diff --git a/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx b/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx index 40d01c1d..434753a9 100644 --- a/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx +++ b/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx @@ -44,7 +44,7 @@ export const GrowingTextarea = (props: Props) => { onBlur={() => setIsFocused(false)} /> - +