feat: Improve keyboard shortcuts guide ally (#13193)

* fix: Ally for keyboard shortcut guide

* Remove translations

* feedback
This commit is contained in:
Tom Moor
2026-07-29 19:17:11 -04:00
committed by GitHub
parent f84ca3b9c3
commit f78f285ec0
8 changed files with 195 additions and 245 deletions
+1
View File
@@ -129,6 +129,7 @@ const InputMaxWidth = styled(Input).attrs({ round: true })`
const Shortcut = styled.span<{ $visible: boolean }>`
flex-shrink: 0;
font-size: 13px;
font-feature-settings: "cv08", "zero";
color: ${s("textTertiary")};
padding-inline: 0 10px;
pointer-events: none;
+2
View File
@@ -11,6 +11,8 @@ const Key = styled.kbd<Props>`
font-size: 11px;
font-family: ${(props) =>
props.symbol ? props.theme.fontFamily : props.theme.fontFamilyMono};
/* Disambiguation for "I" and slashed zero so "0" doesn't read as "O" */
font-feature-settings: "cv08", "zero";
line-height: 10px;
color: ${(props) => props.theme.almostBlack};
vertical-align: middle;
+107
View File
@@ -0,0 +1,107 @@
import { Fragment } from "react";
import { useTranslation } from "react-i18next";
import { isMac } from "@shared/utils/browser";
import { altDisplay, metaDisplay } from "@shared/utils/keyboard";
import Key from "~/components/Key";
/** A key in a shortcut, either the name of a well-known key or an explicit definition. */
export type ShortcutKey =
| string
| {
/** The character(s) shown on screen */
display: string;
/** The name announced by screen readers, defaults to the displayed character(s) */
label?: string;
/** Set to true if displaying a single symbol character to disable monospace */
symbol?: boolean;
};
/** How the keys of a shortcut relate to one another. */
export type KeyCombination =
/** Keys are held down together */
| "hold"
/** Keys are pressed one after another */
| "sequence"
/** Any one of the keys triggers the shortcut */
| "alternative";
type Props = {
/** The keys that make up the shortcut, in the order they are pressed */
keys: ShortcutKey[];
/** How the keys relate to one another, defaults to being held down together */
combination?: KeyCombination;
};
type ResolvedKey = { display: string; label: string; symbol: boolean };
/** Keys that have a platform-specific display, or a name that differs from it. */
const namedKeys: Record<string, ResolvedKey> = {
meta: {
display: metaDisplay,
label: isMac ? "Command" : "Control",
symbol: true,
},
ctrl: { display: "Ctrl", label: "Control", symbol: false },
alt: { display: altDisplay, label: isMac ? "Option" : "Alt", symbol: true },
shift: { display: "⇧", label: "Shift", symbol: true },
enter: isMac
? { display: "Return", label: "Return", symbol: false }
: { display: "Enter", label: "Enter", symbol: false },
tab: { display: "Tab", label: "Tab", symbol: false },
space: { display: "Space", label: "Space", symbol: false },
esc: { display: "Esc", label: "Escape", symbol: false },
up: { display: "↑", label: "Up arrow", symbol: true },
down: { display: "↓", label: "Down arrow", symbol: true },
};
/**
* Displays a keyboard shortcut as a series of keys, announced to screen readers
* as a single instruction such as "Command plus K".
*
* @param props The keys of the shortcut and how they are combined.
* @returns A React element displaying the shortcut.
*/
export function KeyboardShortcut({ keys, combination = "hold" }: Props) {
const { t } = useTranslation();
const resolved = keys.map((key): ResolvedKey => {
if (typeof key === "string") {
return (
namedKeys[key] ?? {
display: key,
label: key.length === 1 ? key.toLocaleUpperCase() : key,
symbol: false,
}
);
}
return {
display: key.display,
label: key.label ?? key.display,
symbol: key.symbol ?? false,
};
});
const separator =
combination === "hold" ? "+" : combination === "alternative" ? t("or") : "";
const spokenSeparator =
combination === "hold"
? t("plus")
: combination === "alternative"
? t("or")
: t("then");
return (
<span
role="img"
aria-label={resolved.map((key) => key.label).join(` ${spokenSeparator} `)}
>
{resolved.map((key, index) => (
<Fragment key={index}>
{index > 0 && (separator ? ` ${separator} ` : " ")}
<Key symbol={key.symbol}>{key.display}</Key>
</Fragment>
))}
</span>
);
}
+1
View File
@@ -161,6 +161,7 @@ const SearchLabel = styled.span`
const Shortcut = styled.span`
flex-shrink: 0;
font-size: 13px;
font-feature-settings: "cv08", "zero";
`;
export default observer(SharedSidebar);
+1
View File
@@ -254,6 +254,7 @@ const Shortcut = styled.kbd`
padding: 2px 4px;
font-size: 12px;
font-family: ${s("fontFamilyMono")};
font-feature-settings: "cv08", "zero";
line-height: 10px;
color: ${s("tooltipText")};
border: 1px solid ${(props) => transparentize(0.75, props.theme.tooltipText)};
@@ -174,6 +174,7 @@ export const MenuShortcut = styled.span`
align-items: center;
gap: 2px;
font-size: 12px;
font-feature-settings: "cv08", "zero";
color: currentColor;
opacity: 0.5;
margin-inline-start: 16px;
+79 -242
View File
@@ -3,10 +3,9 @@ import { useTranslation } from "react-i18next";
import styled from "styled-components";
import { s } from "@shared/styles";
import { isMac } from "@shared/utils/browser";
import { metaDisplay, altDisplay } from "@shared/utils/keyboard";
import Flex from "~/components/Flex";
import InputSearch from "~/components/InputSearch";
import Key from "~/components/Key";
import { KeyboardShortcut } from "~/components/KeyboardShortcut";
type Props = {
/** Initial search query to filter shortcuts */
@@ -21,125 +20,86 @@ function KeyboardShortcuts({ defaultQuery = "" }: Props) {
title: t("Navigation"),
items: [
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>k</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "k"]} />,
label: t("Open command menu"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol>[</Key>
</>
<KeyboardShortcut
keys={["meta", { display: "[", symbol: true }]}
/>
),
label: t("Back"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol>]</Key>
</>
<KeyboardShortcut
keys={["meta", { display: "]", symbol: true }]}
/>
),
label: t("Forward"),
},
{
shortcut: <Key>n</Key>,
shortcut: <KeyboardShortcut keys={["n"]} />,
label: t("New document"),
},
{
shortcut: <Key>e</Key>,
shortcut: <KeyboardShortcut keys={["e"]} />,
label: t("Edit current document"),
},
{
shortcut: <Key>m</Key>,
shortcut: <KeyboardShortcut keys={["m"]} />,
label: t("Move current document"),
},
{
shortcut: <Key>h</Key>,
shortcut: <KeyboardShortcut keys={["h"]} />,
label: t("Open document history"),
},
{
shortcut: (
<>
<Key>/</Key> or <Key>t</Key>
</>
<KeyboardShortcut keys={["/", "t"]} combination="alternative" />
),
label: t("Jump to search"),
},
{
shortcut: <Key>d</Key>,
shortcut: <KeyboardShortcut keys={["d"]} />,
label: t("Jump to home"),
},
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol>{altDisplay}</Key> + <Key>h</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "alt", "h"]} />,
label: t("Table of contents"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>.</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "."]} />,
label: t("Toggle sidebar"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol></Key> +{" "}
<Key>l</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "shift", "l"]} />,
label: t("Toggle theme"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>f</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "f"]} />,
label: t("Focus search input"),
},
{
shortcut: <Key>?</Key>,
shortcut: <KeyboardShortcut keys={["?"]} />,
label: t("Open this guide"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>{t("Enter")}</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "enter"]} />,
label: t("Go to link"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol>{altDisplay}</Key>{" "}
+ <Key>p</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "alt", "p"]} />,
label: t("Present document"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol></Key> +{" "}
<Key>p</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "shift", "p"]} />,
label: t("Publish document and exit"),
},
{
shortcut: (
<>
<Key symbol>{isMac ? metaDisplay : "⇧"}</Key> + <Key>Esc</Key>
</>
<KeyboardShortcut keys={[isMac ? "meta" : "shift", "esc"]} />
),
label: t("Cancel editing"),
},
@@ -149,11 +109,7 @@ function KeyboardShortcuts({ defaultQuery = "" }: Props) {
title: t("Collaboration"),
items: [
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>Alt</Key> + <Key>m</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "alt", "m"]} />,
label: t("Comment"),
},
],
@@ -162,136 +118,67 @@ function KeyboardShortcuts({ defaultQuery = "" }: Props) {
title: t("Formatting"),
items: [
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>0</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "0"]} />,
label: t("Paragraph"),
},
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>1</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "1"]} />,
label: t("Large header"),
},
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>2</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "2"]} />,
label: t("Medium header"),
},
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>3</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "3"]} />,
label: t("Small header"),
},
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>\</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "\\"]} />,
label: t("Code block"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>b</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "b"]} />,
label: t("Bold"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol></Key> +{" "}
<Key>c</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "shift", "c"]} />,
label: t("Code"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol></Key> +{" "}
<Key>h</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "shift", "h"]} />,
label: t("Highlight"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>i</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "i"]} />,
label: t("Italic"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>k</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "k"]} />,
label: t("Link"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>d</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "d"]} />,
label: t("Strikethrough"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>u</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "u"]} />,
label: t("Underline"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>z</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "z"]} />,
label: t("Undo"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol></Key> +{" "}
<Key>z</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "shift", "z"]} />,
label: t("Redo"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol>{altDisplay}</Key>{" "}
+ <Key symbol></Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "alt", "up"]} />,
label: t("Move block up"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key symbol>{altDisplay}</Key>{" "}
+ <Key symbol></Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "alt", "down"]} />,
label: t("Move block down"),
},
],
@@ -300,63 +187,35 @@ function KeyboardShortcuts({ defaultQuery = "" }: Props) {
title: t("Lists"),
items: [
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>7</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "7"]} />,
label: t("Todo list"),
},
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>8</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "8"]} />,
label: t("Bulleted list"),
},
{
shortcut: (
<>
<Key>Ctrl</Key> + <Key symbol></Key> + <Key>9</Key>
</>
),
shortcut: <KeyboardShortcut keys={["ctrl", "shift", "9"]} />,
label: t("Ordered list"),
},
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>Enter</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "enter"]} />,
label: t("Toggle task list item"),
},
{
shortcut: <Key>{t("Tab")}</Key>,
shortcut: <KeyboardShortcut keys={["tab"]} />,
label: t("Indent list item"),
},
{
shortcut: (
<>
<Key symbol></Key> + <Key>{t("Tab")}</Key>
</>
),
shortcut: <KeyboardShortcut keys={["shift", "tab"]} />,
label: t("Outdent list item"),
},
{
shortcut: (
<>
<Key symbol>{altDisplay}</Key> + <Key symbol></Key>
</>
),
shortcut: <KeyboardShortcut keys={["alt", "up"]} />,
label: t("Move list item up"),
},
{
shortcut: (
<>
<Key symbol>{altDisplay}</Key> + <Key symbol></Key>
</>
),
shortcut: <KeyboardShortcut keys={["alt", "down"]} />,
label: t("Move list item down"),
},
],
@@ -365,23 +224,15 @@ function KeyboardShortcuts({ defaultQuery = "" }: Props) {
title: t("Toggle blocks"),
items: [
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>Enter</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "enter"]} />,
label: t("Open / close"),
},
{
shortcut: <Key>{t("Tab")}</Key>,
shortcut: <KeyboardShortcut keys={["tab"]} />,
label: t("Indent item"),
},
{
shortcut: (
<>
<Key symbol></Key> + <Key>{t("Tab")}</Key>
</>
),
shortcut: <KeyboardShortcut keys={["shift", "tab"]} />,
label: t("Outdent item"),
},
],
@@ -390,23 +241,15 @@ function KeyboardShortcuts({ defaultQuery = "" }: Props) {
title: t("Tables"),
items: [
{
shortcut: (
<>
<Key symbol>{metaDisplay}</Key> + <Key>{t("Enter")}</Key>
</>
),
shortcut: <KeyboardShortcut keys={["meta", "enter"]} />,
label: t("Insert row"),
},
{
shortcut: <Key>{t("Tab")}</Key>,
shortcut: <KeyboardShortcut keys={["tab"]} />,
label: t("Next cell"),
},
{
shortcut: (
<>
<Key symbol></Key> + <Key>{t("Tab")}</Key>
</>
),
shortcut: <KeyboardShortcut keys={["shift", "tab"]} />,
label: t("Previous cell"),
},
],
@@ -416,90 +259,84 @@ function KeyboardShortcuts({ defaultQuery = "" }: Props) {
items: [
{
shortcut: (
<>
<Key>#</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut keys={["#", "space"]} combination="sequence" />
),
label: t("Large header"),
},
{
shortcut: (
<>
<Key>##</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut keys={["##", "space"]} combination="sequence" />
),
label: t("Medium header"),
},
{
shortcut: (
<>
<Key>###</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut
keys={["###", "space"]}
combination="sequence"
/>
),
label: t("Small header"),
},
{
shortcut: (
<>
<Key>1.</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut keys={["1.", "space"]} combination="sequence" />
),
label: t("Numbered list"),
},
{
shortcut: (
<>
<Key>-</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut keys={["-", "space"]} combination="sequence" />
),
label: t("Bulleted list"),
},
{
shortcut: (
<>
<Key>[ ]</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut
keys={["[ ]", "space"]}
combination="sequence"
/>
),
label: t("Todo list"),
},
{
shortcut: (
<>
<Key>&gt;</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut keys={[">", "space"]} combination="sequence" />
),
label: t("Blockquote"),
},
{
shortcut: <Key>---</Key>,
shortcut: <KeyboardShortcut keys={["---"]} />,
label: t("Horizontal divider"),
},
{
shortcut: <Key>{"|--"}</Key>,
shortcut: <KeyboardShortcut keys={["|--"]} />,
label: t("Table"),
},
{
shortcut: <Key>{"```"}</Key>,
shortcut: <KeyboardShortcut keys={["```"]} />,
label: t("Code block"),
},
{
shortcut: (
<>
<Key>$$$</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut
keys={["$$$", "space"]}
combination="sequence"
/>
),
label: t("LaTeX block"),
},
{
shortcut: (
<>
<Key>+++</Key> <Key>{t("Space")}</Key>
</>
<KeyboardShortcut
keys={["+++", "space"]}
combination="sequence"
/>
),
label: t("Toggle block"),
},
{
shortcut: <Key>{":::"}</Key>,
shortcut: <KeyboardShortcut keys={[":::"]} />,
label: t("Info notice"),
},
{
+3 -3
View File
@@ -396,6 +396,9 @@
"Can edit": "Can edit",
"No access": "No access",
"Permission": "Permission",
"or": "or",
"plus": "plus",
"then": "then",
"Change Language": "Change Language",
"Dismiss": "Dismiss",
"Unable to download image": "Unable to download image",
@@ -970,7 +973,6 @@
"Jump to home": "Jump to home",
"Focus search input": "Focus search input",
"Open this guide": "Open this guide",
"Enter": "Enter",
"Publish document and exit": "Publish document and exit",
"Cancel editing": "Cancel editing",
"Collaboration": "Collaboration",
@@ -987,7 +989,6 @@
"Move block down": "Move block down",
"Lists": "Lists",
"Toggle task list item": "Toggle task list item",
"Tab": "Tab",
"Indent list item": "Indent list item",
"Outdent list item": "Outdent list item",
"Move list item up": "Move list item up",
@@ -1000,7 +1001,6 @@
"Insert row": "Insert row",
"Next cell": "Next cell",
"Previous cell": "Previous cell",
"Space": "Space",
"Numbered list": "Numbered list",
"Blockquote": "Blockquote",
"Horizontal divider": "Horizontal divider",