diff --git a/packages/models/src/Domain/Syncable/UserPrefs/EditorFontFamily.ts b/packages/models/src/Domain/Syncable/UserPrefs/EditorFontFamily.ts
new file mode 100644
index 00000000000..dc778bcc75c
--- /dev/null
+++ b/packages/models/src/Domain/Syncable/UserPrefs/EditorFontFamily.ts
@@ -0,0 +1,25 @@
+export enum EditorFontFamily {
+ SansSerif = 'SansSerif',
+ Monospace = 'Monospace',
+ Serif = 'Serif',
+ Lora = 'Lora',
+ Merriweather = 'Merriweather',
+ OpenSans = 'OpenSans',
+ RobotoMono = 'RobotoMono',
+ Dyslexic = 'Dyslexic',
+ Quicksand = 'Quicksand',
+ ComicSans = 'ComicSans',
+}
+
+export const EditorFontFamilyValues: { [key in EditorFontFamily]: string } = {
+ SansSerif: 'var(--sn-stylekit-sans-serif-font)',
+ Monospace: 'var(--sn-stylekit-monospace-font)',
+ Serif: 'Georgia, Times New Roman, Times, serif',
+ Lora: 'Lora, Georgia, serif',
+ Merriweather: 'Merriweather, Georgia, serif',
+ OpenSans: 'Open Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
+ RobotoMono: 'Roboto Mono, var(--sn-stylekit-monospace-font)',
+ Dyslexic: 'Comic Neue, Comic Sans MS, sans-serif',
+ Quicksand: 'Quicksand, Open Sans, Segoe UI, sans-serif',
+ ComicSans: 'Comic Sans MS, Comic Sans, Comic Neue, cursive, sans-serif',
+}
diff --git a/packages/models/src/Domain/Syncable/UserPrefs/index.ts b/packages/models/src/Domain/Syncable/UserPrefs/index.ts
index 859f7e4de00..2c58241aea9 100644
--- a/packages/models/src/Domain/Syncable/UserPrefs/index.ts
+++ b/packages/models/src/Domain/Syncable/UserPrefs/index.ts
@@ -7,3 +7,4 @@ export * from './EditorLineWidth'
export * from './NewNoteTitleFormat'
export * from './ComponentPreferences'
export * from './PrefDefaults'
+export * from './EditorFontFamily'
diff --git a/packages/services/src/Domain/Preferences/LocalPrefKey.ts b/packages/services/src/Domain/Preferences/LocalPrefKey.ts
index 51e89e02fa8..5496c814b30 100644
--- a/packages/services/src/Domain/Preferences/LocalPrefKey.ts
+++ b/packages/services/src/Domain/Preferences/LocalPrefKey.ts
@@ -1,4 +1,4 @@
-import { EditorFontSize, EditorLineHeight, EditorLineWidth } from '@standardnotes/models'
+import { EditorFontSize, EditorLineHeight, EditorLineWidth, EditorFontFamily } from '@standardnotes/models'
import { NativeFeatureIdentifier } from '@standardnotes/features'
export enum LocalPrefKey {
@@ -14,6 +14,7 @@ export enum LocalPrefKey {
EditorLineHeight = 'editorLineHeight',
EditorLineWidth = 'editorLineWidth',
EditorFontSize = 'editorFontSize',
+ EditorFontFamily = 'editorFontFamily',
}
export type LocalPrefValue = {
@@ -29,6 +30,7 @@ export type LocalPrefValue = {
[LocalPrefKey.EditorLineHeight]: EditorLineHeight
[LocalPrefKey.EditorLineWidth]: EditorLineWidth
[LocalPrefKey.EditorFontSize]: EditorFontSize
+ [LocalPrefKey.EditorFontFamily]: EditorFontFamily
}
export const LocalPrefDefaults = {
@@ -44,6 +46,7 @@ export const LocalPrefDefaults = {
[LocalPrefKey.EditorLineHeight]: EditorLineHeight.Normal,
[LocalPrefKey.EditorLineWidth]: EditorLineWidth.FullWidth,
[LocalPrefKey.EditorFontSize]: EditorFontSize.Normal,
+ [LocalPrefKey.EditorFontFamily]: EditorFontFamily.SansSerif,
} satisfies {
[key in LocalPrefKey]: LocalPrefValue[key]
}
diff --git a/packages/web/src/index.html b/packages/web/src/index.html
index bb112e0c9c2..2a5f1fbeeb2 100644
--- a/packages/web/src/index.html
+++ b/packages/web/src/index.html
@@ -22,6 +22,10 @@
Notes ยท Standard Notes
+
+
+
+
diff --git a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx
index d92d2cd765f..4b81a65642e 100644
--- a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx
+++ b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorMenu.tsx
@@ -13,6 +13,8 @@ import {
SNNote,
ContentType,
LocalPrefKey,
+ LocalPrefDefaults,
+ EditorFontFamily,
} from '@standardnotes/snjs'
import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import { EditorMenuGroup } from '@/Components/NotesOptions/EditorMenuGroup'
@@ -131,7 +133,18 @@ const ChangeEditorMenu: FunctionComponent = ({
setCurrentFeature(application.componentManager.editorForNote(note))
if (uiFeature.featureIdentifier === NativeFeatureIdentifier.TYPES.PlainEditor) {
- reloadFont(application.preferences.getLocalValue(LocalPrefKey.EditorMonospaceEnabled))
+ let fontFamily = application.preferences.getLocalValue(
+ LocalPrefKey.EditorFontFamily,
+ LocalPrefDefaults[LocalPrefKey.EditorFontFamily],
+ )
+ const legacyMonospace = application.preferences.getLocalValue(
+ LocalPrefKey.EditorMonospaceEnabled,
+ LocalPrefDefaults[LocalPrefKey.EditorMonospaceEnabled],
+ )
+ if (fontFamily === EditorFontFamily.SansSerif && legacyMonospace) {
+ fontFamily = EditorFontFamily.Monospace
+ }
+ reloadFont(fontFamily)
}
},
[application],
diff --git a/packages/web/src/javascripts/Components/NoteView/FontFunctions.ts b/packages/web/src/javascripts/Components/NoteView/FontFunctions.ts
index b50ec318526..31588a32ef5 100644
--- a/packages/web/src/javascripts/Components/NoteView/FontFunctions.ts
+++ b/packages/web/src/javascripts/Components/NoteView/FontFunctions.ts
@@ -1,10 +1,19 @@
-export const reloadFont = (monospaceFont?: boolean) => {
+import { EditorFontFamily, EditorFontFamilyValues } from '@standardnotes/snjs'
+
+export const reloadFont = (fontFamily?: EditorFontFamily | boolean) => {
const root = document.querySelector(':root') as HTMLElement
const propertyName = '--sn-stylekit-editor-font-family'
- if (monospaceFont) {
- root.style.setProperty(propertyName, 'var(--sn-stylekit-monospace-font)')
- } else {
- root.style.setProperty(propertyName, 'var(--sn-stylekit-sans-serif-font)')
+
+ let resolvedFont: EditorFontFamily = EditorFontFamily.SansSerif
+ if (typeof fontFamily === 'boolean') {
+ resolvedFont = fontFamily ? EditorFontFamily.Monospace : EditorFontFamily.SansSerif
+ } else if (fontFamily) {
+ resolvedFont = fontFamily
}
- document.documentElement.classList.toggle('monospace-font', monospaceFont)
+
+ const value = EditorFontFamilyValues[resolvedFont] || EditorFontFamilyValues[EditorFontFamily.SansSerif]
+ root.style.setProperty(propertyName, value)
+
+ const isMonospace = resolvedFont === EditorFontFamily.Monospace || resolvedFont === EditorFontFamily.RobotoMono
+ document.documentElement.classList.toggle('monospace-font', isMonospace)
}
diff --git a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx
index 98f953413e1..464300f8975 100644
--- a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx
+++ b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx
@@ -28,6 +28,8 @@ import {
SNNote,
VaultUserServiceEvent,
LocalPrefKey,
+ LocalPrefDefaults,
+ EditorFontFamily,
} from '@standardnotes/snjs'
import { confirmDialog, DELETE_NOTE_KEYBOARD_COMMAND, KeyboardKey } from '@standardnotes/ui-services'
import { ChangeEventHandler, createRef, FocusEvent, KeyboardEventHandler, RefObject } from 'react'
@@ -75,7 +77,7 @@ type State = {
spellcheck: boolean
stackComponentViewers: ComponentViewerInterface[]
syncTakingTooLong: boolean
- monospaceFont?: boolean
+ fontFamily?: EditorFontFamily
editorFocused?: boolean
paneGestureEnabled?: boolean
noteLastEditedByUuid?: string
@@ -547,7 +549,7 @@ class NoteView extends AbstractComponent {
editorStateDidLoad: true,
})
} else {
- reloadFont(this.state.monospaceFont)
+ reloadFont(this.state.fontFamily)
this.setState({
editorStateDidLoad: true,
})
@@ -654,7 +656,7 @@ class NoteView extends AbstractComponent {
async reloadSpellcheck() {
const spellcheck = this.application.notesController.getSpellcheckStateForNote(this.note)
if (spellcheck !== this.state.spellcheck) {
- reloadFont(this.state.monospaceFont)
+ reloadFont(this.state.fontFamily)
this.setState({ spellcheck })
}
}
@@ -669,11 +671,20 @@ class NoteView extends AbstractComponent {
async reloadPreferences() {
log(LoggingDomain.NoteView, 'Reload preferences')
- const monospaceFont = this.application.preferences.getLocalValue(
+ let fontFamily = this.application.preferences.getLocalValue(
+ LocalPrefKey.EditorFontFamily,
+ LocalPrefDefaults[LocalPrefKey.EditorFontFamily],
+ )
+
+ const legacyMonospace = this.application.preferences.getLocalValue(
LocalPrefKey.EditorMonospaceEnabled,
- PrefDefaults[LocalPrefKey.EditorMonospaceEnabled],
+ LocalPrefDefaults[LocalPrefKey.EditorMonospaceEnabled],
)
+ if (fontFamily === EditorFontFamily.SansSerif && legacyMonospace) {
+ fontFamily = EditorFontFamily.Monospace
+ }
+
const updateSavingIndicator = this.application.getPreference(
PrefKey.UpdateSavingStatusIndicator,
PrefDefaults[PrefKey.UpdateSavingStatusIndicator],
@@ -689,12 +700,12 @@ class NoteView extends AbstractComponent {
this.reloadLineWidth()
this.setState({
- monospaceFont,
+ fontFamily,
updateSavingIndicator,
paneGestureEnabled,
})
- reloadFont(monospaceFont)
+ reloadFont(fontFamily)
}
async reloadStackComponents() {
diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Appearance/EditorAppearance.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Appearance/EditorAppearance.tsx
index 956ff8460ba..72b3bf459be 100644
--- a/packages/web/src/javascripts/Components/Preferences/Panes/Appearance/EditorAppearance.tsx
+++ b/packages/web/src/javascripts/Components/Preferences/Panes/Appearance/EditorAppearance.tsx
@@ -2,8 +2,7 @@ import { WebApplication } from '@/Application/WebApplication'
import Dropdown from '@/Components/Dropdown/Dropdown'
import Icon from '@/Components/Icon/Icon'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
-import Switch from '@/Components/Switch/Switch'
-import { EditorFontSize, EditorLineHeight, EditorLineWidth, LocalPrefKey } from '@standardnotes/snjs'
+import { EditorFontSize, EditorLineHeight, EditorLineWidth, LocalPrefKey, EditorFontFamily } from '@standardnotes/snjs'
import { useCallback, useMemo } from 'react'
import { Subtitle, Title, Text } from '../../PreferencesComponents/Content'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
@@ -31,11 +30,27 @@ const EditorDefaults = ({ application }: Props) => {
[],
)
- const [monospaceFont, setMonospaceFont] = useLocalPreference(LocalPrefKey.EditorMonospaceEnabled)
- const toggleMonospaceFont = () => {
- setMonospaceFont(!monospaceFont)
+ const [fontFamily, setFontFamily] = useLocalPreference(LocalPrefKey.EditorFontFamily)
+ const handleFontFamilyChange = (value: string) => {
+ setFontFamily(value as EditorFontFamily)
}
+ const fontFamilyDropdownOptions = useMemo(
+ () => [
+ { label: 'Sans-serif (System default)', value: EditorFontFamily.SansSerif },
+ { label: 'Monospace (System default)', value: EditorFontFamily.Monospace },
+ { label: 'Serif (Georgia)', value: EditorFontFamily.Serif },
+ { label: 'Lora (Serif)', value: EditorFontFamily.Lora },
+ { label: 'Merriweather (Serif)', value: EditorFontFamily.Merriweather },
+ { label: 'Open Sans (Modern sans-serif)', value: EditorFontFamily.OpenSans },
+ { label: 'Roboto Mono (Modern monospace)', value: EditorFontFamily.RobotoMono },
+ { label: 'Dyslexic-friendly (Comic Neue)', value: EditorFontFamily.Dyslexic },
+ { label: 'Quicksand (Rounded sans-serif)', value: EditorFontFamily.Quicksand },
+ { label: 'Comic Sans', value: EditorFontFamily.ComicSans },
+ ],
+ [],
+ )
+
const [fontSize, setFontSize] = useLocalPreference(LocalPrefKey.EditorFontSize)
const handleFontSizeChange = (value: string) => {
setFontSize(value as EditorFontSize)
@@ -61,12 +76,17 @@ const EditorDefaults = ({ application }: Props) => {
Editor
-
-
-
Monospace Font
-
Toggles the font style in plaintext and Super notes
+
+
Font family
+
Sets the font family in plaintext and Super notes
+
+
-