diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 09a3e7b..4cf03bc 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -6,5 +6,8 @@ "Background": "Background", "Text": "Text", "Links": "Links", - "Colors": "Colors" + "Colors": "Colors", + "Inline code": "Inline code", + "Ok": "Ok", + "Settings": "Settings" } diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 73d416d..d166822 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -6,5 +6,8 @@ "Background": "Фон", "Text": "Текст", "Links": "Ссылки", - "Colors": "Цвета" + "Colors": "Цвета", + "Inline code": "Код в строке", + "Ok": "Ok", + "Settings": "Настройки" } diff --git a/src/components/buttons/Button/styles.module.scss b/src/components/buttons/Button/styles.module.scss index e7ecd2d..835a2d4 100644 --- a/src/components/buttons/Button/styles.module.scss +++ b/src/components/buttons/Button/styles.module.scss @@ -6,6 +6,10 @@ cursor: pointer; transition: all 0.25s; + &.size-normal { + padding: 4px 20px; + } + &.size-small { padding: 2px 16px; font-size: 0.8rem; diff --git a/src/components/containers/RowGroup/index.tsx b/src/components/containers/RowGroup/index.tsx new file mode 100644 index 0000000..a611360 --- /dev/null +++ b/src/components/containers/RowGroup/index.tsx @@ -0,0 +1,18 @@ +import { FC, ReactNode } from "react"; +import styles from "./styles.module.scss"; + +interface RowGroupProps { + children: ReactNode[]; +} + +const RowGroup: FC = ({ children }) => ( +
+ {children.map((item, key) => ( +
+ {item} +
+ ))} +
+); + +export { RowGroup }; diff --git a/src/components/containers/RowGroup/styles.module.scss b/src/components/containers/RowGroup/styles.module.scss new file mode 100644 index 0000000..fc3a8fb --- /dev/null +++ b/src/components/containers/RowGroup/styles.module.scss @@ -0,0 +1,12 @@ +.group { + display: flex; + flex-direction: column; + border-radius: 6px; + box-shadow: var(--color-border) 0 0 0 1px; +} + +.row { + &:not(:last-child) { + box-shadow: var(--color-border) 0 1px; + } +} diff --git a/src/components/containers/SettingsRow/index.tsx b/src/components/containers/SettingsRow/index.tsx new file mode 100644 index 0000000..bfb3bb9 --- /dev/null +++ b/src/components/containers/SettingsRow/index.tsx @@ -0,0 +1,15 @@ +import { FC, PropsWithChildren } from "react"; +import styles from "./styles.module.scss"; + +type SettingsRowProps = PropsWithChildren & { + title: string; +}; + +const SettingsRow: FC = ({ title, children }) => ( +
+
{title}
+
{children}
+
+); + +export { SettingsRow }; diff --git a/src/components/containers/SettingsRow/styles.module.scss b/src/components/containers/SettingsRow/styles.module.scss new file mode 100644 index 0000000..ccdee35 --- /dev/null +++ b/src/components/containers/SettingsRow/styles.module.scss @@ -0,0 +1,11 @@ +.row { + display: flex; + flex-direction: row; + padding: 10px; + align-items: center; + gap: 20px; +} + +.title { + flex: 1; +} diff --git a/src/modules/editor/components/ReactMarkdownViewer/styles.module.scss b/src/modules/editor/components/ReactMarkdownViewer/styles.module.scss index 000781b..096de6b 100644 --- a/src/modules/editor/components/ReactMarkdownViewer/styles.module.scss +++ b/src/modules/editor/components/ReactMarkdownViewer/styles.module.scss @@ -1,6 +1,5 @@ .editor { - position: relative; - height: 100%; + min-height: 100%; box-sizing: border-box; } @@ -17,7 +16,7 @@ } &:hover { - opacity: 1; + opacity: 1 !important; } } diff --git a/src/modules/modal/components/ModalPage/index.tsx b/src/modules/modal/components/ModalPage/index.tsx index e5b7f8d..da7d81a 100644 --- a/src/modules/modal/components/ModalPage/index.tsx +++ b/src/modules/modal/components/ModalPage/index.tsx @@ -1,12 +1,25 @@ import { FC, PropsWithChildren } from "react"; import styles from "./styles.module.scss"; +import { IconButton } from "~/components/buttons/IconButton"; interface ModalPageProps extends PropsWithChildren { + title?: string; onClose: () => void; } -const ModalPage: FC = ({ children }) => ( -
{children}
+const ModalPage: FC = ({ children, title, onClose }) => ( +
+
+
{title}
+
+ + x + +
+
+ + {children} +
); export { ModalPage }; diff --git a/src/modules/modal/components/ModalPage/styles.module.scss b/src/modules/modal/components/ModalPage/styles.module.scss index 29fcf86..4f797e5 100644 --- a/src/modules/modal/components/ModalPage/styles.module.scss +++ b/src/modules/modal/components/ModalPage/styles.module.scss @@ -2,4 +2,16 @@ background: var(--color-background); padding: 16px; border-radius: 10px; + box-shadow: var(--color-border) 0 0 0 1px; +} + +.header { + display: flex; + flex-direction: row; + padding: 0 0 20px 0; +} + +.title { + flex: 1; + font-size: 1.4em; } diff --git a/src/modules/settings/containers/ColorSettings/index.tsx b/src/modules/settings/containers/ColorSettings/index.tsx new file mode 100644 index 0000000..281af32 --- /dev/null +++ b/src/modules/settings/containers/ColorSettings/index.tsx @@ -0,0 +1,70 @@ +import { ChangeEvent, FC, useCallback } from "react"; +import { useTranslation } from "react-i18next"; +import { RowGroup } from "~/components/containers/RowGroup"; +import { SettingsRow } from "~/components/containers/SettingsRow"; +import { + SettingsValue, + useSettings, +} from "~/modules/settings/context/SettingsContext"; + +const ColorSettings: FC = () => { + const { update, settings } = useSettings(); + const { t } = useTranslation(); + + const setString = useCallback( + (field: keyof SettingsValue) => (event: ChangeEvent) => { + update({ [field]: event.target.value }); + }, + [update] + ); + + return ( + + + + + + + + + + ); +}; + +export { ColorSettings }; diff --git a/src/modules/settings/containers/SettingsContainer/index.tsx b/src/modules/settings/containers/SettingsContainer/index.tsx index 9e3c440..c53eb15 100644 --- a/src/modules/settings/containers/SettingsContainer/index.tsx +++ b/src/modules/settings/containers/SettingsContainer/index.tsx @@ -1,66 +1,11 @@ -import { ChangeEvent, FC, useCallback } from "react"; -import { useSettings } from "../../context/SettingsContext"; -import { useTranslation } from "react-i18next"; +import { FC } from "react"; +import { ColorSettings } from "../ColorSettings"; +import styles from "./styles.module.scss"; const SettingsContainer: FC = () => { - const { update, settings } = useSettings(); - const { t } = useTranslation(); - - const updateBackgroundColor = useCallback( - (event: ChangeEvent) => { - update({ backgroundColor: event.target.value }); - }, - [update] - ); - const updateTextColor = useCallback( - (event: ChangeEvent) => { - update({ textColor: event.target.value }); - }, - [update] - ); - - const updateLinkColor = useCallback( - (event: ChangeEvent) => { - update({ linkColor: event.target.value }); - }, - [update] - ); - return ( -
-

{t("Colors")}

- - - - - - +
+
); }; diff --git a/src/modules/settings/containers/SettingsContainer/styles.module.scss b/src/modules/settings/containers/SettingsContainer/styles.module.scss new file mode 100644 index 0000000..649c1e8 --- /dev/null +++ b/src/modules/settings/containers/SettingsContainer/styles.module.scss @@ -0,0 +1,3 @@ +.container { + width: min(100vw, 400px); +} diff --git a/src/modules/settings/context/SettingsContext.ts b/src/modules/settings/context/SettingsContext.ts index 5719c58..7d79234 100644 --- a/src/modules/settings/context/SettingsContext.ts +++ b/src/modules/settings/context/SettingsContext.ts @@ -4,6 +4,7 @@ export interface ColorSettings { backgroundColor: string; textColor: string; linkColor: string; + codeColor: string; } export type SettingsValue = ColorSettings & { @@ -15,6 +16,7 @@ export const defaultSettings: SettingsValue = { backgroundColor: "", textColor: "", linkColor: "", + codeColor: "", }; export const SettingsContext = createContext({ diff --git a/src/modules/settings/providers/SettingsProvider/index.tsx b/src/modules/settings/providers/SettingsProvider/index.tsx index b1a2e43..9565c25 100644 --- a/src/modules/settings/providers/SettingsProvider/index.tsx +++ b/src/modules/settings/providers/SettingsProvider/index.tsx @@ -13,8 +13,12 @@ import { defaultDarkTheme, defaultLightTheme, } from "~/modules/theme/constants/theme"; +import { Button } from "~/components/buttons/Button"; +import { useTranslation } from "react-i18next"; +import styles from "./styles.module.scss"; const SettingsProvider: FC = ({ children }) => { + const { t } = useTranslation(); const theme = useDetectTheme(); const defaultColors = theme === Theme.Dark ? defaultDarkTheme : defaultLightTheme; @@ -36,8 +40,14 @@ const SettingsProvider: FC = ({ children }) => { {settingsModalVisible && ( - + + +
+
+ +
+
)} diff --git a/src/modules/settings/providers/SettingsProvider/styles.module.scss b/src/modules/settings/providers/SettingsProvider/styles.module.scss new file mode 100644 index 0000000..0567957 --- /dev/null +++ b/src/modules/settings/providers/SettingsProvider/styles.module.scss @@ -0,0 +1,9 @@ +.buttons { + padding-top: 20px; + display: flex; + flex-direction: row; +} + +.filler { + flex: 1; +} diff --git a/src/modules/theme/constants/theme.ts b/src/modules/theme/constants/theme.ts index bff3dc3..5c98241 100644 --- a/src/modules/theme/constants/theme.ts +++ b/src/modules/theme/constants/theme.ts @@ -9,10 +9,12 @@ export const defaultDarkTheme: ColorSettings = { backgroundColor: "#2e2e2e", textColor: "#eeeeee", linkColor: "#25bfe6", + codeColor: "#ff3344", }; export const defaultLightTheme: ColorSettings = { backgroundColor: "#eeeeee", textColor: "#2e2e2e", linkColor: "#25bfe6", + codeColor: "#ff3344", }; diff --git a/src/modules/theme/hooks/useThemeColors.ts b/src/modules/theme/hooks/useThemeColors.ts index de005d3..e4d3385 100644 --- a/src/modules/theme/hooks/useThemeColors.ts +++ b/src/modules/theme/hooks/useThemeColors.ts @@ -9,11 +9,22 @@ export const useThemeColors = (settings: ColorSettings) => { const border = isDark ? background.mix(Color("white"), 0.1) - : background.mix(Color("black"), 0.1); + : background.mix(Color("black"), 0.2); + + const code = new Color(settings.codeColor); document.body.style.setProperty("--color-background", background.hex()); + document.body.style.setProperty("--color-code", code.hex()); + document.body.style.setProperty( + "--color-code-background", + code.fade(isDark ? 0.9 : 0.7).toString() + ); document.body.style.setProperty("--color-text", settings.textColor); document.body.style.setProperty("--color-link", settings.linkColor); document.body.style.setProperty("--color-border", border.hex()); + document.body.style.setProperty( + "--color-pre-background", + isDark ? background.lighten(0.2).hex() : background.darken(0.2).hex() + ); }, [settings]); }; diff --git a/src/styles/main.scss b/src/styles/main.scss index a70ab08..74a138e 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -54,3 +54,20 @@ pre { color: inherit; } } + +blockquote { + background: var(--color-pre-background); + margin-left: 0; + padding: 5px 10px; + border-radius: 4px; + font-size: 0.9em; + border-left: var(--color-border) 4px solid; + + p { + margin: 5px 0; + } +} + +img { + max-width: 100%; +}