Skip to content

Commit 778657b

Browse files
committed
frontend/aria: hotkey nav
1 parent 0a92469 commit 778657b

32 files changed

+3382
-12
lines changed

src/dev/ARIA.md

Lines changed: 706 additions & 5 deletions
Large diffs are not rendered by default.

src/packages/frontend/account/account-preferences-appearance.tsx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import {
2727
get_dark_mode_config,
2828
} from "./dark-mode";
2929
import { EditorSettingsColorScheme } from "./editor-settings/color-schemes";
30+
import { HotkeyDelayTest } from "./hotkey-delay-test";
31+
import { HotkeySelector } from "./hotkey-selector";
3032
import { I18NSelector, I18N_MESSAGE, I18N_TITLE } from "./i18n-selector";
3133
import { OtherSettings } from "./other-settings";
3234
import { TerminalSettings } from "./terminal-settings";
@@ -241,6 +243,78 @@ export function AccountPreferencesAppearance() {
241243
</HelpIcon>
242244
</div>
243245
</LabeledRow>
246+
<LabeledRow
247+
label={
248+
<>
249+
<Icon name="flash" /> Quick Navigation Hotkey
250+
</>
251+
}
252+
>
253+
<HotkeySelector
254+
value={other_settings.get("quick_nav_hotkey") ?? "shift+shift"}
255+
onChange={(value) => on_change("quick_nav_hotkey", value)}
256+
style={{ width: 200 }}
257+
/>
258+
</LabeledRow>
259+
{(other_settings.get("quick_nav_hotkey") ?? "shift+shift") ===
260+
"shift+shift" && (
261+
<LabeledRow
262+
label={
263+
<>
264+
<Icon name="clock" /> Hotkey Delay (milliseconds)
265+
</>
266+
}
267+
>
268+
<div style={{ display: "flex", gap: 16, alignItems: "stretch" }}>
269+
<div
270+
style={{
271+
flex: "1 1 auto",
272+
display: "flex",
273+
alignItems: "center",
274+
}}
275+
>
276+
<Slider
277+
min={100}
278+
max={800}
279+
step={100}
280+
value={other_settings.get("quick_nav_hotkey_delay") ?? 300}
281+
onChange={(value) =>
282+
on_change("quick_nav_hotkey_delay", value)
283+
}
284+
style={{ flex: 1 }}
285+
marks={Object.fromEntries(
286+
Array.from({ length: 8 }, (_, i) => (i + 1) * 100).map(
287+
(ms) => [ms, `${ms}ms`],
288+
),
289+
)}
290+
/>
291+
<span
292+
style={{
293+
minWidth: 60,
294+
textAlign: "right",
295+
fontWeight: 500,
296+
color: COLORS.GRAY_M,
297+
marginLeft: 12,
298+
}}
299+
>
300+
{other_settings.get("quick_nav_hotkey_delay") ?? 300}ms
301+
</span>
302+
</div>
303+
<div
304+
style={{
305+
flex: "0 1 auto",
306+
display: "flex",
307+
flexDirection: "column",
308+
gap: 8,
309+
}}
310+
>
311+
<HotkeyDelayTest
312+
delayMs={other_settings.get("quick_nav_hotkey_delay") ?? 300}
313+
/>
314+
</div>
315+
</div>
316+
</LabeledRow>
317+
)}
244318
<Switch
245319
checked={!!other_settings.get("auto_focus")}
246320
onChange={(e) => on_change("auto_focus", e.target.checked)}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* This file is part of CoCalc: Copyright © 2025 Sagemath, Inc.
3+
* License: MS-RSL – see LICENSE.md for details
4+
*/
5+
6+
/**
7+
* Shared configuration for account menu items and preferences sub-tabs
8+
* Used by both account-page.tsx and hotkey quick navigation
9+
*/
10+
11+
export interface AccountMenuItem {
12+
id: string; // Menu item ID (e.g., "subscriptions", "preferences-appearance")
13+
key: string; // Tree node key (e.g., "account-subscriptions")
14+
label: string; // Display name
15+
icon?: string; // Icon name (or undefined for special components like AIAvatar)
16+
useAIAvatar?: boolean; // Special case for AI preferences
17+
isPreferencesSubTab?: boolean; // True if this is a sub-tab under Preferences
18+
}
19+
20+
/**
21+
* Preferences sub-tabs (nested under "Preferences")
22+
*/
23+
export const PREFERENCES_SUB_TABS: AccountMenuItem[] = [
24+
{
25+
id: "preferences-appearance",
26+
key: "account-preferences-appearance",
27+
label: "Appearance",
28+
icon: "eye",
29+
isPreferencesSubTab: true,
30+
},
31+
{
32+
id: "preferences-editor",
33+
key: "account-preferences-editor",
34+
label: "Editor",
35+
icon: "edit",
36+
isPreferencesSubTab: true,
37+
},
38+
{
39+
id: "preferences-keyboard",
40+
key: "account-preferences-keyboard",
41+
label: "Keyboard",
42+
icon: "keyboard",
43+
isPreferencesSubTab: true,
44+
},
45+
{
46+
id: "preferences-ai",
47+
key: "account-preferences-ai",
48+
label: "AI",
49+
useAIAvatar: true,
50+
isPreferencesSubTab: true,
51+
},
52+
{
53+
id: "preferences-communication",
54+
key: "account-preferences-communication",
55+
label: "Communication",
56+
icon: "comments",
57+
isPreferencesSubTab: true,
58+
},
59+
{
60+
id: "preferences-keys",
61+
key: "account-preferences-keys",
62+
label: "SSH and API Keys",
63+
icon: "key",
64+
isPreferencesSubTab: true,
65+
},
66+
{
67+
id: "preferences-other",
68+
key: "account-preferences-other",
69+
label: "Other",
70+
icon: "sliders",
71+
isPreferencesSubTab: true,
72+
},
73+
];
74+
75+
/**
76+
* Main account menu items (top-level, excluding preferences which are nested)
77+
*/
78+
export const ACCOUNT_MAIN_MENU_ITEMS: AccountMenuItem[] = [
79+
{
80+
id: "index",
81+
key: "account-index",
82+
label: "Settings",
83+
icon: "settings",
84+
},
85+
{
86+
id: "profile",
87+
key: "account-profile",
88+
label: "Profile",
89+
icon: "user",
90+
},
91+
// Preferences is handled separately as it has sub-items
92+
{
93+
id: "subscriptions",
94+
key: "account-subscriptions",
95+
label: "Subscriptions",
96+
icon: "calendar",
97+
},
98+
{
99+
id: "licenses",
100+
key: "account-licenses",
101+
label: "Licenses",
102+
icon: "key",
103+
},
104+
{
105+
id: "payg",
106+
key: "account-payg",
107+
label: "Pay as you Go",
108+
icon: "line-chart",
109+
},
110+
{
111+
id: "upgrades",
112+
key: "account-upgrades",
113+
label: "Upgrades",
114+
icon: "arrow-circle-up",
115+
},
116+
{
117+
id: "purchases",
118+
key: "account-purchases",
119+
label: "Purchases",
120+
icon: "money-check",
121+
},
122+
{
123+
id: "payments",
124+
key: "account-payments",
125+
label: "Payments",
126+
icon: "credit-card",
127+
},
128+
{
129+
id: "payment-methods",
130+
key: "account-payment-methods",
131+
label: "Payment Methods",
132+
icon: "credit-card",
133+
},
134+
{
135+
id: "statements",
136+
key: "account-statements",
137+
label: "Statements",
138+
icon: "calendar-week",
139+
},
140+
{
141+
id: "cloud-filesystems",
142+
key: "account-cloud-filesystems",
143+
label: "Cloud Filesystems",
144+
icon: "cloud",
145+
},
146+
{
147+
id: "public-paths",
148+
key: "account-public-paths",
149+
label: "Public Paths",
150+
icon: "share-square",
151+
},
152+
{
153+
id: "support",
154+
key: "account-support",
155+
label: "Support",
156+
icon: "question-circle",
157+
},
158+
];

0 commit comments

Comments
 (0)