diff --git a/app/assets/javascripts/initializers/runtime.js b/app/assets/javascripts/initializers/runtime.js
index 88e11f484..175875b6b 100644
--- a/app/assets/javascripts/initializers/runtime.js
+++ b/app/assets/javascripts/initializers/runtime.js
@@ -156,4 +156,14 @@ class Runtime {
return event.ctrlKey;
}
}
+
+ /**
+ * Returns a string representation of the expected modifier key for the current OS.
+ * This allows us to display correct shortcut key hints to users in the UI, and set up correct shortcut key bindings.
+ *
+ * @returns {string} either 'cmd' if on macOS, or 'ctrl' otherwise
+ */
+ static getOSKeyboardModifierKeyString() {
+ return Runtime.currentOS() === 'macOS' ? 'cmd' : 'ctrl';
+ }
}
diff --git a/app/javascript/.storybook/preview-head.html b/app/javascript/.storybook/preview-head.html
index a30435dfe..2a30f665c 100644
--- a/app/javascript/.storybook/preview-head.html
+++ b/app/javascript/.storybook/preview-head.html
@@ -1,7 +1,7 @@
diff --git a/app/javascript/article-form/articleForm.jsx b/app/javascript/article-form/articleForm.jsx
index ad17139ba..52ef7eeef 100644
--- a/app/javascript/article-form/articleForm.jsx
+++ b/app/javascript/article-form/articleForm.jsx
@@ -1,3 +1,4 @@
+/* global Runtime */
import { h, Component } from 'preact';
import PropTypes from 'prop-types';
import linkState from 'linkstate';
@@ -476,7 +477,8 @@ export class ArticleForm extends Component {
diff --git a/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx b/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx
index 23623ac01..b1c5509ed 100644
--- a/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx
+++ b/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx
@@ -1,4 +1,3 @@
-/* global Runtime */
import { h } from 'preact';
import { useState, useLayoutEffect } from 'preact/hooks';
import {
@@ -16,9 +15,6 @@ export const MarkdownToolbar = ({ textAreaId }) => {
const [overflowMenuOpen, setOverflowMenuOpen] = useState(false);
const smallScreen = useMediaQuery(`(max-width: ${BREAKPOINTS.Medium - 1}px)`);
- const keyboardShortcutModifierText =
- Runtime.currentOS() === 'macOS' ? 'CMD' : 'CTRL';
-
const markdownSyntaxFormatters = {
...coreSyntaxFormatters,
...secondarySyntaxFormatters,
@@ -27,11 +23,13 @@ export const MarkdownToolbar = ({ textAreaId }) => {
const keyboardShortcuts = Object.fromEntries(
Object.keys(markdownSyntaxFormatters)
.filter(
- (syntaxName) => !!markdownSyntaxFormatters[syntaxName].keyboardShortcut,
+ (syntaxName) =>
+ !!markdownSyntaxFormatters[syntaxName].getKeyboardShortcut,
)
.map((syntaxName) => {
- const { keyboardShortcut } = markdownSyntaxFormatters[syntaxName];
- return [keyboardShortcut, () => insertSyntax(syntaxName)];
+ const { command } =
+ markdownSyntaxFormatters[syntaxName].getKeyboardShortcut?.();
+ return [command, () => insertSyntax(syntaxName)];
}),
);
@@ -189,8 +187,9 @@ export const MarkdownToolbar = ({ textAreaId }) => {
const getSecondaryFormatterButtons = (isOverflow) =>
Object.keys(secondarySyntaxFormatters).map((controlName, index) => {
- const { icon, label, keyboardShortcutKeys } =
+ const { icon, label, getKeyboardShortcut } =
secondarySyntaxFormatters[controlName];
+
return (